PY32F003F18的HAL_GPIO_Init()函数功能强大。
1、HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
这个函数把将引脚配置为"输入,输出,模拟或AF辅助功能",以及外部中断中断和中断事件使能都放在里面,还包括了中断线连接。功能强大,有点难理解。
源函数:
//函数功能:根据GPIO_Init结构指针所指向的参数初始化GPIOx的外设寄存器
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
uint32_t position = 0x00u;
uint32_t iocurrent;
uint32_t temp;
/* Check the parameters */
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
/* Configure the port pins */
while (((GPIO_Init->Pin) >> position) != 0x00u)
{
iocurrent = (GPIO_Init->Pin) & (1uL << position);
//获取引脚位置,Get current io position
if (iocurrent != 0x00u)//这个引脚需要配置
{
/*--------------------- GPIO Mode Configuration ------------------------*/
/* In case of Alternate function mode selection */
if ((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
{//复用功能推挽模式,复用功能开漏极模式
//将外设连接选择的引脚,Peripheral to be connected to the selected pins
/* Check the Alternate function parameters */
assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
/* Configure Alternate function mapped with the current IO */
temp = GPIOx->AFR[position >> 3u];
//当position<8时,表示GPIOx->AFR[0],读"GPIO复用功能寄存器(low)GPIOx_AFRL"
//当position>7时,表示GPIOx->AFR[1],读"GPIO复用功能寄存器(high)GPIOx_AFRH"
temp &= ~(0xFu << ((position & 0x07u) * 4u));//将第position个AF值清除
temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * 4u));//修改第position个AF值
GPIOx->AFR[position >> 3u] = temp;
//当position<8时,表示GPIOx->AFR[0],将temp写入"GPIO复用功能寄存器(low)GPIOx_AFRL"
//当position>7时,表示GPIOx->AFR[1],将temp写入读"GPIO复用功能寄存器(high)GPIOx_AFRH"
}
/* Configure IO Direction mode (Input, Output, Alternate or Analog) */
temp = GPIOx->MODER;//读"GPIO端口模式寄存器GPIOx_MODER",x=A,B,F
temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2u));
//GPIO_Init->Mode=00B: 输入模式
//GPIO_Init->Mode=01B: 通用输出模式
//GPIO_Init->Mode=10B: 复用功能模式
//GPIO_Init->Mode=11B: 模拟模式(CPU复位时的状态)
GPIOx->MODER = temp;//将temp写入"GPIO端口模式寄存器GPIOx_MODER",x=A,B,F
/* In case of Output or Alternate function mode selection */
if ((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
(GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
{//推挽输出方式,输出开漏极模式,复用功能推挽模式,复用功能开漏极模式
/* Check the Speed parameter */
assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
/* Configure the IO Speed */
temp = GPIOx->OSPEEDR;//读"GPIO端口输出速度寄存器GPIOx_OSPEEDR"
temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
temp |= (GPIO_Init->Speed << (position * 2u));
//GPIO_Init->Speed=00B:IO口的输出速度为非常低
//GPIO_Init->Speed=01B:IO口的输出速度为低速
//GPIO_Init->Speed=10B:IO口的输出速度为高速
//GPIO_Init->Speed=11B:IO口的输出速度为非常高
GPIOx->OSPEEDR = temp;//将temp写入"GPIO端口输出速度寄存器GPIOx_OSPEEDR"
/* Configure the IO Output Type */
temp = GPIOx->OTYPER;//读"GPIO端口输出类型寄存器GPIOx_OTYPER"
temp &= ~(GPIO_OTYPER_OT0 << position) ;
temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4u) << position);
//GPIO_Init->Mode=0B: 推挽输出(CPU复位时的状态)
//GPIO_Init->Mode=1B: 开漏输出
GPIOx->OTYPER = temp;//将temp写入"GPIO端口输出类型寄存器GPIOx_OTYPER"
}
/* Activate the Pull-up or Pull down resistor for the current IO */
temp = GPIOx->PUPDR;//读"GPIO 端口上下拉寄存器GPIOx_PUPDR",x=A,B,F
temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
temp |= ((GPIO_Init->Pull) << (position * 2u));
//GPIO_Init->Pull=00B: 无上下拉
//GPIO_Init->Pull=01B: 上拉
//GPIO_Init->Pull=10B: 下拉
//GPIO_Init->Pull=11B: 保留
GPIOx->PUPDR = temp;//将temp写入"GPIO 端口上下拉寄存器GPIOx_PUPDR",x=A,B,F
/*--------------------- EXTI Mode Configuration ------------------------*/
/* Configure the External Interrupt or event for the current IO */
if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
{
temp = EXTI->EXTICR[position >> 2u];//读"外部中断选择寄存器"
//外部中断选择寄存器1(EXTI_EXTICR1)
//外部中断选择寄存器2(EXTI_EXTICR2)
//外部中断选择寄存器3(EXTI_EXTICR3)
temp &= ~(0x0FuL << (8u * (position & 0x03u)));
temp |= (GPIO_GET_INDEX(GPIOx) << (8u * (position & 0x03u)));
EXTI->EXTICR[position >> 2u] = temp;//将temp写入"外部中断选择寄存器"
/* Clear EXTI line configuration */
temp = EXTI->IMR;//读"中断屏蔽寄存器EXTI_IMR"
temp &= ~(iocurrent);//不使能引脚建立中断标志
if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
{
temp |= iocurrent;//允许引脚在外部触发时建立中断标志
}
EXTI->IMR = temp;//将temp值写入"中断屏蔽寄存器EXTI_IMR"
temp = EXTI->EMR;//读"事件屏蔽寄存器EXTI_EMR"
temp &= ~(iocurrent);//不使能引脚建立事件标志
if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
{
temp |= iocurrent;//允许引脚在外部触发时建立事件标志
}
EXTI->EMR = temp;//将temp值写入"事件屏蔽寄存器EXTI_EMR"
/* Clear Rising Falling edge configuration */
temp = EXTI->RTSR;//读"上升沿触发选择寄存器EXTI_RTSR"
temp &= ~(iocurrent);
if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
{
temp |= iocurrent;
}
EXTI->RTSR = temp;//将temp值写入"上升沿触发选择寄存器EXTI_RTSR"
temp = EXTI->FTSR;//读"下降沿触发选择寄存器EXTI_FTSR"
temp &= ~(iocurrent);
if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
{
temp |= iocurrent;
}
EXTI->FTSR = temp;//将temp值写入"下降沿触发选择寄存器EXTI_FTSR"
}
}
position++;
}
}
2、函数分解:
如果把它们搬开,需要下面这几个函数才能实现其一个函数的功能。
void Configure_Alternate_function_mapped_with_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t alternate);
void Configure_Pin_Direction_mode(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode);
void Configure_Pin_Speed(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t speed);
void Configure_Pin_Output_Type(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode);
void Activate_Pull_up_or_Pull_down_for_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t pull);
void Select_External_Interrupt_Line(GPIO_TypeDef *GPIOx,uint32_t Pin);
void Set_EXTI_line_X_InterruptSwitch(uint32_t Pin,uint32_t mode);
void Set_EXTI_line_X_EventSwitch(uint32_t Pin,uint32_t mode);
void Set_Rising_And_Falling_Mode(uint32_t Pin,uint32_t mode);
#include "MyGPIO.h"
void Configure_Alternate_function_mapped_with_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t alternate);
void Configure_Pin_Direction_mode(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode);
void Configure_Pin_Speed(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t speed);
void Configure_Pin_Output_Type(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode);
void Activate_Pull_up_or_Pull_down_for_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t pull);
void Select_External_Interrupt_Line(GPIO_TypeDef *GPIOx,uint32_t Pin);
void Set_EXTI_line_X_InterruptSwitch(uint32_t Pin,uint32_t mode);
void Set_EXTI_line_X_EventSwitch(uint32_t Pin,uint32_t mode);
void Set_Rising_And_Falling_Mode(uint32_t Pin,uint32_t mode);
GPIO模式配置开始,GPIO Mode Configuration
//函数功能:当引脚配置为"AF复用功能时,需要将外设映射到引脚上
//alternate=GPIO_AF0_USART1,将引脚复用为USART1
//alternate=GPIO_AF1_USART1,将引脚复用为USART1
//alternate=GPIO_AF3_USART1,将引脚复用为USART1
//alternate=GPIO_AF3_USART2,将引脚复用为USART2
//alternate=GPIO_AF4_USART2,将引脚复用为USART2
//alternate=GPIO_AF5_USART2,将引脚复用为USART2
//alternate=GPIO_AF9_USART2,将引脚复用为USART2
void Configure_Alternate_function_mapped_with_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t alternate)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = GPIOx->AFR[position >> 3u];
//当position<8时,表示GPIOx->AFR[0],读"GPIO复用功能寄存器(low)GPIOx_AFRL"
//当position>7时,表示GPIOx->AFR[1],读"GPIO复用功能寄存器(high)GPIOx_AFRH"
temp &= ~(0xFu << ((position & 0x07u) * 4u));//将第position个AF值清除
temp |= ( alternate << ((position & 0x07u) * 4u) );//修改第position个AF值
GPIOx->AFR[position >> 3u] = temp;
//当position<8时,表示GPIOx->AFR[0],将temp写入"GPIO复用功能寄存器(low)GPIOx_AFRL"
//当position>7时,表示GPIOx->AFR[1],将temp写入读"GPIO复用功能寄存器(high)GPIOx_AFRH"
}
position++;
}
}
//函数功能:将引脚配置为"输入,输出,模拟或AF辅助功能"
//mode=00B: 输入模式
//mode=01B: 通用输出模式
//mode=10B: 复用功能模式
//mode=11B: 模拟模式(CPU复位时的状态)
//mode=GPIO_MODE_INPUT,输入
//mode=GPIO_MODE_IT_RISING,输入
//mode=GPIO_MODE_IT_FALLING,输入
//mode=GPIO_MODE_IT_RISING_FALLING,输入
//mode=GPIO_MODE_EVT_RISING,输入
//mode=GPIO_MODE_EVT_FALLING,输入
//mode=GPIO_MODE_EVT_RISING_FALLING,输入
//mode=GPIO_MODE_OUTPUT_PP,输出
//mode=GPIO_MODE_OUTPUT_OD,输出
//mode=GPIO_MODE_AF_PP,AF复用功能模式
//mode=GPIO_MODE_AF_OD,AF复用功能模式
//mode=GPIO_MODE_ANALOG,模拟模式
//外部引脚边沿检测事件属于输入事件,不属于AF复用功能模式
void Configure_Pin_Direction_mode(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = GPIOx->MODER;//读"GPIO端口模式寄存器GPIOx_MODER",x=A,B,F
temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
temp |= ((mode & 0x00000003) << (position * 2u));
//mode=00B: 输入模式
//mode=01B: 通用输出模式
//mode=10B: 复用功能模式
//mode=11B: 模拟模式(CPU复位时的状态)
GPIOx->MODER = temp;//将temp写入"GPIO端口模式寄存器GPIOx_MODER",x=A,B,F
}
position++;
}
}
//函数功能:在"引脚为输出或AF复用功能"时,需要配置引脚工作速度,输入和模拟不需要配置速度
//speed=GPIO_SPEED_FREQ_LOW,IO口的输出速度为非常低
//speed=GPIO_SPEED_FREQ_MEDIUM,IO口的输出速度为低速
//speed=GPIO_SPEED_FREQ_HIGH,IO口的输出速度为高速
//speed=GPIO_SPEED_FREQ_VERY_HIGH,IO口的输出速度为非常高
void Configure_Pin_Speed(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t speed)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = GPIOx->OSPEEDR;//读"GPIO端口输出速度寄存器GPIOx_OSPEEDR"
temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
temp |= (speed << (position * 2u));
//speed=00B:IO口的输出速度为非常低
//speed=01B:IO口的输出速度为低速
//speed=10B:IO口的输出速度为高速
//speed=11B:IO口的输出速度为非常高
GPIOx->OSPEEDR = temp;//将temp写入"GPIO端口输出速度寄存器GPIOx_OSPEEDR"
}
position++;
}
}
//函数功能:在"引脚为输出或AF复用功能"时,需要配置"引脚输出模式",输入和模拟不需要配置速度
//mode=0B: 推挽输出(CPU复位时的状态)
//mode=1B: 开漏输出
//mode=GPIO_MODE_OUTPUT_PP,推挽输出
//mode=GPIO_MODE_OUTPUT_OD,开漏输出
//mode=GPIO_MODE_AF_PP,AF复用功能推挽输出模式
//mode=GPIO_MODE_AF_OD,AF复用功能开漏输出模式
void Configure_Pin_Output_Type(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = GPIOx->OTYPER;//读"GPIO端口输出类型寄存器GPIOx_OTYPER"
temp &= ~(GPIO_OTYPER_OT0 << position) ;
temp |= ( ( (mode & 0x00000010) >> 4u) << position );
//mode=0B: 推挽输出(CPU复位时的状态)
//mode=1B: 开漏输出
GPIOx->OTYPER = temp;//将temp写入"GPIO端口输出类型寄存器GPIOx_OTYPER"
}
position++;
}
}
//函数功能:输入时,可配置"无上下拉,上拉,下拉";模拟功能配置为"无上下拉"
//pull=GPIO_NOPULL: 无上下拉
//pull=GPIO_PULLUP: 上拉
//pull=GPIO_PULLDOWN: 下拉
//pull=11B: 保留
void Activate_Pull_up_or_Pull_down_for_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t pull)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = GPIOx->PUPDR;//读"GPIO 端口上下拉寄存器GPIOx_PUPDR",x=A,B,F
temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
temp |= ( pull << (position * 2u) );
//pull=00B: 无上下拉
//pull=01B: 上拉
//pull=10B: 下拉
//pull=11B: 保留
GPIOx->PUPDR = temp;//将temp写入"GPIO 端口上下拉寄存器GPIOx_PUPDR",x=A,B,F
}
position++;
}
}
GPIO模式配置开始,GPIO Mode Configuration
外部模式配置开始,EXTI Mode Configuration
//函数功能:连接引脚和EXTI中断线
void Select_External_Interrupt_Line(GPIO_TypeDef *GPIOx,uint32_t Pin)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
uint32_t port_x;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = EXTI->EXTICR[position >> 2u];//读"外部中断选择寄存器"
//外部中断选择寄存器1(EXTI_EXTICR1)
//外部中断选择寄存器2(EXTI_EXTICR2)
//外部中断选择寄存器3(EXTI_EXTICR3)
temp &= ~(0x0FuL << (8u * (position & 0x03u)));
port_x=GPIO_GET_INDEX(GPIOx);
//当GPIOx=GPIOA,port_x=00B,映射到PA[position]引脚
//当GPIOx=GPIOB,port_x=01B,映射到PB[position]引脚
//当GPIOx=GPIOF,port_x=10B,映射到PF[position]引脚
temp |= ( port_x << (8u * (position & 0x03u)));
EXTI->EXTICR[position >> 2u] = temp;//将temp写入"外部中断选择寄存器"
}
position++;
}
}
//函数功能:设置中断线x的中断开关
//mode=GPIO_MODE_IT_RISING,输入
//mode=GPIO_MODE_IT_FALLING,输入
//mode=GPIO_MODE_IT_RISING_FALLING,输入
//外部引脚边沿检测事件属于输入事件
void Set_EXTI_line_X_InterruptSwitch(uint32_t Pin,uint32_t mode)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = EXTI->IMR;//读"中断屏蔽寄存器EXTI_IMR"
temp &= ~(iocurrent);//不使能引脚建立中断标志
if( (mode & 0x00010000) == 0x00010000 )
{
temp |= iocurrent;//允许引脚在外部触发时建立中断标志
}
EXTI->IMR = temp;//将temp值写入"中断屏蔽寄存器EXTI_IMR"
}
position++;
}
}
//函数功能:设置中断线x的事件开关
//mode=GPIO_MODE_EVT_RISING,输入
//mode=GPIO_MODE_EVT_FALLING,输入
//mode=GPIO_MODE_EVT_RISING_FALLING,输入
//外部引脚边沿检测事件属于输入事件
void Set_EXTI_line_X_EventSwitch(uint32_t Pin,uint32_t mode)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = EXTI->EMR;//读"事件屏蔽寄存器EXTI_EMR"
temp &= ~(iocurrent);//不使能引脚建立事件标志
if (( mode & 0x00020000) == 0x00020000 )
{
temp |= iocurrent;//允许引脚在外部触发时建立事件标志
}
EXTI->EMR = temp;//将temp值写入"事件屏蔽寄存器EXTI_EMR"
}
position++;
}
}
//函数功能:设置引脚边沿检测模式
//mode=GPIO_MODE_IT_RISING,输入
//mode=GPIO_MODE_IT_FALLING,输入
//mode=GPIO_MODE_IT_RISING_FALLING,输入
//mode=GPIO_MODE_EVT_RISING,输入
//mode=GPIO_MODE_EVT_FALLING,输入
//mode=GPIO_MODE_EVT_RISING_FALLING,输入
//外部引脚边沿检测事件属于输入事件,不属于AF复用功能模式
void Set_Rising_And_Falling_Mode(uint32_t Pin,uint32_t mode)
{
uint32_t temp;
uint32_t position;
uint32_t iocurrent;
position=0;
while( (Pin >> position) != 0x00u )
{
iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
if(iocurrent != 0x00u)//这个引脚需要配置
{
temp = EXTI->RTSR;//读"上升沿触发选择寄存器EXTI_RTSR"
temp &= ~(iocurrent);
if ((mode & 0x00100000) == 0x00100000)
{
temp |= iocurrent;
}
EXTI->RTSR = temp;//将temp值写入"上升沿触发选择寄存器EXTI_RTSR"
temp = EXTI->FTSR;//读"下降沿触发选择寄存器EXTI_FTSR"
temp &= ~(iocurrent);
if ((mode & 0x00200000) == 0x00200000)
{
temp |= iocurrent;
}
EXTI->FTSR = temp;//将temp值写入"下降沿触发选择寄存器EXTI_FTSR"
}
position++;
}
}
外部模式配置结束,EXTI Mode Configuration
/*
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
//这个回调函数没啥用,用户可根据需要修改,建议不用,用了后反而不方便程序移植和管理
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
用处不大,若"中断服务程序"需要调用该函数,就需要修改HAL_GPIO_EXTI_Callback()
设置中断源的中断优先级:
NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
将IRQn中断源的中断优先级设置为priority
HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
它是通过调用NVIC_SetPriority()来实现的
将IRQn中断源的中断优先级设置为PreemptPriority,SubPriority在程序中不使用
0<=PreemptPriority<=3,值越大,表示中断优先级越低
允许中断源产生中断:
NVIC_EnableIRQ(IRQn_Type IRQn)
允许中断源IRQn在中断标志建立时能够产生中断
HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
它是通过调用NVIC_EnableIRQ()来实现的
允许中断源IRQn在中断标志建立时能够产生中断
不允许中断源产生中断:
NVIC_DisableIRQ(IRQn_Type IRQn)
不允许中断源IRQn在中断标志建立时能够产生中断
HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
它是通过调用NVIC_DisableIRQ()来实现的
不允许中断源IRQn在中断标志建立时能够产生中断
读取中断源的中断标志位:
NVIC_GetPendingIRQ(IRQn_Type IRQn)
读取IRQn中断源的中断标志位
将中断源的中断标志位置位:
NVIC_SetPendingIRQ(IRQn_Type IRQn)
将IRQn中断源的中断标志位置1,使其产生中断
清除中断源的中断标志位:
NVIC_ClearPendingIRQ(IRQn_Type IRQn)
//清除IRQn中断源的中断标志位,使其不产生中断
清除事件标志位:
__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_X)和__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_X)
这两个功能相同
根据GPIO_PIN_x,清除"外部中断挂起寄存器EXTI_PR中的PRx位",
取消引脚产生的上升沿,下降沿或软件触发产生事件标志位;
清除事件标志位
读事件标志位:
__HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_X)和__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_X)
这两个功能相同
读"GPIO_PIN_X外部中断线建立的事件标志位"
在某个外部中断线上上升沿触发事件:
__HAL_GPIO_EXTI_GENERATE_SWIT(GPIO_PIN_X)
根据GPIO_PIN_x,将"外部软件中断事件寄存器EXTI_SWIER中的SWx位"置1,
使其产生EXTI line_x上升沿触发事件,进而产生中断,该位由硬件清零;
普通GPIO功能:
__HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA时钟
__HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟
__HAL_RCC_GPIOF_CLK_ENABLE();//使能GPIOF时钟
HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
根据GPIO_InitTypeDef型结构变量指定的参数初始化GPIOx的外设寄存器
HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
PinState=0,GPIOx端口的GPIO_Pin引脚输出低电平;PinState=1,GPIOx端口的GPIO_Pin引脚输出高电平
HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
GPIOx端口的GPIO_Pin的输出电平翻转
HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
读取"GPIOx端口的第GPIO_Pin引脚"输入的电平值
HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
将"GPIOx端口的GPIO_Pin引脚"的外设寄存器恢复到"复位时的默认值"
HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
锁定GPIO引脚GPIO_Pin的配置;当GPIO_Pin执行了"锁键的写入时序"后,在下次系统复位前将不能再更改端口位的配置;
//这个回调函数没啥用
*/
3、经过测试,可以使用
#include "LED.h"
#include "MyGPIO.h"
void MCU_LED_Init(void);
//函数功能:MCU_LED灯引脚初始化,并配置为关灯
void MCU_LED_Init(void)
{
/*
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟
//初始化GPIOB5
GPIO_InitStructure.Pin = GPIO_PIN_5; //选择第5脚
GPIO_InitStructure.Pull = GPIO_PULLUP; //引脚上拉被激活
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //配置GPIO速度为极高
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //设置引脚工作模式为推挽输出方式
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
//根据GPIO_InitStructure结构变量指定的参数初始化GPIOB的外设寄存器
*/
__HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟
Configure_Pin_Direction_mode(GPIOB,GPIO_PIN_5,GPIO_MODE_OUTPUT_PP);
Activate_Pull_up_or_Pull_down_for_Pin(GPIOB,GPIO_PIN_5,GPIO_PULLUP);
MCU_LED_Off();
}