本文主要介绍了通过中断来实现开关控制LED灯的亮和灭。
软件:Keil μVision
芯片:STM32F103C8T6


文章目录

  • 一、实验简介
  • 二、实验原理
    • 1. NVIC简介
    • 2.EXTI简介
  • 三、实验代码
    • 1.库函数方式
    • 2.HAL函数方式
  • 四、实验结果
  • 五、总结
  • 六、参考文献

一、实验简介

本次实验通过B1端口的开关控制A1端口的LED灯,即B1端口接高电平时LED亮,B1端口接低电平时LED灭。实验电路图比较简单,这里就不做展示。

二、实验原理

本次实验主要使用了中断、GPIO输入和输出模式来进行实验。

CM3内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级可编程中断设置。STM32并没有CM3的全部中断服务。STM32有84个中断,包括16个内核中断和68个可屏蔽中断,具有16级可编程的中断优先级(STM32F103系列有60个可屏蔽中断)。在STM32中文参考手册第9章,第130页,比较详细的介绍了STM32的中断事件。

对于这么多中断,如何管理?通过寄存器对STM32中断进行分组,再对每个中断设置一个抢占优先级和一个响应优先级。在STM32固件库使用手册第165页中有分组情况。具体可以在B站观看相关视频。

1. NVIC简介

所以我们需要设置中断分组,比如我们设置中断分组为2

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

还需要初始化NVIC,配置相关参数

NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00;
NVIC_Init(&NVIC_InitStructure);

这里设置中断为EXTI1中断(下一小节介绍),然后使能,设置抢占优先级和响应优先级。其中IRQChannel的值可以在stm32f10x.h中找到,也可以在STM32固件库使用手册第166也查到。下面是部分表

2.EXTI简介

通用I/O端口以下图的方式连接到16个外部中断/事件线上:(STM32中文参考手册第137页)

和之前类似,首先初始化EXTI。

EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);
EXTI_InitStructure.EXTI_Line=EXTI_Line1;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising_Falling;
EXTI_Init(&EXTI_InitStructure);

EXTI_Line的值和GPIOX端口类似,参考上面图片,EXTI_Line的值如下

EXTI_LineCmd的值设置为ENABLE,使能,模式(EXTI_Mode)设置为中断(Interrupt),触发方式(EXTI_Trigger)选择为上下沿触发,最后调用初始化函数EXTI_Init(&EXTI_InitStructure)

然后是写中断函数,在启动文件中,已经写了中断函数的引用

中断函数如下:

void EXTI1_IRQHandler(void)
{delay_ms(10);//消除抖动if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==1){GPIO_ResetBits(GPIOA,GPIO_Pin_1);}else{GPIO_SetBits(GPIOA,GPIO_Pin_1);}EXTI_ClearITPendingBit(EXTI_Line1);
}

最后一定要清除中断位,用EXTI_ClearPendingBit(EXTI_LineX)函数

当B1端口是高电平时,A1端口是低电平,LED灯亮;当A1端口是低电平时,A1端口是高电平,LED灯灭。

有关LED灯和按键的代码这里不做讲解,可以在我之前博客STM32F103点亮LED流水灯_江南烟浓雨的博客-CSDN博客中查看原理

三、实验代码

1.库函数方式

创建工程后,新建四个文件夹,分别为DELAY、EXTI、KEY、LED,分别对应四个C文件和四个头文件,代码如下

delay.h

#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f10x.h"
void DELAY_Init(void);
void delay_ms(u16 nms);
#endif

delay.c

#include "delay.h"
static u16 fac_ms = 0;
void DELAY_Init()
{SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);fac_ms = (u16)(SystemCoreClock/8000);
}void delay_ms(u16 nms)
{                 u32 temp;        SysTick->LOAD=(u32)nms*fac_ms;               //时间加载(SysTick->LOAD为24bit)SysTick->VAL =0x00;                           //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数  do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));       //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器SysTick->VAL =0X00;                          //清空计数器
}

exti.h

#ifndef __EXTI_H
#define __EXTI_H
#include "stm32f10x.h"
#include "delay.h"
#include "key.h"
void EXTIX_Init(void);
#endif

exti.c

#include "exti.h"
void EXTIX_Init(void)
{EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);KEY_Init();//GPIOB.1中断线初始化配置GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);EXTI_InitStructure.EXTI_Line=EXTI_Line1;EXTI_InitStructure.EXTI_LineCmd=ENABLE;EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising_Falling;EXTI_Init(&EXTI_InitStructure);NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00;NVIC_Init(&NVIC_InitStructure);
}void EXTI1_IRQHandler(void)
{delay_ms(10);//消除抖动if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==1){GPIO_ResetBits(GPIOA,GPIO_Pin_1);}else{GPIO_SetBits(GPIOA,GPIO_Pin_1);}EXTI_ClearITPendingBit(EXTI_Line1);
}

key.h

#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
void KEY_Init(void);
u8 KEY_Scan(void);
#endif

key.c

#include "key.h"
void KEY_Init(void)
{/* 定义一个GPIO_InitTypeDef类型的结构体 */GPIO_InitTypeDef GPIO_InitStructure;/* 设置时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);/* 将B1端口GPIO_Mode和GPIO_Speed设置为下拉输入模式 */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_Init(GPIOB,&GPIO_InitStructure);
}

led.h

#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
#include "key.h"
void LED_Init(void);
#endif

led.c

#include "led.h"
void LED_Init(void)
{/* 定义一个GPIO_InitTypeDef类型的结构体 */GPIO_InitTypeDef GPIO_InitStructure;/* 设置时钟 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/* 将A1端口GPIO_Mode和GPIO_Speed设置为PP模式和50MHz */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==1){GPIO_ResetBits(GPIOA,GPIO_Pin_1);}else{GPIO_SetBits(GPIOA,GPIO_Pin_1);}
}

main.c

#include "stm32f10x.h"
#include "delay.h"
#include "exti.h"
#include "key.h"
#include "led.h"
int main(void)
{   DELAY_Init();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);EXTIX_Init();LED_Init();while(1){}
}

2.HAL函数方式

我们使用STM32CubeMX来生成代码,和上次的实验类似,需要GPIO口的设置类似。需要注意的是,需要设置PB1口位EXTI1。

GPIO口设置位上下沿触发中断

注意:NVIC中System tick timer需要设置优先级高于EXTI

EXTI中断可以比较随便的设置,这里设置为2和0

其他方面可以参考STM32CubeMX的安装与简单应用_江南烟脓雨的博客-CSDN博客

代码修改如下:

if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==1)
{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
}
else
{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
}

这里我们希望刚通电时(初始状态)灯的亮灭和开关状态保持一致

接下来修改stm32f1xx_hal_gpio.c中的中断函数

HAL_Delay(10);
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==1)
{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
}
else
{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
}

添加中断函数内容,如下图所示

四、实验结果

五、总结

本次实验初步实现了中断函数,因为实验比较简单,所以没有设计复杂的函数。对于中断函数的学习可以参考stm32中文手册和库函数手册,或通过网络资源学习。

六、参考文献

【正点原子】STM32开发板实验教程(F103)_哔哩哔哩_bilibili

STM32F103开关控制LED灯相关推荐

  1. 单片机基础:开关控制LED灯的亮灭

    (一) 单片机的初级运用.通过两个开关来控制LED灯的亮灭.首先要使用Proteus来绘制电路原理图.图中的LED灯为共阴接法.如图: (二)当单片机P3口做输入时,首要让其端口输出1.如图中的P3^ ...

  2. 【Arduino基础】倾斜开关控制led灯的亮灭

    实验现象 手拿着面包板,当倾斜到一定程度时,LED被点亮:没有倾斜时,led不亮. 理论学习 当开关一端低于水平位置倾斜,开关导通,模拟口电压值为5V左右 (数字二进制表示为1023),点亮led灯. ...

  3. arduino通过开关控制led灯代码理解(适合所有开关类型)

    方法一 const int LED=13; //声明变量 LED灯接在13针脚: const int BUTTON=7; //声明变量,按钮接在第7针脚: int val=0; //声明变量,用来存储 ...

  4. proteus实现开关控制LED灯的亮灭

    keil5代码: #include<reg52.h>#define unit unsigned sbit led1=P2^0;sbit led2=P2^1;sbit led3=P2^2;s ...

  5. Arduino开关控制LED(布尔变量、上拉输入模式、逻辑运算)

    开关控制LED灯 元器件: 开关X1.ArduinoUNO R3开发板X1.乱七八糟线X2 控制的是开发板上自带的LED灯(13号引脚) 电路连接: 开关一端 开关另一端 引脚2 GND int bu ...

  6. Arduino-Mixly-超声波测距仪-实现距离控制LED灯的开关

    Arduino-Mixly-超声波测距仪-实现距离控制LED灯的开关 Arduino:个人理解那块电板就叫arduino,本质上它是一块单片机(功能不怎么强大的计算机),具备了接受信息处理信息的能力, ...

  7. 怎么控制LED灯的开关呢?最简单的方法是给它加一个开关

    怎么控制LED灯的开关呢?最简单的方法是给它加一个开关,然后串联一个电阻,闭合开关,LED灯就会亮,断开开关,LED灯就会熄灭,但这种方法的缺陷是得需要人为的参与. 如果频率很快,比如一秒钟开关100 ...

  8. STM32F103系列之按键控制LED灯

    上篇已经介绍了点灯的操作了,本篇主要介绍按键控制LED灯进行相关操作. 同样,我们需要对GPIO进行相关的初始化配置,这里我们将LED相关的代码全部放在LED.C和LED.H文件里面. LED.C文件 ...

  9. 基于STM32F103芯片实现LED灯闪烁

    基于STM32F103芯片实现LED灯闪烁 前言 一,寄存器配置 1,时钟控制 2,GPIO端口设置: 二.实际操作 1.具体代码 2.keil5项目运行 3.硬件的连接 4.链接到 mcuisp 串 ...

最新文章

  1. 产品运行所需的信息检索失败_域名解析失败
  2. Linux上iptables防火墙的基本应用教程
  3. 赛门铁克公布Q3财报 亏损68亿美元
  4. Hadoop记录-监控几个思路
  5. 五家共井java_算法练习02:五家共井
  6. 思维 || Make It Equal
  7. Intellij IDEA 配置 Code Style
  8. html选择区域高亮,css+js实现部分区域高亮可编辑遮罩层
  9. JUC学习之CountDownLatch入门
  10. 大秦帝国之崛起的几点启发
  11. 小罗说敏捷 | 使用关键路径法优化项目进度管理
  12. 如何在PC,Mac或iPhone上启用iTunes家长限制
  13. git pull 详解
  14. 电脑W ndoWs未能启动怎么办,Win7系统电脑开机显示“Windows未能启动”的解决方法...
  15. 【爱生活】新冠 - 风寒和风热感冒的区别及措施
  16. 《构建之法》读书笔记——第1章 概论
  17. 开源 | 爱奇艺网络流量分析引擎QNSM及其应用
  18. h5 微信支付 php,用h5做出微信的支付过程的实现步骤
  19. 【SSH项目实战】国税协同平台-1.项目介绍
  20. SAP PCA利润中心会计案例教程案例介绍

热门文章

  1. 百度贴吧怎么进不去_百度贴吧怎么留微信号?
  2. 【C语言】extern 关键字
  3. 全连接条件随机场_【项目案例】北京大兴机场BIM技术应用
  4. iframe显示微信公众号文章
  5. 控制中心可录屏下载_ios11的录屏功能在哪?设置中添加控制中心即可显示!
  6. 抖音中强大的面具贴纸美颜sdk您了解多少?
  7. 第77部分- Linux x86 64位汇编 优化编译器代码
  8. java中相当于memcpy的函数_(C语言)memcpy函数原型的实现
  9. ArcGIS栅格导出成tiff并设置为无黑边
  10. 微信支付服务端与客户端