欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 八卦 > 舵机、震动传感器、超声波使用代码

舵机、震动传感器、超声波使用代码

2025/4/19 1:20:01 来源:https://blog.csdn.net/2202_75840803/article/details/147109027  浏览:    关键词:舵机、震动传感器、超声波使用代码

震动传感器

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,就是最后测距距离

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词