目录
超声波模块HC-SR04:
工作原理:
超声波时序图:
![](https://img-blog.csdnimg.cn/11ed037a7ca4456d9e453abb7c139c41.png)
void HC_SR04_init(void)
{
GPIO_InitTypeDef HC_SR04_GPIO_Init_Structure;
TIM_TimeBaseInitTypeDef Timer4_Init_Structure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
//配置Trig(PB11)初始化结构体
HC_SR04_GPIO_Init_Structure.GPIO_Mode = GPIO_Mode_Out_PP;
HC_SR04_GPIO_Init_Structure.GPIO_Speed = GPIO_Speed_50MHz;
HC_SR04_GPIO_Init_Structure.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOB, &HC_SR04_GPIO_Init_Structure);
//配置Echo(PB10)初始化结构体
HC_SR04_GPIO_Init_Structure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
HC_SR04_GPIO_Init_Structure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOB, &HC_SR04_GPIO_Init_Structure);
Timer4_Init_Structure.TIM_ClockDivision = TIM_CKD_DIV1; //设置分频系数,通常默认不分频
Timer4_Init_Structure.TIM_CounterMode = TIM_CounterMode_Up; //设置计数模式为向上计数
Timer4_Init_Structure.TIM_Period = 1000-1; //设置重装载值为1000(计数周期为1毫秒)
Timer4_Init_Structure.TIM_Prescaler = 72-1; //设置初始化与分频值为72
TIM_TimeBaseInit(TIM4, &Timer4_Init_Structure);
TIM_Cmd(TIM4, DISABLE); //失能定时器4
}
/**
* 功能:打开定时器4函数
* 参数:None
* 返回值:None
*/
void open_timer4(void)
{
TIM_SetCounter(TIM4, 0);
HS_count_us=0;
TIM_Cmd(TIM4, ENABLE);
}
/**
* 功能:关闭定时器4函数
* 参数:None
* 返回值:None
*/
void close_timer4(void)
{
TIM_Cmd(TIM4, DISABLE);
}
/**
* 功能:获取Echo引脚电平
* 参数:None
* 返回值:Echo_Value:高电平 or 低电平
*/
int Get_HS_Echo_Value(void)
{
uint16_t Echo_Value;
Echo_Value = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10);
return Echo_Value;
}
/**
* 功能:获取高电平持续时间
* 参数:None
* 返回值:HS_Timer高电平持续时间
*/
int Get_HS_Time_Value(void)
{
uint32_t HS_Timer = 0;
HS_Timer = HS_count_us*1000;
HS_Timer += TIM_GetCounter(TIM4);
TIM4 -> CNT = 0; //清除计数器寄存器的值
delay_ms(50);
return HS_Timer;
}
/**
* 功能:获取距离
* 参数:None
* 返回值:length :距离
*/
float Get_HS_Length_Value(void)
{
uint32_t time = 0;
uint16_t i;
float length = 0;
float sum =0 ;
for(i=0;i<5;i++)
{
HC_SR04_Trig_H();
delay_us(20);
HC_SR04_Trig_L();
while(Get_HS_Echo_Value() == 0);
open_timer4();
while(Get_HS_Echo_Value() == 1);
close_timer4();
time=Get_HS_Time_Value();
length = ((float)time/58.0);
sum = sum + length;
}
length=sum/5.0;
return length;
}
舵机模块:
PWM:
PWM波,这是什么东西呢?其实就是一种方波,其频率为50Hz,周期就是20ms,
在每个周期里面,舵机高电平的占空比在0.5ms到2.5ms之间。
而0.5ms代表的是0度,2.5ms代表的是180度。其他的度数可以直接按照比例换算过去
0.5ms----------- 0度
1.0ms----------- 45度
1.5ms----------- 90度
2.0ms----------- 135度
2.5ms----------- 180度
PWM比较换算,控制角度:
一个周期为20ms,pwm配置为模式1,低电平有效,
200 ----- 20ms
195 ----- 0.5ms, 小于195,低电平,高于195,高电平 (5/200)*20=0.5
190 ----- 1ms
185 ------ 1.5ms
180 ------ 2ms
175 ------ 2.5ms
问题:像195,190,......175怎么来的呢?
由于PWM周期为20ms,所以(以舵机会转动 45°为例),占空比就应该为1ms/20ms = 5%,
所以TIM_SetCompare1的 TIMx 捕获比较 1 寄存器值就为200-200*5% = 190,其他的做类比可得出结果。
对于TIM_SetCompare2(TIM3, 175);这个函数:
//TIM_SetCompare2(TIMx,你想要的比较值);
舵机控制代码部分:
void servo_init(void)
{
GPIO_InitTypeDef GPIO_Init_Structure; //定义GPIO初始化结构体
TIM_TimeBaseInitTypeDef Timer_Init_Structure; //定义定时器初始化结构体
TIM_OCInitTypeDef Timer_OC_Init_Structure; //定义定时器输出PWM结构体
RCC_APB2PeriphClockCmd(SERVO_GPIO_CLK, ENABLE); //使能Timer3 GPIOB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能复用时钟
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //选择部分重映射
//配置GPIO初始化结构体
GPIO_Init_Structure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init_Structure.GPIO_Pin = SERVO_GPIO_PIN; //GPIO_Pin_5
GPIO_Init_Structure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SERVO_GPIO_PORT, &GPIO_Init_Structure);
//配置通用定时器初始化结构体,实现定时20ms
Timer_Init_Structure.TIM_ClockDivision = TIM_CKD_DIV1; //设置分频系数,通常采用默认的分频
Timer_Init_Structure.TIM_CounterMode = TIM_CounterMode_Up; //设置捕获模式为向上计数(基本定时器仅有向上计数)
Timer_Init_Structure.TIM_Period = 200-1; //设置重装载值(在预分频值为72000下,10000为一秒)
Timer_Init_Structure.TIM_Prescaler = 7200-1; //设置初始化预分频值为7200
// Timer_Init_Structure.TIM_RepetitionCounter = 0 //重复计数器,仅高级定时器需要设置
TIM_TimeBaseInit(TIM3, &Timer_Init_Structure);
//配置定时器输出PWM结构体
//在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;比较值不可大于等于重装载值
Timer_OC_Init_Structure.TIM_OCMode = TIM_OCMode_PWM1; //定时器模式选择Timer脉冲宽度调制模式 1
Timer_OC_Init_Structure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
Timer_OC_Init_Structure.TIM_OCPolarity = TIM_OCPolarity_Low; //选择有效输出为低电平
TIM_OC2Init(TIM3, &Timer_OC_Init_Structure);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_Cmd(TIM3, ENABLE);
}
void Servo_Run(uint16_t angle)
{
switch(angle)
{
case 180 :TIM_SetCompare2(TIM3, 175); break;//对应180度
case 135 :TIM_SetCompare2(TIM3, 180); break;//对应135度
case 90 :TIM_SetCompare2(TIM3, 185); break;//对应90度
case 45 :TIM_SetCompare2(TIM3, 190); break;//对应45度
case 0 :TIM_SetCompare2(TIM3, 195); break;//对应0度
}
}