GPIO使用输入——中断按键检测
一、实验目的
1.使用配置工具配置IO口功能。
2.实现开发板上的KEY2和KEY3按键检测。
3.能够熟练完成代码,实现外部中断。
二、实验内容
1.STM32软件开发环境搭建与操作
2.STM32通用IO口的引脚功能与代码实现
3.熟悉GPIO中断相关函数的使用。
三、实验原理及说明
首先 STM32 的 IO 口可以由软件配置成如下 8 种模式:
1、输入浮空
2、输入上拉
3、输入下拉
4、模拟输入
5、开漏输出
6、推挽输出
7、推挽式复用功能
8、开漏复用功能
其次,在使用cubemx生成的工程中,所有与中断相关的函数都在stm32f1xx_it.c文件中,该函数用于处理GPIO10-15生成的中断,中断函数使用回调的方式,库函数的回调函数使用偌定义的形式,用户可以编写自定义的回调函数覆盖。
四、实验设备
一套STM32实验设备、头歌实践教学平台。
五、实验步骤
1.1 双击打开软件 stm32cubemx。
1.2 开始创建工程,打开软件后选择 access to mcu selector。
1.3 搜索芯片STM32F103C8T6,并选择芯片型号 STM32F103C8T6 ,并点击“start project”创建工程。
1.4 展开“system core”标签,找到“SYS"选项,在右边选择如图所示配置调试模式。
1.5 切换到”RCC“标签,按如图所示配置。

1.6 切换到“Connectivity”标签,按照如图所示配置“USART1”。
1.7 鼠标定位到右侧MCU引脚图,选择PB12和PB13引脚,单击相应引脚,按如图所示配置。

1.8 切换到“System Core”的“GPIO”标签,找到刚才配置的GPIO引脚PB12,按如图所示配置名称和引脚,名称输入“KEY2”。

按照同样的方法配置PB13引脚,最后如图所示

1.9 切换到“System Core”的“NVIC”标签,找到外部中断,并使能,如图所示

1.10设置系统时钟为72M。

1.11 配置工程并生成代码,输入工程名称“KEY_EXTI",具体如图所示

切换到“code generator”标签,按如图所示生成代码。
1.12打开STM32CubeIDE,打开之前生成的工程。
点击”File--> open project from file system......”。

1.13 找到生成文件的文件夹,并打开
1.14 按下右边的标签“MX",即可显示项目文件。

1.15 为项目添加一个C语言源文件,命名为“retarget.c”,如图所示

在文件中添加如下代码:
#include "retarget.h"
#include <_ansi.h>
#include <_syslist.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/times.h>
#include "retarget.h"
#include <stdint.h>
//#include "usart.h"
#if !defined(OS_USE_SEMIHOSTING)
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
UART_HandleTypeDef *gHuart;
void RetargetInit(UART_HandleTypeDef *huart)
{
gHuart = huart;
/* Disable I/O buffering for STDOUT stream, so that
* chars are sent out as soon as they are printed. */
setvbuf(stdout, NULL, _IONBF, 0);
}
int _isatty(int fd)
{
if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
return 1;
errno = EBADF;
return 0;
}
int _write(int fd, char *ptr, int len)
{
HAL_StatusTypeDef hstatus;
if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
{
hstatus = HAL_UART_Transmit(gHuart, (uint8_t *) ptr, len, HAL_MAX_DELAY);
if (hstatus == HAL_OK)
return len;
else
return EIO;
}
errno = EBADF;
return -1;
}
int _close(int fd)
{
if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
return 0;
errno = EBADF;
return -1;
}
int _lseek(int fd, int ptr, int dir)
{
(void) fd;
(void) ptr;
(void) dir;
errno = EBADF;
return -1;
}
int _read(int fd, char *ptr, int len)
{
HAL_StatusTypeDef hstatus;
if (fd == STDIN_FILENO)
{
hstatus = HAL_UART_Receive(gHuart, (uint8_t *) ptr, 1, HAL_MAX_DELAY);
if (hstatus == HAL_OK)
return 1;
else
return EIO;
}
errno = EBADF;
return -1;
}
int _fstat(int fd, struct stat *st)
{
if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)
{
st->st_mode = S_IFCHR;
return 0;
}
errno = EBADF;
return 0;
}
#endif //#if !defined(OS_USE_SEMIHOSTING)
1.16 为项目添加一个C语言头文件,命名为“retarget.h”,如图所示

添加头文件代码如下:
#ifndef FIRMWARE_RETARGET_H
#define FIRMWARE_RETARGET_H
#ifndef _RETARGET_H__
#define _RETARGET_H__
#include "stm32f1xx_hal.h"
#include <sys/stat.h>
#include <stdio.h>
void RetargetInit(UART_HandleTypeDef *huart);
int _isatty(int fd);
int _write(int fd, char *ptr, int len);
int _close(int fd);
int _lseek(int fd, int ptr, int dir);
int _read(int fd, char *ptr, int len);
int _fstat(int fd, struct stat *st);
#endif //#ifndef _RETARGET_H__
#endif //FIRMWARE_RETARGET_H
1.17 打开项目文件Core->Src->syscalls.c,并将以下几行注释:

1.18 打开项目文件Core->Src->main.c ,在如下位置添加一行代码,如图所示:

1.19 打开项目文件Core->Src->gpio.c,在如下位置添加代码,如图所示:

添加函数如下图使得:
KEY2 按下会输出 KEY2 down
KEY3 按下会输出 KEY3 down

示例代码:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == KEY2_Pin)
printf("KEY 2 down!\r\n");
}
1.20 编译项目,并将生成的hex文件下载到开发板,观察现象。
六、实验结果:
KEY2 按下会输出 KEY2 down
KEY3 按下会输出 KEY3 down