【WCH蓝牙系列芯片】-基于CH592开发板—多串口协同与 GPIO 复用引脚释放技巧
------------------------------------------------------------------------------------------------------------------------------------

1、串口3-PA5做串口发送、PA4做普通GPIO
int main() { uint8_t len; uint8_t current_cmd = '0'; // 测试指令,在 '0' 和 '1' 之间切换 SetSysClock(CLK_SOURCE_PLL_60MHz); /* 配置串口1:先配置IO口模式,再配置串口 */ GPIOA_SetBits(GPIO_Pin_9); GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); // RXD-配置上拉输入 GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平 UART1_DefInit(); //将 PA4 彻底释放为普通 GPIO,推挽输出, GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeOut_PP_5mA); GPIOA_ResetBits(GPIO_Pin_4); // 初始默认拉低电平 GPIOA_SetBits(GPIO_Pin_5); // 串口空闲状态为高电平,先拉高避免产生错误起始位 GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeOut_PP_5mA); // PA5 配置为推挽输出,供 UART3 发送使用 // UART3_DefInit(); UART3_BaudRateCfg(115200); R8_UART3_FCR = (2 << 6) | RB_FCR_TX_FIFO_CLR | RB_FCR_RX_FIFO_CLR | RB_FCR_FIFO_EN; R8_UART3_LCR = RB_LCR_WORD_SZ; // PA5 只做接收,我们需要清零 RB_IER_TXD_EN,关闭串口对引脚的强制输出驱动 // 否则 PA5 可能会被内部拉高,导致外部设备发进来的数据无法拉低电平 R8_UART3_IER |= RB_IER_TXD_EN; R8_UART3_DIV = 1; #if 1 // 测试串口发送字符串 UART1_SendString(TxBuff, sizeof(TxBuff)); #endif while(1) { // 通过 PA5 (UART3) 发送 1 个字节的数据 ('1' 或 '0') R8_UART3_THR = current_cmd; // 等待 UART3 数据彻底发送完成 (移位寄存器为空) while((R8_UART3_LSR & RB_LSR_TX_ALL_EMP) == 0); //根据刚才发出的数据,同步改变 PA4 的电平 if(current_cmd == '1') { GPIOA_SetBits(GPIO_Pin_4); // 发送1,拉高PA4 } else if(current_cmd == '0') { GPIOA_ResetBits(GPIO_Pin_4); // 发送0,拉低PA4 } // 用 UART1 接收 PA5 发过来的数据 len = UART1_RecvString(RxBuff); if(len == 0) { // 抓取到了 PA5 发出的信号,通过 PA9 打印 UART1_SendString((uint8_t *)"UART1 Monitored Data from PA5: ", 31); UART1_SendString(RxBuff, len); // 打印一下当前 PA4的值 if(GPIOA_ReadPortPin(GPIO_Pin_4)) { UART1_SendString((uint8_t *)" | PA4 is HIGH\r\n", 16); } else { UART1_SendString((uint8_t *)" | PA4 is LOW\r\n", 15); } } // 切换指令,延时 1 秒, if(current_cmd == '1') { current_cmd = '0'; } else { current_cmd = '1'; } mDelaymS(1000); } #endif
在程序中,将PA4为普通 GPIO(做推挽输出),初始化拉低状态。配置PA5也是推挽输出,用作串口发送。关键在于开启 UART3 对 PA5 的强制发送输出驱动 R8_UART3_IER |= RB_IER_TXD_EN;在主循环中间,先通过PA5的发送保持寄存器R8_UART3_THR 直接发送一个字节数据,然后阻塞等待:读取线状态寄存器(LSR),确认发送FIFO和移位寄存器彻底清空,while((R8_UART3_LSR & RB_LSR_TX_ALL_EMP) == 0);
然后根据发出的数据,同步改变 PA4 的电平,用 UART1串口接收传过来的 PA5 数据。

2、串口3-PA4做串口接收、PA5做普通GPIO
#if 1 int main() { uint8_t len; SetSysClock(CLK_SOURCE_PLL_60MHz); /* 配置串口1:先配置IO口模式,再配置串口 */ GPIOA_SetBits(GPIO_Pin_9); GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); // RXD-配置上拉输入 GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); // TXD-配置推挽输出,注意先让IO口输出高电平 UART1_DefInit(); // 配置 PA4 为串口接收(上拉输入) GPIOA_ModeCfg(GPIO_Pin_4, GPIO_ModeIN_PU); UART3_DefInit(); R8_UART3_IER &= ~RB_IER_TXD_EN; //关闭 UART3 的发送使能,彻底释放 PA5 的控制权给 GPIO // 配置 PA5 为普通 GPIO GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeOut_PP_5mA); GPIOA_ResetBits(GPIO_Pin_5); // 测试:拉低 PA5 #if 1 // 测试串口发送字符串 UART1_SendString(TxBuff, sizeof(TxBuff)); #endif // 查询方式:接收数据后发送出去 while(1) { len = UART3_RecvString(RxBuff); if(len > 0) { // 判断接收到的第一个字节数据 // 注意:这里假设您通过串口助手发送的是字符 if(RxBuff[0] == '1') { // 如果收到字符 '1',将 PA5 置为高电平 GPIOA_SetBits(GPIO_Pin_5); } else if(RxBuff[0] == '0') { // 如果收到字符 '0',将 GPIOA_ResetBits(GPIO_Pin_5); } // 通过 UART1 打印回电脑 UART1_SendString((uint8_t *)"Received cmd: ", 14); UART1_SendString(RxBuff, len); UART1_SendString((uint8_t *)"\r\n", 2); // 换行 // GPIOA_ReadPortPin 返回非 0 表示高电平,返回 0 表示低电平 if (GPIOA_ReadPortPin(GPIO_Pin_5)) { // 此时 PA5 是高电平 UART1_SendString((uint8_t *)"PA5 Current State: HIGH (1)\r\n", 29); } else { // 此时 PA5 是低电平 UART1_SendString((uint8_t *)"PA5 Current State: LOW (0)\r\n", 28); } } } #endif
在程序中配置PA4为上拉输入,PA5为普通GPIO使用,关键的是关闭 UART3 的发送使能,使用寄存器对 R8_UART3_IER &= ~RB_IER_TXD_EN; 阻断了 UART3 外设对 PA5 物理引脚的映射,这样当PA4作为串口接收时,PA5就是GPIO功能,在主循环中,就用串口3接收串口调试工具发送的数据,并根据接收的数据来改变PA5的GPIO的电平变化。

浙公网安备 33010602011771号