问题1
主函数:
1 #include "stm32f10x.h" // Device header 2 #include "Delay.h" 4 #include "DMA.h" 5 #include "Serial.h" 7 9 uint8_t arr[3]; 10 int main(void) 11 { 12 int a=0; 13 /*模块初始化*/ 14 OLED_Init(); //OLED初始化 15 Key_Init(); //按键初始化 16 Serial_Init(); //串口初始化 17 MyDMA_TX_Init(DMA1_Channel4,(uint32_t)&USART1->DR,(uint32_t) arr,3); 18 19 20 arr[0]=0x01; 21 arr[1]=0xFA; 22 arr[2]=0x02; 23 SRAM_USART1_Transfer(); 24 25 arr[0]=0x03; 26 arr[1]=0xFB; 27 arr[2]=0x04; 28 SRAM_USART1_Transfer(); 29 30 }
1 #include "DMA.h" 2 3 uint16_t _count; 4 5 void MyDMA_TX_Init(DMA_Channel_TypeDef* DMA_CHx,uint32_t PeripheralAddr,uint32_t MemoryAddr,uint16_t count) 6 { 7 _count=count; 8 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); 9 10 DMA_InitTypeDef DMA_InitStructure; 11 12 DMA_InitStructure.DMA_PeripheralBaseAddr=PeripheralAddr; 13 DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; 14 DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable; 15 16 DMA_InitStructure.DMA_MemoryBaseAddr=MemoryAddr; 17 DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte; 18 DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; 19 20 DMA_InitStructure.DMA_BufferSize=count; 21 DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST; 22 DMA_InitStructure.DMA_M2M=DMA_M2M_Disable; 23 DMA_InitStructure.DMA_Mode=DMA_Mode_Normal; 24 DMA_InitStructure.DMA_Priority=DMA_Priority_High; 25 DMA_Init(DMA_CHx, &DMA_InitStructure); 26 27 // DMA_Cmd(DMA1_Channel4,ENABLE); 28 USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送 29 } 30 31 void SRAM_USART1_Transfer(void) 32 { 33 DMA_Cmd(DMA1_Channel4,DISABLE);//失能DMA通道 34 DMA_SetCurrDataCounter(DMA1_Channel4, _count);//将传输计数器赋值 35 DMA_Cmd(DMA1_Channel4,ENABLE);//使能DMA 36 37 while(DMA_GetFlagStatus(DMA1_FLAG_TC4)==RESET);//等待DMA转运完成 38 DMA_ClearFlag(DMA1_FLAG_TC4); 39 }
黄色的地方取消注释:
初始化后根本没有程序触发DMA搬运数据,为什么会有00的出现
问题2
1 Serial_SendByte(0x01); 2 arr[0]=0xFA; 3 // Delay_ms(500); 4 SRAM_USART1_Transfer(); 5 Serial_SendByte(0x02);
当我把黄色的注释掉的时候DMA转运的数据没有显示到串口上,也就是用DMA向串口转运数据后立刻向这个串口的串口数据寄存器写数据会导致DMA转运失败
我查了一下DMA不会在你让它转运数据的时候立刻转运数据,也就是DMA想转运数据的时候串口数据寄存器被占了
STM32利用DMA发送无法正确发送数据的问题_stm32f hal usart dma 发送 数据 不正确-CSDN博客
问题3
问题3.1
使用串口空中断,当空中断到来的时候需要延时大概40ms才能收到正常数据
1 void USART3_IRQHandler(void) 2 { 3 uint8_t clear=clear; 4 if (USART_GetITStatus(USART3, USART_IT_IDLE) != RESET) 5 { 6 7 Delay_ms(40); 8 SRAM_USART1_Transfer((uint32_t) USART3_RX_BUF,40);//在最前面,而且处理数据要延时之后才能处理 9 DMA_Cmd(DMA1_Channel3,DISABLE); 10 DMA_SetCurrDataCounter(DMA1_Channel3, 200);//将传输计数器赋值 11 DMA_Cmd(DMA1_Channel3,ENABLE); 12 13 clear = USART3->SR; //读寄存器就等于清寄存器 14 clear = USART3->DR; //读寄存器就等于清寄存器 15 16 } 17 }
不加延时:
加延时:
问题3.2
1 Delay_ms(500); 2 USART3_RX_LEN = USART3_MAX_RECV_LEN - DMA1_Channel3->CNDTR;//计算DMA搬运了几个字节的数据,也就是串口3接收到了几个字节的数据 3 if(USART3_RX_BUF[0]==0xFF) 4 { 5 // pUSART1_TX_FLOAT=(void*)(USART3_RX_BUF+1);//接收到的第一个元素是帧头,用来判断是命令还是数据的 6 // for(uint16_t i=0;i<(USART3_RX_LEN/4);i++) 7 // { 8 // sprintf(USART_RXChange_BUF+i*8,"%05.3f",pUSART1_TX_FLOAT[i]); 9 // USART_RXChange_BUF[6+i*8]='\r'; 10 // USART_RXChange_BUF[7+i*8]='\n'; 11 // } 12 // SRAM_USART1_Transfer((uint32_t) USART_RXChange_BUF,(USART3_RX_LEN/4)*8);//在最前面,而且处理数据要延时之后才能处理 13 u1_printf("%d\r\n",USART3_RX_LEN); 14 }
而且DMA的转运次数和延时有关,当我给网关81个字节数据时(20个4字节数据加一个字节的帧头),延时500ms,DMA的传输计数器减了81,数据全都得到了,但是延时40ms传输计数器减了41,只得到了10个数据,因此我怀疑DMA没有转运开始,串口中断就进入了,延时只是等待转运完成。根据问题2猜测是:串口3接收到了数据,RXNE位置1,DMA没有及时将数据搬走,导致出现了总线空闲,进入了串口空中断。