原理部分按照下面这个链接理解即可y小白跟做江科大32单片机之对射式红外传感器计次-CSDN博客https://blog.csdn.net/weixin_58051657/article/details/139350487https://blog.csdn.net/weixin_58051657/article/details/139350487
实验过程
1.按照江科大老师给的电路图进行连接
2.rev.h代码
#ifndef _REV__H
#define _REV__H
void xuanzhuan_Init(void);
int16_t turn(void);
#endif
3.rev.c代码
#include "stm32f10x.h"
int16_t rev_Count;
void xuanzhuan_Init(void)
{
//使用各个外设前必须开启时钟,否则对外设的操作无效
//中断只需开始B口和AFIO即可,EXTI和NVIC无需开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //GPIO模式,赋值为上拉输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //GPIO引脚,赋值为第1,2号引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO速度,赋值为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //将赋值后的构体变量传递给GPIO_Init函数
//函数内部会自动根据结构体的参数配置相应寄存器
//实现GPIOB的初始化
/*AFIO选择中断引脚*/
//将外部中断的0号线映射到GPIOB,即选择PB0为外部中断引脚
//将外部中断的1号线映射到GPIOB,即选择PB1为外部中断引脚
//AFIO这个函数在GPIO那个里面
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
/*EXTI初始化*/
//这个在library中找一下
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line=EXTI_Line0|EXTI_Line1; //选择哪个口
EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt; //中断
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling; //这个需要搜索一下EXTI_Trigger,现在是上升沿触发
EXTI_InitStruct.EXTI_LineCmd=ENABLE; //中断打开
EXTI_Init(&EXTI_InitStruct);
//NVIC在初始化之前需要指定中断优先级分组
/*NVIC中断分组*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*NVIC初始化*/
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn; //选择配置NVIC的EXTI0线,因为那个0线过来的
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; //这个是自己给的,值越低优先级越高
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel=EXTI1_IRQn; //选择配置NVIC的EXTI1线,因为那个0线过来的
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1; //这个是自己给的,值越低优先级越高
NVIC_InitStruct.NVIC_IRQChannelSubPriority=2; //次优先级低一点
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
int16_t turn(void)
{
int16_t temp;
temp=rev_Count;
rev_Count=0;
return temp;
}
//中断函数不需要声明
//这里还没有弄懂
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)==SET) //判断是否是外部中断14号线触发的中断
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0) //PB0的下降沿触发中断,此时检测另一相PB1的电平,目的是判断旋转方向
{
rev_Count--; //此方向定义为反转,计数变量自减
}
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除外部中断14号线的中断标志位
//中断标志位必须清除
//否则中断将连续不断地触发,导致主程序卡死
}
}
void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1)==SET) //判断是否是外部中断14号线触发的中断
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0) //PB0的下降沿触发中断,此时检测另一相PB1的电平,目的是判断旋转方向
{
rev_Count++; //此方向定义为反转,计数变量自减
}
}
EXTI_ClearITPendingBit(EXTI_Line1); //清除外部中断14号线的中断标志位
//中断标志位必须清除
//否则中断将连续不断地触发,导致主程序卡死
}
}
4.main.c代码
#include "stm32f10x.h" // Device header
#include "OLED.h"
#include "rev.h"
int16_t num;
int main()
{
OLED_Init();
xuanzhuan_Init();
OLED_ShowString(1, 2, "zhuan:");
while (1)
{
num+=turn();
OLED_ShowNum(2, 2,num, 5);
}
}
5.试验结果
STM32旋转编码器计次试验结果