震动传感器
void SHAKE_Init(void)
{
GPIO_InitTypeDef shake_init; //GPIO_InitTypeDef½á¹¹ÌåÔÚGPIO.h
//ʹÄÜAPB2µÄʱÖÓ GPIOA
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //rcc.hÖÐ
//½á¹¹ÌåÅäÖÃ
shake_init.GPIO_Mode = GPIO_Mode_IPD;//ÏÂÀ/ÉÏÀ¶¼¿ÉÒÔ£¬Ö>>Êdzõʼ>>¯Á˵çƽ£¬×îÖÕÒÔIOÒý½ÅΪÖ÷
shake_init.GPIO_Pin = GPIO_Pin_4;
shake_init.GPIO_Speed= GPIO_Speed_10MHz;
GPIO_Init(GPIOB,&shake_init);
}
舵机
舵机PWM引脚不是随便选着的,根据下面的选择,选择引脚后定时器也是需要根据表里的去配置

void motor_config(void)
{
GPIO_InitTypeDef GPIO_Motorinit;//GPIO结构体
TIM_TimeBaseInitTypeDef TIM_Motorinit;//通用定时器结构体
TIM_OCInitTypeDef TIMPWM_Motorinit;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //定时器
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //引脚复用
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); //部分重映射
GPIO_Motorinit.GPIO_Mode= GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Motorinit.GPIO_Pin= GPIO_Pin_5;//
GPIO_Motorinit.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_Motorinit);
TIM_Motorinit.TIM_ClockDivision= TIM_CKD_DIV1; / /设置时钟分割为不分频
TIM_Motorinit.TIM_CounterMode= TIM_CounterMode_Up; //TIM 向上计数
TIM_Motorinit.TIM_Period= 200-1; // ARR
TIM_Motorinit.TIM_Prescaler= 7200-1; //PSC
TIM_TimeBaseInit(TIM3,&TIM_Motorinit);
TIMPWM_Motorinit.TIM_OCMode= TIM_OCMode_PWM1 ; // 定时器模式
TIMPWM_Motorinit.TIM_OutputState= TIM_OutputState_Enable; / 比较输出使能
TIMPWM_Motorinit.TIM_OCPolarity= TIM_OCPolarity_Low ; // 有效输出极性
TIM_OC2Init(TIM3,&TIMPWM_Motorinit); // 初始化定时器三通道二
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); 通道二预装载值
TIM_Cmd(TIM3,ENABLE);//ʹÄÜ
}
HC_SR04超声波模块

1.定义GPIO引脚一个发送引脚,一个接收引脚
void HC_SR04Config(void)
{
GPIO_InitTypeDef GPIO_hcsr04init;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//Trig PB11 发送
GPIO_hcsr04init.GPIO_Mode= GPIO_Mode_Out_PP; // 推挽输出
GPIO_hcsr04init.GPIO_Pin= GPIO_Pin_11;
GPIO_hcsr04init.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_hcsr04init);
//ECHO PB10 接收
GPIO_hcsr04init.GPIO_Mode= GPIO_Mode_IN_FLOATING; // 浮空输入检查高电平
GPIO_hcsr04init.GPIO_Pin= GPIO_Pin_10;
GPIO_Init(GPIOB, &GPIO_hcsr04init);
}
2.定时器配置,配置微秒定时器
TIM_TimeBaseInitTypeDef TIM_hcsr04init;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_Motorinit.TIM_ClockDivision= TIM_CKD_DIV1; / /设置时钟分割为不分频
TIM_Motorinit.TIM_CounterMode= TIM_CounterMode_Up; //TIM 向上计数
TIM_Motorinit.TIM_Period= 200-1; // ARR
TIM_Motorinit.TIM_Prescaler= 7200-1; //PSC
TIM_TimeBaseInit(TIM3,&TIM_Motorinit);
TIM_Cmd(TIM4,DISABLE);//先关闭,检查高低电平时再打开
TIM_ITConfig(TIM4,TIM_IT_Update, ENABLE); // 定时器中断,允许溢出更新
3.配置中断,配置再内核里,在misc.c的misc.h中找结构体
NVIC_InitTypeDef NVIC_hcsr04init;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_hcsr04init.NVIC_IRQChannel=TIM4_IRQn ; // 通道,使用定时器4的,因为定时器
配置的时候就是用定时器,在stm32f10x.h
中找TIM4_IRQn
//需要定义优先级分组misc.h中找NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_hcsr04init.NVIC_IRQChannelPreemptionPriority= 0 ; // 抢占优先级 misc.c中
NVIC_hcsr04init.NVIC_IRQChannelSubPriority= 0; // 子优先级
NVIC_hcsr04init.NVIC_IRQChannelCmd= ENABLE; //使能
NVIC_Init(&NVIC_hcsr04init);//结构体初始化
完整代码
#include "HC_SR04.h"
#include "stm32f10x.h"
void HC_SR04Config(void)
{
GPIO_InitTypeDef GPIO_hcsr04init;
TIM_TimeBaseInitTypeDef TIM_hcsr04init;
NVIC_InitTypeDef NVIC_hcsr04init;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//Trig PB11 ·¢Ë͵çƽ
GPIO_hcsr04init.GPIO_Mode= GPIO_Mode_Out_PP;
GPIO_hcsr04init.GPIO_Pin= GPIO_Pin_11;
GPIO_hcsr04init.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_hcsr04init);
//ECHO PB10 ½ÓÊÕµçƽ²>>ÐèÅäÖÃËÙ¶È
GPIO_hcsr04init.GPIO_Mode= GPIO_Mode_IN_FLOATING;
GPIO_hcsr04init.GPIO_Pin= GPIO_Pin_10;
GPIO_Init(GPIOB, &GPIO_hcsr04init);
//¶¨Ê±Æ÷4
TIM_hcsr04init.TIM_ClockDivision=TIM_CKD_DIV1 ;
TIM_hcsr04init.TIM_CounterMode =TIM_CounterMode_Up;
TIM_hcsr04init.TIM_Period =1000-1;
TIM_hcsr04init.TIM_Prescaler =72-1;
TIM_TimeBaseInit(TIM4,&TIM_hcsr04init);
TIM_ITConfig(TIM4,TIM_IT_Update, ENABLE); //¶¨Ê±Æ÷ÖÐ¶Ï ÔÊÐíÒç³ö¸üÐÂ
TIM_Cmd(TIM4,DISABLE);//¼ì²é¸ßµÍµçƽÔÙ´ò¿ª
//ÖжÏ
NVIC_hcsr04init.NVIC_IRQChannel=TIM4_IRQn ;
NVIC_hcsr04init.NVIC_IRQChannelPreemptionPriority= 0 ;
NVIC_hcsr04init.NVIC_IRQChannelSubPriority= 0;
NVIC_hcsr04init.NVIC_IRQChannelCmd= ENABLE;
NVIC_Init(&NVIC_hcsr04init);
}
4.开启定时器,上三步的时候已经开启了
5.Trig引脚
在.h中宏定义
#define ECHO_Reci GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)//读取PB10引脚高低电平,也就是下面定义的发送出的10us电平
//通过这个宏定义去发送10us以上高电平
#define TRIG_Send(a) if(a) \
GPIO_SetBits(GPIOB, GPIO_Pin_11); \
else \
GPIO_ResetBits(GPIOB, GPIO_Pin_11);\
\:换行,告诉编译器连接下一行的作用
6.等待Ec引脚输入高电平开始,定时器打开------开启计数器计数
定义一个定时器开打函数
//打开定时器4
extern uint16_t mscount =0;
void Open_tim4(void)
{
TIM_SetCounter(TIM4,0); //开打之后开始计数
mscount =0;//mscount用于计算五次取平均值减少误差
TIM_Cmd(TIM4,ENABLE);//打开定时器
}
7.等待Ec引脚输入高电平结束,定时器关闭------停止计数器计数
//关闭定时器4
void Close_tim4(void)
{
TIM_Cmd(TIM4,DISABLE);
}
需要已给中断服务函数
TIM4_IRQHandler()在startup_stm32f10x_hd.s中
void TIM4_IRQHandler(void)
{
if( TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET) // 检查是否发生中断,TIM_GetITStatus
在tim.h里
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update); // 清除中断标志
mscount++;//计数加一(一共计数五次)
}
}
8.通过计数器的值计算超声波测量距离
//获取定时器计数值
int GetEcho_time(void)
{
uint32_t t=0;
t=mscount*1000;//固定搭配
t+=TIM_GetCounter(TIM4); //获取定时器计数值
TIM4->CNT =0;//定时器计数值清零
delay_xms(50);
return t;
}
//获取超声波测距距离
float Getlength(void) //在循环中调用,不断获取距离
{
int i=0;
uint32_t t=0;
float length=0;
float sum=0;
while(i!=5)//计算五次取平均值
{
TRIG_Send(1); // .h宏定义里PB11发出高电平
delay_us(20); //高电平持续20us,超声波配置要求
TRIG_Send(0); //.h宏定义里PB11发出低电平
while( ECHO_Reci == 0); // ECHO_Reci宏定义:检测PB11接收的是高电平还是低电平,只有是高
电平才继续往下执行代码,不然继续等待接收到高电平
Open_tim4(); //定义的定时器计数函数
i=i+1; //打开一次计数一次
while(ECHO_Reci==1);
Close_tim4();//关闭定时器计数
t=GetEcho_time();//关闭定时器计数之后取获取计数值
length=((float)t/58.0);//测距距离
sum=sum+length;//五次的总和距离
}
length=sum/5.0;//平均距离
return length;
}
距离计算的总思路:为了减小误差我们取五次值计算平均值 。在主循环中不断执行距离获取函数Get length(),在这个函数中发送20us以上高电平,这次引脚检测到高电平,定时器计数函数打开,开始计数。计数次数i+1。当20us高电平过去了,引脚检测到低电平,关闭定时器计数,然后获取定时器计数的值 (cnt),
cnt的计算就是mscount*1000+TIM_GetCounter()。mscount每次发生中断加一
测距长度就l=t/58.0(固定公式)
然后五次l相加除以5,就是最后测距距离