之前用51写过一个超声波模块的测距,所以基本原理都了解的很清楚了,对于32的超声波模块,关键的有三点
1.驱动trig之后,对echo电平的输入捕获。输入捕获中的关键是对中断服务函数的理解,通过设置STA标志位这个变量来判断是否完成定时器中断,通过比较串口,两者都是采用这种方式来判断是否完成中断
当捕获到上升沿后,&0x40将第6位置1,捕获完成&0x80将第七位置1,通过TIM_GetCapture()函数得到echo端高电平的时间从而计算出距离。
void TIM5_IRQHandler(void)
{
if((TIM5CH1_CAPTURE_STA&0X80)==0)//»¹Î´³É¹¦²¶»ñ
{
if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)//Òç³ö
{
if(TIM5CH1_CAPTURE_STA&0X40)//ÒѾ²¶»ñµ½¸ßµçƽÁË
{
if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//¸ßµçƽ̫³¤ÁË
{
TIM5CH1_CAPTURE_STA|=0X80; //±ê¼Ç³É¹¦²¶»ñÁËÒ»´Î
TIM5CH1_CAPTURE_VAL=0XFFFFFFFF;
}
else TIM5CH1_CAPTURE_STA++; //
}
}
if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)//²¶»ñ1·¢Éú²¶»ñʼþ£¬resetÒ²¾ÍÊÇ0,´Ëʱ¿ªÆôÖжÏ
{
if(TIM5CH1_CAPTURE_STA&0X40) //²¶»ñµ½Ò»¸öϽµÑØ
{
TIM5CH1_CAPTURE_STA|=0X80; //±ê¼Ç³É¹¦²¶»ñµ½Ò»´Î¸ßµçƽÂö¿í
TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);//»ñÈ¡µ±Ç°µÄ²¶»ñÖµ.
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 ÉèÖÃΪÉÏÉýÑز¶»ñ
}else //»¹Î´¿ªÊ¼,µÚÒ»´Î²¶»ñÉÏÉýÑØ
{
TIM5CH1_CAPTURE_STA=0; //Çå¿Õ
TIM5CH1_CAPTURE_VAL=0;
TIM5CH1_CAPTURE_STA|=0X40; //±ê¼Ç²¶»ñµ½ÁËÉÏÉýÑØ
TIM_Cmd(TIM5,DISABLE ); //¹Ø±Õ¶¨Ê±Æ÷5
TIM_SetCounter(TIM5,0);
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 ÉèÖÃΪϽµÑز¶»ñ
TIM_Cmd(TIM5,ENABLE ); //ʹÄܶ¨Ê±Æ÷5
}
}
}
TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //Çå³ýÖжϱê־λ
}
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //½ÓÊÕÖжÏ(½ÓÊÕµ½µÄÊý¾Ý±ØÐëÊÇ0x0d 0x0a½áβ)
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //¶ÁÈ¡½ÓÊÕµ½µÄÊý¾Ý
if((USART_RX_STA&0x8000)==0)//½ÓÊÕδÍê³É
{
if(USART_RX_STA&0x4000)//½ÓÊÕµ½ÁË0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//½ÓÊÕ´íÎó,ÖØпªÊ¼
else USART_RX_STA|=0x8000; //½ÓÊÕÍê³ÉÁË
}
else //»¹Ã»ÊÕµ½0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//½ÓÊÕÊý¾Ý´íÎó,ÖØпªÊ¼½ÓÊÕ
}
}
}
}
这种方法很值得学习,在以后使用。
2.如何通过串口向单片机发送阈值,这个的关键之处在于要知道PC端与单片机之间的数据传输,是通过字符的形式进行的也就是说你想传输1000,但单片机能读去的只有1 0 0 0的字符并不是1000,并且字符是以ASCII的形式保存在数组中,通过查表可以得了解到0的ASCII为48,表明数与ASCII间通过-48可以得到对应的数
根据串口通信的例程,是全双工串行通信,可以将得到的数据保存在USART_BUF数组中通过STA标志可以判断接受数据是否完成,以及得到保存字符的数组的长度。知道数组的名字和数组长度,我们便可以访问访问数组中的任何一位数据,
然后我们可以通过一个权值数组来表示每一位的值,将对应位上的USART_BUF[t]*quanzhi[t],相加的到对应的十进制数。
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//µÃµ½´Ë´Î½ÓÊÕµ½µÄÊý¾Ý³¤¶È
for(i=0;i
3.测量误差的处理,测量时会有各种噪声会影响测量的结果。了解到可以用卡尔曼滤波算法减少误差,试了一下,发现有效果,但是会有点影响测量结果,测量结果会有一点偏小,因为不太明白算法的具体内容,试着改了下参数,但效果并不明显,稳定但是测量的结果还时稍微有点偏小。又试了下传统消除误差的办法,效果还不错还比较稳定,但时不时还是会有跳变的情况。
2.1
今天又调试了一下,又在网上查了很多关于卡尔曼滤波的用法,又换了一个卡尔曼滤波的程序效果还挺好的,测的数据还比较稳,当距离突然变化较大时,体现的是一个渐变得过程,会有一两个数据为中途变化的过程量。然后学长给我们讲解程序需要注意的问题又添加了一些限制条件,当距离测的较远的时候空间里的噪音影响很大,而且实际用的时候并不需要那么远的距离就限制时间在30000us内,这样就可以将一些误差特别大的数据过滤掉,为了更加稳定,又试着输出后的测量距离取平均值,和卡尔曼滤波算法配合着使用,效果比昨天的好很多,不会出现一些特别夸张的数,抖动不是特别大的时候,误差也很小,几乎没有。
滤波总结:得到一个好的滤波效果,需要多种滤波方法结合起来使用,效果可能会更好一点