2019-12-12 18:17发布
love_ourdev 发表于 2019-3-18 13:01 ST官方都有APPNOTE指导的(对于UART没有RS485功能的单片机型号而言): 1、启动DMA前,先关闭UART发送完 ...
jaky80000 发表于 2019-3-20 07:33 我在实际测试过程中有这个现象,初始化时并没有开启发送完成中断,在dma传输完成中断里开启发送完成中断 ...
最多设置5个标签!
如果你是使能的DMA传送完成中断,那一定是只是送到串口中了
建议,在DMA中断完成后,可以判断下串口发送完成标志,然后再启动下一次发送
我在实际测试过程中有这个现象,初始化时并没有开启发送完成中断,在dma传输完成中断里开启发送完成中断,在串口发送完成中断由发送转接收,然后清除发送完成标志(SR &= 0XFFBF),然后关闭发送完成中断。这个流程会发现发送出去的字节数会比设定的少两个字节。
分析,按理论上说在开启发送完成中断时,串口数据寄存器和移位寄存器中都还有数据,也就是在如果在串口发送完成中断里如果不关闭发送完成中断,会产生两次中断。但在实际测试过程中发现并没有产生两次中断,而且如果发送完成中断函数只添加发转收,却能正确传输所有数据,并且再下次发起dma传输时也并不会发送完一个字节产生一次发送完成中断,没搞太明白,请帮忙想想,谢谢。
正应了IT界那句名言,“Talk is cheap, show me the code!”,这是我用在STM32F1XX的串口发送代码,USART2用DMA1_Channel7通道发送,你看看:
- void Drv_Usart2TxStream(uint8_t const data[], uint32_t num)
- {
- if(!data || !num){
- return;
- }
- if(is_tx_busy){
- return;
- }
- /* 设置发送忙标志,表示占用硬件 */
- is_tx_busy = TRUE;
-
- /* 清除串口发送完成中断标志 */
- USART_ITConfig(USART2, USART_IT_TC, DISABLE);
- USART_ClearFlag(USART2, USART_FLAG_TC);
- /* 启动DMA发送 */
- DMA1->IFCR = DMA_IFCR_CGIF7;
- DMA1_Channel7->CCR = ((0<<12)|(0<<8)|DMA_CCR7_MINC|DMA_CCR7_DIR);
- DMA1_Channel7->CCR |= (DMA_CCR7_TCIE|DMA_CCR7_TEIE);
- DMA1_Channel7->CPAR = (uint32_t)&USART2->DR;
- DMA1_Channel7->CMAR = (uint32_t)data;
- DMA1_Channel7->CNDTR = (uint16_t)num;
- DMA1_Channel7->CCR |= DMA_CCR7_EN;
- }
- void DMA1_Channel7_IRQHandler(void)
- {
- uint32_t isr = DMA1->ISR;
- DMA1->IFCR = DMA_IFCR_CGIF7;
- if(isr & (DMA_ISR_TEIF7|DMA_ISR_TCIF7)){
- DMA1_Channel7->CCR = 0;
- USART_ITConfig(USART2, USART_IT_TC, ENABLE);
- }
- }
- void USART2_IRQHandler(void)
- {
- // 最后一字节发送完成中断
- if((USART2->CR1 & USART_CR1_TCIE) && (USART2->SR & USART_SR_TC)){
- USART_ITConfig(USART2, USART_IT_TC, DISABLE);
- is_tx_busy = 0;
- // 至此,最后一字节也发送完成了
- }
- }
复制代码代码中更新is_tx_busy变量的地方,对应某些应用种RS485切换方向的地方。
一周热门 更多>