C语言串口收发UARTARM,STM32 USART串口DMA 接收和发送的源码详解!

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                      // 设置外设位目标,内存缓冲区 ->外设寄存器

DMA_InitStructure.DMA_BufferSize = LUMMOD_TX_BSIZE;                     // 需要发送的字节数,这里其实可以设置为0,因为在实际要发送的时候,会重新设置次值

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        // 外设地址不做增加调整,调整不调整是DMA自动实现的

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                 // 内存缓冲区地址增加调整

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度8位,1个字节

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         // 内存数据宽度8位,1个字节

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                           // 单次传输模式

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                 // 优先级设置

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                            // 关闭内存到内存的DMA模式

DMA_Init(LUMMOD_UART_Tx_DMA_Channel, &DMA_InitStructure);               // 写入配置

DMA_ClearFlag(LUMMOD_UART_Tx_DMA_FLAG);                                 // 清除DMA所有标志

DMA_Cmd(LUMMOD_UART_Tx_DMA_Channel, DISABLE); // 关闭DMA

DMA_ITConfig(LUMMOD_UART_Tx_DMA_Channel, DMA_IT_TC, ENABLE);            // 开启发送DMA通道中断

/*--- LUMMOD_UART_Rx_DMA_Channel DMA Config ---*/

DMA_Cmd(LUMMOD_UART_Rx_DMA_Channel, DISABLE);                           // 关DMA通道

DMA_DeInit(LUMMOD_UART_Rx_DMA_Channel);                                 // 恢复缺省值

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&LUMMOD_UART->DR);// 设置串口接收数据寄存器

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)LumMod_Rx_Buf;         // 设置接收缓冲区首地址

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                     // 设置外设为数据源,外设寄存器 -> 内存缓冲区

DMA_InitStructure.DMA_BufferSize = LUMMOD_RX_BSIZE;                     // 需要最大可能接收到的字节数

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        // 外设地址不做增加调整,调整不调整是DMA自动实现的

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                 // 内存缓冲区地址增加调整

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度8位,1个字节

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;         // 内存数据宽度8位,1个字节

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                           // 单次传输模式

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;                 // 优先级设置

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                            // 关闭内存到内存的DMA模式

DMA_Init(LUMMOD_UART_Rx_DMA_Channel, &DMA_InitStructure);               // 写入配置

DMA_ClearFlag(LUMMOD_UART_Rx_DMA_FLAG);                                 // 清除DMA所有标志

DMA_Cmd(LUMMOD_UART_Rx_DMA_Channel, ENABLE);                            // 开启接收DMA通道,等待接收数据

}

void BSP_Init(void)

{

Uart_Init();

}

//============================================================//

DMA 发送应用源码

void DMA1_Channel2_IRQHandler(void)

{

if(DMA_GetITStatus(DMA1_FLAG_TC2))

{

LumMod_Uart_DAM_Tx_Over();

}

}

void LumMod_Uart_DAM_Tx_Over(void)

{

DMA_ClearFlag(LUMMOD_UART_Tx_DMA_FLAG);         // 清除标志

DMA_Cmd(LUMMOD_UART_Tx_DMA_Channel, DISABLE);   // 关闭DMA通道

OSMboxPost(mbLumModule_Tx, (void*)1);           // 设置标志位,这里我用的是UCOSII ,可以根据自己的需求进行修改

}

void LumMod_Cmd_WriteParam( uint8 sample_num, uint8 *psz_param )

{

uint8 err;

uint8 LumMod_Tx_Index ;

LumMod_Tx_Index = 0;

LumMod_Tx_Buf[LumMod_Tx_Index++] = 1;

LumMod_Tx_Buf[LumMod_Tx_Index++] = 2;

LumMod_Tx_Buf[LumMod_Tx_Index++] = 3;

LumMod_Tx_Buf[LumMod_Tx_Index++] = 4;

LumMod_Tx_Buf[LumMod_Tx_Index++] = 5;

LumMod_Tx_Buf[LumMod_Tx_Index++] = 6;

LumMod_Tx_Buf[LumMod_Tx_Index++] = 7;

LumMod_Tx_Buf[LumMod_Tx_Index++] = 8;

LumMod_Uart_Start_DMA_Tx( LumMod_Tx_Index );

OSMboxPend(mbLumModule_Tx, 0, &err);

}

void LumMod_Uart_Start_DMA_Tx(uint16_t size)

{

LUMMOD_UART_Tx_DMA_Channel->CNDTR = (uint16_t)size; // 设置要发送的字节数目

DMA_Cmd(LUMMOD_UART_Tx_DMA_Channel, ENABLE);        //开始DMA发送

}

//============================================================//

DMA 接收应用源码

void USART3_IRQHandler(void)

{

if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET)  // 空闲中断

{

LumMod_Uart_DMA_Rx_Data();

USART_ReceiveData( USART3 ); // Clear IDLE interrupt flag bit

}

}

void LumMod_Uart_DMA_Rx_Data(void)

{

DMA_Cmd(LUMMOD_UART_Rx_DMA_Channel, DISABLE);       // 关闭DMA ,防止干扰

DMA_ClearFlag( LUMMOD_UART_Rx_DMA_FLAG );           // 清DMA标志位

LumMod_Rx_Data.index = LUMMOD_RX_BSIZE - DMA_GetCurrDataCounter(LUMMOD_UART_Rx_DMA_Channel); //获得接收到的字节数

LUMMOD_UART_Rx_DMA_Channel->CNDTR = LUMMOD_RX_BSIZE;    //  重新赋值计数值,必须大于等于最大可能接收到的数据帧数目

DMA_Cmd(LUMMOD_UART_Rx_DMA_Channel, ENABLE);        /* DMA 开启,等待数据。注意,如果中断发送数据帧的速率很快,MCU来不及处理此次接收到的数据,中断又发来数据的话,这里不能开启,否则数据会被覆盖。有2种方式解决。

}

1. 在重新开启接收DMA通道之前,将LumMod_Rx_Buf缓冲区里面的数据复制到另外一个数组中,然后再开启DMA,然后马上处理复制出来的数据。

2. 建立双缓冲,在LumMod_Uart_DMA_Rx_Data函数中,重新配置DMA_MemoryBaseAddr 的缓冲区地址,那么下次接收到的数据就会保存到新的缓冲区中,不至于被覆盖。*/

OSMboxPost(mbLumModule_Rx,  LumMod_Rx_Buf); // 发送接收到新数据标志,供前台程序查询

c2c9ed493cd281aa86d8a6f5178c4c01.gif [1] [2] 610626052e95c7fbe3d254abc769d9ad.gif

本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值