赞
踩
开发板:秉火-霸道V1
芯片:STM32F103ZET6
定时器:TIM2
通道: 3
我们可以借助通用定时器的 输入捕获 来测量 Echo 引脚高电平持续的时间
#ifndef _BSP_HCSR04_H #define _BSP_HCSR04_H #include"stm32f10x.h" #include"stm32f10x_tim.h" //TIM2 #define GENERAL_TIMx TIM2 #define GENERAL_TIMx_CLK_FUN RCC_APB1PeriphClockCmd #define GENERAL_TIMx_CLK RCC_APB1Periph_TIM2 //Trig引脚定义---PA10 #define HCSR04_GPIO_CLK_FUN RCC_APB2PeriphClockCmd #define HCSR04_GPIO_CLK RCC_APB2Periph_GPIOA #define HCSR04_GPIO_TRIG_PORT GPIOA #define HCSR04_GPIO_TRIG_PIN GPIO_Pin_10 #define HCSR04_TRIG_Hight HCSR04_GPIO_TRIG_PORT->BSRR = HCSR04_GPIO_TRIG_PIN #define HCSR04_TRIG_Low HCSR04_GPIO_TRIG_PORT->BRR = HCSR04_GPIO_TRIG_PIN //TIM引脚定义 #define GENERAL_TIMx_CH3_CLK_FUN RCC_APB2PeriphClockCmd #define GENERAL_TIMx_CH3_CLK RCC_APB2Periph_GPIOA #define GENERAL_TIMx_CH3_PORT GPIOA #define GENERAL_TIMx_CH3_PIN GPIO_Pin_2 #define GENERAL_TIMx_CHANNEL_x TIM_Channel_3 //TIM2中断 #define GENERAL_TIMx_IRQn TIM2_IRQn #define GENERAL_TIMx_IRQHandler TIM2_IRQHandler typedef struct { uint8_t Capture_FinishFlag; // 捕获结束标志位 uint8_t Capture_StartFlag; // 捕获开始标志位 uint16_t Capture_CcrValue; // 捕获寄存器的值 uint16_t Capture_Period; // 自动重装载寄存器更新标志 } TIM_ICUserValueTypeDef; extern TIM_ICUserValueTypeDef TIM_ICUserValueStruct; void TIM_Config(void); void HCSR04_GPIO_Config(void); void HCSR04_TRIG_Send(void); #endif /*_BSP_HCSR04_H*/
/* Trig: PA2 Echo: PA10 */ #include"bsp_HCSR04.h" #include "bsp_delay.h" TIM_ICUserValueTypeDef TIM_ICUserValueStruct = {0,0,0,0}; //HCSR04初始化引脚 void HCSR04_GPIO_Config(void) { //定义GPIO结构体变量 GPIO_InitTypeDef GPIO_InitStruct; //打开时钟 HCSR04_GPIO_CLK_FUN(HCSR04_GPIO_CLK,ENABLE); //Trig引脚 GPIO_InitStruct.GPIO_Pin = HCSR04_GPIO_TRIG_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(HCSR04_GPIO_TRIG_PORT,&GPIO_InitStruct); } void HCSR04_TRIG_Send(void) { HCSR04_TRIG_Hight; Delay_Us(15); HCSR04_TRIG_Low; } static void GENERAL_TIMx_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; GENERAL_TIMx_CH3_CLK_FUN(GENERAL_TIMx_CH3_CLK,ENABLE); GPIO_InitStruct.GPIO_Pin = GENERAL_TIMx_CH3_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GENERAL_TIMx_CH3_PORT,&GPIO_InitStruct); } //中断初始化 static void GENERAL_TIMx_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //设置中断通道 NVIC_InitStruct.NVIC_IRQChannel = GENERAL_TIMx_IRQn; //设置子优先级 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //中断通道使能 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); } static void GENERAL_TIMx_Mode_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_ICInitTypeDef TIM_ICInitStruct; GENERAL_TIMx_CLK_FUN(GENERAL_TIMx_CLK,ENABLE); //初始化时基 TIM_TimeBaseInitStruct.TIM_Prescaler = (72-1); TIM_TimeBaseInitStruct.TIM_Period = 0xFFFF; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(GENERAL_TIMx,&TIM_TimeBaseInitStruct); //初始化 IC TIM_ICInitStruct.TIM_Channel = GENERAL_TIMx_CHANNEL_x; TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICFilter = 0; TIM_ICInit(GENERAL_TIMx,&TIM_ICInitStruct); //清楚更新中断标志 TIM_ClearFlag(GENERAL_TIMx,TIM_FLAG_Update | TIM_FLAG_CC3); //中断初始化 TIM_ITConfig(GENERAL_TIMx,TIM_FLAG_Update | TIM_FLAG_CC3,ENABLE); //使能TIM TIM_Cmd(GENERAL_TIMx,ENABLE); } void TIM_Config(void) { GENERAL_TIMx_GPIO_Config(); GENERAL_TIMx_NVIC_Config(); GENERAL_TIMx_Mode_Config(); }
详细过程参考野火例徎 32-TIM—高级定时器
//TIM2中断函数 void GENERAL_TIMx_IRQHandler(void) { //判断是否超出Period 检测位为更新中断 //若是更新,改变Capture_Period值 if(TIM_GetITStatus(GENERAL_TIMx,TIM_IT_Update) != RESET) { TIM_ICUserValueStruct.Capture_Period++; //清除中断等待 TIM_ClearITPendingBit(GENERAL_TIMx,TIM_IT_Update); } //捕获边沿 if(TIM_GetITStatus(GENERAL_TIMx,TIM_IT_CC3) != RESET) { //表示第一次捕获 清除CCR if(TIM_ICUserValueStruct.Capture_StartFlag == 0) { TIM_SetCounter(GENERAL_TIMx,0); //从0开始计数 TIM_ICUserValueStruct.Capture_CcrValue = 0; //捕获值为0 // 自动重装载寄存器更新标志清0 TIM_ICUserValueStruct.Capture_Period = 0; //改变捕获极性 TIM_OC3PolarityConfig(GENERAL_TIMx,TIM_ICPolarity_Falling); TIM_ICUserValueStruct.Capture_StartFlag = 1; } //第二次捕获 else { //得到CCR的值 TIM_ICUserValueStruct.Capture_CcrValue = TIM_GetCapture3(GENERAL_TIMx); //改变捕获极性 TIM_OC3PolarityConfig(GENERAL_TIMx,TIM_ICPolarity_Rising); //改变标志 TIM_ICUserValueStruct.Capture_StartFlag = 0; TIM_ICUserValueStruct.Capture_FinishFlag = 1; } TIM_ClearITPendingBit (GENERAL_TIMx,TIM_IT_CC3); } }
#include "bsp_delay.h" void Delay_Us( __IO uint32_t us) { uint32_t i; SysTick_Config(SystemCoreClock/1000000); for (i=0; i<us; i++) { // 当计数器的值减小到 0 的时候,CRTL 寄存器的位 16 会置 1 while ( !((SysTick->CTRL)&(1<<16)) ); } // 关闭 SysTick 定时器 SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; }
/* 按下 K1 启动测量 */ #include"bsp_HCSR04.h" #include"bsp_usart.h" #include"bsp_key.h" int main() { uint32_t time; // TIM 计数器的驱动时钟 uint32_t TIM_PscCLK = 72000000 / (71+1); float d = 0; USART_Config(); HCSR04_GPIO_Config(); TIM_Config(); KEY_GPIO_Config(); printf("\rHC_SR04实验\n"); while (1) { if(Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN)== KEY_ON) HCSR04_TRIG_Send(); if(TIM_ICUserValueStruct.Capture_FinishFlag == 1) { // 计算高电平时间的计数器的值 time = TIM_ICUserValueStruct.Capture_Period * (0xFFFF+1) + (TIM_ICUserValueStruct.Capture_CcrValue+1); printf ( "\r\n测得高电平脉宽时间:%ld.%ld s\r\n",time/TIM_PscCLK,time%TIM_PscCLK ); d = (float)time * 170 / 10000; printf("距离为:"); Print_Float(d); TIM_ICUserValueStruct.Capture_FinishFlag = 0; } } }
上述部分代码移植了野火的例程代码
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。