学习目标
学习STM32的外部中断。STM32的每个 IO 口都可以作为外部中断的中断输入口。本次内容需要我们掌握外设、EXTI、NVIC之间的关系。
一、任务要求
(1)通过对传感器的设计,在OLED 屏幕上实现计数操作。
(2)通过旋转编码器实现OLED屏上的数字加减。
二、传感器计数
1.主函数main
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "CountSensor.h"
int main(void)
{
OLED_Init();
CountSensor_Init();
OLED_ShowString(1, 3, "HelloWorld!");
OLED_ShowString(2, 1, "Count:");
while (1)
{
OLED_ShowNum(2, 7, Count_Get(), 5);
}
}
2.函数封装CountSensor
//CountSensor.c
#include "stm32f10x.h" // Device header
uint16_t Count = 0;
void CountSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIO时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO时钟。
//(1)设定GPIO模式
GPIO_InitTypeDef GPIO_InitStuct;
GPIO_InitStuct.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_InitStuct.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStuct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStuct);
//(2)设定EXTI触发条件
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14); //设置IO口与中断线的映射关系
EXTI_InitTypeDef EXTI_InitStuct;
EXTI_InitStuct.EXTI_Line = EXTI_Line14; //指定要配置的中断线
EXTI_InitStuct.EXTI_LineCmd = ENABLE; //使能 OR失能
EXTI_InitStuct.EXTI_Mode = EXTI_Mode_Interrupt; //模式:事件 OR中断
EXTI_InitStuct.EXTI_Trigger = EXTI_Trigger_Falling; //触发方式:上升沿/下降沿/双沿触发
EXTI_Init(&EXTI_InitStuct); //初始化中断线:触发方式等
//(3)配置中断优先级(NVIC)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置 NVIC 优先级组
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn; //配置中断源
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能中断通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //配置抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //配置子优先级
NVIC_Init(&NVIC_InitStruct);
}
//(4)编写中断服务函数。
void EXTI15_10_IRQHandler()
{
if (EXTI_GetITStatus(EXTI_Line14) ==SET){ //判断中断线中断状态是否发生
Count++;
}
EXTI_ClearITPendingBit(EXTI_Line14); //清除中断线上的中断标志位
}
uint16_t Count_Get(void)
{
return Count;
}
//CountSensor.h
#ifndef _COUNT_SENSOR_H
#define _COUNT_SENSOR_H
uint16_t Count_Get(void);
void CountSensor_Init(void);
#endif
三、旋转编码器
1.主函数main
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "OLED.h"
#include "counter.h"
int16_t Num;
int main(void)
{
OLED_Init();
counter_Init();
OLED_ShowString(1, 1, "Num:");
while (1)
{
Num += Get_counter();
OLED_ShowSignedNum(2,5,Num,5);
}
}
2.函数封装counter
#include "stm32f10x.h" // Device header
void counter_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource12);
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line11;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStruct);
EXTI_InitTypeDef EXTI_InitStruct1;
EXTI_InitStruct1.EXTI_Line = EXTI_Line12;
EXTI_InitStruct1.EXTI_LineCmd = ENABLE;
EXTI_InitStruct1.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct1.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStruct1);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
}
int16_t counter;
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line11) == SET){
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0){
counter ++;
}
EXTI_ClearITPendingBit(EXTI_Line11);
}
if (EXTI_GetITStatus(EXTI_Line12) == SET){
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0){
counter --;
}
EXTI_ClearITPendingBit(EXTI_Line12);
}
}
int16_t Get_counter(void) //返回变化值
{
int16_t temp;
temp = counter;
counter = 0;
return temp;
}
四、OLED封装函数
温馨提示:OLED的函数封装代码可以私信找我拿(免费)!