编码电机pwm驱动 以及脉冲数读取

开发板 正点原子 stm32F103ZET6

#define _encoder_H_ 

#ifndef _encoder_H_
#define _encoder_H_#include "stm32f10x.h"
#include "stm32f10x_tim.h"#define ENCODER_TIM_PERIOD (u16)(65535)   //不可大于65535 因为F103的定时器是16位的。typedef struct bianmadianji 
{float coderA;float coderB;u8 mode; //正反转状态}G_ENCODER;extern G_ENCODER g_ENCODER;void Encoder_Init_TIM2(void); 
void Encoder_Init_TIM3(void);float Read_EncoderA(void);  //读取编码电机A 单位时间内的脉冲数
float Read_EncoderB(void);  //读取编码电机B 单位时间内的脉冲数void TIM2_IRQHandler(void); //cnt 计数满,清除
void TIM3_IRQHandler(void);#endif

 encoder.c

#include "encoder.h"G_ENCODER g_ENCODER={0,0,0};/**************************************************************************
*  函数功能:把TIM2初始化为编码器接口模式
*  端口配置: PA_15  ;   PB_3 
*  入口参数:无
*  返 回 值:无
**************************************************************************/
void Encoder_Init_TIM2(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  TIM_ICInitTypeDef TIM_ICInitStructure;  GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器2的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);//使能PA PB端口时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //重映射GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;	//端口配置 PA15GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);					      //根据设定参数初始化GPIOAGPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;	//端口配置 PB3GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure);					      //根据设定参数初始化GPIOBTIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//边沿计数模式 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  //初始化定时器2TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入TIM_ICInitStructure.TIM_ICFilter = 10;  //设置滤波器长度TIM_ICInit(TIM2, &TIM_ICInitStructure);//根据 TIM_ICInitStruct 的参数初始化外设	TIMxTIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能定时器中断TIM_SetCounter(TIM2,0); //计数初值设定TIM_Cmd(TIM2, ENABLE); //使能定时器2
}/**************************************************************************
函数功能:把TIM3初始化为编码器接口模式
端口配置: PA6 PA7
入口参数:无
返回  值:无
**************************************************************************/
void Encoder_Init_TIM3(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  TIM_ICInitTypeDef TIM_ICInitStructure;  GPIO_InitTypeDef GPIO_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能定时器3的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	//端口配置 PA6 PA7GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOA, &GPIO_InitStructure);					      //根据设定参数初始化GPIOATIM_TimeBaseStructInit(&TIM_TimeBaseStructure);TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//边沿计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  //初始化定时器3TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3(TIM_ICPolarity_Rising或者TIM_ICPolarity_Falling效果相同,都是4倍频)TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入TIM_ICInitStructure.TIM_ICFilter = 10;  //设置滤波器长度TIM_ICInit(TIM3, &TIM_ICInitStructure);//根据 TIM_ICInitStruct 的参数初始化外设	TIMxTIM_ClearFlag(TIM3, TIM_FLAG_Update);//清除TIM的更新标志位TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//使能定时器中断TIM_SetCounter(TIM3,0);//计数初值设定TIM_Cmd(TIM3, ENABLE); //使能定时器
}/**************************************************************************
函数功能:单位时间读取编码器A计数
入口参数:无
返回  值:计数值
**************************************************************************/
float Read_EncoderA(void)
{g_ENCODER.encoderA= (short)TIM2 -> CNT; //该寄存器储存了 编码器的位置信息 TIM2->CNT=0;     //读取之后 编码计数--清零--,不清零请注释掉return g_ENCODER.encoderA;
}/**************************************************************************
函数功能:单位时间读取编码器B计数
入口参数:无
返回  值:计数值
**************************************************************************/
float Read_EncoderB(void)
{g_ENCODER.encoderB= (short)TIM3 -> CNT; //该寄存器储存了 编码器的位置信息, TIM3->CNT = 0 ;  //读取之后 编码计数--清零--,不清零请注释掉return g_ENCODER.encoderB;
}/**************************************************************************
*  函数功能:TIM2中断服务函数
*
*  入口参数:无
*
*  返 回 值:无
**************************************************************************/
void TIM2_IRQHandler(void)
{ 		    		  			    if(TIM2->SR& 0X0001)//溢出中断{    				   				     	    	}				   TIM2->SR&=~(1<<0);//清除中断标志位 	    
}/**************************************************************************
*  函数功能:TIM3中断服务函数
*
*  入口参数:无
*
*  返 回 值:无
**************************************************************************/
void TIM3_IRQHandler(void)
{ 		    		  			    if(TIM3->SR&0X0001)//溢出中断{    				   				     	    	}				   TIM3->SR&=~(1<<0);//清除中断标志位 	    
}

pwm_motor.h

#ifndef _pwm_motor_H
#define _pwm_motor_H#include "sys.h"
#include "stdio.h"
#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#include "encoder.h"typedef struct pwm_motor_data
{uint16_t CCR1_Val ;uint16_t CCR2_Val ;uint16_t CCR3_Val ;uint16_t CCR4_Val ;float speedA;float speedB;uint16_t arr  		; //10ms秒读取一次uint16_t psc 		;
}G_PWM_MOTOR;extern G_PWM_MOTOR g_PWM_MOTOR;void Timer_5_pwm_init();
void MOTOR_encoder( uint16_t ccr1,uint16_t ccr2, uint16_t ccr3, uint16_t ccr4);#endif // !1

pwm_motor.c

#include "pwm_motor.h"
#include "sys.h"uint16_t arr_5 = 100; //10ms秒读取一次uint16_t psc_5 = 7200-1;G_PWM_MOTOR g_PWM_MOTOR={ .arr= 100-1,			.psc= 7200-1,	// 占空比配置  有效占比/高电平占比    n/100  %.CCR1_Val=20,   .CCR2_Val=20,.CCR3_Val=20,.CCR4_Val=20
};void Timer_5_pwm_init() //arr :自动重装值   psc :时钟预分频数
{//1) TIM5 时钟使能。RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);// 时钟使能//2) 初始化定时器参数,设置自动重装值, 分频系数,计数方式等。TIM_TimeBaseInitTypeDef Timer_5_initstruct;Timer_5_initstruct.TIM_ClockDivision=TIM_CKD_DIV1;  //时钟分频银子Timer_5_initstruct.TIM_CounterMode=TIM_CounterMode_Up;//计数方式 上下....Timer_5_initstruct.TIM_Period= arr_5;//自动重装载时钟周期Timer_5_initstruct.TIM_Prescaler= psc_5;//时钟分频银子//Timer_5_initstruct.TIM_RepetitionCounterTIM_TimeBaseInit( TIM5 , &Timer_5_initstruct);//3) 设置 TIM5_DIER 允许更新中断。TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);//4) TIM5 中断优先级设置。NVIC_InitTypeDef NVIC_init_struct;NVIC_init_struct.NVIC_IRQChannel= TIM5_IRQn; //中断通道NVIC_init_struct.NVIC_IRQChannelPreemptionPriority=0;  //抢占优先级NVIC_init_struct.NVIC_IRQChannelSubPriority=1; //相应NVIC_init_struct.NVIC_IRQChannelCmd=ENABLE;//使能中断通道NVIC_Init(&NVIC_init_struct); //初始化/*--------------------pwm输出结构体初始化-------------------*/	TIM_OCInitTypeDef  TIM_OCInitStructure;// 配置为PWM模式1TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 输出使能TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;// 输出通道电平极性配置	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//pwm输出通道 1TIM_OCInitStructure.TIM_Pulse = g_PWM_MOTOR.CCR1_Val;TIM_OC1Init(TIM5, &TIM_OCInitStructure);TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);// pwm输出通道 2TIM_OCInitStructure.TIM_Pulse = g_PWM_MOTOR.CCR2_Val;TIM_OC2Init(TIM5, &TIM_OCInitStructure);TIM_OC2PreloadConfig(TIM5, TIM_OCPreload_Enable);// pwm输出通道 3TIM_OCInitStructure.TIM_Pulse = g_PWM_MOTOR.CCR3_Val;TIM_OC3Init(TIM5, &TIM_OCInitStructure);TIM_OC3PreloadConfig(TIM5, TIM_OCPreload_Enable);// pwm输出通道 4TIM_OCInitStructure.TIM_Pulse = g_PWM_MOTOR.CCR4_Val;TIM_OC4Init(TIM5, &TIM_OCInitStructure);TIM_OC4PreloadConfig(TIM5, TIM_OCPreload_Enable);//5) TIM5 的使能 启动。TIM_Cmd(TIM5, ENABLE);//使能相应 计时器
}void MOTOR_encoder( uint16_t ccr1,uint16_t ccr2, uint16_t ccr3, uint16_t ccr4)
{TIM_SetCompare1(TIM5, ccr1);TIM_SetCompare2(TIM5, ccr2);TIM_SetCompare3(TIM5, ccr3);TIM_SetCompare4(TIM5, ccr4);
}void TIM5_IRQHandler(void)
{if(RESET!=TIM_GetITStatus(TIM5, TIM_IT_Update)){TIM_ClearITPendingBit(TIM5,TIM_IT_Update);//触发中断后 重新计时  Read_EncoderA();         //更新编码机 读取到的 10ms内的 脉冲数Read_EncoderB();// g_PWM_MOTOR.speedA =     //知道了 10ms 的脉冲数,可以计算电机转速// g_PWM_MOTOR.speedB =  printf("编码机A脉冲数:%.2f /10ms", g_ENCODER.coderA);printf("编码机B脉冲数:%.2f /10ms", g_ENCODER.coderB);}
}

main.c

 
#include "usart.h"
#include "delay.h"
#include "lcd.h"
#include "led.h"
#include "key.h"
#include "encoder.h"
#include "pwm_motor.h"void init____(void)
{delay_init();	LED_Init(); 	KEY_Init();   LCD_Init();   uart_init(115200);Timer_5_pwm_init(); //电机pwm发生源初始化Encoder_Init_TIM2(); Encoder_Init_TIM3();
}	int main(void)
{//编码器数值的读取 以及串口打印 //在 pwm_motor.c文件内的 TIM5中断函数u8 key_value = 0xff;while(1){key_value=KEY_Scan(0);switch(  key_value  ){case KEY0_PRES:  g_PWM_MOTOR.CCR1_Val-=20 ; break;  //这里 只控制 TIM5 的 通道一输出的 pwm波 占空比 用作测试case KEY1_PRES:	 g_PWM_MOTOR.CCR1_Val+=20 ;	break;	case WKUP_PRES:  g_PWM_MOTOR.CCR1_Val =100  ; break;default : break;}if( g_PWM_MOTOR.CCR1_Val > 100 || g_PWM_MOTOR.CCR1_Val <0){g_PWM_MOTOR.CCR1_Val = 0 ;}}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部