直接进入正题:
CUBEMX配置(本次使用的的是V5.4.0,附上链接 https://www.st.com/stm32cubemx),时基使用的是sysTick。
高速时钟使用的是外部8M晶振,配置如下:
脉冲产生的用的是定时器1的通道2,配置如下:
DMA的配置如下,因为DMA是默认开中断的,所以DMA的中断不用管。
本次超声波的接收用的是GPIO外部中断,ECHO下面的6个GPIO用于驱动1.44的TFT_LCD,配置如下:
配置完毕,开始生成代码,我用的是VSCODE,所以用带makefile的的代码,配置如下:
下面展示代码,DMA发送完成后会进入DMA中断,TIM开始向上计数,在计数完成后会进入中断,两个中断函数的处理如下:
如果不太清楚脉冲个数的问题,请参考:https://blog.csdn.net/lkmmmqfn2222/article/details/103280839
void DMA2_Stream2_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream2_IRQn 0 */
TIM_CCxChannelCmd(&htim1,TIM_CHANNEL_2,TIM_CCx_DISABLE);
/* USER CODE END DMA2_Stream2_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_tim1_ch2);
/* USER CODE BEGIN DMA2_Stream2_IRQn 1 */
/* USER CODE END DMA2_Stream2_IRQn 1 */
}
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef* htim){
if(htim == &htim1){
TIM_CCxChannelCmd(&htim1,TIM_CHANNEL_2,TIM_CCx_DISABLE);
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);//used for debug
myUltrasonic.trigFlag = 1;
myUltrasonic.timCnt0 = __HAL_TIM_GET_COUNTER(&htim1);
HAL_NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}
}
下面贴出超声波部分的代码:
#ifndef _TEST_H
#define _TEST_H
#include "main.h"
#include "tim.h"
#define ACC_STEP_NUM 16
typedef struct {
uint8_t num; //number of ultrasonic sensors
uint8_t sensorType; //0:一体式 1:分立式
uint8_t trigFlag; //sensor drivered flag 0:no trig 1:trig
uint8_t trigEndFlag;
uint32_t timCnt0; //
uint32_t timCnt1; //
float distance; //
float distanceTemp; //
float preDistance; //
}ULTRASONIC,*pULTRASONIC;
void ledTest(void);
void pwmTest(void);
void itoa(uint32_t n,uint8_t s[]);
void reverseCString(uint8_t* ch);
#endif
#include "test.h"
#include "leddrv.h"
#include "string.h"
uint16_t accStep[ACC_STEP_NUM] ;
ULTRASONIC myUltrasonic;
uint8_t testD[] = {"152"};
void ledTest(void){
uint8_t testA[] = {"*Cairne Studio*"};
uint8_t testB[] = {"UltrasonicModule"};
uint8_t testC[] = {"Distance is:"};
Lcd_Clear(GRAY0);
Gui_DrawFont_GBK16(0, 16, GRAY2, WHITE,(uint8_t*) &testA);
Gui_DrawFont_GBK16(0,40,GRAY1,GRAY0,(uint8_t*)&testB);
Gui_DrawFont_GBK16(0,64,GRAY2,GRAY0,(uint8_t*)&testC);
LCD_BLK_SET;
}
void pwmTest(void){
myUltrasonic.trigEndFlag = 0;
myUltrasonic.trigFlag = 0;
for(int i = 1; i < ACC_STEP_NUM ; i++){
accStep[i] = accStep[i-1] + 11;
}
HAL_TIM_OC_Start_DMA(&htim1,TIM_CHANNEL_2,(uint32_t*)accStep,ACC_STEP_NUM);
}
// void ultralsonicTest(pULTRASONIC mySensor){
// }
void ultrasonicInit(pULTRASONIC mySensor){
mySensor->distance = 0;
mySensor->num = 1;
}
void reverseCString(uint8_t* ch){
uint8_t size = strlen(ch);
uint8_t head = 0;
uint8_t tail = size - 1;
while(head < tail){
uint8_t temp = ch[head];
ch[head++] = ch[tail];
ch[tail--] = temp;
}
}
void itoa(uint32_t n,uint8_t s[]){
int i, sign;
// uint8_t s[] = {};
if((sign = n) < 0){
n = -n;
}
i = 0;
do{
s[i++] = n%10 + '0';
}while((n /= 10) > 0);
if(sign < 0){
s[i++] = '-';
}
s[i] = '\0';
// reverseCString(&s);
// sout = s;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == GPIO_PIN_11){
uint32_t temCnt = __HAL_TIM_GetCounter(&htim1);
if(temCnt < myUltrasonic.timCnt0){
if(1500 <= (65535 - myUltrasonic.timCnt0 + temCnt)){
myUltrasonic.timCnt1 = __HAL_TIM_GetCounter(&htim1);
myUltrasonic.distance = (65535 - (myUltrasonic.timCnt0 - myUltrasonic.timCnt1))*0.17;
if(myUltrasonic.distanceTemp >= 2600){
myUltrasonic.distanceTemp = 2600;
}
else if(myUltrasonic.distanceTemp <= 100){
myUltrasonic.distanceTemp = 100;
}
myUltrasonic.distance = myUltrasonic.distanceTemp;
myUltrasonic.preDistance = myUltrasonic.distance;
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_14);
HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);
}
}
else{
if(((temCnt - myUltrasonic.timCnt0) <= 20000)&& ((temCnt - myUltrasonic.timCnt0) >= 1500)){
myUltrasonic.timCnt1 = __HAL_TIM_GetCounter(&htim1);
myUltrasonic.distanceTemp = (myUltrasonic.timCnt1 - myUltrasonic.timCnt0)*0.17;
if(myUltrasonic.distanceTemp >= 2600){
myUltrasonic.distanceTemp = 2600;
}
else if(myUltrasonic.distanceTemp <= 100){
myUltrasonic.distanceTemp = 100;
}
myUltrasonic.distance = myUltrasonic.distanceTemp;
myUltrasonic.preDistance = myUltrasonic.distance;
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_14);
HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);
}
else{
myUltrasonic.distance = myUltrasonic.preDistance;
}
}
}
}
最终实现原理解释如下:
下图所示的A部分为驱动发射波形,因为是收发一体,所以会有一些死区,B部分为回波接到的波形(本模块在测试平面可以到3m+,人体腿部可以到接近2m,因为这个小模块的原理PCB以及代码都是本人设计,需要交流的请联系我[email protected]),C为脉冲发送完成中断标志位,D为接收到第一个回波的中断标志位。
完整代码链接(带显示),链接://download.csdn.net/download/lkmmmqfn2222/12014550