[G32R] 【极海G32R430 TinyBoard开发板测评】+eint测试

[复制链接]
50|1
yinxiangxv 发表于 2026-5-10 12:11 | 显示全部楼层 |阅读模式
这个是实验的终端输出:

eint.jpg

这个是demo的没有修改时现象:
eint.gif

修改后的现象就是串口输出的那个图片,视频的现象比较一致?
下面提供代码:
  1. /**
  2. *
  3. * [url=/u/file]@file[/url]        main.c
  4. *
  5. * [url=/u/brief]@brief[/url]       Main program body
  6. *
  7. * [url=/u/version]@version[/url]     V1.0.0
  8. *
  9. * [url=/u/date]@date[/url]        2025-10-30
  10. *
  11. * @attention
  12. *
  13. *  Copyright (C) 2025 Geehy Semiconductor
  14. *
  15. *  You may not use this file except in compliance with the
  16. *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
  17. *
  18. *  The program is only for reference, which is distributed in the hope
  19. *  that it will be useful and instructional for customers to develop
  20. *  their software. Unless required by applicable law or agreed to in
  21. *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
  22. *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
  23. *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
  24. *  and limitations under the License.
  25. */

  26. /* Includes ***************************************************************/
  27. #include "main.h"

  28. /* Private includes *******************************************************/
  29. #include "g32r4xx_ddl_usart.h"
  30. #include <stdio.h>

  31. /* Private macro **********************************************************/

  32. /* Private typedef ********************************************************/

  33. /* Private variables ******************************************************/
  34. /* 定义中断计数器 */
  35. volatile uint32_t eint1_cnt = 0;
  36. volatile uint32_t eint2_cnt = 0;
  37. volatile uint8_t eint1_flag = 0; // 增加标志位
  38. volatile uint8_t eint2_flag = 0; // 增加标志位
  39. /* Private function prototypes ********************************************/
  40. void DDL_SysClkConfig(void);
  41. void GPIO_Init(void);
  42. void EINT1_Isr(void);
  43. void EINT2_Isr(void);
  44. /* 1. 在文件顶部定义标准中断函数名,绕过注册 API */
  45. void EINT1_IRQHandler(void);
  46. void EINT2_IRQHandler(void);
  47. /* External variables *****************************************************/

  48. /* External functions *****************************************************/

  49. /**
  50. * @brief     Main program
  51. *
  52. * @param     None
  53. *
  54. * @retval    None
  55. *
  56. */
  57. // int main(void) {
  58. //   /* Configure system clock */
  59. //   DDL_SysClkConfig();

  60. //   /* Configure interrupt group 4: 4-bit preemptive priority, 0-bit
  61. //   subpriority
  62. //    */
  63. //   DDL_NVIC_ConfigPriorityGroup(DDL_NVIC_PRIORITY_GROUP_4);

  64. //   /* Initialize LEDs */
  65. //   BOARD_LEDInit(LED1);
  66. //   BOARD_LEDInit(LED2);

  67. //   /* Turn off LEDs */
  68. //   BOARD_LEDOff(LED1);
  69. //   BOARD_LEDOff(LED2);

  70. //   /* Initialize GPIO as EINT */
  71. //   GPIO_Init();

  72. //   while (1) {
  73. //   }
  74. // }

  75. // int main(void) {
  76. //   DDL_USART_InitTypeDef USART_InitStruct = {0U};

  77. //   /* 1. 直接解锁时钟,但不配置 HSE/PLL (默认使用内部时钟) */
  78. //   DDL_RCM_Unlock();
  79. //   // 暂时跳过 DDL_SysClkConfig(); 看看是不是卡在那里了

  80. //   /* 2. 初始化串口 */
  81. //   USART_InitStruct.BaudRate = 115200U;
  82. //   USART_InitStruct.DataWidth = DDL_USART_DATAWIDTH_8B;
  83. //   USART_InitStruct.StopBits = DDL_USART_STOPBITS_1;
  84. //   USART_InitStruct.Parity = DDL_USART_PARITY_NONE;
  85. //   USART_InitStruct.TransferDirection = DDL_USART_DIRECTION_TX_RX;
  86. //   USART_InitStruct.HardwareFlowControl = DDL_USART_HWCONTROL_NONE;
  87. //   USART_InitStruct.OverSampling = DDL_USART_OVERSAMPLING_16;

  88. //   /* 3. 使用默认配置初始化 */
  89. //   BOARD_COMInit(COM2, &USART_InitStruct);

  90. //   /* 4. 点亮一个 LED 证明程序在跑 */
  91. //   BOARD_LEDInit(LED1);
  92. //   BOARD_LEDOn(LED1);

  93. //   while (1) {
  94. //     /* 直接通过底层 API 发送一个字符 'A' 验证硬件是否连接 */
  95. //     DDL_USART_TransmitData8(USART2, (uint8_t)'A');
  96. //     /* 等待发送寄存器为空 */
  97. //     while (DDL_USART_IsActiveFlag_TXE(USART2) == RESET)
  98. //       ;

  99. //     printf("Hello! I am alive! eint1_cnt = %d\r\n", eint1_cnt);
  100. //     BOARD_LEDToggle(LED1);
  101. //     for (volatile int i = 0; i < 1000000; i++)
  102. //       ;
  103. //   }
  104. // }

  105. int main(void) {
  106.   DDL_SysClkConfig();
  107.   DDL_USART_InitTypeDef USART_InitStruct = {0U};

  108.   /* 1. 解锁并配置系统时钟 (如果之前卡死,可以暂时用内部时钟) */
  109.   DDL_RCM_Unlock();
  110.   DDL_SysClkConfig();

  111.   /* 2. 初始化串口 */
  112.   USART_InitStruct.BaudRate = 115200U;
  113.   USART_InitStruct.DataWidth = DDL_USART_DATAWIDTH_8B;
  114.   USART_InitStruct.StopBits = DDL_USART_STOPBITS_1;
  115.   USART_InitStruct.Parity = DDL_USART_PARITY_NONE;
  116.   USART_InitStruct.TransferDirection = DDL_USART_DIRECTION_TX_RX;
  117.   USART_InitStruct.HardwareFlowControl = DDL_USART_HWCONTROL_NONE;
  118.   USART_InitStruct.OverSampling = DDL_USART_OVERSAMPLING_16;
  119.   BOARD_COMInit(COM2, &USART_InitStruct);

  120.   /* 3. 配置中断分组 (这步非常关键,否则中断可能不响应) */
  121.   DDL_NVIC_ConfigPriorityGroup(DDL_NVIC_PRIORITY_GROUP_4);

  122.   /* 4. 初始化 LED 和 外部中断 GPIO */
  123.   BOARD_LEDInit(LED1);
  124.   BOARD_LEDInit(LED2);
  125.   GPIO_Init(); // 这一步会配置 PC1/PC2 为中断源

  126.   printf("\r\n--- 外部中断 (EINT) 计数器测试正式开始 ---\r\n");

  127.   while (1) {
  128.     // 心跳包,证明没死机
  129.     BOARD_LEDToggle(LED1);

  130.     // 在主循环中处理中断打印,避免在中断内打印
  131.     if (eint1_flag) {
  132.       eint1_flag = 0;
  133.       printf("EINT1 (PC1) Triggered! Total: %d\r\n", eint1_cnt);
  134.     }

  135.     if (eint2_flag) {
  136.       eint2_flag = 0;
  137.       printf("EINT2 (PC2) Triggered! Total: %d\r\n", eint2_cnt);
  138.     }

  139.     for (volatile int i = 0; i < 5000000; i++)
  140.       ;
  141.   }
  142. }

  143. /**
  144. * @brief   System clock configuration
  145. *
  146. * @param   None
  147. *
  148. * @retval  None
  149. */
  150. void DDL_SysClkConfig(void) {
  151.   /* Unlock clock control registers */
  152.   /* Wait until the registers are unlocked */
  153.   DDL_RCM_Unlock();
  154.   while ((RCM->KEY & RCM_KEY_KEYST) != RCM_KEY_KEYST) {
  155.   }

  156.   /* Enable HSE and wait for ready */
  157.   /* Enable HSE input clock */
  158.   DDL_RCM_HSE_Enable();
  159.   /* Wait until HSE is ready */
  160.   while (DDL_RCM_HSE_IsReady() != 1) {
  161.     /* wait for HSERDY */
  162.   }

  163.   /* Configure Flash wait states appropriate for 120 MHz */
  164.   /* Set Flash wait period to accommodate higher frequency */
  165.   DDL_FLASH_SetWaitPeriod(FLASH_DDL_WAIT_PERIOD_3);
  166.   /* Set Flash erase time base to 120 MHz (use 119 to represent 120 MHz) */
  167.   DDL_FLASH_SetEraseTimeBase(119);

  168.   /* Configure PLL */
  169.   /* Ensure PLL is disabled prior to configuration */
  170.   DDL_RCM_PLL_Disable();

  171.   /* Configure PLL settings: multiplier, prescaler, and clock source */
  172.   /* PLL multiplier set to 15 (x15), prescaler no division, clock source from
  173.    * HSE */
  174.   DDL_RCM_PLL_SetMultiplier(15);
  175.   DDL_RCM_PLL_SetPrescaler(DDL_RCM_PLL_DIV1);
  176.   DDL_RCM_PLL_SetClkSource(DDL_RCM_PLL_CLKSOURCE_HSE);

  177.   /* Enable PLL and wait for ready */
  178.   DDL_RCM_PLL_Enable();
  179.   while (DDL_RCM_PLL_IsReady() != 1) {
  180.     /* wait for PLL Ready */
  181.   }

  182.   /* Switch system clock to PLL output */
  183.   DDL_RCM_SetSysClkSource(DDL_RCM_SYS_CLKSOURCE_PLL);

  184.   /* Enable clock switch and wait for completion */
  185.   DDL_RCM_EnableSysClkSwitch();
  186.   while (DDL_RCM_IsActiveFlag_SWDONE() != 1) {
  187.   }

  188.   /* Set AHB, APB prescalers */
  189.   DDL_RCM_SetAHBPrescaler(DDL_RCM_AHB_DIV_1);
  190.   DDL_RCM_SetAPBPrescaler(DDL_RCM_APB_DIV_1);

  191.   /* Disable clock switch controls */
  192.   DDL_RCM_DisableSysClkSwitch();

  193.   /* Lock clock control registers */
  194.   DDL_RCM_Unlock();

  195.   /* Update SystemCoreClock if used by the project */
  196.   SystemCoreClockUpdate();
  197. }

  198. /*!
  199. * @brief     ADC Init
  200. *
  201. * @param     None
  202. *
  203. * @retval    None
  204. */
  205. void GPIO_Init(void) {
  206.   DDL_GPIO_InitTypeDef GPIO_InitStruct = {0U};
  207.   DDL_EINT_InitTypeDef EINT_InitStruct = {0U};

  208.   /* Config Clock */
  209.   DDL_RCM_Unlock();
  210.   DDL_RCM_EnableAHBPeripheral(DDL_RCM_AHB_PERIPHERAL_GPIO);
  211.   DDL_RCM_EnableAPBPeripheral(DDL_RCM_APB_PERIPHERAL_EINT);
  212.   DDL_RCM_Lock();

  213.   /* Config PC1, PC2 as EINT */
  214.   GPIO_InitStruct.Pin = DDL_GPIO_PIN_1 | DDL_GPIO_PIN_2;
  215.   GPIO_InitStruct.Mode = DDL_GPIO_MODE_INPUT;
  216.   GPIO_InitStruct.Speed = DDL_GPIO_SPEED_FREQ_HIGH;
  217.   GPIO_InitStruct.OutputType = DDL_GPIO_OUTPUT_PUSHPULL;
  218.   GPIO_InitStruct.Pull = DDL_GPIO_PULL_UP;
  219.   GPIO_InitStruct.Alternate = DDL_GPIO_AF_0;
  220.   DDL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  221.   /* Set EINT line source to port C */
  222.   DDL_EINT_SetLineSource(DDL_EINT_LINE_1, DDL_EINT_LINE_SOURCE_GPIOC);
  223.   DDL_EINT_SetLineSource(DDL_EINT_LINE_2, DDL_EINT_LINE_SOURCE_GPIOC);

  224.   /* Config EINT */
  225.   EINT_InitStruct.Line = DDL_EINT_LINE_1 | DDL_EINT_LINE_2;
  226.   EINT_InitStruct.LineCommand = ENABLE;
  227.   EINT_InitStruct.Mode = DDL_EINT_MODE_IT;
  228.   EINT_InitStruct.Trigger = DDL_EINT_TRIGGER_FALLING;
  229.   DDL_EINT_Init(&EINT_InitStruct);

  230.   DDL_Interrupt_Register(EINT1_IRQn, EINT1_Isr);
  231.   DDL_Interrupt_Register(EINT2_IRQn, EINT2_Isr);

  232.   DDL_NVIC_EnableIRQRequest(EINT1_IRQn, 0, 0);
  233.   DDL_NVIC_EnableIRQRequest(EINT2_IRQn, 0, 0);
  234. }

  235. /*!
  236. * @brief     EINT0 interrupt service routine
  237. *
  238. * @param     None
  239. *
  240. * @retval    None
  241. */
  242. // void EINT1_Isr(void)
  243. // {
  244. //     if (DDL_EINT_ReadFlag(DDL_EINT_LINE_1))
  245. //     {
  246. //         BOARD_LEDToggle(LED1);
  247. //         DDL_EINT_ClearFlag(DDL_EINT_LINE_1);
  248. //     }
  249. // }

  250. // /*!
  251. //  * @brief     EINT1 interrupt service routine
  252. //  *
  253. //  * @param     None
  254. //  *
  255. //  * @retval    None
  256. //  */
  257. // void EINT2_Isr(void)
  258. // {
  259. //     if (DDL_EINT_ReadFlag(DDL_EINT_LINE_2))
  260. //     {
  261. //         BOARD_LEDToggle(LED2);
  262. //         DDL_EINT_ClearFlag(DDL_EINT_LINE_2);
  263. //     }
  264. // }

  265. // void EINT1_Isr(void) {
  266. //   if (DDL_EINT_ReadFlag(DDL_EINT_LINE_1)) {
  267. //     eint1_cnt++;           // 计数器加 1
  268. //     BOARD_LEDToggle(LED1); // 翻转 LED1 状态

  269. //     /*
  270. //     实时通过串口打印当前计数值(注意:生产环境不建议在中断里打印,测试可以)
  271. //      */
  272. //     printf("EINT1 (PC1) Triggered! Total: %d\r\n", eint1_cnt);

  273. //     DDL_EINT_ClearFlag(DDL_EINT_LINE_1); // 清除中断标志
  274. //   }
  275. // }

  276. void EINT1_Isr(void) {
  277.   if (DDL_EINT_ReadFlag(DDL_EINT_LINE_1)) {
  278.     eint1_cnt++;
  279.     eint1_flag = 1; // 通知主循环打印
  280.     DDL_EINT_ClearFlag(DDL_EINT_LINE_1);
  281.   }
  282. }

  283. void EINT2_Isr(void) {
  284.   if (DDL_EINT_ReadFlag(DDL_EINT_LINE_2)) {
  285.     eint2_cnt++;
  286.     eint2_flag = 1; // 通知主循环打印
  287.     BOARD_LEDToggle(LED2);
  288.     DDL_EINT_ClearFlag(DDL_EINT_LINE_2);
  289.   }
  290. }

  291. /* 5. 核心:直接实现硬件中断函数名 (由 startup_g32r4xx.s 调用) */
  292. void EINT1_IRQHandler(void) {
  293.   if (DDL_EINT_ReadFlag(DDL_EINT_LINE_1)) {
  294.     eint1_cnt++;
  295.     BOARD_LEDToggle(LED2);                // 触发时 LED2 闪烁
  296.     DDL_USART_TransmitData8(USART2, '!'); // 触发时发个感叹号
  297.     DDL_EINT_ClearFlag(DDL_EINT_LINE_1);
  298.   }
  299. }

  300. /* 5. 核心:直接实现硬件中断函数名 (由 startup_g32r4xx.s 调用) */
  301. void EINT2_IRQHandler(void) {
  302.   if (DDL_EINT_ReadFlag(DDL_EINT_LINE_2)) {
  303.     eint2_cnt++;
  304.     BOARD_LEDToggle(LED2);                // 触发时 LED2 闪烁
  305.     DDL_USART_TransmitData8(USART2, '!'); // 触发时发个感叹号
  306.     DDL_EINT_ClearFlag(DDL_EINT_LINE_2);
  307.   }
  308. }

  309. /* ========================================================================= */
  310. /* printf 重定向 (解决不输出和卡死的核心) */
  311. /* ========================================================================= */
  312. #if defined(__CC_ARM) || defined(__ARMCC_VERSION)
  313. int fputc(int ch, FILE *f) {
  314.   /* 假设你用的是 USART2,如果不是请修改 */
  315.   DDL_USART_TransmitData8(USART2, (uint8_t)ch);
  316.   while (DDL_USART_IsActiveFlag_TXE(USART2) == RESET)
  317.     ;
  318.   return ch;
  319. }
  320. #elif defined(__ICCARM__)
  321. int __io_putchar(int ch) {
  322.   DDL_USART_TransmitData8(USART2, (uint8_t)ch);
  323.   while (DDL_USART_IsActiveFlag_TXE(USART2) == RESET)
  324.     ;
  325.   return ch;
  326. }
  327. int __write(int file, char *ptr, int len) {
  328.   int i;
  329.   for (i = 0; i < len; i++) {
  330.     __io_putchar(*ptr++);
  331.   }
  332.   return len;
  333. }
  334. #endif
下次看看有没有什么其他的
笨蛋无需搭理 发表于 2026-6-5 18:50 | 显示全部楼层
代码中处理中断的方式很清晰,通过标志位在主循环中处理打印,避免了中断服务程序中直接打印可能带来的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

70

主题

434

帖子

0

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