震动传感器
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; // ARRTIM_Motorinit.TIM_Prescaler= 7200-1; //PSCTIM_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; // ARRTIM_Motorinit.TIM_Prescaler= 7200-1; //PSCTIM_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);//¶¨Ê±Æ÷4TIM_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,就是最后测距距离