GPIO开发
掌握两个GPIO输出的HAL库函数
GPIO电平输出HAL库函数
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
理解三个参数:
/*1-GPIOx:目标引脚的端口号
*2-GPIO_Pin:目标引脚的引脚号
*3-PinState:高电平--GPIO_PIN_SET;低电平--高电平--GPIO_PIN_RESET
*/
例:向PB8引脚输出高电平
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
GPIO电平翻转HAL库函数
void HAL_GPIO_TogglePin(GPIO_TypeDef GPIOx, uint16_t GPIO_Pin)
例:将PA3的引脚输出电平翻转
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_3);
跑马灯实验:以STM32F103C8T6为例
CubeMx配置
1.通用配置以后所有模块第一步先配置调试接口System Core -->SYS–>Debug(Serial Wire)
2.设置时钟(更精确)(可选),不设置的话默认使用内部时钟RCC–>外部高速时钟(外部低速时钟)二选一–>Crystal/Ceramic Resonator
内部时钟是由单片机内部的振荡器或晶体产生的,而外部时钟是由外部提供的稳定时钟信号源提供的
由于外部时钟是由外部提供的稳定时钟信号源,因此它通常具有更高的稳定性和精度。 而内部时钟则受到单片机内部环境和温度的影响,稳定性和精度可能较低。
3.设置时钟树(见时钟树章节),在HCLK里输入72(具体看芯片最大时钟)即可
以上均为通用模块配置
4.将引脚(我这里LED为PC13引脚)设置为输出模式,其他GPIO初始化(速率,模式等)在GPIO中配置 这里配置为开漏模式(GPIO八种工作模式)低电平点亮LED
5.最后在Project Manager配置(后面不再掩饰)
第三个为输入模式在按键开发中设置为输入上拉模式,默认为浮空
实验代码
#include "main.h"
#include "gpio.h"
void SystemClock_Config(void);
int main(void)
{
//初始化
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
//逻辑代码
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);// HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);//HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_3);
HAL_Delay(500);
}
}
//以下代码都为CUBEMX初始化自动生成,以后将直接忽视
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {
0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {
0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
按键开发
HAL库中关于GPIO的3个重要函数
电平输出函数
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)
电平输入函数
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
例:判断PC13引脚的输入信号,若为高电平则将PB9引脚控制的LED灯的开关状态切换
if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) == GPIO_PIN_SET)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
}
实例:按下KEY2,切换LED1的开关状态
按下KEY3,松开后切换LED2的开关状态
按下KEY3,关闭所有LED
实例代码
#include "main.h"
#include "gpio.h"
#define KEY2 HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_5)
#define KEY3 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)
#define KEY4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
void SystemClock_Config(void);
void Scan_Keys(void);
void Scan_Keys()
{
if(KEY2 == 0)
{
HAL_Delay(10);
if(KEY2 == 0)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
while(KEY2 == 0);//等待按键松开 防止代码重复执行
}
}
if(KEY3 == 0)
{
HAL_Delay(10);
{
if(KEY3 == 0)
{
while(KEY3 == 0);//等待按键松开
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
}
}
}
if(KEY4 == 0)
{
HAL_Delay(10);
{
if(KEY4 == 0)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0|GPIO_PIN_1,1);
while(KEY == 0);
}
}
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
Scan_Keys();
}
}
外部中断
EXTI0,EXTI1,EXTI2,EXTI3,EXTI4专用(EXTI0的引脚为每个端口 的0号引脚PA0 PB0~PG0)
EXTI5~~EXTI9共用
EXTI10~~EXTI15共用
外部中断程序设计思路
传统标准库中断设计步骤:
1.将GPIO初始化为输入端口
2.配置相关I/O引脚与中断的映射关系
3.设置I/O引脚对应的中断触发条件
4.配置NVIC
5.设置中断优先级
6.编写中断服务函数
基于CubeMX的外部中断设计步骤
1.在CubeMX中指定引脚,配置中断初始化参数
2.重写I/O引脚对应的中断回调函数
例:将PC13引脚设置为外部中断,下降沿触发,在中断服务函数中翻转PB9引脚的电平信号
中断初始化配置
1.将GPIO设置为:GPIO_EXTI功能
2.设置中断触发条件:上升沿,下降沿,上升沿或下降沿
3.使能相关的NVIC通道
实训:将key2(PC13)设置为外部中断输入,下降沿触发在中断服务函数中切换LED1的开关状态
将key4(PB5)设置为外部中断输入,上升沿触发在中断服务函数中切换LED2的开关状态
CubeMX配置,将PB8,PB9设置为开漏输出,将PB5,PC13设置为GPIO_EXTIx,
GPIO mode 将PB5设置为上升沿,PC13设置为下降沿都输入上拉
然后使能NVIC
#include "main.h"
#include "gpio.h"
void SystemClock_Config(void);
//HAL库中所有中断服务函都跳转到同一个回调函数,只用判断产生中断的引脚作出对应的处理即可
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_13)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
}
if(GPIO_Pin == GPIO_PIN_13)
{
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_5);
}
}
int main(void)
{
HAL_Init(<