串口发送中断的应用
串口接收中断在各蓝牙芯片的EVT中已经包含,不过并没有提供主机发送中断例程,本篇博客以CH582为例调试串口发送中断。
见手册中下表,发送保持寄存器空,或者使能发送中断时会触发中断。方法很简单,主函数中的处理:①判断标志是否需要发送数据,②将待发送数据拷贝到发送缓存,③手动使能发送中断,触发一次中断。
代码跑进UART中断后,会进入发送寄存器空case,用户代码在这个case中填充待发送数据,一次最多填8字节。发完刚填充完的8字节数据后,FIFO空了,会自动触发中断,如此循环直到发送完。
注意:用户代码填写完所有数据,MCU自动触发最后一次的发送中断,只是表明FIFO空了,移位寄存器中仍有一个字节还没来得及发出去。
#include "CH58x_common.h" struct _u1_send_str_{ uint8_t u1_sending; //正在发送标志,置1表示正在发送 uint8_t u1_send_len; //发送总长度 uint8_t u1_send_cnt; //已发送字节数 }; typedef struct _u1_send_str_ u1_send_str; volatile u1_send_str u1_str1 = {0}; uint8_t u1_tx_Buff[64]; //存放待发送数据 char *Test_Str="0123456789abdef13579bdf02468ace\r\n"; /********************************************************************* * @fn main * * @brief 主函数 * * @return none */ 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(); // UART1_ByteTrigCfg(UART_7BYTE_TRIG); // UART1_INTCfg(ENABLE, RB_IER_RECV_RDY | RB_IER_LINE_STAT | RB_IER_THR_EMPTY); PFIC_EnableIRQ(UART1_IRQn); DelayMs(100); printf("CH582M Init @ChipID=%02X %s %s \r\n", R8_CHIP_ID, __DATE__,__TIME__); while(1) { if(!u1_str1.u1_sending) { u1_str1.u1_send_len = strlen(Test_Str); memcpy(u1_tx_Buff, Test_Str, u1_str1.u1_send_len); //拷贝数据 UART1_INTCfg(ENABLE, RB_IER_THR_EMPTY); //使能发送中断,会置发送缓存空标志,触发中断 DelayMs(1000); } } } /********************************************************************* * @fn UART1_IRQHandler * * @brief UART1中断函数 * * @return none */ __INTERRUPT __HIGH_CODE void UART1_IRQHandler(void) { uint8_t tx_num_now = 0; u1_str1.u1_sending = 1; switch(UART1_GetITFlag()) { case UART_II_LINE_STAT: // 线路状态错误 { UART1_GetLinSTA(); break; } case UART_II_RECV_RDY: // 数据达到设置触发点 break; case UART_II_RECV_TOUT: // 接收超时,暂时一帧数据接收完成 break; case UART_II_THR_EMPTY: // 发送缓存区空,可继续发送 if(u1_str1.u1_send_len) //查看是否需要分包 { if(u1_str1.u1_send_len <= 8) //全部向FIFO填充 { tx_num_now = u1_str1.u1_send_len; u1_str1.u1_send_len = 0; } else //分包填充,一次填8字节 { tx_num_now = 8; u1_str1.u1_send_len -= 8; } for(uint8_t i=0; i<tx_num_now; i++) { R8_UART1_THR = *(u1_tx_Buff + u1_str1.u1_send_cnt + i); //向FIFO填充数据 } u1_str1.u1_send_cnt += tx_num_now; //累计已发送的数据个数 } else //最后一次发送缓存区数据空,处理标志,关发送中断。注意移位寄存器中最后一个字节的数据还没有来得及发出去。 { u1_str1.u1_send_cnt = 0; u1_str1.u1_sending = 0; UART1_INTCfg(DISABLE, RB_IER_THR_EMPTY); } break; case UART_II_MODEM_CHG: // 只支持串口0 break; default: break; } }