金牌会员
 
- 积分
- 1991
- 金钱
- 1991
- 注册时间
- 2014-7-1
- 在线时间
- 188 小时
|
本帖最后由 shenqihao 于 2020-11-30 13:16 编辑
首先感谢正点原子网站网友的分享帮助。
DMA模式的串口接收,有几个注意点
1、内存中的数组地址要32字节对齐,数组大小要32字节整数倍。
比如://SendBuff地址一定要32字节对齐,SEND_BUF_SIZE一定要32字节整数倍
#define SEND_BUF_SIZE 32
u8 SendBuff[SEND_BUF_SIZE]__attribute__((section(".ARM.__at_0x24000000")));
2、关闭DCache,不然读出数据错误。
SCB_InvalidateDCache_by_Addr((uint32_t*)SendBuff,SEND_BUF_SIZE);
3、串口中断可以不开,但接收使能要记得开
//UART3配置
USART3->CR3=1<<6; //使能串口3的DMA发送
USART3->CR1|=1<<2; //串口接收使能
4、MCU读写数组后,要再次关闭DCache
以下是DMA配置,在正点原子例程基础上修改的。
- void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u8 chx,u32 par,u32 mar,u16 ndtr)
- {
- DMA_TypeDef *DMAx;
- DMAMUX_Channel_TypeDef *DMAMUXx;
- u8 streamx;
- if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
- {
- DMAx=DMA2;
- RCC->AHB1ENR|=1<<1; //DMA2时钟使能
- }else
- {
- DMAx=DMA1;
- RCC->AHB1ENR|=1<<0; //DMA1时钟使能
- }
- while(DMA_Streamx->CR&0X01);//等待DMA可配置
- streamx=(((u32)DMA_Streamx-(u32)DMAx)-0X10)/0X18; //得到stream通道号
- if(streamx>=6)DMAx->HIFCR|=0X3D<<(6*(streamx-6)+16); //清空之前该stream上的所有中断标志
- else if(streamx>=4)DMAx->HIFCR|=0X3D<<6*(streamx-4); //清空之前该stream上的所有中断标志
- else if(streamx>=2)DMAx->LIFCR|=0X3D<<(6*(streamx-2)+16); //清空之前该stream上的所有中断标志
- else DMAx->LIFCR|=0X3D<<6*streamx; //清空之前该stream上的所有中断标志
- if((u32)DMA_Streamx>(u32)DMA2)streamx+=8; //如果是DMA2,通道编号+8
- DMAMUXx=(DMAMUX_Channel_TypeDef *)(DMAMUX1_BASE+streamx*4); //得到对应的DMAMUX通道控制地址
- DMAMUXx->CCR=chx&0XFF; //通道选择
-
-
- DMA_Streamx->CR&=~(1<<0); //先全部复位CR寄存器值 //关闭DMA传输
- while(DMA_Streamx->CR&0X1); //确保DMA可以被设置
-
- DMA_Streamx->PAR=par; //DMA外设地址
- DMA_Streamx->M0AR=mar; //DMA 存储器0地址
- DMA_Streamx->NDTR=ndtr; //DMA 存储器0地址
- DMA_Streamx->FCR &=~(1<<2); //直接模式
-
- DMA_Streamx->CR|=1<<4; //传输完成中断使能
- DMA_Streamx->CR|=0<<6; //外设到存储器模式
- DMA_Streamx->CR|=1<<8; //循环模式
- DMA_Streamx->CR|=0<<9; //外设非增量模式
- DMA_Streamx->CR|=1<<10; //存储器增量模式
- DMA_Streamx->CR|=0<<11; //外设数据长度:8位
- DMA_Streamx->CR|=0<<13; //存储器数据长度:8位
- DMA_Streamx->CR|=0<<16; //低优先级
- DMA_Streamx->CR|=1<<0; //开启DMA
-
- //DMA_Streamx->FCR=0X21; //FIFO控制寄存器
- }
复制代码 以下是串口3的DMA配置
- //Uart3接收使能设置
- void DMA_Uart3ReceiveSet(void)
- {
- //DMA配置
- MYDMA_Config(DMA2_Stream7,45,(u32)&USART3->RDR,(u32)SendBuff,SEND_BUF_SIZE);
- //UART3配置
- USART3->CR3=1<<6; //使能串口3的DMA接收
- USART3->CR1|=1<<2; //串口接收使能
- //不要Cache功能,DMA数据要直接透写进内存,否则读出数据有问题
- //SendBuff地址一定要32字节对齐,SEND_BUF_SIZE一定要32字节整数倍
- SCB_InvalidateDCache_by_Addr((uint32_t*)SendBuff,SEND_BUF_SIZE);
- }
复制代码 最后是主函数里面的while- while(1)
- {
- // t++;
- // Send_Uart3(t);
- delay_ms(1000);
- if((DMA2->HISR&(1<<27)) ==(1<<27))
- {
- DMA2->HIFCR |=1<<27;
- if(SendBuff[SEND_BUF_SIZE-1]!=0)
- {
- for(t=0;t<SEND_BUF_SIZE;t++)
- {
- SendBuffR[t]=SendBuff[t];
- Send_Uart3(SendBuff[t]);
- }
- SendBuff[SEND_BUF_SIZE-1]='\0';
- SCB_InvalidateDCache_by_Addr((uint32_t*)SendBuff,SEND_BUF_SIZE);
- // SendBuff[SEND_BUF_SIZE-1]=0;
- }
- }
- }
复制代码
|
|