基于32的超声波测距(串口显示距离,串口设置阀值)

这个超声波测距是利用定时器中的输入捕获为主要技术手段设计而成

测距模块:

超声波测距的型号是HC_SR04,这个超声波模块有一个控制端trig,和一个测距口echo。只要给trig一个超过20us的高电平,那么echo就会产生高电平,直到超声波回到超声波模块中,整个程序的难点在于怎么计数高电平时间,而输入捕获可以捕获echo口的高电平时间,正好做到这一点。其实用通用定时器简单的计数功能也可以做到这一点,准备下一步采用这一方法写一个程序。

显示模块:

显示距离可以直接调用mdk中usart.c文件中的printf,可以直接打印距离。

设置最小距离

这是这个超声波测距中的另一难点,我们是直接使用串口向单片机传数据,但是串口只能传字符串,这个时候我们就需要利用ASCII码将一个个字符转换成数字。串口是一位一位传数据的,会将数据存在一个缓冲数组(USART_RX_BUF【】)中,并且在传数据的过程中我们会得到这个数据的长度len。利用这个式子将接收到的字符串转化成数字:

 for(i=0;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_AF_TIM5); //PA0¸´ÓÃλ¶¨Ê±Æ÷5
  
	  
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //¶¨Ê±Æ÷·ÖƵ
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //ÏòÉϼÆÊýģʽ
	TIM_TimeBaseStructure.TIM_Period=arr;   //×Ô¶¯ÖØ×°ÔØÖµ
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
	

	//³õʼ»¯TIM5ÊäÈ벶»ñ²ÎÊý
	TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 	Ñ¡ÔñÊäÈë¶Ë IC1Ó³Éäµ½TI1ÉÏ
  TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	//ÉÏÉýÑز¶»ñ
  TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //Ó³Éäµ½TI1ÉÏ
  TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;	 //ÅäÖÃÊäÈë·ÖƵ,²»·ÖƵ 
  TIM5_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 ÅäÖÃÊäÈëÂ˲¨Æ÷ ²»Â˲¨
  TIM_ICInit(TIM5, &TIM5_ICInitStructure);
		
	TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);//ÔÊÐí¸üÐÂÖÐ¶Ï ,ÔÊÐíCC1IE²¶»ñÖжÏ	
	
  TIM_Cmd(TIM5,ENABLE ); 	//ʹÄܶ¨Ê±Æ÷5

 
  NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//ÇÀÕ¼ÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;		//×ÓÓÅÏȼ¶3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQͨµÀʹÄÜ
	NVIC_Init(&NVIC_InitStructure);	//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯VIC¼Ä´æÆ÷¡¢
	
	
}
//²¶»ñ״̬
//[7]:0,ûÓгɹ¦µÄ²¶»ñ;1,³É¹¦²¶»ñµ½Ò»´Î.
//[6]:0,»¹Ã»²¶»ñµ½µÍµçƽ;1,ÒѾ­²¶»ñµ½µÍµçƽÁË.
//[5:0]:²¶»ñµÍµçƽºóÒç³öµÄ´ÎÊý(¶ÔÓÚ32λ¶¨Ê±Æ÷À´Ëµ,1us¼ÆÊýÆ÷¼Ó1,Òç³öʱ¼ä:4294Ãë)
u8  TIM5CH1_CAPTURE_STA=0;	//ÊäÈ벶»ñ״̬		    				
u32	TIM5CH1_CAPTURE_VAL;	//ÊäÈ벶»ñÖµ(TIM2/TIM5ÊÇ32λ)
//¶¨Ê±Æ÷5ÖжϷþÎñ³ÌÐò	 
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·¢Éú²¶»ñʼþ
		{	
			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); //Çå³ýÖжϱê־λ
}

 这是主函数:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "beep.h"

extern u8  TIM5CH1_CAPTURE_STA;		//ÊäÈ벶»ñ״̬		    				
extern u32	TIM5CH1_CAPTURE_VAL;	//ÊäÈ벶»ñÖµ  
long long temp=0;//²â¾àʱ¼ä
long long S=0,s1=0,t=0,Sm=0;//¾àÀë

int table1[]={1,10,100,1000};

//¿ªÆô³¬Éù²¨Ä£¿é
void count()
{
   trig=1;
	 delay_ms(20);
	 trig=0; 
}

//½ÓÊÕÊý¾Ý
float js()
{
	u8 i;
	u8 len;	 
	if(USART_RX_STA&0x8000)//Èç¹û½ÓÊÕµ½Êý¾Ý
		{					   
			len=USART_RX_STA&0x3fff;//µÃµ½´Ë´Î½ÓÊÕµ½µÄÊý¾Ý³¤¶È
			for(i=0;i
在此加上我的主程序:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "beep.h"
#include "bmp.h"
#include "oled.h"


extern u8  TIM5CH1_CAPTURE_STA;		//ÊäÈ벶»ñ״̬		    				
extern u32	TIM5CH1_CAPTURE_VAL;	//ÊäÈ벶»ñÖµ  
long long temp=0;//²â¾àʱ¼ä
long long S=0,s1=0,t=0,Sm=0;//¾àÀë

int table1[]={1,10,100,1000};

//¿ªÆô³¬Éù²¨Ä£¿é
void count()
{
   trig=1;
	 delay_ms(20);
	 trig=0; 
}

//½ÓÊÕÊý¾Ý
float js()
{
	u8 i;
	u8 len;	 
	if(USART_RX_STA&0x8000)//Èç¹û½ÓÊÕµ½Êý¾Ý
		{					   
			len=USART_RX_STA&0x3fff;//µÃµ½´Ë´Î½ÓÊÕµ½µÄÊý¾Ý³¤¶È
			for(i=0;it)
	 {
		  OLED_ShowCHinese(0,0,0);//?
		OLED_ShowCHinese(18,0,1);//?
		OLED_ShowCHinese(36,0,2);//?
		OLED_ShowCHinese(54,0,3);//?
		OLED_ShowCHinese(72,0,4);//?
		OLED_ShowCHinese(90,0,5);//?
		OLED_ShowCHinese(108,0,6);//?
		OLED_ShowCHinese(20,3,7);//?
		OLED_ShowCHinese(38,3,8);//?
		OLED_ShowString(60,3,": "); 
		OLED_ShowNum(72,3,t,6,16);//??ASCII?????
	  	OLED_ShowString(0,6,"Distance: "); 
		  OLED_ShowNum(72,6,Sm,6,16);//??ASCII????? 	
		  delay_ms(2);
  	}
	 else
	 {
		 OLED_Clear();
		 OLED_ShowCHinese(0,0,0);//?
		OLED_ShowCHinese(18,0,1);//?
		OLED_ShowCHinese(36,0,2);//?
		OLED_ShowCHinese(54,0,3);//?
		OLED_ShowCHinese(72,0,4);//?
		OLED_ShowCHinese(90,0,5);//?
		OLED_ShowCHinese(108,0,6);//?
		OLED_ShowCHinese(20,3,7);//?
		OLED_ShowCHinese(38,3,8);//?
		OLED_ShowString(60,3,": "); 
		OLED_ShowNum(72,3,t,6,16);//??ASCII?????
	  OLED_ShowString(48,6,"error!!!"); 
	 }
}

//Ö÷º¯Êý
int main(void)
{   
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é2
	delay_init(168);  //³õʼ»¯ÑÓʱº¯Êý
	uart_init(9600);//³õʼ»¯´®¿Ú²¨ÌØÂÊΪ115200
	LED_Init();
	OLED_Init();			//???OLED  
	OLED_Clear();
	LED0=0;
 	TIM5_CH1_Cap_Init(0XFFFFFFFF,84-1); //ÒÔ1MhzµÄƵÂʼÆÊý 
  while(1)
	{
		
		count();//¿ªÆô³¬Éù²¨Ä£¿é
		jisuan();//¼ÆËã¾àÀë
		delay_ms(20);
		js();//½ÓÊÕ´®¿ÚÉèÖõÄ×îС¾àÀë
		display();
		LED0=!LED0;//ÅжϺ¯ÊýÕý³£½øÐÐ
		delay_ms(2);
	}
}

加上OLED后会使程序跑得很慢,使测距显示没有那么及时。甚至会出现程序跑死的情况存在。。。。目前为止没有找到解决方法。





你可能感兴趣的:(基于32的超声波测距(串口显示距离,串口设置阀值))