[STM32H7] 【STM32H745I-DISCO 试用】+GPIO及使用方法学习

[复制链接]
1151|2
 楼主| jinglixixi 发表于 2025-3-17 22:29 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2025-3-17 22:35 编辑

上一次完成了基础性的测试工作,实现2个LED的按键控制。
开始还以为这样的例程很简单也很基础,在仔细看过程序之后就认识到其实并非看失去的那样平常。
下面就看一下,M4与M7的主程序。
M7的主程序为:
  1. int main(void)
  2. {
  3. MPU_Config();
  4. CPU_CACHE_Enable();
  5. HAL_Init();
  6. SystemClock_Config();
  7. __HAL_RCC_HSEM_CLK_ENABLE();
  8. HAL_HSEM_FastTake(HSEM_ID_0);
  9. HAL_HSEM_Release(HSEM_ID_0,0);
  10. BSP_LED_Init(LED1);
  11. EXTI15_10_IRQHandler_Config();
  12. while (1)
  13. {
  14. }
  15. }

M4的主程序为:
  1. int main(void)
  2. {
  3. __HAL_RCC_HSEM_CLK_ENABLE();
  4. HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
  5. HAL_PWREx_ClearPendingEvent();
  6. HAL_PWREx_EnterSTOPMode(PWR_MAINREGULATOR_ON,PWR_STOPENTRY_WFE, PWR_D2_DOMAIN);
  7. __HAL_HSEM_CLEAR_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
  8. HAL_Init();
  9. BSP_LED_Init(LED2);
  10. HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);
  11. HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
  12. while (1)
  13. {
  14. }
  15. }

发现没有,2个LED是分别存在2个不同的内核程序上运行,且在同一个按键控制下同步进行状态的切换,这就绝非是在单核的情况下,一个按控制2个LED处理场景,它是在双核下实现的一种触发同步处理呀!
所以说,它绝非是表面看上去是按键控制LED,在其背后却是双核控制下的同步机制。
由图1可知,LED1和LED2所连接的引脚分别为PJ2和PI13,这从程序中的定义也可得到印证。
#define LED1_GPIO_PORT                   GPIOJ
#define LED1_PIN                         GPIO_PIN_2
#define LED2_GPIO_PORT                   GPIOI
#define LED2_PIN                         GPIO_PIN_13
9b3a5dddd4a0b4434d95debb01f282af
c7df6429a1112aa094b710941ad6f7e4
图1  LED电路
那在H745I中是如何来配置引脚输出功能呢?
这从LED的初始化函数中可以获得,其内容为:
  1. int32_t BSP_LED_Init(Led_TypeDef Led)
  2. {
  3. int32_t ret = BSP_ERROR_NONE;
  4. GPIO_InitTypeDef gpio_init_structure;
  5. /* Enable the GPIO_LED clock */
  6. if (Led == LED1)
  7. {
  8. LED1_GPIO_CLK_ENABLE() ;
  9. }
  10. else if (Led == LED2)
  11. {
  12. LED2_GPIO_CLK_ENABLE() ;
  13. }
  14. else
  15. {
  16. ret = BSP_ERROR_WRONG_PARAM;
  17. }
  18. /* configure the GPIO_LED pin */
  19. gpio_init_structure.Pin = LED_PIN [Led];
  20. gpio_init_structure.Mode = GPIO_MODE_OUTPUT_PP;
  21. gpio_init_structure.Pull = GPIO_PULLUP;
  22. gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  23. HAL_GPIO_Init(LED_PORT [Led], &gpio_init_structure);
  24. /* By default, turn off LED */
  25. HAL_GPIO_WritePin(LED_PORT [Led], (uint16_t)LED_PIN [Led], GPIO_PIN_SET);
  26. return ret;
  27. }

而对于高低电平的输出,从可从LED状态的控制函数来得到,其控制函数的内容分别为:
  1. int32_t BSP_LED_On(Led_TypeDef Led)
  2. {
  3. int32_t ret = BSP_ERROR_NONE;
  4. HAL_GPIO_WritePin(LED_PORT [Led], (uint16_t)LED_PIN [Led], GPIO_PIN_RESET);
  5. return ret;
  6. }


由图2可知,蓝色按键所连接的引脚为PC13,这由从程序中的定义也可得到印证。
#define BUTTON_USER_PIN                   GPIO_PIN_13
#define BUTTON_USER_GPIO_PORT             GPIOC
6b86c14be2ce9894100a4e57122020d2
图2 按键电路
那在H745I中又是如何来配置引脚输入功能的呢?
这从按键的初始化函数中可以获得,其内容为:
  1. int32_t BSP_PB_Init(Button_TypeDef Button, ButtonMode_TypeDef ButtonMode)
  2. {
  3. GPIO_InitTypeDef gpio_init_structure;
  4. static BSP_EXTI_LineCallback ButtonCallback[BUTTONn] = {BUTTON_USER_EXTI_Callback};
  5. static uint32_t BSP_BUTTON_PRIO [BUTTONn] = {BSP_BUTTON_USER_IT_PRIORITY};
  6. static const uint32_t BUTTON_EXTI_LINE[BUTTONn] = {BUTTON_USER_EXTI_LINE};
  7. /* Enable the BUTTON clock*/
  8. BUTTON_USER_GPIO_CLK_ENABLE();
  9. gpio_init_structure.Pin = BUTTON_PIN [Button];
  10. gpio_init_structure.Pull = GPIO_PULLDOWN;
  11. gpio_init_structure.Speed = GPIO_SPEED_FREQ_HIGH;
  12. if (ButtonMode == BUTTON_MODE_GPIO)
  13. {
  14. /* Configure Button pin as input */
  15. gpio_init_structure.Mode = GPIO_MODE_INPUT;
  16. HAL_GPIO_Init(BUTTON_PORT [Button], &gpio_init_structure);
  17. }
  18. else /* (ButtonMode == BUTTON_MODE_EXTI) */
  19. {
  20. /* Configure Button pin as input with External interrupt */
  21. gpio_init_structure.Mode = GPIO_MODE_IT_RISING;
  22. HAL_GPIO_Init(BUTTON_PORT[Button], &gpio_init_structure);
  23. (void)HAL_EXTI_GetHandle(&hpb_exti[Button], BUTTON_EXTI_LINE[Button]);
  24. (void)HAL_EXTI_RegisterCallback(&hpb_exti[Button], HAL_EXTI_COMMON_CB_ID, ButtonCallback[Button]);
  25. /* Enable and set Button EXTI Interrupt to the lowest priority */
  26. HAL_NVIC_SetPriority((BUTTON_IRQn[Button]), BSP_BUTTON_PRIO[Button], 0x00);
  27. HAL_NVIC_EnableIRQ((BUTTON_IRQn[Button]));
  28. }
  29. return BSP_ERROR_NONE;
  30. }

要读取引脚的电平高低,则可从按键的状态读取函数来获得,其内容为:
  1. int32_t BSP_PB_GetState(Button_TypeDef Button)
  2. {
  3. return (int32_t)HAL_GPIO_ReadPin(BUTTON_PORT[Button], BUTTON_PIN[Button]);
  4. }

下面我们再把问题转回到双核同步响应的机制上,它是以按键来触发中断处理机制,然后在不同的内核中以2个中断响应来实现的。
对中断事件的响应处理,是在M7内核配置的,其函数为:
  1. static void EXTI15_10_IRQHandler_Config(void)
  2. {
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. /* Enable GPIOC clock */
  5. __HAL_RCC_GPIOC_CLK_ENABLE();
  6. /* Configure PC.13 pin as the EXTI input event line in interrupt mode for both CPU1 and CPU2*/
  7. GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING; /* current CPU (CM7) config in IT rising */
  8. GPIO_InitStructure.Pull = GPIO_NOPULL;
  9. GPIO_InitStructure.Pin = GPIO_PIN_13;
  10. HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
  11. /* Enable and set EXTI lines 15 to 10 Interrupt to the lowest priority */
  12. HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0);
  13. HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
  14. /* Configure the second CPU (CM4) EXTI line for IT*/
  15. HAL_EXTI_D2_EventInputConfig(EXTI_LINE13 , EXTI_MODE_IT, ENABLE);
  16. }

在M4内核的响应处理函数为:
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  2. {
  3. if (GPIO_Pin == GPIO_PIN_13)
  4. {
  5. /* Toggle LED2 */
  6. BSP_LED_Toggle(LED2);
  7. }
  8. }

在M7内核的响应处理函数为:
  1. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
  2. {
  3. if (GPIO_Pin == GPIO_PIN_13)
  4. {
  5. /* Toggle LED1 */
  6. BSP_LED_Toggle(LED1);
  7. }
  8. }

这样,就通过一个中断事件在2个内核上实现了同步的响应机制,也我们提供了一个良好应用示例。

yangjiaxu 发表于 2025-4-9 14:39 | 显示全部楼层
其实 要是使用cubemx来弄应该会有一个更好的开发体验,哈哈
 楼主| jinglixixi 发表于 2025-4-9 19:01 | 显示全部楼层
yangjiaxu 发表于 2025-4-9 14:39
其实 要是使用cubemx来弄应该会有一个更好的开发体验,哈哈

说的对!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

521

主题

2949

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部