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

震动传感器

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

相关推荐
FreakStudio7 小时前
一文速通 Python 并行计算:07 Python 多线程编程-线程池的使用和多线程的性能评估
python·单片机·嵌入式·多线程·面向对象·并行计算·电子diy
SlientICE10 小时前
TCP是什么?不需要!使用ESP32网络层直接通信!
网络·单片机·网络协议·tcp/ip
BW.SU13 小时前
单片机 + 图像处理芯片 + TFT彩屏 触摸开关控件 v1.2
单片机·人机交互·ra8889·开关控件·触摸屏设计
双叶83613 小时前
(51单片机)点阵屏LED显示图片(点阵屏LED教程)(74Hc595教程)
c语言·开发语言·单片机·嵌入式硬件·51单片机
深圳市青牛科技实业有限公司13 小时前
D3502C:一款高性能降压转换器的技术解析,可替代U3502C采用ESOP8封装
单片机·嵌入式硬件·快充·扫地机器人吸尘·筋膜枪电机·驱动轮电机
顾念`13 小时前
履带小车+六轴机械臂(2)
单片机·嵌入式硬件
努力创造奇迹13 小时前
STM32 HAL库 ADC+TIM+DMA 3路 1S采样一次电压
stm32·单片机·嵌入式硬件
leoFY12314 小时前
STM32 BOOT设置,bootloader,死锁使用方法
stm32·单片机·嵌入式硬件
czhaii15 小时前
单片机任意普通IO引脚使用定时器扩展外部中断的巧妙方法
单片机·嵌入式硬件
二块烧肉17 小时前
STM32 认识STM32
stm32·单片机·嵌入式硬件