|
项目要求
1、设置三种模式,
第一种模式:超声波测距,测距距离不在设置范围内蜂鸣器发出响声,测距距离在设置范围内,蜂鸣器不响,
第二种模式:设置超声波最大测距距离,该模式下不能进行超声波测距,
第三种模式:设置超声波最小测距距离,该模式下不能进行超声波测距,
2、四位数码管:最高位表示模式,其余三位数码管显示数据
3、三个按键,
第一个按键:按下跳换模式,
第二个按键:第一种模式不能按下,第二种模式按下最大值加1,第三种模式按下最小值加1,
第三个按键:第一种模式不能按下,第二种模式按下最大值减1,第三种模式按下最小值减1,
设计思路
1、首先点亮一个数码管,然后实现动态扫描所有数码管,
2、实现按键按下变换数码管,设置出三种模式,
3、实现超声波测距,蜂鸣器发出响声,
4、将所有模块结合,完成项目要求,
单片机程序:
- #include <reg52.h>
- #include <intrins.h>
- /* 全局运行参数定义 */
- #define OSC_FREQ (11059200) //振荡器频率值,单位Hz
- #define SYS_MCLK (OSC_FREQ/12) //系统主时钟频率,即振荡器频率÷12
- //数码管io口定义
- sbit TUBE4=P3^4;
- sbit TUBE3=P3^5;
- sbit TUBE2=P3^6;
- sbit TUBE1=P3^7;
- //按键io口定义
- sbit KEY0=P2^0;
- sbit KEY1=P2^1;
- sbit KEY2=P2^2;
- //蜂鸣器io口定义
- sbit BUZZ=P2^3;
- sbit trig = P3^2;//超声波发射
- sbit echo = P3^3; //超声波接收
- static unsigned char index=0;//模式选择的索引
- unsigned int flag1s = 0; //1s定时标志
- unsigned char T0RH = 0; //T0重载值的高字节
- unsigned char T0RL = 0; //T0重载值的低字节
- unsigned int HIGHEST = 400; //超声波最大测距距离(cm)
- unsigned int LOWEST = 2; //超声波最小测距距离(cm)
- static unsigned int testHighest = 100; //超声波最高测距距离(设置值)
- static unsigned int testLowest = 10; //超声波最低测距距离(设置值)
- unsigned char pdata KeySta[3] = { 1, 1, 1}; //全部矩阵按键的当前状态
- unsigned char code LedChar[] = { //数码管显示字符转换表
- 0x28,0xee,0x32,0xa2,0xe4,0xa1,0x21,0xea,0x20,
- 0xa0,0x60,0x25,0x39,0x26,0x31,0x71,0xff
- };
- unsigned char LedBuff[4] = { //数码管显示缓冲区,初值0xFF确保启动时都不亮
- 0xFF,0xFF,0xFF,0xFF
- };
- /* 数码管初始化函数 */
- void TUBE_Init();
- /* 数码管显示函数 */
- void TUBE_Display(unsigned int dis);
- /* 数码管按键显示函数 */
- void TUBE_KeyDisplay(unsigned int key);
- /* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
- void KeyDriver();
- /* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
- void KeyScan();
- /* 超声波测距函数 */
- unsigned int GetDistance(void);
- /* 蜂鸣器警报函数 */
- void IfDistance(void);
- /* 配置并启动T0,ms-T0定时时间 */
- void ConfigTimer0(unsigned int ms)
- {
- unsigned long tmp;
- tmp = (SYS_MCLK*ms)/1000; //计算所需的计数值
- tmp = 65536 - tmp; //计算定时器重载值
- tmp = tmp + 33; //补偿中断响应延时造成的误差
- T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
- T0RL = (unsigned char)tmp;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0为模式1
- TH0 = T0RH; //加载T0重载值
- TL0 = T0RL;
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- }
- /* 配置并启动T1,用于超声波测距 */
- void ConfigTimer1()
- {
- TMOD &= 0x0F; //清零T1的控制位
- TMOD |= 0x10; //配置T1为模式1
- TH1 = 0; //加载T1重载值
- TL1 = 0;
- ET1 = 1; //使能T1中断
- }
- /*mian函数*/
- void main()
- {
- EA = 1; //开总中断
- ConfigTimer0(1); //配置T0定时1ms
- ConfigTimer1(); //配置T1
- TUBE_Display(0);//数码管初始化
- BUZZ=0;//蜂鸣器提示,程序开启,
- while(1)
- {
- KeyDriver();//按键驱动函数,
- }
- }
- /* T0中断服务函数,实现系统定时和按键扫描 */
- void InterruptTimer0() interrupt 1
- {
- static unsigned int tmr1000ms = 0;
- TH0 = T0RH; //重新加载重载值
- TL0 = T0RL;
- TUBE_Init(); //数码管扫描函数
- KeyScan(); //按键扫描函数
- tmr1000ms++; //定时1000ms
- if (tmr1000ms >= 1000)//tmr1000ms=1000,时间为1S
- {
- tmr1000ms = 0;
- flag1s ++;
- if(flag1s>=2)BUZZ=1;//两秒后,蜂鸣器停止,
- if(0==index)//模式=1,开启超声波测距
- {
- TUBE_Display(GetDistance());
- IfDistance();//蜂鸣器警报
- }
- }
- }
- /* 数码管初始化函数 */
- void TUBE_Init()
- {
- static unsigned char choice=0;
- //P1=0XFF;
- switch(choice)//数码管扫描
- {
- case 0: TUBE4=0;TUBE3=1;TUBE2=1;TUBE1=1;choice++;P1=LedBuff[0];break;
- case 1: TUBE4=1;TUBE3=0;TUBE2=1;TUBE1=1;choice++;P1=LedBuff[1];break;
- case 2: TUBE4=1;TUBE3=1;TUBE2=0;TUBE1=1;choice++;P1=LedBuff[2];break;
- case 3: TUBE4=1;TUBE3=1;TUBE2=1;TUBE1=0;choice=0;P1=LedBuff[3];break;
- default:break;
- }
- }
- /* 数码管显示函数 */
- void TUBE_Display(unsigned int dis)
- {
- //更改显示数码管数据
- LedBuff[0]=LedChar[dis%10];
- LedBuff[1]=LedChar[dis/10%10];
- LedBuff[2]=LedChar[dis/100%10];
- //判断模式,最高位数码管表示模式
- if(0==index)LedBuff[3]=LedChar[10];
- if(1==index)LedBuff[3]=LedChar[11];
- if(2==index)LedBuff[3]=LedChar[12];
- }
- /* 数码管按键显示函数 */
- void TUBE_KeyDisplay(unsigned int key)
- {
-
- switch(index)//判断模式
- {
- case 0://模式一,超声波测距
- if(0==key)//按下按键一,模式+1
- {
- ++index;
- TUBE_Display(testHighest);
- }
- break;
- case 1://模式二,设置超声波最高测距距离
- if(0==key)//按下按键一,模式+1
- {
- ++index;
- TUBE_Display(testLowest);
- }
- if(1==key)//按下按键二,超声波设置的最高测距距离+1
- {
- if(HIGHEST>testHighest)testHighest++;
- TUBE_Display(testHighest);
- }
- if(2==key)//按下按键三,超声波设置的最高测距距离-1
- {
- if(LOWEST<testHighest)testHighest--;
- TUBE_Display(testHighest);
- }
- break;
- case 2://模式三,设置超声波最低测距距离
- if(0==key)//按下按键一,模式+1
- {
- ++index;
- TUBE_Display(GetDistance());
- }
- if(1==key)//按下按键二,超声波设置的最低测距距离+1
- {
- if(HIGHEST>testLowest)testLowest++;
- TUBE_Display(testLowest);
- }
- if(2==key)//按下按键三,超声波设置的最低测距距离-1
- {
- if(LOWEST<testLowest)testLowest--;
- TUBE_Display(testLowest);
- }
- break;
- default:break;
- }
- if(index>=3)index=0;
- }
- /* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
- void KeyDriver()
- {
- unsigned char i;
- static unsigned char pdata backup[3] = { 1, 1, 1}; //按键值备份,保存前一次的值
- for (i=0; i<3; i++) //循环检测按键
- {
- if (backup[i] != KeySta[i]) //检测按键动作
- {
- if (backup[i] != 0) //按键按下时执行动作
- {
- TUBE_KeyDisplay(i);//调用按键动作函数
- }
- backup[i] = KeySta[i]; //刷新前一次的备份值
- }
- }
- }
- /* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
- void KeyScan()
- {
- unsigned char i;
- static unsigned char keyout = 0; //矩阵按键扫描输出索引
- static unsigned char keybuf[3] = {0xFF, 0xFF, 0xFF}; //矩阵按键扫描缓冲区
- //将3个按键值移入缓冲区
- keybuf[0] = (keybuf[0] << 1) | KEY0;
- keybuf[1] = (keybuf[1] << 1) | KEY1;
- keybuf[2] = (keybuf[2] << 1) | KEY2;
- //消抖后更新按键状态
- for (i=0; i<3; i++) //3个按键,循环3次
- {
- if (keybuf[i] == 0x00)
- { //连续8次扫描值为0,即8ms内都是按下状态时,可认为按键已稳定的按下
- KeySta[i] = 0;
- }
- else if (keybuf[i] == 0xFF)
- { //连续8次扫描值为1,即8ms内都是弹起状态时,可认为按键已稳定的弹起
- KeySta[i] = 1;
- }
- }
- //执行下一次的扫描输出
- keyout++; //输出索引递增
- if(keyout>=3)keyout = 0; //索引值加到3即归零
- }
- /* 超声波测距函数 */
- unsigned int GetDistance(void)
- {
- unsigned int ss;//用于记录测得的距离
- trig = 1;//给IO口trig高电平
- _nop_();//延时 时间要大于10us
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- trig = 0;//给IO口trig低电平
- while(!echo);//当echo为高电平的时候,跳出循环
- TH1 = 0;//定时器清零
- TL1 = 0;
- TR1 = 1;//启动定时器1,开启计时
- while(echo);//echo不为0,即脉冲返回结束,计时结束
- TR1 = 0;//停止计时
- //ss = ((TH1 * 256 + TL1) * 0.34) / 2;//计算距离
- ss = (TH1 * 256 + TL1) /58;//计算距离,公式= us/58 单位是cm 或 us/148 单位是英寸
- if(ss<HIGHEST && ss>LOWEST)return ss; //判断距离是否在超声波测距的最大值和最小值范围内,“是”返回SS
-
- return 0; // “否”返回0
- }
- /* 蜂鸣器警报函数 */
- void IfDistance(void)
- {
- unsigned int ss;//用于记录测得的距离
- ss=GetDistance();//得到超声波测得的距离
- //判断超声波测到的距离是否在超声波设置测距的最大值和最小值范围内
- if(ss>testHighest || ss<testLowest)BUZZ=0;//蜂鸣器发声
- }
复制代码 全部资料51hei下载地址:
|
评分
-
查看全部评分
|