能找到这的肯定是找了好久没找到问题的,代码就不介绍了,直接说问题。
单独使用HC-SR04测距没问题,但涉及到测距控制小车移动就会卡死(能找到这的应该都知道),经过我的测试,卡在了等待接收超声波返回信号这行代码,只需要再增加一个计时变量(和超声波计时变量同步计时),放在中断里++,然后这个变量放在等待接收超声波信号这行代码中if时间大于等待时间就break;这个等待时间可以自己设置。
举个例子,下面是我的代码,我增加了个T用来计时,10us进一次中断,我的主程序中,小车距离障碍物大于200mm就前行,如果T设置成T*10/1000=38ms的话,卡死的时候就要卡38ms,小车就认为距离前方障碍物4米,如果前方有障碍物就会撞上去,所以我T设置成1995(小车认为距离前方障碍物210mm),小车就会快点的脱离卡死,并且210mm大于200mm,小车还是前进。简单说这句话的逻辑就是:如果T=1995,超声波没有返回 ,认为前方无障碍物,退出等待信号循环,小车前进(我代码有写手动翻转电平)。我就是这样防止卡死,当然这个防卡死时间我这个不一定是最合适的,大家根据自己的实际情况自己配置,希望对大家有所帮助。能力有限,有不足之处还望谅解。
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "Timer1.h"
-
- #define Trig GPIO_Pin_0 //HC-SR04模块的Trig脚接GPIOA1
- #define Echo GPIO_Pin_1 //HC-SR04模块的Echo脚接GPIOA2
-
- uint64_t Time=0,T=0; //用来计时
- uint64_t Time_end=0; //接收保存计时,用来对比
-
- void HC_SR04_Init(void) //超声波检测
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
-
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
- GPIO_InitStructure.GPIO_Pin=Trig;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_InitStructure);
- GPIO_WriteBit(GPIOA,Trig,Bit_RESET); //先将端口拉低防止干扰
- Delay_us(15);
-
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; //下拉输出
- GPIO_InitStructure.GPIO_Pin=Echo;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_InitStructure);
-
- Timer1_Init(); //开启定时器中断
- }
-
- uint16_t HC_SR04_Time(void) //计算距离
- {
- uint32_t distance_mm=0; //距离
- GPIO_WriteBit(GPIOA,Trig,Bit_SET); //给至少10us高电平启动模块
- Delay_us(50);
- GPIO_WriteBit(GPIOA,Trig,Bit_RESET); //输出低电平
- TIM_Cmd(TIM2,ENABLE); //开启TIM2定时器
- while(GPIO_ReadInputDataBit(GPIOA,Echo)==0)
- {
- Time=0; //低电平未开始time为0
- if(T>1995)
- {
- break;
- }
- }
- GPIO_WriteBit(GPIOA,Echo,Bit_SET); //输出高电平
- while(GPIO_ReadInputDataBit(GPIOA,Echo)==1){Time_end=Time;} //高电平开始计时time增加赋值给Time_end
- TIM_Cmd(TIM2,DISABLE); //关闭TIM2定时器
- TIM_SetCounter(TIM2,0); //计数器清零
- T=0; //防卡死计时清零
- if(Time_end/100<38)
- {
- distance_mm=(Time_end*346)/200; //距离计算,声音在25℃空气中传播速度为346mm/ms
- }
- return distance_mm;
- }
-
- void TIM2_IRQHandler(void) //TIM2中断函数
- {
- if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
- {
- Time++;
- T++;
- }
- TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
- }