STM32 的 USART 支持一个总线空闲中断,如果这个中断和DMA配合,能够较好的实现接收不定长数据的功能。
总线空闲中断是在检测到在接收数据后,数据总线上一个字节的时间内,没有再接到数据后发生。也就是RXNE位被置位之后,才开始检测,只被置位一次,除非再次检测到RXNE位被置位,然后才开始检测下一次的总线空闲。
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | // 配置串口3 void USART3_Init(void) { // 使能PORTB口时钟 RCC->APB2ENR |= APB2_IOPB_EN; // 使能串口3时钟 RCC->APB1ENR |= APB1_USART3_EN; // IO口模式设置 GPIOB->CRH &= 0xFFFF00FF; // IO状态设置 GPIOB->CRH |= 0x00008B00; // 复位串口3 RCC->APB1RSTR |= APB1_USART3_EN; // 停止复位 RCC->APB1RSTR &= ~(APB1_USART3_EN); // 波特率 USART3->BRR = (ulMantissa << 4) + ulFraction; // 收发允许,1位停止,无校验位. USART3->CR1 = (0x200C | ulParity | ulData); // 停止位 USART3->CR2 |= ulStop; // 设置DMA DMA_Config(DMA1_Channel2, 1, (ulong)&USART3->DR,(ulong)NULL, 256); // 发送dma使能 USART3->CR3 |= 1 << 7; // 设置DMA DMA_Config(DMA1_Channel3, 0, (ulong)&USART3->DR,(ulong)NULL, 256); // 接收dma使能 USART3->CR3 |= 1 << 6; // 开启DMA DMA_Enable(DMA1_Channel3,(u32)l_ucRecvBuf[2],256); // USART3->CR1|=1<<8; //PE中断使能 USART3->CR1|=1<<4; //空闲中断使能 NVIC_SetPriority(USART3_IRQn, 0); NVIC_EnableIRQ(USART3_IRQn); } // 串口3的中断服务函数 void USART3_IRQHandler(void) { u8 tmp; u8 len; // 响应空闲中断 if( USART3->SR & (1<<4) ) { // 清除状态标志 tmp = USART3->DR; // 获取本次传输数据长度 len = DMA1_Channel3->CNTR; len = 256 - len; // do } } |
得
无论帧是否等长、无论帧中是否包含长度信息、无论是否包含同步位 都能有较好的效果。
失
必须保证单个数据帧是连续的发送过来的,发送端最好是DMA控制的。如果帧数据被间隔,将被拆为两个帧。