这是我之前做的基于STM32的超声波测距系统,
附件里面包含了keil仿真代码以及Proteus仿真工程
请大家多多指教
单片机源程序如下:
- //头文件包含
- #include <reg52.h> //提供单片机寄存器地址
- #include <intrins.h> //提供_nop_()函数
- unsigned int code duan_ma[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0~9
- 0x77,0x7c,0x39,0x5e,0x79,0x71}; //A~F
- unsigned int dis_buf[4]; //显示缓存的数组
- unsigned int S = 0; //距离缓存变量
- unsigned long time = 0; //时间缓存变量
- unsigned int S_H = 400, S_L = 10; //S_H:报警上限值,默认400cm,S_L:报警下限值,默认10cm
- //引脚定义
- sbit BEEP = P3^7; //蜂鸣器控制端口,低电平有效,无源蜂鸣器
-
- #define digDuan P0 //数码管段控制端口,高电平有效
- sbit digWei1 = P2^4; //第1位数码管控制端口,低电平有效
- sbit digWei2 = P2^5; //第2位数码管控制端口,低电平有效
- sbit digWei3 = P2^6; //第3位数码管控制端口,低电平有效
- sbit digWei4 = P2^7; //第4位数码管控制端口,低电平有效
-
- sbit KEY1 = P1^0; //设置键
- sbit KEY2 = P1^1; //加键
- sbit KEY3 = P1^2; //减键
-
- sbit Ttig = P1^3; //触发信号控制端口
- sbit Echo = P1^4; //回响信号接收端口
-
- /* 定时器0和1初始化,定时1ms */
- void InitTimer0(void)
- {
- TMOD = 0x11; //配置定时器0为工作方式1,定时器1位工作方式1
- TH0 = 0;
- TL0 = 0;
- TH1 = 0x0EC; //定时5ms
- TL1 = 0x78;
- EA = 1; //打开总中断
- ET1 = 1; //打开定时器0中断
- TR1 = 1; //打开定时器1
- TR0 = 0; //打开定时器0
- }
- /*
- * 数码管扫描
- * *dat:以数组的方式传值,使用的时候直接填入数组名即可
- */
- void dig_scan(unsigned int *dat)
- {
- static unsigned char i = 0; //循环变量
- /* 数码管扫描处理 */
- digDuan = 0x00; //消隐
- digWei1 = 1;
- digWei2 = 1;
- digWei3 = 1;
- digWei4 = 1;
- switch(i)
- {
- case 0:
- {
- digWei1 = 0; //选通第1位数码管
- digDuan = dat[0]; //显示第1位数码管的内容
- break;
- }
- case 1:
- {
- digWei2 = 0; //选通第2位数码管
- digDuan = dat[1]; //显示第2位数码管的内容
- break;
- }
- case 2:
- {
- digWei3 = 0; //选通第3位数码管
- digDuan = dat[2] + 0x80; //显示第3位数码管的内容,顺便也显示小数点
- break;
- }
- case 3:
- {
- digWei4 = 0; //选通第4位数码管
- digDuan = dat[3]; //显示第4位数码管的内容
- break;
- }
- default: break;
- }
- ++i; //数码管位选变量循环
- if(i >= 4)
- i = 0;
- }
- /* 按键延时函数,单位:ms */
- static void key_delayms(unsigned int ms)
- {
- unsigned char a,b,c;
- while(--ms)
- {
- for(c=1;c>0;c--)
- for(b=142;b>0;b--)
- for(a=2;a>0;a--);
- }
- }
- /* 按键扫描 */
- unsigned char key_scan(void)
- {
- if(KEY1 == 0) //如果按键1按下
- {
- key_delayms(10); //延时10ms,去除按键抖动
- if(KEY1 == 0) //再判断一次按键按下
- {
- return 1; //输出键值1
- }
- }
- if(KEY2 == 0) //如果按键2按下
- {
- key_delayms(10); //延时10ms,去除按键抖动
- if(KEY2 == 0) //再判断一次按键按下
- {
- return 2; //输出键值2
- }
- }
- if(KEY3 == 0) //如果按键3按下
- {
- key_delayms(10); //延时10ms,去除按键抖动
- if(KEY3 == 0) //再判断一次按键按下
- {
- return 3; //输出键值3
- }
- }
- return 0; //如果没有按键按下,则输出0
- }
- /* 启动超声波程序 */
- void StartModule(void)
- {
- Ttig = 1; //启动一次模块
- _nop_(); //延时一段时间,至少10us以上
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- Ttig = 0;
- }
- /* 延时,单位:ms */
- void delayms(unsigned int ms)
- {
- unsigned char a,b,c;
- while(--ms)
- {
- for(c=1;c>0;c--)
- for(b=142;b>0;b--)
- for(a=2;a>0;a--);
- }
- }
- /* 计算测距 */
- void count(void)
- {
- StartModule(); //启动一次超声波
- while(!Echo); //等待超声波模块输出IO拉高
- TR0 = 1; //开启定时器计时
- while(Echo); //等待超声波模块输出IO拉低
- TR0 = 0; //关闭定时器计时
-
- /* 计算距离 */
- time = TH0 * 256 + TL0; //得到的时间,专业写法应该是这样:time = TH0 << 8 | TL0
- TH0 = 0; //定时计数器清零
- TL0 = 0;
-
- S = (time * 1.7) / 100; //算出来是M
- }
- /* 显示距离 */
- void dis_distance(void)
- {
- dis_buf[3] = 0x00;
- dis_buf[2] = duan_ma[S / 100 %10]; //取出百位数,并在数码管的第3位显示,从右往左数
- dis_buf[1] = duan_ma[S / 10 %10]; //取出十位数,并在数码管的第2位显示,从右往左数
- dis_buf[0] = duan_ma[S % 10]; //取出个位数,并在数码管的第1位显示,从右往左数
- }
- /* 设置报警功能 */
- void key_fuction(void)
- {
- unsigned char mode_flag = 1; //模式切换标记位,1:设置上限值,2:设置下限值,3:退出
- while(1)
- {
- if(key_scan() == 1)
- {
- BEEP = 0; //按键提示音
- delayms(50);
- BEEP = 1;
- delayms(1000);
- ++mode_flag;
- if(mode_flag >= 3) //如果满3了,则退出
- break;
- }
- if(key_scan() == 2) //如果加键按下
- {
- BEEP = 0; //按键提示音
- delayms(50);
- BEEP = 1;
- delayms(1000);
- if(mode_flag == 1) //设置上限值
- {
- ++S_H;
- if(S_H > 400)
- S_H = 2;
- }
- if(mode_flag == 2) //设置下限值
- {
- ++S_L;
- if(S_L > 400)
- S_L = 2;
- }
- }
- if(key_scan() == 3) //如果减键按下
- {
- BEEP = 0; //按键提示音
- delayms(50);
- BEEP = 1;
- delayms(1000);
- if(mode_flag == 1) //设置上限值
- {
- --S_H;
- if(S_H < 2)
- S_H = 400;
- }
- if(mode_flag == 2) //设置下限值
- {
- --S_L;
- if(S_L < 2)
- S_L = 400;
- }
- }
- /* 报警设置显示 */
- if(mode_flag == 1) //显示设置上限值内容
- {
- dis_buf[3] = 0x76; //第4位数码管显示字母 H
- dis_buf[2] = duan_ma[S_H / 100 % 10]; //显示百位数
- dis_buf[1] = duan_ma[S_H / 10 % 10]; //显示十位数
- dis_buf[0] = duan_ma[S_H % 10]; //显示个位数
- }
- if(mode_flag == 2) //显示设置下限值内容
- {
- dis_buf[3] = 0x38; //第4位数码管显示字母 L
- dis_buf[2] = duan_ma[S_L / 100 % 10]; //显示百位数
- dis_buf[1] = duan_ma[S_L / 10 % 10]; //显示十位数
- dis_buf[0] = duan_ma[S_L % 10]; //显示个位数
- }
- }
- }
- /* 主函数 */
- void main(void)
- {
- digDuan = 0x40; //显示"----"
- digWei1 = 0;
- digWei2 = 0;
- digWei3 = 0;
- digWei4 = 0;
- delayms(1000); //延时大约1s
- InitTimer0(); //定时器0初始化
- while(1)
- {
- count(); //计算距离
- if(S>=S_H || S<=S_L) //如果超出设定的范围,则显示"---"
- {
- dis_buf[3] = 0x00;
- dis_buf[2] = 0x40; //显示"---"
- dis_buf[1] = 0x40;
- dis_buf[0] = 0x40;
- BEEP = 0; //蜂鸣器鸣叫
- delayms(1000);
- }
- else
- {
- BEEP = 1; //关闭蜂鸣器
- dis_distance(); //显示距离
- }
- if(key_scan() == 1) //如果按下设置键,则进入设置报警功能
- {
- BEEP = 0; //按键提示音
- delayms(50);
- BEEP = 1;
- delayms(100);
- key_fuction(); //进入设置报警功能
- }
- }
- }
- /* 定时器0中断服务函数,5ms进一次本中断,用于数码管扫描 */
- void Timer1Interrupt(void) interrupt 3
- {
- TH1 = 0x0EC; //定时5ms,重新赋值
- TL1 = 0x78;
- dig_scan(dis_buf); //数码管显示距离
- }
复制代码
Proteus8.17仿真程序:
单片机超声波.zip
(149.3 KB, 下载次数: 0)
|