接线图如下:
顺时针旋转count++,反之count--。(这个可以自己在中断函数自己定义count的变化)
旋转编码计次Encode.c和Encode.h 文件
进行STM32外部中断的步骤如下:
1. /第一步配置RCC 把涉及的外设的时钟打开 EXTI 和NVIC(内核)两个不需要开启时钟 GPIOB和AFIO需要开启时钟 打开时钟
2.配置GPIO 选择我们的端口为输入模式 我连接是是B0和B1接口分别接旋转编码器的A和B
3.配置APIO外部中断引脚选择 来选择我们要中断的引脚 中断的引脚 也分别是B0和B1
4.配置EXTI 选择边沿触发方式
5.配置NVIC 给中断选择合适的优先级 并且对两个通道分别设置优先级
下面是Encode.c的代码与注释:
#include "stm32f10x.h" // Device header
int16_t cnt;
void Encode_Init(void)
{
//打开时钟
//第一步配置RCC 把涉及的外设的时钟打开 EXTI NVIC(内核)两个不需要开启时钟 GPIOB和AFIO需要开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO ,ENABLE);//AFIO的时钟
//第二步 配置GPIO 选择我们的端口为输入模式
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//对于外部中断来说 要选择浮空输入、上拉输入或者下拉输入去其中一种
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 |GPIO_Pin_1 ;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//第三步 配置APIO外部中断引脚选择 来选择我们要中断的引脚
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);//这个函数可以配置AFIO的数据选择器
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);
//第四步 配置EXTI 选择边沿触发方式 触发响应方式
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line0 | EXTI_Line1 ;//指定我们要配置的中断线
EXTI_InitStructure.EXTI_LineCmd=ENABLE;//指定选择的中断线的新状态
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//指定外部中断线的模式 选中断模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//指定触发信号的有效边沿 下降沿触发
EXTI_Init(&EXTI_InitStructure);
//第五步配置NVIC 给中断选择合适的优先级 对两个通道分别设置优先级
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置优先级分组 2个抢占2个响应
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;//指定中断通道来开启或关闭 我们用的是STM32F10X_MD的15_10
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//指定的通道是使能还是失能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//设置抢占优先级 2组的取值是0-3
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//设置响应优先级 2组的取值是0-3
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;//指定中断通道来开启或关闭 我们用的是STM32F10X_MD的15_10
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//指定的通道是使能还是失能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//设置抢占优先级 2组的取值是0-3
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;//设置响应优先级 2组的取值是0-3
NVIC_Init(&NVIC_InitStructure);
}
int16_t getcnt(void)//返回cnt的变化值 用于外部加减变量
{
int16_t lsbl;
lsbl=cnt;
cnt=0;
return lsbl;
}
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)==SET)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0)//判断另外一个引脚的电频 正反可以自己设置 我这里设置的是都是1 就是反转
{
cnt--;//正反可以自己定义
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1)==SET)
{
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0)
{
cnt++;
}
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
Encode.h代码如下:
#ifndef _ENCODE_H
#define _ENCODE_H
void Encode_Init(void);
int16_t getcnt(void);
#endif
主函数代码如下:
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "Encode.h"
int16_t SSum;
int main(void)
{
Encode_Init();
/*模块初始化*/
OLED_Init(); //OLED初始化
//CountSensor_Init();
/*OLED显示*/
OLED_ShowChar(1, 1, 'A'); //1行1列显示字符A
OLED_ShowString(2, 1, "Count:");
while (1)
{
SSum+=getcnt();
OLED_ShowSignedNum(3,1,SSum,5);
}
}