问题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没有及时将数据搬走,导致出现了总线空闲,进入了串口空中断。

posted on 2024-01-13 22:10  小凉拖  阅读(14)  评论(0编辑  收藏  举报