一、设计描述
核心硬件
主控单元:采用STM32F103C8T6单片机,凭借其强大的处理能力和丰富的外设接口,为系统提供了坚实的硬件基础。
软件平台
开发工具:利用STM32CUBEMX + Keil5这一直观易用的集成开发环境,极大地提升了软件编程与调试的效率,确保了系统软件的稳定可靠。
系统应用场景
此方案适合短期内要求实现利用超声波避障,对测距精度要求不高的情况。
二、硬件连接
HC-SR04
|------|-----|
| VCC | 5V |
| Trig | PB0 |
| Echo | PB1 |
| Gnd | GND |
[HC-SR04连线表格]
STM32F103C8T6
|-----|------|------|
| PB0 | Trig | 触发信号 |
| PB1 | Echo | 回响信号 |
[STM32F103C8T6连线表格]
三、STM32CUBEMX配置
了解工作原理
由图表可知,我们只需要处理触发信号和回响信号即可。
STM32CUBEMX配置
四、软件编写
1. 初始化HC-SR04
初始化原理就是保持触发信号低电平
void HC_SR04_Init(void)
{
HAL_GPIO_WritePin(TRIG_GPIOX, TRIG_GPIO_PIN_X, GPIO_PIN_RESET);
}
2. 等待回响信号
如果直接while() 将可能进入死循环,所以加上总体计数来做预防
while(HAL_GPIO_ReadPin(ECHO_GPIOX,ECHO_GPIO_PIN_X) == GPIO_PIN_RESET){
all_time++;
if(all_time >= MaxCnt) return false;
}
3. 计算回响数据高电平
while(HAL_GPIO_ReadPin(ECHO_GPIOX,ECHO_GPIO_PIN_X) == GPIO_PIN_SET){
cnt++;
all_time++;
if(all_time >= MaxCnt) return false;
}
4. 综合获取计数
bool HcSr04_Echo(int *time_cnt) // ????????
{
int cnt = 0;
long int all_time = 0;
while(HAL_GPIO_ReadPin(ECHO_GPIOX,ECHO_GPIO_PIN_X) == GPIO_PIN_RESET){
all_time++;
if(all_time >= MaxCnt) return false;
}
while(HAL_GPIO_ReadPin(ECHO_GPIOX,ECHO_GPIO_PIN_X) == GPIO_PIN_SET){
cnt++;
all_time++;
if(all_time >= MaxCnt) return false;
}
*time_cnt = cnt;
return true;
//printf("%d\r\n",cnt);
}
5. 获取距离
此距离不准确,但通过计算差不多得出的距离distance以毫米(mm)为单位,足以应对5cm以上2m以下的避障处理。
bool Get_HcSr04_distance(float *distance, int *timecnt) // ?????????(CM???)
{
HC_SR04_Init();
HcSr04_Trig();
if(HcSr04_Echo(timecnt)){
*distance = (*timecnt)/2.35;
return true;
}
return false;
}
6. 串口重定义
//重写标准输出函数
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart4, (uint8_t *)&ch, 1, 10);
return ch;
}
五、总代码
hcsr04.h
#ifndef __HCSR04_H
#define __HCSR04_H
#include "stdbool.h"
#include "usart.h"
/*
float distance = 0; int timecnt = 0;
if(Get_HcSr04_distance(&distance,&timecnt) == true){
printf(" distance = %f; timecnt = %d\r\n",distance,timecnt);
}
*/
//printf(" distance = %f; timecnt = %d\r\n",distance,timecnt);
#define TRIG_delay 1 // ·¢ËÍÐźÅʱ¼ä (ms)
#define MaxCnt 2000000 // ¼ÆÊý·¶Î§
#define TRIG_GPIOX
#define ECHO_GPIOX GPIOB
#define TRIG_GPIO_PIN_X GPIO_PIN_0
#define ECHO_GPIO_PIN_X GPIO_PIN_1
void HC_SR04_Init(void);
bool HcSr04_Trig(void) ;
float Get_InitDistance(void);
bool HcSr04_Echo(int *time_cnt) ;
bool Get_HcSr04_distance(float *distance, int *timecnt) ;
#endif
hcsr04.c
#include "hcsr04.h"
#include "gpio.h"
#include "tim.h"
#include "stdio.h"
#include "usart.h"
float init_distance = 0;
// int TF1C = 0;
void HC_SR04_Init(void)
{
HAL_GPIO_WritePin(TRIG_GPIOX, TRIG_GPIO_PIN_X, GPIO_PIN_RESET);
/*
if(TF1C == 0){
HAL_Delay(10);
TF1C = 1;
float distance = 0; int timecnt = 0;
int cnt = 0;int i = 0;
while(cnt == 0){
init_distance = 0;
for(i = 0;i<50;i++){
if(Get_HcSr04_distance(&distance,&timecnt) == true && i >= 2){
cnt = cnt + 1;
printf("initing -- >init_distance:%2f;distance:%2f;timecnt:%d;\r\n",init_distance,distance, timecnt);
init_distance = init_distance + distance;
}
}
}
if(cnt == 0) return;
init_distance = init_distance / cnt;
init_distance = init_distance / 2;
}
*/
}
float Get_InitDistance(void){
return init_distance;
}
bool HcSr04_Trig(void) // ?????????
{
HAL_GPIO_WritePin(TRIG_GPIOX, TRIG_GPIO_PIN_X, GPIO_PIN_SET);
HAL_Delay(TRIG_delay);
HAL_GPIO_WritePin(TRIG_GPIOX, TRIG_GPIO_PIN_X, GPIO_PIN_RESET);
return true;
}
bool HcSr04_Echo(int *time_cnt) // ????????
{
int cnt = 0;
long int all_time = 0;
while(HAL_GPIO_ReadPin(ECHO_GPIOX,ECHO_GPIO_PIN_X) == GPIO_PIN_RESET){
all_time++;
if(all_time >= MaxCnt) return false;
}
while(HAL_GPIO_ReadPin(ECHO_GPIOX,ECHO_GPIO_PIN_X) == GPIO_PIN_SET){
cnt++;
all_time++;
if(all_time >= MaxCnt) return false;
}
*time_cnt = cnt;
return true;
//printf("%d\r\n",cnt);
}
bool Get_HcSr04_distance(float *distance, int *timecnt) // ?????????(CM???)
{
HC_SR04_Init();
HcSr04_Trig();
if(HcSr04_Echo(timecnt)){
*distance = (*timecnt)/2.35;
return true;
}
return false;
}
main.c
HC_SR04_Init();
float distance = 0; int timecnt = 0 ;
while(1){
if(Get_HcSr04_distance(&distance,&timecnt) == true){
printf("distance:%f; timecnt:%d;\r\n", distance, timecnt);
}
}