STM32学习笔记(十三) - 库函数 使用OLED屏显示 旋转编码器和对射式红外传感器

//江科大stm32教程

关于EXTI知识,查看我上一篇学习笔记

 STM32学习笔记(十二)- EXTI外部中断

1.旋转编码器

1.旋转编码器简介

1.旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向

2.类型:机械触点式/霍尔传感器式/光栅式

2.硬件电路

这里使用A相接PB0  B相接PB1  (注意引脚号要不一样)

当A相是下降沿,B相是低电平为反转; 当B相是下降沿, A相是低电平是高电平;当然,这个你可以自己在Encoder文件配置,只要符合要求;判断编码器方向在网上已有很多文章

3.接线图

4.工程

1.在Hardware新建Encoder.c和Encoder.h文件

2.Encoder.c全部代码

常规操作:开启时钟,初始化GPIO,配置AFIO,配置EXTI,配置NVIC 

 

获取旋转次数:封装函数,用一个变量Encoder_Count(stm32函数),清除Encoder_Count

 

#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;

void Encoder_Init(void)
{
	//开启GPIO时钟和AFIO时钟 EXIT和NVIC的时钟是一直打开的
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	//配置GPIO
	GPIO_InitTypeDef GPIO_InitStruture;
	GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;		//可以在用户手册查看需要配置的模式
	GPIO_InitStruture.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruture);
	
	//配置AFIO
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_Pin_0);	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_Pin_1);
	
	//配置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);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;	//指定中断通道来开启或关闭 中等密度MD
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//指定NVIC状态
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//指定所选通道的抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			//指定所选通道的响应优先级
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;	//指定中断通道来开启或关闭 中等密度MD
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//指定NVIC状态
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//指定所选通道的抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;			//指定所选通道的响应优先级
	NVIC_Init(&NVIC_InitStructure);
	
}

int16_t Encoder_Get(void)
{
	int16_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}

void EXTI1_IRQHandler(void)
{
	//判断B相是否为下降沿
	if (EXTI_GetITStatus(EXTI_Line1) == SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			//判断A相是否为低电平, 如果是为正转
			if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
			{
				Encoder_Count++;
			}
		}
		//调用清除中断标志位函数
		EXTI_ClearITPendingBit(EXTI_Line1);
	}
}

void EXTI0_IRQHandler(void)
{
	//判断A相是否为下降沿
	if (EXTI_GetITStatus(EXTI_Line0) == SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
		{
			//判断B相是否为低电平,如果是则为反转
			if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
			{
				Encoder_Count--;
			}
		}
		//调用清除中断标志位函数
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}



3.Encoder.h全部代码

#ifndef _ENCODER_H
#define _ENCODER_H

int16_t Encoder_Get(void);
void EXTI0_IRQHandler(void);
void EXTI1_IRQHandler(void);
void Encoder_Init(void);

#endif

4. mian. c 全部代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"

int16_t Num;

int main(void)
{
	OLED_Init();
	Encoder_Init();
	
	OLED_ShowString(1, 1, "Num:");
	
	while(1)
	{
		Num += Encoder_Get();
		OLED_ShowSignedNum(1, 5, Num, 5);
	}
}

不知道为什么无法识别到反转的次数,只能识别正转的,如果有人知道的话劳烦指正

我后面会出一个调试的教程

1. 对射式红外传感器

1.对射式红外传感器的内容我在 STM32学习笔记(十)- 库函数 光敏传感器控制蜂鸣器 已经讲过了

 

 

2.对射式红外传感器 的DO连接开发板的PB14, OLED SCL接PB8, SDA接PB9

 

3.复制  STM32学习笔记(十一)- 库函数 驱动OLED  的文件

链接:https://pan.baidu.com/s/1qpF13BmCOtzoATwQ6xNFeg?pwd=q2f8 
提取码:q2f8

 

4.添加CountSensor.c 和 CountSensor.h文件

 

5.工程       

1. EXTI配置流程

1.打开RCC, 外设才能正常工作

2.配置GPIO, 选择引脚为输入模式

3.配置AFIO, 选择所用GPIO通路,连接后面的EXIT

4.配置EXTI, 选择边沿触发方式, 选择触发响应方式(中断响应/事件响应)

5. 配置NVIC, 选择合适的中断优先级

2. 相关函数

1. 配置输出模式

2.相关gpio.h函数

//复位AFIO外设
void GPIO_AFIODeInit(void);

//锁定GPIO配置
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

//配置AFIO的事件输出功能
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
void GPIO_EventOutputCmd(FunctionalState NewState);

//引脚重映射 重映射的方式和新的状态
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

//配置AFIO的数据选择器,来选择需要的中断引脚
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);

3. exti.h函数

//把exti的配置全部清除,恢复为上电默认状态
void EXTI_DeInit(void);

//结构体参数配置EXIT外设
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

//把参数传递的结构体变量赋一个默认值
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);

//软件触发中断
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);

//在主程序 获取指定的标志位是否被置1
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);

//在主程序 对置1的标志位清除
void EXTI_ClearFlag(uint32_t EXTI_Line);

//在中断函数 获取中断标志位是否被置1
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);

//在中断函数 清除中断挂起标志位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

4. NVIC的函数在mis. h文件

//用来中断分组,参数是中断分组的方式
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

//根据结构体里面的参数初始化NVIC
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

//设置中断向量表
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);

//系统低功耗配置
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);

3.代码部分

1.CountSensor.c 

#include "stm32f10x.h"                  // Device header

//用一个数字来统计中断触发的次数
uint16_t CountSensor_Count;

//初始化
void CountSensor_Init(void)
{
	//开启GPIO时钟和AFIO时钟 EXIT和NVIC的时钟是一直打开的
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	//配置GPIO
	GPIO_InitTypeDef GPIO_InitStruture;
	GPIO_InitStruture.GPIO_Mode = GPIO_Mode_IPU;		//可以在用户手册查看需要配置的模式
	GPIO_InitStruture.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruture);
	
	//配置AFIO
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);	//我用的是PB14
	
	//配置EXTI
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;	//指定要配置的中断线
	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);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;	//指定中断通道来开启或关闭 中等密度MD,14在EXTI15_10
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//指定NVIC状态
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	//指定所选通道的抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			//指定所选通道的响应优先级
	NVIC_Init(&NVIC_InitStructure);
	
}

//返回中断次数
uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}

//中断函数,名字固定了,在启动文件找
void EXTI15_10_IRQHandler(void)
{
	//中断标志位的判断, 判断14通道是否为1
	if (EXTI_GetITStatus(EXTI_Line14) == SET)
	{
		CountSensor_Count++;
		//调用清除中断标志位函数
		EXTI_ClearITPendingBit(EXTI_Line14);
		
	}
	
}

2.CountSensor.h

#ifndef _COUNT_SENSOR_H 
#define _COUNT_SENSOR_H

void CountSensor_Init(void);
uint16_t CountSensor_Get(void);
//void EXTI15_10_IRQHandler(void); 中断函数不需要调用,自动执行

#endif

3. main.c

       

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"

int main(void)
{
	OLED_Init();
	CountSensor_Init();
	
	OLED_ShowString(1,1,"COunt:");
	
	while(1)
	{
		OLED_ShowNum(1, 7, CountSensor_Get(), 5);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值