Introducción al experimento: el
experimento utiliza el módulo HC-SR04 para la medición de distancia, utiliza el microordenador de un solo chip STM32F103RCT6 para el control y lo carga en la PC utilizando el puerto serie.
Introducción al módulo HC-SR04: el módulo
HC-SR04 tiene cuatro pines: VCC GND Trig Echo
① VCC está conectado a la interfaz de 5V del microcontrolador.
② GND conectado a la GND del microcontrolador.
SingUtilizando el puerto IO TRIG para activar el rango, para dar una señal de alto nivel de al menos 10us, el módulo envía automáticamente ocho ondas cuadradas de 40khz, y detecta automáticamente si una señal regresa.
④ Cuando regresa una señal, se emite un nivel alto a través del puerto IO ECHO. La duración del nivel alto es el tiempo desde la transmisión de la onda ultrasónica hasta el retorno. Distancia de prueba = (tiempo de alto nivel * velocidad del sonido (340M / S)) / 2.
Uso del módulo:
un puerto de control envía un nivel alto de más de 10us, puede esperar una salida de alto nivel en el puerto receptor. El temporizador se puede iniciar tan pronto como haya una salida. Cuando el puerto llega a un nivel bajo, se puede leer el valor del temporizador. En este momento, es el momento del rango y se puede calcular la distancia.
La parte del código utiliza principalmente la entrada de átomos puntuales para capturar los cambios del código.
Adopte el pin PA6 de un solo chip para producir un nivel alto de 10
us . Use el pin PB8 (TIM4_CH3) para calcular el tiempo.
Sección de captura de entrada:
#include "timer.h"
#include "usart.h"
#include "sys.h"
//定时器4通道3输入捕获配置
TIM_ICInitTypeDef TIM4_ICInitStructure;
void TIM4_Cap_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能TIM4时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //PB8 清除之前设置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PB8 输入
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_8); //PB8 下拉
//初始化定时器4 TIM4
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //预分频器
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
//初始化TIM2输入捕获参数
TIM4_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //配置输入分频,不分频
TIM4_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
TIM_ICInit(TIM4, &TIM4_ICInitStructure);
//中断分组初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
TIM_ITConfig(TIM4,TIM_IT_Update|TIM_IT_CC3,ENABLE);//允许更新中断 ,允许CC1IE捕获中断
TIM_Cmd(TIM4,ENABLE ); //使能定时器4
}
u8 TIM4CH3_CAPTURE_STA=0; //输入捕获状态
u16 TIM4CH3_CAPTURE_VAL; //输入捕获值
//定时器5中断服务程序
void TIM4_IRQHandler(void)
{
if((TIM4CH3_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
if(TIM4CH3_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM4CH3_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
{
TIM4CH3_CAPTURE_STA|=0X80;//标记成功捕获了一次
TIM4CH3_CAPTURE_VAL=0XFFFF;
}else TIM4CH3_CAPTURE_STA++;
}
}
if (TIM_GetITStatus(TIM4, TIM_IT_CC3) != RESET)//捕获1发生捕获事件
{
if(TIM4CH3_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM4CH3_CAPTURE_STA|=0X80; //标记成功捕获到一次上升沿
TIM4CH3_CAPTURE_VAL=TIM_GetCapture3(TIM4);
TIM_OC3PolarityConfig(TIM4,TIM_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获
}else //还未开始,第一次捕获上升沿
{
TIM4CH3_CAPTURE_STA=0; //清空
TIM4CH3_CAPTURE_VAL=0;
TIM_SetCounter(TIM4,0);
TIM4CH3_CAPTURE_STA|=0X40; //标记捕获到了上升沿
TIM_OC3PolarityConfig(TIM4,TIM_ICPolarity_Falling); //CC1P=1 设置为下降沿捕获
}
}
}
TIM_ClearITPendingBit(TIM4, TIM_IT_CC3|TIM_IT_Update); //清除中断标志位
}
Archivo de captura de entrada .h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
void TIM4_Cap_Init(u16 arr,u16 psc);
#endif
Parte de salida GPIO PA6:
#include "gpio.h"
void gpio_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //LED0-->PA.6 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.6
}
GPIO PA6 .h parte
#ifndef __LED_H
#define __LED_H
#include "sys.h"
void gpio_Init(void);//初始化
#endif
función principal:
#include "delay.h"
#include "usart.h"
#include "stm32f10x.h"
#include "timer.h"
#include "sys.h"
#include "gpio.h"
extern u8 TIM4CH3_CAPTURE_STA; //输入捕获状态
extern u16 TIM4CH3_CAPTURE_VAL; //输入捕获值
int main(void)
{
float temp=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
delay_init(); //延时函数初始化
uart_init(9600); //9600
gpio_Init();
TIM4_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数
while(1)
{
GPIO_SetBits(GPIOA,GPIO_Pin_6); //PA.6 输出高
delay_us(10);
GPIO_ResetBits(GPIOA,GPIO_Pin_6); //PA.6 输出低
delay_ms(10);
if(TIM4CH3_CAPTURE_STA&0X80)//成功捕获到了一次高电平
{
temp=TIM4CH3_CAPTURE_STA&0X3F;
temp*=65536; //溢出时间总和
temp+=TIM4CH3_CAPTURE_VAL; //得到总的高电平时间
temp=temp*170*0.0001;
printf("distance:%f cm\r\n",temp); //打印总的高点平时间
TIM4CH3_CAPTURE_STA=0; //开启下一次捕获
}
delay_ms(500);
}
}
Para lograr el efecto:
Las últimas dos líneas de datos solo aparecieron cuando fueron bloqueadas por la mano
Paquete de compresión de código: código HC-SR04