STM32F103RCT6学习之二:GPIO开发
-
GPIO基础
1.简介
2.GPIO基本结构
3.种模式
-
GPIO基本功能
1.输出功能--LED灯闪烁
1)进行基本配置
2)编辑代码
主要在main.c中编辑。
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 */HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);//将LED0点亮/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */HAL_Delay(50);HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET);//将LED0熄灭HAL_Delay(50);HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);//将LED0点亮/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
3)分析:
涉及2个函数
HAL_GPIO_WritePin();//定义于stm32f1xx_hal_gpio.c
HAL_Delay();//定义于stm32f1xx_hal.c
涉及2个宏-
LED0_GPIO_Port //定义于main.h
LED0_Pin//定义于main.h
实现闪烁功能也可以用如下代码:
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 */HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);//将LED0点亮/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */HAL_Delay(50);HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);//将LED0翻转/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
2.输入功能--按键控制LED灯
要求KEY0控制LED0,按一下点亮,再按一下熄灭
1)进行基本配置
2)编辑代码
3)分析
1、可能存在抖动问题
2、效率不高
考虑用中断的方式实现
3.GPIO外部中断方式实现按键功能
要求KEY0控制LED0,按一下点亮,再按一下熄灭
1)进行基本配置
2)编辑代码
触发中断时系统会调用定义于stm32f1xx_it.c的void EXTI9_5_IRQHandler(void)
可以看到该中断服务函数又调用 HAL_GPIO_EXTI_IRQHandler(KEY0_Pin),该函数定义于stm32f1xx_hal_gpio.c中:
而该函数又调用了HAL_GPIO_EXTI_Callback(GPIO_Pin); 这是一个同样定义于tm32f1xx_hal_gpio.c中的可重定义函数
在main.c中重定义HAL_GPIO_EXTI_Callback(GPIO_Pin):
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if(GPIO_Pin==KEY0_Pin){if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==GPIO_PIN_RESET){HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);}
}
3)分析
4.GPIO-三个按键控制2个LED
要求KEY1控制LED0,按一下点亮,再按一下熄灭
要求KEY1控制LED2,按一下点亮,再按一下熄灭
要求KEY_WKUP控制LED0、LED1,按一下取反
1)进行基本配置
**配置KEY_WKUP应该是下拉模式,上升沿触发
**配置KEY0、KEY1应该是上拉模式,下降沿触发
2)编辑代码
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
// if(GPIO_Pin==KEY0_Pin){
// if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==GPIO_PIN_RESET){
// HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
// }
//
// }else if(GPIO_Pin==KEY1_Pin){
// if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET){
// HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
// }
//
// }else if(GPIO_Pin==KEY_WKUP_Pin){
// if(HAL_GPIO_ReadPin(KEY_WKUP_GPIO_Port,KEY_WKUP_Pin)==GPIO_PIN_RESET){
// HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
// HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
// }
// }switch(GPIO_Pin){case KEY0_Pin:HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); break;case KEY1_Pin:HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin); break;case KEY_WKUP_Pin:HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);break;default:break;}}
3)分析
5.GPIO-控制4位动态数码管及4X4矩阵键盘
数码管段选信号SEG_A~SEG_DP经74HC240反相输出到数码管各段(阳极),编程时用低电平点亮;
数码管位选信号BIT3~BIT0经两片75452反向驱动后输出到数码管各位()阴极),编程时高电平选中。
1)进行基本配置
2)编辑代码
键盘扫描
#define ROW_NUM 4
#define COL_NUM 4
GPIO_TypeDef* row_ports[ROW_NUM] = {GPIOB, GPIOB, GPIOB, GPIOB}; //数据类型为端口号的指针数组
uint16_t row_pins[ROW_NUM] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3}; //引脚编号数组GPIO_TypeDef* col_ports[COL_NUM] = {GPIOB, GPIOB, GPIOB, GPIOB}; //数据类型为端口号的指针数组
uint16_t col_pins[COL_NUM] = {GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7}; //引脚编号数组
uint8_t key_num_map[ROW_NUM][COL_NUM] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}
};
uint8_t scan_keypad_num(void) {for (int row = 0; row < ROW_NUM; row++) {// 设置当前行输出低电平,其余行输出高电平for (int i = 0; i < ROW_NUM; i++) {HAL_GPIO_WritePin(row_ports[i], row_pins[i], GPIO_PIN_SET);}HAL_GPIO_WritePin(row_ports[row], row_pins[row], GPIO_PIN_RESET);// 检测列输入状态for (int col = 0; col < COL_NUM; col++) {if (HAL_GPIO_ReadPin(col_ports[col], col_pins[col]) == GPIO_PIN_RESET) {HAL_Delay(10); // 按键消抖if (HAL_GPIO_ReadPin(col_ports[col], col_pins[col]) == GPIO_PIN_RESET) {return key_num_map[row][col];}}}}return NULL; // 无按键按下
}
主程序
int main(void)
{/* USER CODE BEGIN 1 */// uint8_t key_num=NULL;/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 *//* USER CODE END WHILE *//* USER CODE BEGIN 3 */uint8_t key_num = scan_keypad_num();if(key_num != NULL){switch(key_num){case 1:HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); //翻转LED0电平HAL_Delay(100); // 消抖防止重复检测同一按键break;case 2:HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin); //翻转LED1电平HAL_Delay(100); // 消抖防止重复检测同一按键break;case 3:HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); //翻转LED0、LED1电平HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);HAL_Delay(100); // 消抖防止重复检测同一按键break;}}}/* USER CODE END 3 */
}
3)分析
1.效率不高
2.重复扫描