STM32F103开关控制LED灯
本文主要介绍了通过中断来实现开关控制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灯相关推荐
- 单片机基础:开关控制LED灯的亮灭
(一) 单片机的初级运用.通过两个开关来控制LED灯的亮灭.首先要使用Proteus来绘制电路原理图.图中的LED灯为共阴接法.如图: (二)当单片机P3口做输入时,首要让其端口输出1.如图中的P3^ ...
- 【Arduino基础】倾斜开关控制led灯的亮灭
实验现象 手拿着面包板,当倾斜到一定程度时,LED被点亮:没有倾斜时,led不亮. 理论学习 当开关一端低于水平位置倾斜,开关导通,模拟口电压值为5V左右 (数字二进制表示为1023),点亮led灯. ...
- arduino通过开关控制led灯代码理解(适合所有开关类型)
方法一 const int LED=13; //声明变量 LED灯接在13针脚: const int BUTTON=7; //声明变量,按钮接在第7针脚: int val=0; //声明变量,用来存储 ...
- proteus实现开关控制LED灯的亮灭
keil5代码: #include<reg52.h>#define unit unsigned sbit led1=P2^0;sbit led2=P2^1;sbit led3=P2^2;s ...
- Arduino开关控制LED(布尔变量、上拉输入模式、逻辑运算)
开关控制LED灯 元器件: 开关X1.ArduinoUNO R3开发板X1.乱七八糟线X2 控制的是开发板上自带的LED灯(13号引脚) 电路连接: 开关一端 开关另一端 引脚2 GND int bu ...
- Arduino-Mixly-超声波测距仪-实现距离控制LED灯的开关
Arduino-Mixly-超声波测距仪-实现距离控制LED灯的开关 Arduino:个人理解那块电板就叫arduino,本质上它是一块单片机(功能不怎么强大的计算机),具备了接受信息处理信息的能力, ...
- 怎么控制LED灯的开关呢?最简单的方法是给它加一个开关
怎么控制LED灯的开关呢?最简单的方法是给它加一个开关,然后串联一个电阻,闭合开关,LED灯就会亮,断开开关,LED灯就会熄灭,但这种方法的缺陷是得需要人为的参与. 如果频率很快,比如一秒钟开关100 ...
- STM32F103系列之按键控制LED灯
上篇已经介绍了点灯的操作了,本篇主要介绍按键控制LED灯进行相关操作. 同样,我们需要对GPIO进行相关的初始化配置,这里我们将LED相关的代码全部放在LED.C和LED.H文件里面. LED.C文件 ...
- 基于STM32F103芯片实现LED灯闪烁
基于STM32F103芯片实现LED灯闪烁 前言 一,寄存器配置 1,时钟控制 2,GPIO端口设置: 二.实际操作 1.具体代码 2.keil5项目运行 3.硬件的连接 4.链接到 mcuisp 串 ...
最新文章
- 产品运行所需的信息检索失败_域名解析失败
- Linux上iptables防火墙的基本应用教程
- 赛门铁克公布Q3财报 亏损68亿美元
- Hadoop记录-监控几个思路
- 五家共井java_算法练习02:五家共井
- 思维 || Make It Equal
- Intellij IDEA 配置 Code Style
- html选择区域高亮,css+js实现部分区域高亮可编辑遮罩层
- JUC学习之CountDownLatch入门
- 大秦帝国之崛起的几点启发
- 小罗说敏捷 | 使用关键路径法优化项目进度管理
- 如何在PC,Mac或iPhone上启用iTunes家长限制
- git pull 详解
- 电脑W ndoWs未能启动怎么办,Win7系统电脑开机显示“Windows未能启动”的解决方法...
- 【爱生活】新冠 - 风寒和风热感冒的区别及措施
- 《构建之法》读书笔记——第1章 概论
- 开源 | 爱奇艺网络流量分析引擎QNSM及其应用
- h5 微信支付 php,用h5做出微信的支付过程的实现步骤
- 【SSH项目实战】国税协同平台-1.项目介绍
- SAP PCA利润中心会计案例教程案例介绍