当前位置:   article > 正文

从新建工程开始使用C++开发单片机(以STM32为例):三、IO篇(1)IO读写操作接口(附代码)_stm32 c++

stm32 c++

一、STM32 GPIO介绍

STM32F103一共最多有7组IO口,每组IO口有16个IO,一共16X7=112个IO口,GPIOA~GPIOG。GPIO有4种输入模式分别为浮空输入、上拉输入、下拉输入、模拟输入;4种输出模式分别为开漏输出,开漏复用输出,推挽输出,推挽复用输出。除了复用为外设的输入输出引脚外,平时输出电平、读取输入电平主要用到的就是浮空输入、上拉输入、下拉输入、开漏输出和推挽输出。对于大部分其他平台的单片机基本上都有这些功能。因此可以针对这些功能进行封装。
目前完成的接口都是操作一个IO口的,以后完成了一组IO口的读写了再来更新~
PS:这里主要是介绍接口,不会对接口内部做过多的介绍。

二、GPIO接口介绍

请添加图片描述

1.枚举
1.1 Pin_enum: 描述一个STM32的IO口分为引脚组(PortA ~ PortG)和引脚号(Pin0 ~ Pin15),引脚组共7组,引脚号共16号,以此可以使用一个字节来描述一个引脚,字节的高四位表示引脚组,低四位表示引脚号,例如A0可以用于0x00来表示,B5可以用0x15来表示,在使用时取出低四位和高四位就能推算出引脚信息。

/**
* @brief GPIO口枚举 \n
* A0:GPIOA,P0口,其他以此类推
*/
typedef enum
{
    A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,
    B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,
    C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,
    D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,D12,D13,D14,D15,
    E0,E1,E2,E3,E4,E5,E6,E7,E8,E9,E10,E11,E12,E13,E14,E15,
    F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,
    G0,G1,G2,G3,G4,G5,G6,G7,G8,G9,G10,G11,G12,G13,G14,G15,
    Pin_null
}Pin_enum;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1.2 GPIO_mode:GPIO的模式枚举,不具体介绍

/**
* @brief GPIO初始化模式枚举 \n
* INPUT:浮空输入
* INPUT_PULLUP:上拉输入
* INPUT_PULLDOWN:下拉输入
* OUT_PP:推挽输出
* OUT_OD:开漏输出
*/
typedef enum
{
  INPUT = GPIO_Mode_IN_FLOATING,
  INPUT_PULLUP = GPIO_Mode_IPU,
  INPUT_PULLDOWN = GPIO_Mode_IPD,
  OUT_PP = GPIO_Mode_Out_PP,
  OUT_OD = GPIO_Mode_Out_OD
} GPIO_mode;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.函数接口
(当前为函数说明,函数内部实现见底下附带代码)
2.1 void gpio_init(Pin_enum pin, GPIO_mode mode):初始化GPIO口

/*************************************************************************
 * @brief   初始化gpio口
 * @param[in]	pin 要初始化的引脚 (可选择的值在 overall.h Pin_enum枚举中),
 *            此参数可以是以下值之一: 
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @param[in] mode 初始化引脚模式 (可选择的模式在 my_gpio.h Mode_enum中)
 *            此参数可以是以下值之一: 
 *              INPUT INPUT_PULLUP INPUT_PULLDOWN OUT_PP OUT_OD
 * @return 无
 * @note 默认设置GPIO速度为50MHZ,可在 my_gpio.h 中修改DEFAULT_GPIO_SPEED
 *       宏进行修改
 * @example gpio_init(A0,OUT_PP)设置A0口为推挽输出
 * @example gpio_init(A0,INPUT_PULLUP)设置A0口上拉输入
 * @history 2021-11-19:创建,完成功能并测试通过
 ************************************************************************/
void gpio_init(Pin_enum pin, GPIO_mode mode);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.2 void gpio_write(Pin_enum pin, uint8_t data):GPIO输出电平

/*************************************************************************
 * @brief   更改gpio输出状态
 * @param[in]	pin 要更改的引脚 (可选择的值在 overall.h Pin_enum枚举中)
 *            此参数可以是以下值之一: 
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @param[in] data 输出的电平
 *             此参数可以是以下值之一:
 *              1高电平,0低电平
 * @return 无
 * @note  使用该函数前,应先将gpio口设置为输出模式
 * @example gpio_write(A0,1)设置A0口为高电平
 * @history 2021-11-19:创建,完成功能并测试通过
 *          2021-11-20:将GPIO_SetBits(~)和GPIO_ResetBits(~)统一为GPIO_WriteBit(),
 *                      测试通过
 ************************************************************************/
void gpio_write(Pin_enum pin, uint8_t data);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.3 void gpio_toggle(Pin_enum pin):GPIO输出电平进行翻转

/*************************************************************************
 * @brief   翻转gpio输出状态
 * @param[in]	pin 要翻转的引脚 (可选择的值在 overall.h Pin_enum枚举中)
 *            此参数可以是以下值之一: 
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @return 无
 * @note  使用该函数前,应先将gpio口设置为输出模式
 * @example gpio_toggle(A0)翻转A0电平
 * @history 2021-11-19:创建,完成功能并测试通过
 *          2021-11-20:将GPIO_SetBits(~)和GPIO_ResetBits(~)统一为GPIO_WriteBit(),
 *                      测试通过
 ************************************************************************/
void gpio_toggle(Pin_enum pin);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.4 uint8_t gpio_read(Pin_enum pin):读取GPIO口电平

/*************************************************************************
 * @brief   读取gpio输入状态
 * @param[in]	pin 要读取的引脚 (可选择的值在 overall.h Pin_enum枚举中)
 *            此参数可以是以下值之一: 
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @return 无
 * @note  使用该函数前,应先将gpio口设置为输入模式
 * @example gpio_read(A0)读取A0电平
 * @history 2021-11-19:创建,完成功能并测试通过
 ************************************************************************/
uint8_t gpio_read(Pin_enum pin);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

三、AFIO接口介绍

AFIO接口主要为该层其他硬件外设初始化函数调用,不开放给上层接口。
1.枚举

typedef enum
{
  INPUT_AF  = GPIO_Mode_AIN,
  OUT_PP_AF = GPIO_Mode_AF_PP,
  OUT_OD_AF = GPIO_Mode_AF_OD
} AFIO_mode;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.函数接口

/*************************************************************************
 * @brief   初始化io口复用
 * @param[in]	pin 要初始化的引脚 (可选择的值在 overall.h Pin_enum枚举中),
 *            此参数可以是以下值之一: 
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @param[in] mode 初始化引脚模式 (可选择的模式在 my_gpio.h Mode_enum中)
 *            此参数可以是以下值之一: 
 *              INPUT_AF OUT_PP_AF OUT_OD_AF
 * @return 无
 * @note 该函数主要供其他外设初始化函数内部调用
 *       默认设置GPIO速度为50MHZ,可在 my_afio.h 中修改DEFAULT_AFIO_SPEED
 *       宏进行修改
 * @history 2021-11-20:创建,完成功能
 *          2021-11-22:通过设置串口测试通过
 ************************************************************************/
void afio_init(Pin_enum pin, AFIO_mode mode);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

附:完整代码(共5个文件)

/*file:resources.h*/
#ifndef __RESOURCES_H
#define __RESOURCES_H

#ifdef __cplusplus
 extern "C" {
#endif

#include "stm32f10x.h"	

/**
* @brief GPIO口枚举 \n
* A0:GPIOA,P0口,其他以此类推
*/
typedef enum
{
    A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,
    B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,
    C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,
    D0,D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,D12,D13,D14,D15,
    E0,E1,E2,E3,E4,E5,E6,E7,E8,E9,E10,E11,E12,E13,E14,E15,
    F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,
    G0,G1,G2,G3,G4,G5,G6,G7,G8,G9,G10,G11,G12,G13,G14,G15,
    Pin_null
}Pin_enum;


typedef struct
{
    volatile uint8_t buf[256];
    volatile uint8_t write_index;
    volatile uint8_t read_index;
    volatile uint16_t data_size;
    /* data */
}__rec_buf;

#ifdef STM32F10X_HD
#define HAVE_SERIAL1
#define HAVE_SERIAL2
#define HAVE_SERIAL3
#define HAVE_SERIAL4
#define HAVE_SERIAL5
#define HAVE_I2C1
#define HAVE_I2C2
#define HAVE_SPI1
#define HAVE_SPI2
#define HAVE_SPI3
#elif STM32F10X_MD
#define HAVE_SERIAL1
#define HAVE_SERIAL2
#define HAVE_SERIAL3
#define HAVE_I2C1
#define HAVE_I2C2
#define HAVE_SPI1
#define HAVE_SPI2
#elif STM32F10X_LD
#define HAVE_SERIAL1
#define HAVE_SERIAL2
#define HAVE_I2C1
#define HAVE_SPI1
#endif

#ifdef __cplusplus
 }
#endif

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
/*file: my_gpio.h*/
/**************************************************************************
 * @brief       : STM32 GPIO 操作
 * @author      : 龚为玮(1461041096)
 * @copyright   : 版权信息
 * @version     : v1.0
 * @note        : 无
 * @history     : 2021年11月19日:创建文件,完成GPIO口的初始化、读、写翻转,并
 *                               利用输出口E5,B5、输入口A0,E3,E4验证部分功能
 *                               测试通过
 *                2021年11月20日:添加注释
 *                2021年11月20日:修改GPIO输出函数所调用的底层库函数
 *                2021年11月22日:修改注释
 *                2021年11月30日:添加初始化GPIO外部中断,测试通过
 *                2021年12月2日: 修改了外部中断初始化接口,将中断服务函数移到
 *                               上层的库中
 *                2021年1月4日:  优化外部中断初始化接口,优化了代码的封装结构,
 *                                将中断服务函数移了回来。
 ***************************************************************************/
#ifndef __MY_GPIO_H
#define __MY_GPIO_H

#ifdef __cplusplus
 extern "C" {
#endif

#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "resources.h"

/**
* @brief GPIO初始化模式枚举 \n
* INPUT:浮空输入
* INPUT_PULLUP:上拉输入
* INPUT_PULLDOWN:下拉输入
* OUT_PP:推挽输出
* OUT_OD:开漏输出
*/
typedef enum
{
  INPUT = GPIO_Mode_IN_FLOATING,
  INPUT_PULLUP = GPIO_Mode_IPU,
  INPUT_PULLDOWN = GPIO_Mode_IPD,
  OUT_PP = GPIO_Mode_Out_PP,
  OUT_OD = GPIO_Mode_Out_OD
} GPIO_mode;

typedef enum
{
  Rising = EXTI_Trigger_Rising,
  Falling = EXTI_Trigger_Falling,
  Change = EXTI_Trigger_Rising_Falling
} EXIT_mode;

#define DEFAULT_GPIO_SPEED GPIO_Speed_50MHz //GPIO初始化默认GPIO速度

void gpio_init(Pin_enum pin, GPIO_mode mode);
void gpio_write(Pin_enum pin, uint8_t data);
void gpio_toggle(Pin_enum pin);
void gpio_interrupt_init(Pin_enum pin, void (*callback)(void), EXIT_mode mode);
uint8_t gpio_read(Pin_enum pin);

extern void (*EXTI_Linex_Callback[16])(void);//外部中断回调函数指针

#ifdef __cplusplus
}
#endif

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
/*file: my_gpio.c*/
/**************************************************************************
 * @brief       : STM32 GPIO 操作
 * @author      : 龚为玮(1461041096)
 * @copyright   : 版权信息
 * @version     : v1.0
 * @note        : 无
 * @history     : 2021年11月19日:创建文件,完成GPIO口的初始化、读、写翻转,并
 *                               利用输出口E5,B5、输入口A0,E3,E4验证部分功能
 *                               测试通过
 *                2021年11月20日:添加注释
 *                2021年11月20日:修改GPIO输出函数所调用的底层库函数
 *                2021年11月22日:修改注释
 *                2021年11月30日:添加初始化GPIO外部中断,测试通过
 *                2021年12月2日: 修改了外部中断初始化接口,将中断服务函数移到
 *                               上层的库中
 *                2021年1月4日:  优化外部中断初始化接口,优化了代码的封装结构,
 *                                将中断服务函数移了回来。
 ***************************************************************************/
#include "my_gpio.h"

/**************************************************************************
 *    GPIO读写接口
 **************************************************************************/
/*************************************************************************
 * @brief   初始化gpio口
 * @param[in]	pin 要初始化的引脚 (可选择的值在 overall.h Pin_enum枚举中),
 *            此参数可以是以下值之一:
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @param[in] mode 初始化引脚模式 (可选择的模式在 my_gpio.h Mode_enum中)
 *            此参数可以是以下值之一:
 *              INPUT INPUT_PULLUP INPUT_PULLDOWN OUT_PP OUT_OD
 * @return 无
 * @note 默认设置GPIO速度为50MHZ,可在 my_gpio.h 中修改DEFAULT_GPIO_SPEED
 *       宏进行修改
 * @example gpio_init(A0,OUT_PP)设置A0口为推挽输出
 * @example gpio_init(A0,INPUT_PULLUP)设置A0口上拉输入
 * @history 2021-11-19:创建,完成功能并测试通过
 ************************************************************************/
void gpio_init(Pin_enum pin, GPIO_mode mode)
{
  uint16_t gpio_pin = GPIO_Pin_0 << (pin & 0x0f);
  uint16_t gpio_port = (pin & 0xf0) >> 4;

  uint32_t RCC_APB2Periph_GPIO = RCC_APB2Periph_GPIOA << gpio_port;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO, ENABLE);

  GPIO_InitTypeDef gpio;

  gpio.GPIO_Pin = gpio_pin;
  gpio.GPIO_Mode = (GPIOMode_TypeDef)mode;
  gpio.GPIO_Speed = DEFAULT_GPIO_SPEED;

  GPIO_TypeDef *GPIOx = (GPIO_TypeDef *)(GPIOA_BASE + 0x0400 * gpio_port);
  GPIO_Init(GPIOx, &gpio);
}

/*************************************************************************
 * @brief   更改gpio输出状态
 * @param[in]	pin 要更改的引脚 (可选择的值在 overall.h Pin_enum枚举中)
 *            此参数可以是以下值之一:
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @param[in] data 输出的电平
 *             此参数可以是以下值之一:
 *              1高电平,0低电平
 * @return 无
 * @note  使用该函数前,应先将gpio口设置为输出模式
 * @example gpio_write(A0,1)设置A0口为高电平
 * @history 2021-11-19:创建,完成功能并测试通过
 *          2021-11-20:将GPIO_SetBits(~)和GPIO_ResetBits(~)统一为GPIO_WriteBit(),
 *                      测试通过
 ************************************************************************/
void gpio_write(Pin_enum pin, uint8_t data)
{
  uint16_t gpio_pin = GPIO_Pin_0 << (pin & 0x0f);
  uint16_t gpio_port = (pin & 0xf0) >> 4;
  GPIO_TypeDef *GPIOx = (GPIO_TypeDef *)(GPIOA_BASE + 0x0400 * gpio_port);

  GPIO_WriteBit(GPIOx, gpio_pin, (BitAction)data);
}

/*************************************************************************
 * @brief   翻转gpio输出状态
 * @param[in]	pin 要翻转的引脚 (可选择的值在 overall.h Pin_enum枚举中)
 *            此参数可以是以下值之一:
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @return 无
 * @note  使用该函数前,应先将gpio口设置为输出模式
 * @example gpio_toggle(A0)翻转A0电平
 * @history 2021-11-19:创建,完成功能并测试通过
 *          2021-11-20:将GPIO_SetBits(~)和GPIO_ResetBits(~)统一为GPIO_WriteBit(),
 *                      测试通过
 ************************************************************************/
void gpio_toggle(Pin_enum pin)
{
  uint16_t gpio_pin = GPIO_Pin_0 << (pin & 0x0f);
  uint16_t gpio_port = (pin & 0xf0) >> 4;
  GPIO_TypeDef *GPIOx = (GPIO_TypeDef *)(GPIOA_BASE + 0x0400 * gpio_port);

  uint8_t data = GPIO_ReadOutputDataBit(GPIOx, gpio_pin);

  GPIO_WriteBit(GPIOx, gpio_pin, (BitAction)!data);
}

/*************************************************************************
 * @brief   读取gpio输入状态
 * @param[in]	pin 要读取的引脚 (可选择的值在 overall.h Pin_enum枚举中)
 *            此参数可以是以下值之一:
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @return 无
 * @note  使用该函数前,应先将gpio口设置为输入模式
 * @example gpio_read(A0)读取A0电平
 * @history 2021-11-19:创建,完成功能并测试通过
 ************************************************************************/
uint8_t gpio_read(Pin_enum pin)
{
  uint16_t gpio_pin = GPIO_Pin_0 << (pin & 0x0f);
  uint16_t gpio_port = (pin & 0xf0) >> 4;
  GPIO_TypeDef *GPIOx = (GPIO_TypeDef *)(GPIOA_BASE + 0x0400 * gpio_port);

  return GPIO_ReadInputDataBit(GPIOx, gpio_pin);
}

/**************************************************************************
 *    GPIO中断接口
 **************************************************************************/
/*************************************************************************
 * @brief   通过引脚标号获取外部中断向量
 * @param[in]	pin 引脚标号 (可选择的值在 overall.h Pin_enum枚举中)
 *            此参数可以是以下值之一:
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @return 对应的外部中断向量
 * @note  内部使用
 * @history 2021-11-30:创建,完成功能并测试通过
 ************************************************************************/
uint8_t get_exit_irqchannel(Pin_enum pin)
{
  uint8_t pin_num = pin & 0x0f;
  if (pin_num <= 4)
  {
    return EXTI0_IRQn + pin_num;
  }
  else if (pin <= 9)
  {
    return EXTI9_5_IRQn;
  }
  else if (pin <= 15)
  {
    return EXTI15_10_IRQn;
  }
  else
  {
    return 0;
  }
}

/*************************************************************************
 * @brief   gpio外部中断初始化
 * @param[in]	pin 要初始化的引脚标号 (可选择的值在 overall.h Pin_enum枚举中)
 *            此参数可以是以下值之一:
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @param[in] callback 自定义的中断服务函数的函数指针,该函数必须为无返回值,无
 *            参数
 * @param[in]	mode 外部中断触发方式
 *            此参数可以是以下值之一:
 *              Rising:上升沿 Faling:下降沿 Change:上升&下降沿
 * @return 无
 * @example gpio_interrupt_init(A0, Rising)配置A0上升沿中断
 * @history 2021-11-30:创建,完成功能并测试通过
 ************************************************************************/
void gpio_interrupt_init(Pin_enum pin, void (*callback)(void), EXIT_mode mode)
{
  uint8_t GPIO_PinSourcex = (pin & 0x0f);
  uint8_t GPIO_PortSourceGPIOx = (pin & 0xf0) >> 4;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO时钟

  switch (mode)
  {
  case Rising:
    gpio_init(pin, INPUT_PULLDOWN); //上升沿选择下拉输入
    break;
  case Falling:
    gpio_init(pin, INPUT_PULLUP); //下降沿选择上拉输入
    break;
  case Change:
    gpio_init(pin, INPUT); //上升&下降沿选择浮空输入
    break;
  default:
    return;
  }
  //初始化IO

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOx, GPIO_PinSourcex); //引脚中断号配置

  EXTI_InitTypeDef EXTI_InitStructure; //外部中断结构体初始化
  NVIC_InitTypeDef NVIC_InitStructure; //中断分组结构体初始化

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;          //中断模式
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                    //使能中断线
  EXTI_InitStructure.EXTI_Line = EXTI_Line0 << (pin & 0x0f);   //中断线标号
  EXTI_InitStructure.EXTI_Trigger = (EXTITrigger_TypeDef)mode; //触发方式

  EXTI_Init(&EXTI_InitStructure);

  //以下为中断优先级的配置
  NVIC_InitStructure.NVIC_IRQChannel = get_exit_irqchannel(pin); //声明使用的中断是哪一个
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;   //设置抢占优先级为2
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;          //设置子优先级为3
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //使能中断

  NVIC_Init(&NVIC_InitStructure);

  EXTI_Linex_Callback[GPIO_PinSourcex] = callback;
}
/*************中断服务函数********************/

void (*EXTI_Linex_Callback[16])(void); //外部中断回调函数指针

void EXTI0_IRQHandler(void)
{
  if (EXTI_GetITStatus(EXTI_Line0) == SET)
  {
    EXTI_Linex_Callback[0]();
    EXTI_ClearITPendingBit(EXTI_Line0);
  }
}

void EXTI1_IRQHandler(void)
{
  if (EXTI_GetITStatus(EXTI_Line1) == SET)
  {
    EXTI_Linex_Callback[1]();
    EXTI_ClearITPendingBit(EXTI_Line1);
  }
}

void EXTI2_IRQHandler(void)
{
  if (EXTI_GetITStatus(EXTI_Line2) == SET)
  {
    EXTI_Linex_Callback[2]();
    EXTI_ClearITPendingBit(EXTI_Line2);
  }
}

void EXTI3_IRQHandler(void)
{
  if (EXTI_GetITStatus(EXTI_Line3) == SET)
  {
    EXTI_Linex_Callback[3]();
    EXTI_ClearITPendingBit(EXTI_Line3);
  }
}

void EXTI4_IRQHandler(void)
{
  if (EXTI_GetITStatus(EXTI_Line4) == SET)
  {
    EXTI_Linex_Callback[4]();
    EXTI_ClearITPendingBit(EXTI_Line4);
  }
}

void EXTI9_5_IRQHandler(void)
{
  if (EXTI_GetITStatus(EXTI_Line5) == SET)
  {
    EXTI_Linex_Callback[5]();
    EXTI_ClearITPendingBit(EXTI_Line5);
  }
  if (EXTI_GetITStatus(EXTI_Line6) == SET)
  {
    EXTI_Linex_Callback[6]();
    EXTI_ClearITPendingBit(EXTI_Line6);
  }
  if (EXTI_GetITStatus(EXTI_Line7) == SET)
  {
    EXTI_Linex_Callback[7]();
    EXTI_ClearITPendingBit(EXTI_Line7);
  }
  if (EXTI_GetITStatus(EXTI_Line8) == SET)
  {
    EXTI_Linex_Callback[8]();
    EXTI_ClearITPendingBit(EXTI_Line8);
  }
  if (EXTI_GetITStatus(EXTI_Line9) == SET)
  {
    EXTI_Linex_Callback[9]();
    EXTI_ClearITPendingBit(EXTI_Line9);
  }
}

void EXTI15_10_IRQHandler(void)
{
  if (EXTI_GetITStatus(EXTI_Line10) == SET)
  {
    EXTI_Linex_Callback[10]();
    EXTI_ClearITPendingBit(EXTI_Line10);
  }
  if (EXTI_GetITStatus(EXTI_Line11) == SET)
  {
    EXTI_Linex_Callback[11]();
    EXTI_ClearITPendingBit(EXTI_Line11);
  }
  if (EXTI_GetITStatus(EXTI_Line12) == SET)
  {
    EXTI_Linex_Callback[12]();
    EXTI_ClearITPendingBit(EXTI_Line12);
  }
  if (EXTI_GetITStatus(EXTI_Line13) == SET)
  {
    EXTI_Linex_Callback[13]();
    EXTI_ClearITPendingBit(EXTI_Line13);
  }
  if (EXTI_GetITStatus(EXTI_Line14) == SET)
  {
    EXTI_Linex_Callback[14]();
    EXTI_ClearITPendingBit(EXTI_Line14);
  }
  if (EXTI_GetITStatus(EXTI_Line15) == SET)
  {
    EXTI_Linex_Callback[15]();
    EXTI_ClearITPendingBit(EXTI_Line15);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
/*file:my_afio.h*/
/**************************************************************************
  * @brief       : STM32 AFIO(端口复用功能)
  * @author      : 龚为玮(1461041096)  
  * @copyright   : 版权信息
  * @version     : v1.0
  * @note        : 主要作为其他外设函数初始化调用
  * @history     : 2021年11月20日:创建文件,完成基础功能
  *                2021年11月22日:测试,添加注释
***************************************************************************/

#ifndef __MY_AFIO_H
#define __MY_AFIO_H

#ifdef __cplusplus
 extern "C" {
#endif

#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "resources.h"

#define DEFAULT_AFIO_SPEED GPIO_Speed_50MHz //GPIO初始化默认GPIO速度

typedef enum
{
  INPUT_AF  = GPIO_Mode_AIN,
  OUT_PP_AF = GPIO_Mode_AF_PP,
  OUT_OD_AF = GPIO_Mode_AF_OD
} AFIO_mode;

void afio_init(Pin_enum pin, AFIO_mode mode);

#ifdef __cplusplus
 }
#endif

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
/*file:my_afio.c*/
/**************************************************************************
  * @brief       : STM32 AFIO(端口复用功能)
  * @author      : 龚为玮(1461041096)  
  * @copyright   : 版权信息
  * @version     : v1.0
  * @note        : 主要作为其他外设函数初始化调用
  * @history     : 2021年11月20日:创建文件,完成基础功能
  *                2021年11月22日:测试,添加注释
***************************************************************************/
#include "my_afio.h"

/*************************************************************************
 * @brief   初始化io口复用
 * @param[in]	pin 要初始化的引脚 (可选择的值在 overall.h Pin_enum枚举中),
 *            此参数可以是以下值之一: 
 *              A0~A15 B0~B15 C0~C15 D0~D15 E0~E15 F0~F15 G0~G15
 * @param[in] mode 初始化引脚模式 (可选择的模式在 my_gpio.h Mode_enum中)
 *            此参数可以是以下值之一: 
 *              INPUT_AF OUT_PP_AF OUT_OD_AF
 * @return 无
 * @note 该函数主要供其他外设初始化函数内部调用
 *       默认设置GPIO速度为50MHZ,可在 my_afio.h 中修改DEFAULT_AFIO_SPEED
 *       宏进行修改
 * @history 2021-11-20:创建,完成功能
 *          2021-11-22:通过设置串口测试通过
 ************************************************************************/
void afio_init(Pin_enum pin, AFIO_mode mode)
{
  uint16_t gpio_pin = GPIO_Pin_0 << (pin & 0x0f);
  uint16_t gpio_port = (pin & 0xf0) >> 4;

  uint32_t RCC_APB2Periph_GPIOx = RCC_APB2Periph_GPIOA << gpio_port;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx, ENABLE);

  GPIO_InitTypeDef gpio;

  gpio.GPIO_Pin = gpio_pin;
  gpio.GPIO_Mode = (GPIOMode_TypeDef)mode;
  gpio.GPIO_Speed = DEFAULT_AFIO_SPEED;

  GPIO_TypeDef *GPIOx = (GPIO_TypeDef *)(GPIOA_BASE + 0x0400 * gpio_port);
  GPIO_Init(GPIOx, &gpio);
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/684087
推荐阅读
相关标签
  

闽ICP备14008679号