1.使用外部中断 读取
#include "spin.h"
#define encoder_port GPIOG
#define encoder_pin (GPIO_Pin_3|GPIO_Pin_5)
#define encoder_pin_A GPIO_Pin_3 //外部中断引脚
#define encoder_pin_B GPIO_Pin_5
void Encoder_Init_Exit()
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //选择触发的通道 EXTI3_IRQn 与 PG3 EXTI_Line3 一致
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级
NVIC_Init(&NVIC_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;// GPIO_Mode_IPU; //配置为上拉模式
GPIO_InitStructure.GPIO_Pin = encoder_pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(encoder_port, &GPIO_InitStructure);
// GPIO_PinRemaConfig() 可以用来引脚重映射
GPIO_EXTILineConfig(GPIO_PortSourceGPIOG, GPIO_PinSource3); //配置AFIO的数据选择器,来选择我们要的引脚,指定外部中断线
EXTI_InitStructure.EXTI_Line = EXTI_Line3; //需要我们配置中断线,我们用PG3所在的 EXTI_Line3
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //开启中断
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //设置触发方式 下降沿触发
EXTI_Init(&EXTI_InitStructure); //调用这个参数,就可以根据这个结构体
}
void EXTI3_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line3) == SET) //确认是 EXTI_Line3引发的中断
{ // encoder_pin_A 设置了外部中断,下降沿触发
delay_ms(1); //很重要,必不可少, 软件滤波
if (0 == GPIO_ReadInputDataBit(encoder_port, encoder_pin_A)) //判断 encoder_pin_A是低电平, 经历了下降沿
{
if (1 == GPIO_ReadInputDataBit(encoder_port, encoder_pin_B)) //判断 encoder_pin_B 电平状态,
{
++encoder_g.counter;
encoder_g.dir= 10; //正转标志
}
else
{
--encoder_g.counter;
encoder_g.dir = 20; //反转标志
}
printf("count %d\n", Encoder_Readnum_Exit(0));
printf("dir %d\n", Encoder_ReadDir_Exit());
}
EXTI_ClearITPendingBit(EXTI_Line3); //手动清除外部中断标志位
}
}
/**
* @brief 正转返回1 反转返回-1 静止返回0
*
*/
int Encoder_ReadDir_Exit(void)
{
if( 10 == encoder_g.dir ){
encoder_g.dir= 0;
return 1;
}
else if (20 == encoder_g.dir ){
encoder_g.dir = 0;
return -1;
}
else{
encoder_g.dir = 0;
return 0;
}
}
/**
* @brief flag=0 读数cnt不清零 flag=0 读数cnt清零
*
*/
int Encoder_Readnum_Exit(u8 flag)
{
int result = encoder_g.counter;
if (flag){
encoder_g.counter = 0;
}
return result;
}
#ifndef _SPIN_H
#define _SPIN_H
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "delay.h"
#include "usart.h"
typedef struct E_g{
int counter; //计数
u8 dir; //旋转方向 正为+ 反为- 静为 0
u8 sw; //按键状态 按下置1
}Encoder_g;
static Encoder_g encoder_g={
.counter=0,
.dir=0,
.sw=0
};
void Encoder_Init_Exit();
int Encoder_Readnum_Exit(u8 flag);
int Encoder_ReadDir_Exit(void);
#endif
2.定时器作编码电机模式读取
#include "encoder.h"
/**************************************************************************
函数功能:单位时间读取编码器B计数
入口参数:无
返回 值:计数值
**************************************************************************/
int Read_Encoder(TIM_TypeDef *TIMx)
{
return (short)TIMx->CNT;
}
/**************************************************************************
函数功能:把TIM初始化为编码器接口模式
端口配置: PB6 PB7
入口参数:无
返回 值:无
**************************************************************************/
void Encoder_Init_TIMx(TIM_TypeDef* TIMx )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
// NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级3
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级3
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // IRQ通道使能
// NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
/*----------------------------不同定时器 修改这里 以及中断函数配置--------------------------------*/
// GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //重映射配置 引脚冲突时配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
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); //初始化PB端口
TIM_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(TIMx, &TIM_TimeBaseStructure); //初始化定时器3
TIM_EncoderInterfaceConfig(TIMx, 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(TIMx, &TIM_ICInitStructure); //根据 TIM_ICInitStruct 的参数初始化外设 TIMx
TIM_ClearFlag(TIMx, TIM_FLAG_Update); //清除TIM的更新标志位
TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE); //使能定时器中断
TIM_SetCounter(TIMx, 0); //计数初值设定
TIM_Cmd(TIMx, ENABLE); //使能定时器
}
/**************************************************************************
* 函数功能:TIM中断服务函数
*
* 功能:防止定时器cnt计数溢出
*
* 入口参数:无
*
* 返 回 值:无
**************************************************************************/
// void TIM3_IRQHandler(void)
// {
// if (_TIM3_->SR & 0X0001) //溢出中断
// {
// }
// _TIM3_->SR &= ~(1 << 0); //清除中断标志位
// }
#ifndef _encoder_H_
#define _encoder_H_
#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_gpio.h"
#define ENCODER_TIM_PERIOD (u16)(65535)
typedef struct bianmadianji
{
int coder;
u8 mode;
}G_ENCODER;
static G_ENCODER g_ENCODER={0,0};
void Encoder_Init_TIMx(TIM_TypeDef* TIMx);
int Read_Encoder(TIM_TypeDef* TIMx);
#endif