stm32(寄存器)超声波程序

我们是基于stm32f103系列,超声波模块用的是:HC-SR04(寄存器版的代码)

编译器用的是:keil5


在此:输入捕获用的是TIM2_CH1(用的是PA0,可以从开发板原理图中看到)

stm32(寄存器)超声波程序_第1张图片

由于本文只是简单的介绍超声波测距,并不涉及其他东西,所以没有加载按键,led灯程序

test.c文件(主函数所存在的地方)

timer.c文件(输入捕获初始化的地方)

ultrasonic.c文件(超声波模块初始化)


test.c

#include "sys.h"
#include "usart.h"		
#include "delay.h"	 
#include "timer.h" 
#include "ultrasonic.h"

extern u8  TIM2CH1_CAPTURE_STA;		//输入捕获状态			
extern u16	TIM2CH1_CAPTURE_VAL;	//输入捕获值


int main(void)
{			 
	u32 temp=0;  	
 	Stm32_Clock_Init(9);		            //系统时钟设置
	uart_init(72,9600);	                    //串口初始化为0
	delay_init(72);	   	 	            //延时初始化
	ultrasonic_Init();
 	TIM2_Cap_Init(0XFFFF,72-1);	            //以1Mhz的频率计数
   	while(1)
	{
	    PAout(4)=1;
	    delay_us(15);  
	    PAout(4)=0;	 
		
		if(TIM2CH1_CAPTURE_STA&0X80)              //成功捕获到了一次高电平
		{
			temp=TIM2CH1_CAPTURE_STA&0X3F;
			temp*=65536;		          //溢出时间总和
			temp+=TIM2CH1_CAPTURE_VAL;	  //得到总的高电平的时间
			
			temp=temp*170/10000;
			printf("Distance:%d cm\r\n",temp);//打印总的高电平的时间,也就是转换后的高度了
 			TIM2CH1_CAPTURE_STA=0;		  //开启下一次捕获
 		}
	}
}

ultrasonic.c

#include "ultrasonic.h"
#include "sys.h"


void ultrasonic_Init(void){

	RCC->APB2ENR |= 1<<2;
	GPIOA->CRL &= 0xfff0ffff;
	GPIOA->CRL |= 0X00030000;
}


ultrasonic.h
#ifndef __ULTRASONIC_H
#define __ULTRASONIC_H
#include "sys.h"

#define ULTRASONIC_TRIG PAout(4)

void ultrasonic_Init(void);

#endif


timer.c

#include "timer.h"
#include "led.h"

 
//定时器2通道1输入捕获配置
//arr:自动重装载值
//psc:时钟分频数
void TIM2_Cap_Init(u16 arr,u16 psc)
{		 
	RCC->APB1ENR|=1<<0;   	//TIM2时钟使能
	RCC->APB2ENR|=1<<2;    	//使能A时钟
	 
	GPIOA->CRL&=0XFFFFFFF0;	
	GPIOA->CRL|=0X00000008;
	GPIOA->ODR|=0<<0;
	  
 	TIM2->ARR=arr;  	//设定计数器自动装载值
	TIM2->PSC=psc;  	//设定预分频数

	TIM2->CCMR1|=1<<0;	//CC1S=01选择输入端,IC1映射到TI1上
 	TIM2->CCMR1|=1<<4; 	//IC1F=0001 配置输入滤波器,以Fck_int采样,2个事件后有效
 	TIM2->CCMR1|=0<<10; 	//IC2PS=00  配置输入分频,不分频

	TIM2->CCER|=0<<1; 	//CC1P=0    上升沿捕获
	TIM2->CCER|=1<<0; 	//CC1E=1    允许捕获计数器的值到捕获寄存器中

	TIM2->DIER|=1<<1;   	//允许捕获中断		
	TIM2->DIER|=1<<0;   	//允许更新中断	
	TIM2->CR1|=0x01;    	//使能计数器2
	MY_NVIC_Init(2,0,TIM2_IRQn,2);//抢占2,子优先级0,组2   
}

//捕获状态2个全局变量
//[7]:0,没有成功捕获,1,成功捕获一次
//[6]:0,还没有捕获到高电平,1,已经捕获到高电平了
//[5:0]:捕获高电平后的溢出次数
u8  TIM2CH1_CAPTURE_STA=0;//输入捕获状态				
u16 TIM2CH1_CAPTURE_VAL;//输入捕获值-用来记录捕获到下降沿时,TIM2_CNT的值

//定时器2中断服务程序
void TIM2_IRQHandler(void)
{ 		    
	u16 tsr;
	tsr=TIM2->SR;
 	if((TIM2CH1_CAPTURE_STA&0X80)==0)//还没有成功捕获
	{
		if(tsr&0X01)//溢出
		{	    
			if(TIM2CH1_CAPTURE_STA&0X40)                   //已经捕获到高电平了
			{
				if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)   //高电平太长了
				{
					TIM2CH1_CAPTURE_STA|=0X80;     //标记成功捕获了一次
					TIM2CH1_CAPTURE_VAL=0XFFFF;
				}else TIM2CH1_CAPTURE_STA++;
			}	 
		}
		if(tsr&0x02)//捕获1发生捕获事件
		{	
			if(TIM2CH1_CAPTURE_STA&0X40)		        //捕获到一个下降沿	
			{	  			
				TIM2CH1_CAPTURE_STA|=0X80;		//标记成功捕获到一次高电平的脉冲宽度
			        TIM2CH1_CAPTURE_VAL=TIM2->CCR1;	        //提取当前的捕获值
	 			TIM2->CCER&=~(1<<1);			//CC1P=0 设置为上升沿捕获
			}else  						//还未开始,第一次捕获上升沿
			{ 
				TIM2CH1_CAPTURE_VAL=0;
				TIM2CH1_CAPTURE_STA=0X40;		//标记捕获到了上升沿
				TIM2->CNT=0;				//计数器清空
				TIM2->CCER|=1<<1; 			//CC1P=1 设置为下降沿捕获
			}		    
		}			     	    					   
 	}
	TIM2->SR=0;                                                     //清空中断标志位 
}


timer.h

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"  

void TIM2_Cap_Init(u16 arr,u16 psc);
#endif


验证效果:

stm32(寄存器)超声波程序_第2张图片


你可能感兴趣的:(STM32-ARM嵌入式)