• PY32F003F18的GPIO函数


    PY32F003F18的HAL_GPIO_Init()函数功能强大。

    1、HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)

    这个函数把将引脚配置为"输入,输出,模拟或AF辅助功能",以及外部中断中断和中断事件使能都放在里面,还包括了中断线连接。功能强大,有点难理解。

    源函数:

    1. //函数功能:根据GPIO_Init结构指针所指向的参数初始化GPIOx的外设寄存器
    2. void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
    3. {
    4. uint32_t position = 0x00u;
    5. uint32_t iocurrent;
    6. uint32_t temp;
    7. /* Check the parameters */
    8. assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
    9. assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
    10. assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
    11. assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
    12. /* Configure the port pins */
    13. while (((GPIO_Init->Pin) >> position) != 0x00u)
    14. {
    15. iocurrent = (GPIO_Init->Pin) & (1uL << position);
    16. //获取引脚位置,Get current io position
    17. if (iocurrent != 0x00u)//这个引脚需要配置
    18. {
    19. /*--------------------- GPIO Mode Configuration ------------------------*/
    20. /* In case of Alternate function mode selection */
    21. if ((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
    22. {//复用功能推挽模式,复用功能开漏极模式
    23. //将外设连接选择的引脚,Peripheral to be connected to the selected pins
    24. /* Check the Alternate function parameters */
    25. assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
    26. assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
    27. /* Configure Alternate function mapped with the current IO */
    28. temp = GPIOx->AFR[position >> 3u];
    29. //当position<8时,表示GPIOx->AFR[0],读"GPIO复用功能寄存器(low)GPIOx_AFRL"
    30. //当position>7时,表示GPIOx->AFR[1],读"GPIO复用功能寄存器(high)GPIOx_AFRH"
    31. temp &= ~(0xFu << ((position & 0x07u) * 4u));//将第position个AF值清除
    32. temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * 4u));//修改第position个AF值
    33. GPIOx->AFR[position >> 3u] = temp;
    34. //当position<8时,表示GPIOx->AFR[0],将temp写入"GPIO复用功能寄存器(low)GPIOx_AFRL"
    35. //当position>7时,表示GPIOx->AFR[1],将temp写入读"GPIO复用功能寄存器(high)GPIOx_AFRH"
    36. }
    37. /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
    38. temp = GPIOx->MODER;//"GPIO端口模式寄存器GPIOx_MODER",x=A,B,F
    39. temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
    40. temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2u));
    41. //GPIO_Init->Mode=00B: 输入模式
    42. //GPIO_Init->Mode=01B: 通用输出模式
    43. //GPIO_Init->Mode=10B: 复用功能模式
    44. //GPIO_Init->Mode=11B: 模拟模式(CPU复位时的状态)
    45. GPIOx->MODER = temp;//将temp写入"GPIO端口模式寄存器GPIOx_MODER",x=A,B,F
    46. /* In case of Output or Alternate function mode selection */
    47. if ((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
    48. (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
    49. {//推挽输出方式,输出开漏极模式,复用功能推挽模式,复用功能开漏极模式
    50. /* Check the Speed parameter */
    51. assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
    52. /* Configure the IO Speed */
    53. temp = GPIOx->OSPEEDR;//"GPIO端口输出速度寄存器GPIOx_OSPEEDR"
    54. temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
    55. temp |= (GPIO_Init->Speed << (position * 2u));
    56. //GPIO_Init->Speed=00B:IO口的输出速度为非常低
    57. //GPIO_Init->Speed=01B:IO口的输出速度为低速
    58. //GPIO_Init->Speed=10B:IO口的输出速度为高速
    59. //GPIO_Init->Speed=11B:IO口的输出速度为非常高
    60. GPIOx->OSPEEDR = temp;//将temp写入"GPIO端口输出速度寄存器GPIOx_OSPEEDR"
    61. /* Configure the IO Output Type */
    62. temp = GPIOx->OTYPER;//"GPIO端口输出类型寄存器GPIOx_OTYPER"
    63. temp &= ~(GPIO_OTYPER_OT0 << position) ;
    64. temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4u) << position);
    65. //GPIO_Init->Mode=0B: 推挽输出(CPU复位时的状态)
    66. //GPIO_Init->Mode=1B: 开漏输出
    67. GPIOx->OTYPER = temp;//将temp写入"GPIO端口输出类型寄存器GPIOx_OTYPER"
    68. }
    69. /* Activate the Pull-up or Pull down resistor for the current IO */
    70. temp = GPIOx->PUPDR;//"GPIO 端口上下拉寄存器GPIOx_PUPDR",x=A,B,F
    71. temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
    72. temp |= ((GPIO_Init->Pull) << (position * 2u));
    73. //GPIO_Init->Pull=00B: 无上下拉
    74. //GPIO_Init->Pull=01B: 上拉
    75. //GPIO_Init->Pull=10B: 下拉
    76. //GPIO_Init->Pull=11B: 保留
    77. GPIOx->PUPDR = temp;//将temp写入"GPIO 端口上下拉寄存器GPIOx_PUPDR",x=A,B,F
    78. /*--------------------- EXTI Mode Configuration ------------------------*/
    79. /* Configure the External Interrupt or event for the current IO */
    80. if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
    81. {
    82. temp = EXTI->EXTICR[position >> 2u];//读"外部中断选择寄存器"
    83. //外部中断选择寄存器1(EXTI_EXTICR1)
    84. //外部中断选择寄存器2(EXTI_EXTICR2)
    85. //外部中断选择寄存器3(EXTI_EXTICR3)
    86. temp &= ~(0x0FuL << (8u * (position & 0x03u)));
    87. temp |= (GPIO_GET_INDEX(GPIOx) << (8u * (position & 0x03u)));
    88. EXTI->EXTICR[position >> 2u] = temp;//将temp写入"外部中断选择寄存器"
    89. /* Clear EXTI line configuration */
    90. temp = EXTI->IMR;//"中断屏蔽寄存器EXTI_IMR"
    91. temp &= ~(iocurrent);//不使能引脚建立中断标志
    92. if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
    93. {
    94. temp |= iocurrent;//允许引脚在外部触发时建立中断标志
    95. }
    96. EXTI->IMR = temp;//将temp值写入"中断屏蔽寄存器EXTI_IMR"
    97. temp = EXTI->EMR;//"事件屏蔽寄存器EXTI_EMR"
    98. temp &= ~(iocurrent);//不使能引脚建立事件标志
    99. if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
    100. {
    101. temp |= iocurrent;//允许引脚在外部触发时建立事件标志
    102. }
    103. EXTI->EMR = temp;//将temp值写入"事件屏蔽寄存器EXTI_EMR"
    104. /* Clear Rising Falling edge configuration */
    105. temp = EXTI->RTSR;//"上升沿触发选择寄存器EXTI_RTSR"
    106. temp &= ~(iocurrent);
    107. if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
    108. {
    109. temp |= iocurrent;
    110. }
    111. EXTI->RTSR = temp;//将temp值写入"上升沿触发选择寄存器EXTI_RTSR"
    112. temp = EXTI->FTSR;//"下降沿触发选择寄存器EXTI_FTSR"
    113. temp &= ~(iocurrent);
    114. if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
    115. {
    116. temp |= iocurrent;
    117. }
    118. EXTI->FTSR = temp;//将temp值写入"下降沿触发选择寄存器EXTI_FTSR"
    119. }
    120. }
    121. position++;
    122. }
    123. }

    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);

    1. #include "MyGPIO.h"
    2. void Configure_Alternate_function_mapped_with_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t alternate);
    3. void Configure_Pin_Direction_mode(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode);
    4. void Configure_Pin_Speed(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t speed);
    5. void Configure_Pin_Output_Type(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode);
    6. void Activate_Pull_up_or_Pull_down_for_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t pull);
    7. void Select_External_Interrupt_Line(GPIO_TypeDef *GPIOx,uint32_t Pin);
    8. void Set_EXTI_line_X_InterruptSwitch(uint32_t Pin,uint32_t mode);
    9. void Set_EXTI_line_X_EventSwitch(uint32_t Pin,uint32_t mode);
    10. void Set_Rising_And_Falling_Mode(uint32_t Pin,uint32_t mode);
    11. GPIO模式配置开始,GPIO Mode Configuration
    12. //函数功能:当引脚配置为"AF复用功能时,需要将外设映射到引脚上
    13. //alternate=GPIO_AF0_USART1,将引脚复用为USART1
    14. //alternate=GPIO_AF1_USART1,将引脚复用为USART1
    15. //alternate=GPIO_AF3_USART1,将引脚复用为USART1
    16. //alternate=GPIO_AF3_USART2,将引脚复用为USART2
    17. //alternate=GPIO_AF4_USART2,将引脚复用为USART2
    18. //alternate=GPIO_AF5_USART2,将引脚复用为USART2
    19. //alternate=GPIO_AF9_USART2,将引脚复用为USART2
    20. void Configure_Alternate_function_mapped_with_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t alternate)
    21. {
    22. uint32_t temp;
    23. uint32_t position;
    24. uint32_t iocurrent;
    25. position=0;
    26. while( (Pin >> position) != 0x00u )
    27. {
    28. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    29. if(iocurrent != 0x00u)//这个引脚需要配置
    30. {
    31. temp = GPIOx->AFR[position >> 3u];
    32. //当position<8时,表示GPIOx->AFR[0],读"GPIO复用功能寄存器(low)GPIOx_AFRL"
    33. //当position>7时,表示GPIOx->AFR[1],读"GPIO复用功能寄存器(high)GPIOx_AFRH"
    34. temp &= ~(0xFu << ((position & 0x07u) * 4u));//将第position个AF值清除
    35. temp |= ( alternate << ((position & 0x07u) * 4u) );//修改第position个AF值
    36. GPIOx->AFR[position >> 3u] = temp;
    37. //当position<8时,表示GPIOx->AFR[0],将temp写入"GPIO复用功能寄存器(low)GPIOx_AFRL"
    38. //当position>7时,表示GPIOx->AFR[1],将temp写入读"GPIO复用功能寄存器(high)GPIOx_AFRH"
    39. }
    40. position++;
    41. }
    42. }
    43. //函数功能:将引脚配置为"输入,输出,模拟或AF辅助功能"
    44. //mode=00B: 输入模式
    45. //mode=01B: 通用输出模式
    46. //mode=10B: 复用功能模式
    47. //mode=11B: 模拟模式(CPU复位时的状态)
    48. //mode=GPIO_MODE_INPUT,输入
    49. //mode=GPIO_MODE_IT_RISING,输入
    50. //mode=GPIO_MODE_IT_FALLING,输入
    51. //mode=GPIO_MODE_IT_RISING_FALLING,输入
    52. //mode=GPIO_MODE_EVT_RISING,输入
    53. //mode=GPIO_MODE_EVT_FALLING,输入
    54. //mode=GPIO_MODE_EVT_RISING_FALLING,输入
    55. //mode=GPIO_MODE_OUTPUT_PP,输出
    56. //mode=GPIO_MODE_OUTPUT_OD,输出
    57. //mode=GPIO_MODE_AF_PP,AF复用功能模式
    58. //mode=GPIO_MODE_AF_OD,AF复用功能模式
    59. //mode=GPIO_MODE_ANALOG,模拟模式
    60. //外部引脚边沿检测事件属于输入事件,不属于AF复用功能模式
    61. void Configure_Pin_Direction_mode(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode)
    62. {
    63. uint32_t temp;
    64. uint32_t position;
    65. uint32_t iocurrent;
    66. position=0;
    67. while( (Pin >> position) != 0x00u )
    68. {
    69. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    70. if(iocurrent != 0x00u)//这个引脚需要配置
    71. {
    72. temp = GPIOx->MODER;//读"GPIO端口模式寄存器GPIOx_MODER",x=A,B,F
    73. temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
    74. temp |= ((mode & 0x00000003) << (position * 2u));
    75. //mode=00B: 输入模式
    76. //mode=01B: 通用输出模式
    77. //mode=10B: 复用功能模式
    78. //mode=11B: 模拟模式(CPU复位时的状态)
    79. GPIOx->MODER = temp;//将temp写入"GPIO端口模式寄存器GPIOx_MODER",x=A,B,F
    80. }
    81. position++;
    82. }
    83. }
    84. //函数功能:在"引脚为输出或AF复用功能"时,需要配置引脚工作速度,输入和模拟不需要配置速度
    85. //speed=GPIO_SPEED_FREQ_LOW,IO口的输出速度为非常低
    86. //speed=GPIO_SPEED_FREQ_MEDIUM,IO口的输出速度为低速
    87. //speed=GPIO_SPEED_FREQ_HIGH,IO口的输出速度为高速
    88. //speed=GPIO_SPEED_FREQ_VERY_HIGH,IO口的输出速度为非常高
    89. void Configure_Pin_Speed(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t speed)
    90. {
    91. uint32_t temp;
    92. uint32_t position;
    93. uint32_t iocurrent;
    94. position=0;
    95. while( (Pin >> position) != 0x00u )
    96. {
    97. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    98. if(iocurrent != 0x00u)//这个引脚需要配置
    99. {
    100. temp = GPIOx->OSPEEDR;//读"GPIO端口输出速度寄存器GPIOx_OSPEEDR"
    101. temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
    102. temp |= (speed << (position * 2u));
    103. //speed=00B:IO口的输出速度为非常低
    104. //speed=01B:IO口的输出速度为低速
    105. //speed=10B:IO口的输出速度为高速
    106. //speed=11B:IO口的输出速度为非常高
    107. GPIOx->OSPEEDR = temp;//将temp写入"GPIO端口输出速度寄存器GPIOx_OSPEEDR"
    108. }
    109. position++;
    110. }
    111. }
    112. //函数功能:在"引脚为输出或AF复用功能"时,需要配置"引脚输出模式",输入和模拟不需要配置速度
    113. //mode=0B: 推挽输出(CPU复位时的状态)
    114. //mode=1B: 开漏输出
    115. //mode=GPIO_MODE_OUTPUT_PP,推挽输出
    116. //mode=GPIO_MODE_OUTPUT_OD,开漏输出
    117. //mode=GPIO_MODE_AF_PP,AF复用功能推挽输出模式
    118. //mode=GPIO_MODE_AF_OD,AF复用功能开漏输出模式
    119. void Configure_Pin_Output_Type(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t mode)
    120. {
    121. uint32_t temp;
    122. uint32_t position;
    123. uint32_t iocurrent;
    124. position=0;
    125. while( (Pin >> position) != 0x00u )
    126. {
    127. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    128. if(iocurrent != 0x00u)//这个引脚需要配置
    129. {
    130. temp = GPIOx->OTYPER;//读"GPIO端口输出类型寄存器GPIOx_OTYPER"
    131. temp &= ~(GPIO_OTYPER_OT0 << position) ;
    132. temp |= ( ( (mode & 0x00000010) >> 4u) << position );
    133. //mode=0B: 推挽输出(CPU复位时的状态)
    134. //mode=1B: 开漏输出
    135. GPIOx->OTYPER = temp;//将temp写入"GPIO端口输出类型寄存器GPIOx_OTYPER"
    136. }
    137. position++;
    138. }
    139. }
    140. //函数功能:输入时,可配置"无上下拉,上拉,下拉";模拟功能配置为"无上下拉"
    141. //pull=GPIO_NOPULL: 无上下拉
    142. //pull=GPIO_PULLUP: 上拉
    143. //pull=GPIO_PULLDOWN: 下拉
    144. //pull=11B: 保留
    145. void Activate_Pull_up_or_Pull_down_for_Pin(GPIO_TypeDef *GPIOx,uint32_t Pin,uint32_t pull)
    146. {
    147. uint32_t temp;
    148. uint32_t position;
    149. uint32_t iocurrent;
    150. position=0;
    151. while( (Pin >> position) != 0x00u )
    152. {
    153. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    154. if(iocurrent != 0x00u)//这个引脚需要配置
    155. {
    156. temp = GPIOx->PUPDR;//读"GPIO 端口上下拉寄存器GPIOx_PUPDR",x=A,B,F
    157. temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
    158. temp |= ( pull << (position * 2u) );
    159. //pull=00B: 无上下拉
    160. //pull=01B: 上拉
    161. //pull=10B: 下拉
    162. //pull=11B: 保留
    163. GPIOx->PUPDR = temp;//将temp写入"GPIO 端口上下拉寄存器GPIOx_PUPDR",x=A,B,F
    164. }
    165. position++;
    166. }
    167. }
    168. GPIO模式配置开始,GPIO Mode Configuration
    169. 外部模式配置开始,EXTI Mode Configuration
    170. //函数功能:连接引脚和EXTI中断线
    171. void Select_External_Interrupt_Line(GPIO_TypeDef *GPIOx,uint32_t Pin)
    172. {
    173. uint32_t temp;
    174. uint32_t position;
    175. uint32_t iocurrent;
    176. uint32_t port_x;
    177. position=0;
    178. while( (Pin >> position) != 0x00u )
    179. {
    180. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    181. if(iocurrent != 0x00u)//这个引脚需要配置
    182. {
    183. temp = EXTI->EXTICR[position >> 2u];//读"外部中断选择寄存器"
    184. //外部中断选择寄存器1(EXTI_EXTICR1)
    185. //外部中断选择寄存器2(EXTI_EXTICR2)
    186. //外部中断选择寄存器3(EXTI_EXTICR3)
    187. temp &= ~(0x0FuL << (8u * (position & 0x03u)));
    188. port_x=GPIO_GET_INDEX(GPIOx);
    189. //当GPIOx=GPIOA,port_x=00B,映射到PA[position]引脚
    190. //当GPIOx=GPIOB,port_x=01B,映射到PB[position]引脚
    191. //当GPIOx=GPIOF,port_x=10B,映射到PF[position]引脚
    192. temp |= ( port_x << (8u * (position & 0x03u)));
    193. EXTI->EXTICR[position >> 2u] = temp;//将temp写入"外部中断选择寄存器"
    194. }
    195. position++;
    196. }
    197. }
    198. //函数功能:设置中断线x的中断开关
    199. //mode=GPIO_MODE_IT_RISING,输入
    200. //mode=GPIO_MODE_IT_FALLING,输入
    201. //mode=GPIO_MODE_IT_RISING_FALLING,输入
    202. //外部引脚边沿检测事件属于输入事件
    203. void Set_EXTI_line_X_InterruptSwitch(uint32_t Pin,uint32_t mode)
    204. {
    205. uint32_t temp;
    206. uint32_t position;
    207. uint32_t iocurrent;
    208. position=0;
    209. while( (Pin >> position) != 0x00u )
    210. {
    211. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    212. if(iocurrent != 0x00u)//这个引脚需要配置
    213. {
    214. temp = EXTI->IMR;//读"中断屏蔽寄存器EXTI_IMR"
    215. temp &= ~(iocurrent);//不使能引脚建立中断标志
    216. if( (mode & 0x00010000) == 0x00010000 )
    217. {
    218. temp |= iocurrent;//允许引脚在外部触发时建立中断标志
    219. }
    220. EXTI->IMR = temp;//将temp值写入"中断屏蔽寄存器EXTI_IMR"
    221. }
    222. position++;
    223. }
    224. }
    225. //函数功能:设置中断线x的事件开关
    226. //mode=GPIO_MODE_EVT_RISING,输入
    227. //mode=GPIO_MODE_EVT_FALLING,输入
    228. //mode=GPIO_MODE_EVT_RISING_FALLING,输入
    229. //外部引脚边沿检测事件属于输入事件
    230. void Set_EXTI_line_X_EventSwitch(uint32_t Pin,uint32_t mode)
    231. {
    232. uint32_t temp;
    233. uint32_t position;
    234. uint32_t iocurrent;
    235. position=0;
    236. while( (Pin >> position) != 0x00u )
    237. {
    238. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    239. if(iocurrent != 0x00u)//这个引脚需要配置
    240. {
    241. temp = EXTI->EMR;//读"事件屏蔽寄存器EXTI_EMR"
    242. temp &= ~(iocurrent);//不使能引脚建立事件标志
    243. if (( mode & 0x00020000) == 0x00020000 )
    244. {
    245. temp |= iocurrent;//允许引脚在外部触发时建立事件标志
    246. }
    247. EXTI->EMR = temp;//将temp值写入"事件屏蔽寄存器EXTI_EMR"
    248. }
    249. position++;
    250. }
    251. }
    252. //函数功能:设置引脚边沿检测模式
    253. //mode=GPIO_MODE_IT_RISING,输入
    254. //mode=GPIO_MODE_IT_FALLING,输入
    255. //mode=GPIO_MODE_IT_RISING_FALLING,输入
    256. //mode=GPIO_MODE_EVT_RISING,输入
    257. //mode=GPIO_MODE_EVT_FALLING,输入
    258. //mode=GPIO_MODE_EVT_RISING_FALLING,输入
    259. //外部引脚边沿检测事件属于输入事件,不属于AF复用功能模式
    260. void Set_Rising_And_Falling_Mode(uint32_t Pin,uint32_t mode)
    261. {
    262. uint32_t temp;
    263. uint32_t position;
    264. uint32_t iocurrent;
    265. position=0;
    266. while( (Pin >> position) != 0x00u )
    267. {
    268. iocurrent = (Pin) & (1uL << position);//获取引脚位置,Get current io position
    269. if(iocurrent != 0x00u)//这个引脚需要配置
    270. {
    271. temp = EXTI->RTSR;//读"上升沿触发选择寄存器EXTI_RTSR"
    272. temp &= ~(iocurrent);
    273. if ((mode & 0x00100000) == 0x00100000)
    274. {
    275. temp |= iocurrent;
    276. }
    277. EXTI->RTSR = temp;//将temp值写入"上升沿触发选择寄存器EXTI_RTSR"
    278. temp = EXTI->FTSR;//读"下降沿触发选择寄存器EXTI_FTSR"
    279. temp &= ~(iocurrent);
    280. if ((mode & 0x00200000) == 0x00200000)
    281. {
    282. temp |= iocurrent;
    283. }
    284. EXTI->FTSR = temp;//将temp值写入"下降沿触发选择寄存器EXTI_FTSR"
    285. }
    286. position++;
    287. }
    288. }
    289. 外部模式配置结束,EXTI Mode Configuration
    290. /*
    291. HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    292. //这个回调函数没啥用,用户可根据需要修改,建议不用,用了后反而不方便程序移植和管理
    293. HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
    294. 用处不大,若"中断服务程序"需要调用该函数,就需要修改HAL_GPIO_EXTI_Callback()
    295. 设置中断源的中断优先级:
    296. NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
    297. 将IRQn中断源的中断优先级设置为priority
    298. HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
    299. 它是通过调用NVIC_SetPriority()来实现的
    300. 将IRQn中断源的中断优先级设置为PreemptPriority,SubPriority在程序中不使用
    301. 0<=PreemptPriority<=3,值越大,表示中断优先级越低
    302. 允许中断源产生中断:
    303. NVIC_EnableIRQ(IRQn_Type IRQn)
    304. 允许中断源IRQn在中断标志建立时能够产生中断
    305. HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
    306. 它是通过调用NVIC_EnableIRQ()来实现的
    307. 允许中断源IRQn在中断标志建立时能够产生中断
    308. 不允许中断源产生中断:
    309. NVIC_DisableIRQ(IRQn_Type IRQn)
    310. 不允许中断源IRQn在中断标志建立时能够产生中断
    311. HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
    312. 它是通过调用NVIC_DisableIRQ()来实现的
    313. 不允许中断源IRQn在中断标志建立时能够产生中断
    314. 读取中断源的中断标志位:
    315. NVIC_GetPendingIRQ(IRQn_Type IRQn)
    316. 读取IRQn中断源的中断标志位
    317. 将中断源的中断标志位置位:
    318. NVIC_SetPendingIRQ(IRQn_Type IRQn)
    319. 将IRQn中断源的中断标志位置1,使其产生中断
    320. 清除中断源的中断标志位:
    321. NVIC_ClearPendingIRQ(IRQn_Type IRQn)
    322. //清除IRQn中断源的中断标志位,使其不产生中断
    323. 清除事件标志位:
    324. __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_X)和__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_X)
    325. 这两个功能相同
    326. 根据GPIO_PIN_x,清除"外部中断挂起寄存器EXTI_PR中的PRx位",
    327. 取消引脚产生的上升沿,下降沿或软件触发产生事件标志位;
    328. 清除事件标志位
    329. 读事件标志位:
    330. __HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_X)和__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_X)
    331. 这两个功能相同
    332. 读"GPIO_PIN_X外部中断线建立的事件标志位"
    333. 在某个外部中断线上上升沿触发事件:
    334. __HAL_GPIO_EXTI_GENERATE_SWIT(GPIO_PIN_X)
    335. 根据GPIO_PIN_x,将"外部软件中断事件寄存器EXTI_SWIER中的SWx位"置1,
    336. 使其产生EXTI line_x上升沿触发事件,进而产生中断,该位由硬件清零;
    337. 普通GPIO功能:
    338. __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA时钟
    339. __HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟
    340. __HAL_RCC_GPIOF_CLK_ENABLE();//使能GPIOF时钟
    341. HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
    342. 根据GPIO_InitTypeDef型结构变量指定的参数初始化GPIOx的外设寄存器
    343. HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
    344. PinState=0,GPIOx端口的GPIO_Pin引脚输出低电平;PinState=1,GPIOx端口的GPIO_Pin引脚输出高电平
    345. HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
    346. GPIOx端口的GPIO_Pin的输出电平翻转
    347. HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
    348. 读取"GPIOx端口的第GPIO_Pin引脚"输入的电平值
    349. HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
    350. 将"GPIOx端口的GPIO_Pin引脚"的外设寄存器恢复到"复位时的默认值"
    351. HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
    352. 锁定GPIO引脚GPIO_Pin的配置;当GPIO_Pin执行了"锁键的写入时序"后,在下次系统复位前将不能再更改端口位的配置;
    353. //这个回调函数没啥用
    354. */

    3、经过测试,可以使用

    1. #include "LED.h"
    2. #include "MyGPIO.h"
    3. void MCU_LED_Init(void);
    4. //函数功能:MCU_LED灯引脚初始化,并配置为关灯
    5. void MCU_LED_Init(void)
    6. {
    7. /*
    8. GPIO_InitTypeDef GPIO_InitStructure;
    9. __HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟
    10. //初始化GPIOB5
    11. GPIO_InitStructure.Pin = GPIO_PIN_5; //选择第5
    12. GPIO_InitStructure.Pull = GPIO_PULLUP; //引脚上拉被激活
    13. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; //配置GPIO速度为极高
    14. GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //设置引脚工作模式为推挽输出方式
    15. HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
    16. //根据GPIO_InitStructure结构变量指定的参数初始化GPIOB的外设寄存器
    17. */
    18. __HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟
    19. Configure_Pin_Direction_mode(GPIOB,GPIO_PIN_5,GPIO_MODE_OUTPUT_PP);
    20. Activate_Pull_up_or_Pull_down_for_Pin(GPIOB,GPIO_PIN_5,GPIO_PULLUP);
    21. MCU_LED_Off();
    22. }

  • 相关阅读:
    ubuntu 22.04通过apt-get安装的apache2将http改造为https的方法
    数字藏品NFT“无聊猿”BAYC的内忧与外患
    阿斯达年代记三强争霸开服 游戏下载安装+账号注册教程一览
    软件测试 08功能自动化 08 基于Python语言的Selenium基础
    初识manim
    【Arduino27】DHT11温湿度传感器模拟值实验
    面试中的情商考察:如何展示你的人际理解能力
    STM32 CubeMX配置USB HID功能,及安装路径
    Ubuntu 20.04 设置开机自启脚本
    Docker数据集与自定义镜像:构建高效容器的关键要素
  • 原文地址:https://blog.csdn.net/weixin_42550185/article/details/132718443