rt-thread-official/bsp/acm32f0x0-nucleo/libraries/HAL_Driver/Src/HAL_GPIO.c

622 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
******************************************************************************
* @file HAL_GPIO.c
* @version V1.0.0
* @date 2020
* @brief GPIO HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the General Purpose Input/Output (GPIO) peripheral:
* @ Initialization functions
* @ IO operation functions
******************************************************************************
*/
#include "ACM32Fxx_HAL.h"
/*********************************************************************************
* Function : HAL_GPIO_IRQHandler
* Description : GPIO interrupt Handler
* Input :
* Outpu :
* Author : Chris_Kyle Date : 2020年
**********************************************************************************/
void HAL_GPIO_IRQHandler(enum_GPIOx_t fe_GPIO, uint32_t fu32_GPIO_Pin)
{
GPIO_TypeDef *GPIOx;
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
}break;
default: break;
}
if (fe_GPIO == GPIOB || fe_GPIO == GPIOD )
{
fu32_GPIO_Pin <<= 16;
}
if (GPIOx->RIS & fu32_GPIO_Pin)
{
GPIOx->IC = fu32_GPIO_Pin;
/* user can call your application process function here */
/* ...... */
}
}
/*********************************************************************************
* Function : HAL_GPIO_Init
* Description : Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init
* Input : fe_GPIO: to select the GPIO peripheral.
* Input : GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
the configuration information for the specified GPIO peripheral.
* Outpu :
* Author : Chris_Kyle Date : 2020年
**********************************************************************************/
void HAL_GPIO_Init(enum_GPIOx_t fe_GPIO, GPIO_InitTypeDef *GPIO_Init)
{
uint32_t lu32_Position = 0;
uint32_t lu32_Current_Pin;
uint32_t lu32_Position_Mask;
volatile uint32_t *lu32_SEL1 = NULL; // 指向 -> 管脚复用寄存器1
volatile uint32_t *lu32_SEL2 = NULL; // 指向 -> 管脚复用寄存器2
volatile uint32_t *lu32_PollUP = NULL; // 指向 -> 上拉选择寄存器
volatile uint32_t *lu32_PollDown = NULL; // 指向 -> 下拉选择寄存器
volatile uint32_t *lu32_ODEnable = NULL; // 指向 -> 开漏使能寄存器
volatile uint32_t *lu32_ADS = NULL; // 指向 -> 数字、模拟选择寄存器
GPIO_TypeDef *GPIOx;
#if (USE_FULL_ASSERT == 1)
/* Check the parameters */
if (!IS_GPIO_ALL_INSTANCE(fe_GPIO)) return;
if (!IS_GPIO_PIN(GPIO_Init->Pin)) return;
if (!IS_GPIO_MODE(GPIO_Init->Mode)) return;
if (!IS_GPIO_PULL(GPIO_Init->Pull)) return;
#endif
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
System_Module_Enable(EN_GPIOAB);
lu32_PollUP = &(SCU->PABPUR);
lu32_PollDown = &(SCU->PABPDR);
lu32_ODEnable = &(SCU->PABODR);
lu32_ADS = &(SCU->PABADS);
if (fe_GPIO == GPIOB)
{
GPIO_Init->Pin <<= 16;
lu32_SEL1 = &(SCU->PBSEL1);
lu32_SEL2 = &(SCU->PBSEL2);
}
else
{
lu32_SEL1 = &(SCU->PASEL1);
lu32_SEL2 = &(SCU->PASEL2);
}
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
System_Module_Enable(EN_GPIOCD);
lu32_PollUP = &(SCU->PCDPUR);
lu32_PollDown = &(SCU->PCDPDR);
lu32_ODEnable = &(SCU->PCDODR);
lu32_ADS = &(SCU->PCDADS);
if (fe_GPIO == GPIOD)
{
GPIO_Init->Pin <<= 16;
lu32_SEL1 = &(SCU->PDSEL1);
}
else
{
lu32_SEL1 = &(SCU->PCSEL1);
lu32_SEL2 = &(SCU->PCSEL2);
}
}break;
default: break;
}
/* Configure Select pins */
while ((GPIO_Init->Pin) >> lu32_Position != 0)
{
/* Get current pin position */
lu32_Current_Pin = (GPIO_Init->Pin) & (1uL << lu32_Position);
if (lu32_Current_Pin)
{
switch (GPIO_Init->Mode)
{
/* GPIO IN Function */
case GPIO_MODE_INPUT:
{
GPIOx->DIR &= ~lu32_Current_Pin;
}break;
/* GPIO OUT Function */
case GPIO_MODE_OUTPUT_PP:
case GPIO_MODE_OUTPUT_OD:
{
GPIOx->DIR |= lu32_Current_Pin;
}break;
/* Alternate Function */
case GPIO_MODE_AF_PP:
case GPIO_MODE_AF_OD:
{
/* Get Position Mask */
if (lu32_Position < 16)
{ /* GOIOA、GPIOC、GPIOE */
lu32_Position_Mask = lu32_Position;
}
else
{ /* GPIOB、GPIOD、GPIOF */
lu32_Position_Mask = lu32_Position - 16;
}
/* SET GPIO Function */
if (lu32_Position_Mask < 8)
{
*lu32_SEL1 = (*lu32_SEL1 & ~(0xF << (lu32_Position_Mask * 4))) | (GPIO_Init->Alternate << (lu32_Position_Mask * 4));
}
else
{
*lu32_SEL2 = (*lu32_SEL2 & ~(0xF << ((lu32_Position_Mask - 8) * 4))) | (GPIO_Init->Alternate << ((lu32_Position_Mask - 8) * 4));
}
}break;
/* GPIO INT Function */
case GPIO_MODE_IT_RISING:
case GPIO_MODE_IT_FALLING:
case GPIO_MODE_IT_RISING_FALLING:
case GPIO_MODE_IT_HIGH_LEVEL:
case GPIO_MODE_IT_LOW_LEVEL:
{
/* Set direction Input、Enable INT */
GPIOx->DIR &= ~lu32_Current_Pin;
GPIOx->IEN |= lu32_Current_Pin;
/* Single edge */
if (GPIO_Init->Mode == GPIO_MODE_IT_RISING || GPIO_Init->Mode == GPIO_MODE_IT_FALLING)
{
/* edge trigger */
GPIOx->IS &= ~lu32_Current_Pin;
/* Single trigger */
GPIOx->IBE &= ~lu32_Current_Pin;
if (GPIO_Init->Mode == GPIO_MODE_IT_RISING)
{
GPIOx->IEV |= lu32_Current_Pin;
}
else
{
GPIOx->IEV &= ~lu32_Current_Pin;
}
}
/* Double edge */
if (GPIO_Init->Mode == GPIO_MODE_IT_RISING_FALLING)
{
/* edge trigger */
GPIOx->IS &= ~lu32_Current_Pin;
/* Double trigger */
GPIOx->IBE |= lu32_Current_Pin;
}
/* LEVEL trigger */
if (GPIO_Init->Mode == GPIO_MODE_IT_HIGH_LEVEL || GPIO_Init->Mode == GPIO_MODE_IT_LOW_LEVEL)
{
/* LEVEL trigger */
GPIOx->IS |= lu32_Current_Pin;
if (GPIO_Init->Mode == GPIO_MODE_IT_HIGH_LEVEL)
{
GPIOx->IEV |= lu32_Current_Pin;
}
else
{
GPIOx->IEV &= ~lu32_Current_Pin;
}
}
}break;
default: break;
}
/* Set Pull UP or DOWN or NO */
if (GPIO_Init->Pull == GPIO_NOPULL)
{
*lu32_PollUP &= ~lu32_Current_Pin;
*lu32_PollDown &= ~lu32_Current_Pin;
}
else if (GPIO_Init->Pull == GPIO_PULLUP)
{
*lu32_PollUP |= lu32_Current_Pin;
*lu32_PollDown &= ~lu32_Current_Pin;
}
else if (GPIO_Init->Pull == GPIO_PULLDOWN)
{
*lu32_PollUP &= ~lu32_Current_Pin;
*lu32_PollDown |= lu32_Current_Pin;
}
/* Set Open Drain Mode */
if (GPIO_Init->Mode & GPIO_MODE_OD_MASK)
{
*lu32_ODEnable |= lu32_Current_Pin;
}
else
{
*lu32_ODEnable &= ~lu32_Current_Pin;
}
/* GPIO Function */
if (GPIO_Init->Mode & GPIO_MODE_IO_MASK)
{
/* Get Position Mask */
if (lu32_Position < 16)
{ /* GOIOA、GPIOC、GPIOE */
lu32_Position_Mask = lu32_Position;
}
else
{ /* GPIOB、GPIOD、GPIOF */
lu32_Position_Mask = lu32_Position - 16;
}
/* SET GPIO Function */
if (lu32_Position_Mask < 8)
{
*lu32_SEL1 = (*lu32_SEL1 & ~(0xF << (lu32_Position_Mask * 4))) | (GPIO_FUNCTION_0 << (lu32_Position_Mask * 4));
}
else
{
*lu32_SEL2 = (*lu32_SEL2 & ~(0xF << ((lu32_Position_Mask - 8) * 4))) | (GPIO_FUNCTION_0 << ((lu32_Position_Mask - 8) * 4));
}
}
/* SET Digital or Analog */
if (GPIO_Init->Mode == GPIO_MODE_ANALOG)
{
*lu32_ADS |= lu32_Current_Pin;
}
else
{
*lu32_ADS &= ~lu32_Current_Pin;
}
}
lu32_Position++;
}
}
/*********************************************************************************
* Function : HAL_GPIO_DeInit
* Description : De-initializes the GPIOx peripheral registers to their default reset values.
* Input : fe_GPIOto select the GPIO peripheral.
* Input : fu32_Pinspecifies the port bit to be written.
This parameter can be one of GPIO_PIN_x where x can be (0..15).
* Outpu :
* Author : Chris_Kyle Date : 2020
**********************************************************************************/
void HAL_GPIO_DeInit(enum_GPIOx_t fe_GPIO, uint32_t fu32_Pin)
{
uint32_t lu32_Position = 0;
uint32_t lu32_Current_Pin;
uint32_t lu32_Position_Mask;
volatile uint32_t *lu32_SEL1 = NULL; // 指向 -> 管脚复用寄存器1
volatile uint32_t *lu32_SEL2 = NULL; // 指向 -> 管脚复用寄存器2
volatile uint32_t *lu32_PollUP = NULL; // 指向 -> 上拉选择寄存器
volatile uint32_t *lu32_PollDown = NULL; // 指向 -> 下拉选择寄存器
volatile uint32_t *lu32_ODEnable = NULL; // 指向 -> 开漏使能寄存器
volatile uint32_t *lu32_ADS = NULL; // 指向 -> 数字、模拟选择寄存器
GPIO_TypeDef *GPIOx;
#if (USE_FULL_ASSERT == 1)
/* Check the parameters */
if (!IS_GPIO_ALL_INSTANCE(fe_GPIO)) return;
if (!IS_GPIO_PIN(fu32_Pin)) return;
#endif
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
System_Module_Enable(EN_GPIOAB);
lu32_PollUP = &(SCU->PABPUR);
lu32_PollDown = &(SCU->PABPDR);
lu32_ODEnable = &(SCU->PABODR);
lu32_ADS = &(SCU->PABADS);
if (fe_GPIO == GPIOB)
{
fu32_Pin <<= 16;
lu32_SEL1 = &(SCU->PBSEL1);
lu32_SEL2 = &(SCU->PBSEL2);
}
else
{
lu32_SEL1 = &(SCU->PASEL1);
lu32_SEL2 = &(SCU->PASEL2);
}
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
System_Module_Enable(EN_GPIOCD);
lu32_PollUP = &(SCU->PCDPUR);
lu32_PollDown = &(SCU->PCDPDR);
lu32_ODEnable = &(SCU->PCDODR);
lu32_ADS = &(SCU->PCDADS);
if (fe_GPIO == GPIOD)
{
fu32_Pin <<= 16;
lu32_SEL1 = &(SCU->PDSEL1);
}
else
{
lu32_SEL1 = &(SCU->PCSEL1);
lu32_SEL2 = &(SCU->PCSEL2);
}
}break;
default: break;
}
/* Configure Select pins */
while (fu32_Pin >> lu32_Position != 0)
{
/* Get current pin position */
lu32_Current_Pin = fu32_Pin & (1uL << lu32_Position);
if (lu32_Current_Pin)
{
/* GPIO IN Function */
GPIOx->DIR &= ~lu32_Current_Pin;
GPIOx->CLR |= lu32_Current_Pin;
/* Disable Enable INT */
GPIOx->IEN &= ~lu32_Current_Pin;
/* Clear trigger config */
GPIOx->IS &= ~lu32_Current_Pin;
GPIOx->IBE &= ~lu32_Current_Pin;
GPIOx->IEV &= ~lu32_Current_Pin;
/* Get Position Mask */
if (lu32_Position < 16)
{ /* GOIOA、GPIOC、GPIOE */
lu32_Position_Mask = lu32_Position;
}
else
{ /* GPIOB、GPIOD、GPIOF */
lu32_Position_Mask = lu32_Position - 16;
}
/* SET GPIO Function */
if (lu32_Position_Mask < 8)
{
*lu32_SEL1 &= ~(0xF << (lu32_Position_Mask * 4));
}
else
{
*lu32_SEL2 &= ~(0xF << ((lu32_Position_Mask - 8) * 4));
}
/* NO Pull */
*lu32_PollUP &= ~lu32_Current_Pin;
*lu32_PollDown &= ~lu32_Current_Pin;
/* Not Open Drain */
*lu32_ODEnable &= ~lu32_Current_Pin;
/* Analog Mode */
*lu32_ADS |= lu32_Current_Pin;
}
lu32_Position++;
}
}
/*********************************************************************************
* Function : HAL_GPIO_AnalogEnable
* Description : Quickly Configure to analog function
* Input : fe_GPIOto select the GPIO peripheral.
* Input : fu32_Pinspecifies the port bit to be written.
This parameter can be one of GPIO_PIN_x where x can be (0..15).
* Outpu :
* Author : Chris_Kyle Date : 2020年
**********************************************************************************/
void HAL_GPIO_AnalogEnable(enum_GPIOx_t fe_GPIO, uint32_t fu32_Pin)
{
uint32_t lu32_Position = 0;
uint32_t lu32_Current_Pin;
volatile uint32_t *lp32_ADS = NULL; // 指向 -> 数字、模拟选择寄存器
#if (USE_FULL_ASSERT == 1)
/* Check the parameters */
if (!IS_GPIO_ALL_INSTANCE(fe_GPIO)) return;
if (!IS_GPIO_PIN(fu32_Pin)) return;
#endif
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
System_Module_Enable(EN_GPIOAB);
lp32_ADS = &(SCU->PABADS);
if (fe_GPIO == GPIOB)
{
fu32_Pin <<= 16;
}
}break;
case GPIOC:
case GPIOD:
{
System_Module_Enable(EN_GPIOCD);
lp32_ADS = &(SCU->PCDADS);
if (fe_GPIO == GPIOD)
{
fu32_Pin <<= 16;
}
}break;
default: break;
}
/* Configure Select pins */
while ((fu32_Pin) >> lu32_Position != 0)
{
/* Get current pin position */
lu32_Current_Pin = (fu32_Pin) & (1uL << lu32_Position);
if (lu32_Current_Pin)
{
*lp32_ADS |= lu32_Current_Pin;
}
lu32_Position++;
}
}
/*********************************************************************************
* Function : HAL_GPIO_WritePin
* Description : Set or clear the selected data port bit.
* Input :
* Outpu :
* Author : Chris_Kyle Date : 2020年
**********************************************************************************/
void HAL_GPIO_WritePin(enum_GPIOx_t fe_GPIO, uint32_t fu32_GPIO_Pin, enum_PinState_t fe_PinState)
{
GPIO_TypeDef *GPIOx;
#if (USE_FULL_ASSERT == 1)
/* Check the parameters */
if (!IS_GPIO_ALL_INSTANCE(fe_GPIO)) return;
if (!IS_GPIO_PIN(fu32_GPIO_Pin)) return;
if (!IS_GPIO_PIN_ACTION(fe_PinState)) return;
#endif
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
}break;
default: break;
}
if (fe_GPIO == GPIOB || fe_GPIO == GPIOD )
{
fu32_GPIO_Pin <<= 16;
}
if (GPIO_PIN_SET == fe_PinState)
{
GPIOx->ODATA |= fu32_GPIO_Pin;
}
else
{
GPIOx->ODATA &= ~fu32_GPIO_Pin;
}
}
/*********************************************************************************
* Function : HAL_GPIO_ReadPin
* Description : Read the specified input port pin.
* Input :
* Outpu :
* Author : Chris_Kyle Date : 2020年
**********************************************************************************/
enum_PinState_t HAL_GPIO_ReadPin(enum_GPIOx_t fe_GPIO, uint32_t fu32_GPIO_Pin)
{
GPIO_TypeDef *GPIOx;
switch (fe_GPIO)
{
case GPIOA:
case GPIOB:
{
GPIOx = GPIOAB;
}break;
case GPIOC:
case GPIOD:
{
GPIOx = GPIOCD;
}break;
default: break;
}
if (fe_GPIO == GPIOB || fe_GPIO == GPIOD )
{
fu32_GPIO_Pin <<= 16;
}
if (GPIOx->IDATA & fu32_GPIO_Pin)
{
return GPIO_PIN_SET;
}
else
{
return GPIO_PIN_CLEAR;
}
}