天天看點

STM32F7xx —— 輸出STM32F7xx —— 輸出

STM32F7xx —— 輸出

目錄

STM32F7xx —— 輸出

一、幾個重要的IO口操作函數

二、幾個重要的結構

三、封裝兩個GPIO初始化函數(普通GPIO,複用GPIO)

四、輸出接口設計

一、幾個重要的IO口操作函數

HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init);  // GPIO初始化

HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState); // 輸出高低電平

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); // 讀IO口電平

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); // 電平取反
           

二、幾個重要的結構

// GPIO口  GPIOA,GPIOB,GPIOC,GPIOD,GPIOE,GPIOF,GPIOG,GPIOH,GPIOI
typedef struct
{
  __IO uint32_t MODER;    /*!< GPIO port mode register,               Address offset: 0x00      */
  __IO uint32_t OTYPER;   /*!< GPIO port output type register,        Address offset: 0x04      */
  __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,       Address offset: 0x08      */
  __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
  __IO uint32_t IDR;      /*!< GPIO port input data register,         Address offset: 0x10      */
  __IO uint32_t ODR;      /*!< GPIO port output data register,        Address offset: 0x14      */
  __IO uint32_t BSRR;     /*!< GPIO port bit set/reset register,      Address offset: 0x18      */
  __IO uint32_t LCKR;     /*!< GPIO port configuration lock register, Address offset: 0x1C      */
  __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
} GPIO_TypeDef; 
           
// GPIO引腳,模式,上下拉,速度,複用等
typedef struct
{
  uint32_t Pin;       /*!< Specifies the GPIO pins to be configured.
                           This parameter can be any value of @ref GPIO_pins_define */

  uint32_t Mode;      /*!< Specifies the operating mode for the selected pins.
                           This parameter can be a value of @ref GPIO_mode_define */

  uint32_t Pull;      /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
                           This parameter can be a value of @ref GPIO_pull_define */

  uint32_t Speed;     /*!< Specifies the speed for the selected pins.
                           This parameter can be a value of @ref GPIO_speed_define */

  uint32_t Alternate;  /*!< Peripheral to be connected to the selected pins. 
                            This parameter can be a value of @ref GPIO_Alternate_function_selection */
}GPIO_InitTypeDef;
           
// GPIO引腳
#define GPIO_PIN_0                 ((uint16_t)0x0001U)  /* Pin 0 selected    */
#define GPIO_PIN_1                 ((uint16_t)0x0002U)  /* Pin 1 selected    */
#define GPIO_PIN_2                 ((uint16_t)0x0004U)  /* Pin 2 selected    */
#define GPIO_PIN_3                 ((uint16_t)0x0008U)  /* Pin 3 selected    */
#define GPIO_PIN_4                 ((uint16_t)0x0010U)  /* Pin 4 selected    */
#define GPIO_PIN_5                 ((uint16_t)0x0020U)  /* Pin 5 selected    */
#define GPIO_PIN_6                 ((uint16_t)0x0040U)  /* Pin 6 selected    */
#define GPIO_PIN_7                 ((uint16_t)0x0080U)  /* Pin 7 selected    */
#define GPIO_PIN_8                 ((uint16_t)0x0100U)  /* Pin 8 selected    */
#define GPIO_PIN_9                 ((uint16_t)0x0200U)  /* Pin 9 selected    */
#define GPIO_PIN_10                ((uint16_t)0x0400U)  /* Pin 10 selected   */
#define GPIO_PIN_11                ((uint16_t)0x0800U)  /* Pin 11 selected   */
#define GPIO_PIN_12                ((uint16_t)0x1000U)  /* Pin 12 selected   */
#define GPIO_PIN_13                ((uint16_t)0x2000U)  /* Pin 13 selected   */
#define GPIO_PIN_14                ((uint16_t)0x4000U)  /* Pin 14 selected   */
#define GPIO_PIN_15                ((uint16_t)0x8000U)  /* Pin 15 selected   */
           
// GPIO模式  輸入 推挽輸出 開漏輸出 推挽複用 開漏複用
#define  GPIO_MODE_INPUT                        ((uint32_t)0x00000000U)   /*!< Input Floating Mode                   */
#define  GPIO_MODE_OUTPUT_PP                    ((uint32_t)0x00000001U)   /*!< Output Push Pull Mode                 */
#define  GPIO_MODE_OUTPUT_OD                    ((uint32_t)0x00000011U)   /*!< Output Open Drain Mode                */
#define  GPIO_MODE_AF_PP                        ((uint32_t)0x00000002U)   /*!< Alternate Function Push Pull Mode     */
#define  GPIO_MODE_AF_OD                        ((uint32_t)0x00000012U)   /*!< Alternate Function Open Drain Mode    */
           
// GPIO速度 低速  中速  高速  極速
#define  GPIO_SPEED_FREQ_LOW         ((uint32_t)0x00000000U)  /*!< Low speed     */
#define  GPIO_SPEED_FREQ_MEDIUM      ((uint32_t)0x00000001U)  /*!< Medium speed  */
#define  GPIO_SPEED_FREQ_HIGH        ((uint32_t)0x00000002U)  /*!< Fast speed    */
#define  GPIO_SPEED_FREQ_VERY_HIGH   ((uint32_t)0x00000003U)  /*!< High speed    */
           
// GPIO上下拉 無上下拉  上拉  下拉
#define  GPIO_NOPULL        ((uint32_t)0x00000000U)   /*!< No Pull-up or Pull-down activation  */
#define  GPIO_PULLUP        ((uint32_t)0x00000001U)   /*!< Pull-up activation                  */
#define  GPIO_PULLDOWN      ((uint32_t)0x00000002U)   /*!< Pull-down activation                */
           
// GPIO引腳高低電平
typedef enum
{
  GPIO_PIN_RESET = 0,
  GPIO_PIN_SET
}GPIO_PinState;
           

三、封裝兩個GPIO初始化函數(普通GPIO,複用GPIO)

// 這裡隻貼出代碼片段,封裝兩個接口,一個普通GPIO初始化,一個帶複用功能。
#define GPIO_CLK_ENABLE() do{ \
  __HAL_RCC_GPIOA_CLK_ENABLE(); \
  __HAL_RCC_GPIOB_CLK_ENABLE(); \
  __HAL_RCC_GPIOC_CLK_ENABLE(); \
  __HAL_RCC_GPIOD_CLK_ENABLE(); \
  __HAL_RCC_GPIOE_CLK_ENABLE(); \
  __HAL_RCC_GPIOF_CLK_ENABLE(); \
  __HAL_RCC_GPIOG_CLK_ENABLE(); \
  __HAL_RCC_GPIOH_CLK_ENABLE(); \
  __HAL_RCC_GPIOI_CLK_ENABLE(); \
} while(0);

void GPIOConfig(GPIO_TypeDef *gpio, uint32_t pin, uint32_t mode, uint32_t pull)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_CLK_ENABLE();

  GPIO_InitStructure.Pin = pin;
  GPIO_InitStructure.Mode = mode;
  GPIO_InitStructure.Pull = pull;
  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;

  HAL_GPIO_Init(gpio, &GPIO_InitStructure);
}

void GPIOConfigExt(GPIO_TypeDef *gpio, uint32_t pin, uint32_t mode, uint32_t pull, uint32_t alternate)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_CLK_ENABLE();

  GPIO_InitStructure.Pin = pin;
  GPIO_InitStructure.Mode = mode;
  GPIO_InitStructure.Pull = pull;
  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
  GPIO_InitStructure.Alternate = alternate;

  HAL_GPIO_Init(gpio, &GPIO_InitStructure);
}
           

四、輸出接口設計

為了靈活使用,我們将輸出的有效電平設定成可配置。

// 配置的有效電平 初始  低電平有效  高電平有效
typedef enum
{
  OUTPUT_INIT_IS_ACTIVE = 0,
  OUTPUT_LOW_IS_ACTIVE  = 1,
  OUTPUT_HIGH_IS_ACTIVE = 2,
} output_active_t;

#define OUTX_CONFIG(gpio, pin)    GPIOConfig(gpio, pin, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL)
#define OUTX_READ(gpio, pin)      HAL_GPIO_ReadPin(gpio, pin)
#define OUTX_ACTIVE(gpio, pin, tag) do{ \
  if(OUTPUT_LOW_IS_ACTIVE == tag) \
  { \
    HAL_GPIO_WritePin(gpio, pin, GPIO_PIN_RESET); \
  } \
  else \
  { \
    HAL_GPIO_WritePin(gpio, pin, GPIO_PIN_SET); \
  } \
} while(0);
#define OUTX_NEGATIVE(gpio, pin, tag) do{ \
  if(OUTPUT_LOW_IS_ACTIVE == tag) \
  { \
    HAL_GPIO_WritePin(gpio, pin, GPIO_PIN_SET); \
  } \
  else \
  { \
    HAL_GPIO_WritePin(gpio, pin, GPIO_PIN_RESET); \
  } \
} while(0);

#define OUT1_PORT                 GPIOA
#define OUT1_PIN                  GPIO_PIN_0

#define OUT2_PORT                 GPIOA
#define OUT2_PIN                  GPIO_PIN_1

#define OUT3_PORT                 GPIOA
#define OUT3_PIN                  GPIO_PIN_2
           
// demo代碼 隻傳遞思想 
// 封裝出對外的四個接口 初始化 輸出有效 輸出無效 輸出取反 
// 以清單的形式封裝 友善增加和删除

static void output_config(GPIO_TypeDef *gpio, uint16_t pin)
{
  OUTX_CONFIG(gpio, pin);
}

static uint8_t output_is_enable(uint8_t index)
{
  // 輸出通道可用 這裡也可以變成可配置 可以配置本IO口有效和無效
  return 1;
}

static void output_active(GPIO_TypeDef *gpio, uint16_t pin, uint8_t tag)
{
  OUTX_ACTIVE(gpio, pin, tag);
}

static void output_negative(GPIO_TypeDef *gpio, uint16_t pin, uint8_t tag)
{
  OUTX_NEGATIVE(gpio, pin, tag);
}

static void output_toggle(GPIO_TypeDef *gpio, uint16_t pin, uint8_t tag)
{
  // 這裡可以不用這麼麻煩,使用HAL_GPIO_TogglePin
  if(OUTX_READ(gpio, pin) == 0)
  {
    OUTX_ACTIVE(gpio, pin, tag);
  }
  else
  {
    OUTX_NEGATIVE(gpio, pin, tag);
  }
}

typedef struct
{
  GPIO_TypeDef *gpio;
  uint16_t pin;
  void (* output_config_cb)(GPIO_TypeDef *gpio, uint16_t pin);
  uint8_t (* output_is_enable_cb)(uint8_t index);
  void (* output_active_cb)(GPIO_TypeDef *gpio, uint16_t pin, uint8_t tag);
  void (* output_negative_cb)(GPIO_TypeDef *gpio, uint16_t pin, uint8_t tag);
  void (* output_toggle_cb)(GPIO_TypeDef *gpio, uint16_t pin, uint8_t tag);
} output_port_t;

static output_port_t output_items[] =
{
  {OUT1_PORT, OUT1_PIN, output_config, output_is_enable, output_active, output_negative, output_toggle},
  {OUT2_PORT, OUT2_PIN, output_config, output_is_enable, output_active, output_negative, output_toggle},
  {OUT3_PORT, OUT3_PIN, output_config, output_is_enable, output_active, output_negative, output_toggle},
};

static void output_init(uint32_t value)
{
  uint32_t i, mask = 1;

  for(i = 0; i < ARRAY_SIZE(output_items); ++i)
  {
    if(value & mask)
    {
#if(CONFIG_OUTPUT_TEST == 1)
      config.output.total_switch = OUTPUT_MODE_OPEN;
      config.output.sub_switch[i] = OUTPUT_MODE_OPEN;
      config.output.active_tag[i] = OUTPUT_HIGH_IS_ACTIVE;
#endif
      output_items[i].output_config_cb(output_items[i].gpio, output_items[i].pin);
      output_items[i].output_negative_cb(output_items[i].gpio, output_items[i].pin, config.output.active_tag[i]);
    }

    mask <<= 1;
  }
}

void OutputHigh(uint32_t value)
{
  uint32_t i, mask = 1;

  for(i = 0; i < ARRAY_SIZE(output_items); ++i)
  {
    if(value & mask)
    {
      if(output_items[i].output_is_enable_cb(i))
      {
        output_items[i].output_active_cb(output_items[i].gpio, output_items[i].pin, config.output.active_tag[i]);
      }
    }

    mask <<= 1;
  }
}

void OutputLow(uint32_t value)
{
  uint32_t i, mask = 1;

  for(i = 0; i < ARRAY_SIZE(output_items); ++i)
  {
    if(value & mask)
    {
      if(output_items[i].output_is_enable_cb(i))
      {
        output_items[i].output_negative_cb(output_items[i].gpio, output_items[i].pin, config.output.active_tag[i]);
      }
    }

    mask <<= 1;
  }
}

void OutputToggle(uint32_t value)
{
  uint32_t i, mask = 1;

  for(i = 0; i < ARRAY_SIZE(output_items); ++i)
  {
    if(value & mask)
    {
      if(output_items[i].output_is_enable_cb(i))
      {
        output_items[i].output_toggle_cb(output_items[i].gpio, output_items[i].pin, config.output.active_tag[i]);
      }
    }

    mask <<= 1;
  }
}

void OutputInit(void)
{
  output_init(0xFFFFFFFF);
  OutputLow(0xFFFFFFFF);
}
           

繼續閱讀