相关原理在原理笔记系列中已有做介绍!那我们就直接动手拉!
一、硬件组成
器件:
1.面包板
2.LED发光二极管
3.电阻(500Ω-1000Ω,最好有,此次操作没用)
4.杜邦线若干
5.ST-LINK下载线
6.按键(分二脚和四脚,本文操作按键为四脚,稍微复杂一点点,有二脚的尽量用二脚)
按键:常见的输入设备,按下导通,松手断开
按键抖动:由于按键内部使用的是机械式弹簧片来进行通断的,所以在按下和松手的瞬间会伴随有一连串的抖动。
按键消抖:通过延时跳过抖动的时间段,再判断IO输入电平。
Tips:本次同样用到的按键是四脚按键(用对角线接法接入STM32中,相当于普通两脚按键的作用,其原理图如下)
接线图:
实物接线图:
二、Cube配置
1.打开STM32CubeMX,点击“File”——>"New Project"
2.CubeMX自动下完补丁包之后,会弹出芯片选择界面,在Commercial搜索框输入F103C8T6右下方会自动出现STM32F103C8T6,双击芯片。
(这里也可以点击⭐收藏然后之后打开时可以不用搜索直接点击⭐,双击对应芯片即可)
3.进入配置界面后单击System Core(系统的核心) → SYS → Debug → Serial Wire(这个是调试模式,如果不选Serial Wire则可能会使得无法使用Stlink或Jlink下载,如果用串口线下载,不调试,不选也没关系),这时PA13与PA14被用来做调试的LCK和DIO口,如果引脚不够用的情况可以不配置为LCK和DIO口,可以把PA13、PA14当做普通IO口使用。
4.单击System Core(系统的核心) → RCC(配置晶振) → High speed Clock(HSE)(高速晶振)→ Crystal/Ceramic Resonator(外部晶振,8M)(如果这里选Disable则无法使用外部高速晶振),这时PD0与PD1被用来做晶振的接口,如果不配置则可以把PD0、PD1当做普通IO口使用。
5.依次单击Pinout & Configuration → System Core → GPIO →右边的PB9和PB6(因为此操作中我LED灯接的PB9和PB6) → GPIO_Output
6.然后将PB15和PA12设置为GPIO_EXTI(外部中断)
7.设置GPIO口属性
- GPIO output level 引脚电平设置: 高/低
- GPIO mode GPIO模式: 推挽输出/开漏输出
- GPIO Pull-up/Pull-dowm 上拉下拉电阻: 上拉电阻/下拉电阻/无上拉或下拉
- Maxinum output speed 引脚速度设置:低速/中速/高速
- User Label 用户标签: 给引脚设置名称
在这里PB6和PB9(两个LED灯无需做修改,按默认配置就好)
GPIO_EXIT的6种模式,我们按默认选择上升沿触发即可。
8.设置NVIC(嵌套向量中断控制器)
- 点击NVIC勾选 EXIT Line[15:10] interrupt 使能中断
9.单击Clock Configuration在这里输入72,按下回车 → OK,自动配置时钟频率为72Mhz
注:如果弹出这个窗口,不能使用72Mhz只能设置为64Mhz,那就是在RCC没有配置外部高速晶振,回去配置即可,如果还不行,那就是芯片选错了。
8.单击Project Manager → Project ,配置准备要生成的工程
9.单击Code Generator 单选Copy only the nacassary library files,勾选Generate peripheral…peripheral,上述的配置都设置好后就可以单击右上角的GENERATE CODE生成工程了。
10.打开工程
三、程序代码
1.HAL库函数介绍
在stm32f1xx_hal_gpio.h中我们可以看到定义的函数
其中uint32_t uint16_t代表的实际上是数据类型
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
以下简单介绍下各个函数
(1)HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
作用:GPIO初始化
示例:(本节用到了PB6)以此为例进行GPIO的初始化可以写为
GPIO_InitStruct.Pin = GPIO_PIN_6
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
(2)HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin);
作用:在函数初始化之后的引脚恢复成默认的状态,即各个寄存器复位时的值
示例:(本节用到了PB6)以此为例HAL_GPIO_Init(GPIOB, GPIO_PIN_6);
(3)HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
作用:读取引脚的电平状态、函数返回值为0或1;
示例:(本节用到了PB6)以此为例HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6);
(4) HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
作用:引脚置0或1,即设置引脚为低电平(RESET)/高电平(SET)
示例:(本节用到了PB6)以此为例HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6,0);或HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6,RRESET);
(5)HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
作用:翻转引脚电平状态(0->1,1->0)
示例:(本节用到了PB6)以此为例HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6); 常用在LED上
(6)HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
作用:锁住引脚电平,比如说一个管脚的当前状态是1,当这个管脚电平变化时保持锁定时的值。
示例:(本节用到了PB6)以此为例HAL_GPIO_LockPin(GPIOB, GPIO_PIN_6);
(7)HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
作用: 外部中断服务函数,清除中断标志位
示例:(本节用到了PB6)以此为例HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
(8)HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
功能: 中断回调函数,可以理解为中断函数具体要响应的动作。
示例:(本节用到了PB6)以此为例HAL_GPIO_EXTI_Callback(GPIO_PIN_6);
2.EXTI按键控制LED程序
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) //函数调用
{
if(GPIO_Pin==GPIO_PIN_15)//判断是否为外部中断15的回调
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_15)==GPIO_PIN_SET) //如果按键松开
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);//PB6对应的LED灯亮
}
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_15)==GPIO_PIN_RESET)//如果按住按键
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);//PB6对应的LED灯灭
}
}
if(GPIO_Pin==GPIO_PIN_12)
{
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET)//如果按键松开
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9对应的LED灯亮
}
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_RESET)//如果按住按键
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9对应的LED灯灭
}
}
//按一下灯灭,再按一个灯亮
//if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_15)==GPIO_PIN_SET)//按键松开瞬间灯亮灭切换
// {
// HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_6);//翻转PB6的电平
// while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_SET){}
// }
//if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET)//按键松开瞬间灯亮灭切换
// {
// HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);//翻转PB9的电平
// while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_12)==GPIO_PIN_SET){}
//}
}