Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序如下:- #include "delay.h"
- #include "sys.h"
- #include "usart.h"
- #include "timer.h"
- #include "HCSR04.h"
- #include "led.h"
- #include "beep.h"
- #include "key.h"
- #include "lcd1602.h"
- #include "stmflash.h" //包含头文件
- unsigned long S=0; //定义超声数据
- #define FLASH_SAVE_ADDR 0X0800FF00 //设置FLASH 保存地址(必须为偶数,且其值要大于本代码所占用FLASH的大小+0X08000000)
- extern unsigned long Clock_time;
- unsigned char Send_flag=0;
- extern u8 TIM3CH1_CAPTURE_STA; //输入捕获状态
- extern u16 TIM3CH1_CAPTURE_VAL; //输入捕获值
- u16 fls[4];
- u8 k=0;
- u32 TL=50;
- u8 beep1;
- u8 t=0;
- void key() //按键函数
- {
- k=KEY_Scan(1); //按键扫描的值给K
- if(k == KEY0_PRES) //如果K等于 KEY0_PRES,就说明是按下加按键
- {
- TL++; //数据加一,如果大于400,则减一,保持最大400
- if(TL>400)
- TL--;
- fls[0]=TL;
- STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)fls,1); //存储
- }
-
- if(k == KEY1_PRES)//同上,不过是减
- {
- TL--;
- if(TL<5)
- TL++;
- fls[0]=TL;
- STMFLASH_Write(FLASH_SAVE_ADDR,(u16*)fls,1);
- }
-
- }
- void ceju()
- {
- Trig=1;
- delay_us(20);
- Trig=0; //启动信号
- S=0; //清零距离数据
- Clock_time=0;
- TIM_Cmd(TIM3, DISABLE); //关定时器,清零计时变量
- while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)); //等待检测到高电平
- Clock_time=0;
- TIM_Cmd(TIM3, ENABLE); //开定时器
- while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==1&&Clock_time<47058); //只要是高,一直算时间,如果时间计数超过 47058,所说有问题,直接跳过,47058不一定精确,是一个大概值,
- S=((Clock_time*2)*340/10000)/2; //时间变量是2us加一,乘以速度,因为时间是us,换成秒是除以1000000,保留两位小数,所以除以 10000,然后除以二得到单方面距离
- TIM_Cmd(TIM3, DISABLE); //关定时器
- Clock_time=0; //清零数据
- printf("Distance:%d cm\r\n",S);//打印总的高点平时间
- }
- void show()
- {
- LCD1602_Show_Str(0,0,"Distance:"); //显示
- if(S>=100&&S<=400) LCD1602_Write_Dat(S/100%10+0x30); //这里是测速数据
- else LCD1602_Show_Str(9,0," ");
- if(S>=10) LCD1602_Write_Dat(S/10%10+0x30);
- else LCD1602_Show_Str(10,0," ");
- LCD1602_Write_Dat(S%10+0x30);
- LCD1602_Show_Str(12,0,"cm ");
-
- LCD1602_Show_Str(0,1,"alarm :"); //这里开始显示报警数据,下面这三段,其实就是判断阈值数据是百位数还是十位数还是个位数,如果是个位数,显示个位数据,百位十位显示空
- if(TL>=100&&TL<=400)
- {
- LCD1602_Write_Dat(TL/100%10+0x30);
- LCD1602_Write_Dat(TL/10%10+0x30);
- LCD1602_Write_Dat(TL%10+0x30);
- LCD1602_Show_Str(12,1,"cm ");
- }
-
- if(TL>=10&&TL<100)
- {
- LCD1602_Show_Str(9,1," ");
- LCD1602_Write_Dat(TL/10%10+0x30);
- LCD1602_Write_Dat(TL%10+0x30);
- LCD1602_Show_Str(12,1,"cm ");
- }
- if(TL>0&&TL<10)
- {
- LCD1602_Show_Str(9,1," ");
- LCD1602_Show_Str(10,1," ");
- LCD1602_Write_Dat(TL%10+0x30);
- LCD1602_Show_Str(12,1,"cm ");
- }
- }
- void problem() //报警函数
- {
- if(S<TL) //小于阈值,蜂鸣器开始响,对应指示灯亮,否则蜂鸣器不响
- {
- beep1=1;
- LED1=1;
- }
- else
- {
- beep1=0;
- LED1=0;
- LED0=1;
- }
- }
-
- int main(void)
- {
- u16 datatemp[1];
- BEEP_Init();
- KEY_Init();
- delay_init(); //延时函数初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
- uart_init(115200); //串口初始化为115200
- LED_Init(); //LED端口初始化
- UltrasonicWave_Configuration(); //初始化超声IO
- TIM3_Cap_Init(1,72-1); //以1Mhz的频率计数,第一个选项,最小只能是1
- LCD1602_Init();
- STMFLASH_Read(FLASH_SAVE_ADDR,(u16*)datatemp,1);
- TL=datatemp[0];
- if(TL<5||TL>400)
- TL=50;
- ceju();
- printf("Distance"); //串口打印一下,调试用
- while(1)
- {
- if(beep1==1) //如果蜂鸣器标志等于1,则开始滴滴叫,指示灯也是闪烁
- {
- BEEP=!BEEP;
- LED0=!LED0;
-
- }
- else
- BEEP=0;
- show(); //调用显示函数
- key(); //调用按键函数
- problem();//调用报警处理函数
- t++; //变量自加,加到5的时候,对5取余会等于0,则启动一次测距函数
- if(t%5==0)
- {
- t=0;
- ceju();
- }
- }
- }
复制代码
全部资料51hei下载地址:
STM32 超声波测距完整资料.7z
(343.7 KB, 下载次数: 116)
|