1,开启一个定时器,选择输入捕获,并开启中断,命名为ECHO;(36-1 -> 65535)//===============注意定时器挂在哪个APB总线上//====该方法不准
2,选择一个输出引脚,并命名为TRIG,默认低电平;
3,开启I2C1,;(可以开一个串口打印)
4,引入头文件: #include "OLED.h"
#include "stdio.h"
#include "string.h"
(需要添加OLED文件)
5,全局变量:
uint8_t IS_FIRST_CAPTURED=0;//标识位
uint32_t IC_Val1=0;
uint32_t IC_Val2=0;
uint32_t NUM1=0;//计算数据1,未转化
uint16_t NUM2=0;//计算数据2,已转化
6,声明自定义函数:
uint16_t HCSR04_Read(void);//声明自定义函数
void delay_ms(uint16_t time);//===================================
7,初始化准备:
OLED_Init();
OLED_Clear();
HAL_TIM_Base_Start(&htim3);//使能定时器
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);//使能定时器的输入捕获中断=======================================这里开了定时器3的通道1
char a[]="Hello World";
char b[]="distance:";
char c[]="cm";
8,循环外,只运行一次:
OLED_ShowString(4,1,b);//=================================位置自取
OLED_ShowString(4,13,c);
9,主函数内容:
OLED_ShowString(1,3,a);
OLED_ShowNum(4,10,HCSR04_Read(),3);
/*printf("Distance: %d cm\r\n",HCSR04_Read());
HAL_Delay(500);*///====================================================串口打印
10,自定义函数:
int fputc(int ch,FILE*f)//串口输出函数,printf函数
{
HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,100);
return ch;
}
//==============================================================================以下为超声波运行程序,根据开启的通道不同可更改
void delay_us(uint16_t time)
{
__HAL_TIM_SET_COUNTER(&htim3,0);//计时器置零
while(__HAL_TIM_GET_COUNTER(&htim3)<time);//获得计数值,并比较
}
void delay_ms(uint16_t time)
{
__HAL_TIM_SET_COUNTER(&htim3,0);//计时器置零
while(__HAL_TIM_GET_COUNTER(&htim3)<time);//获得计数值,并比较
}
uint16_t HCSR04_Read(void)//超声波读取函数
{
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_RESET);//先拉低电平
delay_us(5);
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_SET);//发送测距信号的高平信号
delay_us(20);
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_RESET);//再次拉低
__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_CC1);
HAL_Delay(500);
return NUM2;
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)//判断定时器的通道1
{
if(IS_FIRST_CAPTURED==0)//判断是否为第一次,防溢出;设标志位
{
IS_FIRST_CAPTURED=1;//不是的第一次捕获,将它置1
IC_Val1=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1);//记录返回值,并赋值于IC_Val1
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);//上升变下降沿
}
else if(IS_FIRST_CAPTURED==1)
{
IS_FIRST_CAPTURED=0;
IC_Val2=HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);//用IC_Val2记录这个值
__HAL_TIM_SET_COUNTER(htim,0);//计时器清零
if(IC_Val1<IC_Val2)//判断是否溢出
{
NUM1=IC_Val2-IC_Val1;//没有溢出,赋值NUM1
}
else if(IC_Val1>IC_Val2)
{
NUM1=0xffff-IC_Val1+IC_Val2;//已经溢出,最大值65536
}
NUM2=NUM1*0.017;//标准大气压,15度;mm换算为cm; NUM2=NUM1*340/2/10000 减轻CPU压力
__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);//变上升沿
__HAL_TIM_DISABLE_IT(&htim3,TIM_IT_CC1);
}
}
}
//=====================================================24/3/15优化代码
1,配置,IC直接与间接捕获
2,工程代码:
uint32_t read_time=0;
uint16_t HCSR04_Read()//超声波读取函数
{
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_RESET);//先拉低电平
delay_us(5);
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_SET);//发送测距信号的高平信号
delay_us(20);
HAL_GPIO_WritePin(TRIG_GPIO_Port,TRIG_Pin,GPIO_PIN_RESET);//再次拉低
__HAL_TIM_ENABLE_IT(&htim2,TIM_IT_CC1);
if(uwTick-read_time<100) return 0;
read_time=uwTick;
return distance;
}
uint32_t run_time=0;
void Tx_proc()//========================================调用即可
{
if(uwTick-run_time<100) return;
run_time=uwTick;
if(HCSR04_Read()!=0)
printf("Distance: %d cm\r\n",distance);
}
void delay_us(uint16_t time)
{
__HAL_TIM_SET_COUNTER(&htim2,0);//计时器置零
while(__HAL_TIM_GET_COUNTER(&htim2)<time);//获得计数值,并比较
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
{
ic1_val=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
ic2_val=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);
if(ic2_val>=ic1_val)
{
distance=(ic2_val-ic1_val)*0.017;
}
else
{
distance=0xffff-ic1_val+ic2_val;
}
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);
}
}
}
struct __FILE
{
int handle;
};
FILE __stdout;
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,50);
return ch;
}
//=========================================================================新方法
1,开启一个定时器直接输入捕获通道即可,并使能,//===========================注意是36-1或72-1
2,开启一个输出通道,并命名为TRIG;
#include "stdio.h"
uint8_t TIM4CH1_CAPTURE_STA=0; //输入捕获状态
uint16_t TIM4CH1_CAPTURE_VAL; //输入捕获值(TIM2是16位)
float len = 0;
uint32_t time= 0;
HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1); //开启TIM2的捕获通道2,并且开启捕获中断
HAL_TIM_ENABLE_IT(&htim4,TIM_IT_UPDATE); //使能更新中断
while (1)
{
CHL_capture();
if(TIM4CH1_CAPTURE_STA & 0x80) //成功捕获一个脉宽
{
time = TIM4CH1_CAPTURE_STA & 0x3F; //获取溢出次数
time *= 65536; //获得溢出的时间值
time += TIM4CH1_CAPTURE_VAL; //加上最后一次取得的值
len = time * 342.62*100/2000000;
TIM4CH1_CAPTURE_STA = 0;
}
printf("%.1fcm\r\n",len);
HAL_Delay(400);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断(溢出)发生时执行
{
if((TIM4CH1_CAPTURE_STA&0X80) ==0) //还未捕获成功
{
if(TIM4CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{
if((TIM4CH1_CAPTURE_STA&0X3F)==0X3F) //高电平时间太长了
{
TIM4CH1_CAPTURE_STA |= 0X80; //标记成功捕获一次
TIM4CH1_CAPTURE_VAL = 0XFFFF; //
}
else
TIM4CH1_CAPTURE_STA++; //否则标记溢出数加一
}
}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{
if((TIM4CH1_CAPTURE_STA&0x80)==0) //还未捕获成功
{
if(TIM4CH1_CAPTURE_STA&0x40) //成功捕获到一个下降沿
{
TIM4CH1_CAPTURE_STA |= 0X80; //标记成功,捕获到一次高电平完成
TIM4CH1_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&htim4, TIM_CHANNEL_1); //获取当前捕获值
TIM_RESET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_1); //清除原来设置
TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_1, TIM_ICPOLARITY_RISING); //捕获到下降沿后,将捕获复位到捕获上升沿
}
else //捕获到一个上升沿
{
TIM4CH1_CAPTURE_STA = 0;
TIM4CH1_CAPTURE_VAL = 0;
TIM4CH1_CAPTURE_STA |= 0x40; //第六位标记为捕获到上升沿
__HAL_TIM_DISABLE(&htim4); //关闭定时器
__HAL_TIM_SET_COUNTER(&htim4, 0); //定时器初始值设置为0
TIM_RESET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_1);
TIM_SET_CAPTUREPOLARITY(&htim4, TIM_CHANNEL_1, TIM_ICPOLARITY_FALLING); //捕获到上升沿之后,将捕获设置为下降沿
__HAL_TIM_ENABLE(&htim4);
}
}
HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1);
}
void CHL_capture(void)
{
uint32_t i;
HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET);
for(i=0;i<72*40;i++)
__NOP();
HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET);
}
struct __FILE
{
int handle;
};
FILE __stdout;
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,50);
return ch;
}