这个超声波测距是利用定时器中的输入捕获为主要技术手段设计而成
测距模块:
超声波测距的型号是HC_SR04,这个超声波模块有一个控制端trig,和一个测距口echo。只要给trig一个超过20us的高电平,那么echo就会产生高电平,直到超声波回到超声波模块中,整个程序的难点在于怎么计数高电平时间,而输入捕获可以捕获echo口的高电平时间,正好做到这一点。其实用通用定时器简单的计数功能也可以做到这一点,准备下一步采用这一方法写一个程序。
显示模块:
显示距离可以直接调用mdk中usart.c文件中的printf,可以直接打印距离。
设置最小距离
这是这个超声波测距中的另一难点,我们是直接使用串口向单片机传数据,但是串口只能传字符串,这个时候我们就需要利用ASCII码将一个个字符转换成数字。串口是一位一位传数据的,会将数据存在一个缓冲数组(USART_RX_BUF【】)中,并且在传数据的过程中我们会得到这个数据的长度len。利用这个式子将接收到的字符串转化成数字:
for(i=0;i<len;i++)
{
s1+=(USART_RX_BUF[len-1-i]-48)*table1[i];
}
int table1[]={1,10,100,1000};
0的ASCII码是48,根据这个可以求得其他数据的ASCII码。
报警模块
当测得的距离小于串口设置的阀值,串口显示error,LED灯闪烁。
接下来是我的程序:
这是超声波模块利用到的GPIO口的初始化和输入捕获的初始化
#include "timer.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
//¶¨Ê±Æ÷5ͨµÀ1ÊäÈ벶»ñÅäÖÃ
//arr£º×Ô¶¯ÖØ×°Öµ(TIM2,TIM5ÊÇ32λµÄ!!)
//psc£ºÊ±ÖÓÔ¤·ÖƵÊý
void TIM5_CH1_Cap_Init(u32 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_ICInitTypeDef TIM5_ICInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); //TIM5ʱÖÓʹÄÜ
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //ʹÄÜPORTAʱÖÓ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIOA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//¸´Óù¦ÄÜ
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //ËÙ¶È100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //ÍÆÍ츴ÓÃÊä³ö
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //ÏÂÀ
GPIO_Init(GPIOA,&GPIO_InitStructure); //³õʼ»¯PA0
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //GPIOA0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//¸´Óù¦ÄÜ
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //ËÙ¶È100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //ÍÆÍ츴ÓÃÊä³ö
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //ÏÂÀ
GPIO_Init(GPIOA,&GPIO_InitStructure); //³õʼ»¯PA0
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO