大家好哇!我是湫湫,一个正在摸索嵌入式的普通大学生。
进入正题,最近在做智能小车,想通过文章记录学习过程。
本次文章主要使用 stm32F1C8T6 实现小车测距。
非常感谢大家的阅读,如果有不对的地方欢迎指正。
目录
一.实物图
1.舵机
本人接触的舵机线序颜色为:
中间红色线:电源正极,棕色线:电源负极,黄色线:控制信号线,具体如下图所示。
(特别说明:不同的厂商制作的舵机的输入线颜色可能会存在不一致,但一般中间的线为红色正极,信号线可能为白色,负极可能为黑色,具体还是要参考舵机的数据手册。)
2.HC_SR04:
可提供 2cm-400cm 的非接触式距离感测功能,
测距精度可达高到的非接触式距离感测功能,测距精度可达高到 3mm ;
模块包括超声波发射器、接收器与控制电路。
VCC:5v供电
Triger引脚:单片机某个引脚--->输入一个信号。
Echo引脚:输出一个信号--->单片机的某个引脚。
GND:接地。
二.基本工作原理
1.舵机工作原理
舵机转动的角度与脉宽在0.5ms~2.5ms的区间内呈线性关系。舵机有90°、180°、270°、360°最大转角,这里以180°舵机为例来说明脉冲宽度和角度的关系,其他角度舵机参考具体参数,180°舵机周期为20ms时的脉宽和转角关系如下图:
舵机的死区,扭矩等相关参数在此我就不多解释了,想多了解的更深入的话,看我文末附上的链接进行深入学习。
2.HC_SR04时序图
1.如单片机某一个引脚输出一个10微秒的高电平,输入到Triger,
2.HC_SR04的上面网状小孔就发出8个4K Hz,
3.再发出来之后,Echo置高电平;
4.如若发出去的波遇到障碍物,就会被反射回来,反射回来的波被小孔接收到后,Echo置低电平
5.Echo持续置高电平的时间,是超声波往返的距离,除于2,就是超声波到障碍物的距离
6.即:测试距离=(高电平时间*音速)/2;音速=340m/s=0.034cm/us。
三.相关代码
1.Servo.c
//舵机
#include "stm32f10x.h" // Device header
#include "PWM.h"
#include "Servo.h"
/**
* 函 数:舵机初始化
* 参 数:无
* 返 回 值:无
*/
void Servo_Init(void)
{
PWM_Init(); //初始化舵机的底层PWM
}
/**
* 函 数:舵机设置角度
* 参 数:Angle 要设置的舵机角度,范围:0~180
* 返 回 值:无
*/
void Servo_SetAngle(float Angle)
{
PWM_SetCompare2(Angle / 180 * 2000 + 500); //设置占空比
//将角度线性变换,对应到舵机要求的占空比范围上
}
2.PWM.c
#include "stm32f10x.h"
#include "myMOTOR.h"
#include "track.h"
void PWM_Init(void)
{
MOTOR_GPIO_Init();
Track_Init();
//开启TIM2的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//选择时基准单元的时钟(内部时钟)
TIM_InternalClockConfig(TIM2);
//配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//不分屏
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=799; //arr 计数周期
TIM_TimeBaseInitStructure.TIM_Prescaler=0; //psc 预分频器
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
//初始化,输出比较单元(OC)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OCPolarity=TIM_CounterMode_Up;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC2Init(TIM2,&TIM_OCInitStructure);
TIM_OC3Init(TIM2,&TIM_OCInitStructure);
//启动定时器
TIM_Cmd(TIM2,ENABLE);
}
/**
* 函 数:PWM设置CCR
* 参 数:Compare 要写入的CCR的值,范围:0~100
* 返 回 值:无
* 注意事项:CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比
* 占空比Duty = CCR / (ARR + 1)
*/
void PWM_SetCompare2(uint16_t Compare)
{
TIM_SetCompare2(TIM2, Compare); //设置CCR2的值
}
3.HCSR04.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "TIME.H"
void HC_SR04_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能GPIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIMx时钟
//GPIO初始化 Trig(STM32发送触发信号给HC-SR04)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出(高低电平均有驱动能力)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//GPIO初始化 Echo(STM32接受回波特率,计算距离)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//定时中断配置
//选择时钟源
TIM_InternalClockConfig(TIM2);
//配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100-1;//ARR 定时时间0.1ms
TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1;//PSC 1MHz(150HZ以上最好)
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//高级定时器采用,给0
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//解除初始化就进入中断(避免数据出错)
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能定时中断
//配置NVIC 分配和管理中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级
NVIC_Init(&NVIC_InitStructure);
//失能定时
TIM_Cmd(TIM2,DISABLE);
}
//计算距离(平均值)
float HCSR04_GetLenght(void)
{
//求解距离,采用平均值最好
int i=0;//次数变量
unsigned int t=0;
float Length=0;
float Sum=0;
for(i=0;i<3;i++)//计算3次
{
//触发信号(触发超声波模块工作)
GPIO_SetBits(GPIOB,GPIO_Pin_11);
Delay_us(15);//10US以上
GPIO_ResetBits(GPIOB,GPIO_Pin_11);
//获取Echo引脚的电平的状态
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==0);//低电平就执行空操作
//读高电平
Time_On();//打开定时器
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_10)==1);//高电平就执行空操作(直到读取完成)
//低电平(接受结束)
Time_Off();//关闭定时器
t=Time_Get_Counter();//获取时间
Length=((float)t/58.0);//计算距离
Sum=Sum+Length;//3次计算的总距离
}
//计算距离的均值
Length=Sum/3.0;
return Length;
}
四.总结
本篇文章主要是记录小车的部分模块,
具体器件的工作和控制原理介绍的不是很全,
要了解舵机和HC-SR04工作原理和控制原理,参考下面链接和视频
欢迎大家指错,看到了就会修改,希望大家一起共同进步!!!
参考链接:
参考视频:
STM32驱动HC-SR04超声波测距模块测距_哔哩哔哩_bilibili
标签:TIM2,NVIC,SR04,舵机,--,STM32,TIM,InitStructure,GPIO From: https://blog.csdn.net/hjq1015/article/details/142255866