电机系列
二、读取编码器数值实现电机测速
2 、配置编码器;
encoder.h
#ifndef __ENCODER_H
#define __ENCODER_H
#include <sys.h>
#include "stm32f10x_tim.h"
/**************************************************************************
作者:chance
**************************************************************************/
#define ENCODER_TIM_PERIOD (u16)(65535) //不可大于65535 因为F103的定时器是16位的。
//小车;
void Encoder_Init_TIM2(u16 arr,u16 psc);
void Encoder_Init_TIM3(u16 arr,u16 psc);
void Encoder_Init_TIM4(u16 arr,u16 psc);
void Encoder_Init_TIM5(u16 arr,u16 psc);
void TIM7_Int_Init(u16 arr,u16 psc);
//单个读取
int Read_Encoder_TIM2(void);
int Read_Encoder_TIM3(void);
int Read_Encoder_TIM4(void);
int Read_Encoder_TIM5(void);
//整合后
int Read_Encoder_test(TIM_TypeDef * TIMx);
void Get_Motor_Speed(int *A_Speed,int *B_Speed,int *C_Speed,int *D_Speed);
#endif
encoder.c
#include "encoder.h"
#include "stm32f10x_gpio.h"
/**************************************************************************
Author:chance
功能:配置定时器为编码器模式,并实现读取数值;
操作:转动电机轮子一圈,就可以得到相应的脉冲个数;用于最后测速;代码上传到下载区;
**************************************************************************/
int Encoder_A,Encoder_B,Encoder_C,Encoder_D; //编码器的脉冲计数
void Encoder_Init_TIM2(u16 arr,u16 psc)
{
//1) 定义相关结构体:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//2) 使能相关时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// 需要使能AFIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口时钟
GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE); //禁止JTAG功能,把PB3,PB4作为普通IO口使用
//3) 初始化 GPIO:(用于AB相,脉冲计数)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB
//4) 设置并初始化定时器 TIM2:
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频器
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
//5) 设置并初始化定时器编码器:
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
//Reset counter
TIM_SetCounter(TIM2,0);
//6) 使能定时器:
TIM_Cmd(TIM2, ENABLE);
}
/**************************************************************************
函数功能:把TIM3初始化为编码器接口模式
入口参数:无
返回 值:无
**************************************************************************/
void Encoder_Init_TIM3(u16 arr,u16 psc)
{
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);//使能PB端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频器
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_ClearFlag(TIM3, TIM_FLAG_Update);//清除TIM的更新标志位
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_SetCounter(TIM3,0);
TIM_Cmd(TIM3, ENABLE);
}
void Encoder_Init_TIM4(u16 arr,u16 psc)
{
//1) 定义相关结构体:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//2) 使能相关时钟:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能定时器4的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口时钟
//3) 初始化 GPIO:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB
//4) 设置并初始化定时器 TIM4
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频器
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
//5) 设置并初始化定时器编码器:
TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式 3:CH1、CH2 同时计数,四分频
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM4, &TIM_ICInitStructure);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);//清除TIM的更新标志位
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
//Reset counter
TIM_SetCounter(TIM4,0);
//6) 使能定时器:
TIM_Cmd(TIM4, ENABLE);
}
void Encoder_Init_TIM5(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);//使能定时器5的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = psc; // 预分频器
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
TIM_EncoderInterfaceConfig(TIM5, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM5, &TIM_ICInitStructure);
TIM_ClearFlag(TIM5, TIM_FLAG_Update);//清除TIM的更新标志位
TIM_ITConfig(TIM5, TIM_IT_Update, ENABLE);
TIM_SetCounter(TIM5,0);
TIM_Cmd(TIM5, ENABLE);
}
/**************************************************************************
函数功能:读取编码器计数
入口参数:定时器
返回 值:速度值
**************************************************************************/
int Read_Encoder_TIM2(void)
{
int Encoder_TIM;
Encoder_TIM= TIM2 -> CNT;
if(Encoder_TIM>0xefff)Encoder_TIM=Encoder_TIM-0xffff; //转化计数值为有方向的值,大于 0 正转,小于 0 反转。
//TIM4->CNT 范围为0-0xffff,初值为 0。
//TIM2->CNT=0; //读取完后计数清零
return Encoder_TIM; //返回值
}
int Read_Encoder_TIM3(void)
{
int Encoder_TIM;
Encoder_TIM= TIM3 -> CNT;
if(Encoder_TIM>0xefff)Encoder_TIM=Encoder_TIM-0xffff; //转化计数值为有方向的值,大于 0 正转,小于 0 反转。
//TIM4->CNT 范围为0-0xffff,初值为 0。
//TIM3->CNT=0; //读取完后计数清零
return Encoder_TIM; //返回值
}
int Read_Encoder_TIM4(void)
{
int Encoder_TIM;
Encoder_TIM= TIM4 -> CNT;
if(Encoder_TIM>0xefff)Encoder_TIM=Encoder_TIM-0xffff; //转化计数值为有方向的值,大于 0 正转,小于 0 反转。
//TIM4->CNT 范围为0-0xffff,初值为 0。
//TIM4->CNT=0; //读取完后计数清零
return Encoder_TIM; //返回值
}
int Read_Encoder_TIM5(void)
{
int Encoder_TIM;
Encoder_TIM= TIM5 -> CNT;
if(Encoder_TIM>0xefff)Encoder_TIM=Encoder_TIM-0xffff; //转化计数值为有方向的值,大于 0 正转,小于 0 反转。
//TIM4->CNT 范围为0-0xffff,初值为 0。
//TIM5->CNT=0; //读取完后计数清零
return Encoder_TIM; //返回值
}
main.c
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "motor.h"
#include "control.h"
#include "usart.h"
#include "encoder.h"
#include "stdio.h"
#include "timer.h"
int ASpeedNow = 0;
int BSpeedNow = 0;
int CSpeedNow = 0;
int DSpeedNow = 0;
int main(void)
{
delay_init(); //=====延时函数初始化
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
MY_NVIC_PriorityGroupConfig(2); //=====设置中断分组
LED_Init(); //=====初始化与 LED 连接的硬件接口
MiniBalance_PWM_Init(7199,0);
//Set_Pwm(1000,1000,1000,1000); //驱动电机
USART3_Init(9600);
Encoder_Init_TIM2(0xffff,0); //=====编码器接口
Encoder_Init_TIM3(0xffff,0); //=====编码器接口
Encoder_Init_TIM4(0xffff,0); //=====编码器接口
Encoder_Init_TIM5(0xffff,0); //=====初始化编码器
//TIM7_Int_Init(5000-1,7200-1);
while(1)
{
Led_Flash(30);
//Set_Pwm(3000,2000,1000,1000);
printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
//delay_ms(150);
// printf("encoder222=%d\r\n",Read_Encoder_test(TIM2));
// printf("encoder333=%d\r\n",Read_Encoder_test(TIM3));
// printf("encoder444=%d\r\n",Read_Encoder_test(TIM4));
// printf("encoder555=%d\r\n",Read_Encoder_test(TIM5));
printf("encoder222=%d\r\n",Read_Encoder_TIM2());
printf("encoder333=%d\r\n",Read_Encoder_TIM3());
printf("encoder444=%d\r\n",Read_Encoder_TIM4());
printf("encoder555=%d\r\n",Read_Encoder_TIM5());
printf("A=%d,B=%d,C=%d,D=%d\r\n",ASpeedNow,BSpeedNow,CSpeedNow,DSpeedNow);
printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n");
delay_ms(100); //=====延时
}
}
3、测速;
实现速度输出;