本帖最后由 JunKook 于 2022-11-1 12:44 编辑
使用DMA传输可以连续获取或发送一段信息而不占用中断或延时,在通信频繁或有大段信息要传输时非常有用,今天给大家分享一篇APM32F103的USART数据发送使用DMA方式传输的例程,本例程使用USART1的PA9作为TX,PA10作为RX,USART1的初始化配置如下:void USART1_Init(uint32_t bound)
{
GPIO_Config_T GPIO_ConfigStruct;
USART_Config_T USART_ConfigStruct;
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA); /* 使能GPIOA时钟 */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART1); /* 使能USART1时钟 */
/* USART1_TX --> PA9*/
GPIO_ConfigStruct.pin = GPIO_PIN_9;
GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP; //复用推挽输出
GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
GPIO_Config(GPIOA, &GPIO_ConfigStruct); //初始化PA9
/* USART1_RX --> PA10*/
GPIO_ConfigStruct.pin = GPIO_PIN_10;
GPIO_ConfigStruct.mode = GPIO_MODE_IN_PU; //上拉输入
GPIO_Config(GPIOA, &GPIO_ConfigStruct); //初始化PA10
/* USART Configuration */
USART_ConfigStruct.baudRate = bound;//波特率
USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;//无硬件数据流控制
USART_ConfigStruct.mode = USART_MODE_TX_RX;//收发模式
USART_ConfigStruct.parity = USART_PARITY_NONE; //无奇偶校验位
USART_ConfigStruct.stopBits = USART_STOP_BIT_1;//一个停止位
USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;//字长为8位数据格式
USART_Config(USART1, &USART_ConfigStruct);
USART_EnableDMA(USART1, USART_DMA_TX);
USART_Enable(USART1);
}
USART_EnableDMA(USART1, USART_DMA_TX)这个API函数即是使能USART1的发送数据使用DMA方式。
接下来是DMA的初始化配置,由于本例程是USART1的TX采用DMA方式传输,所以在配置DMA之前我们一定要先明确USART1的TX对应到DMA哪个通道?通过查询用户手册,我们知道USART1的TX对应到DMA1的通道4,如下图所示。
然后开始初始化配置,如下所示:
void DMA_Init(void)
{
DMA_Config_T DMA_ConfigStruct;
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1); /* 使能DMA1时钟 */
DMA_Reset(DMA1_Channel4); /* 复位DMA1通道1 */
DMA_ConfigStruct.peripheralBaseAddr = USART1_DR_Address; /* DMA通道外设基地址 */
DMA_ConfigStruct.memoryBaseAddr = (uint32_t)UART_TX_Buff; /* DMA通道数据存储器 */
DMA_ConfigStruct.dir = DMA_DIR_PERIPHERAL_DST; /* 指定外设为目的地址 */
DMA_ConfigStruct.bufferSize = DMA_DATA_LENGTH; /* DMA缓冲区大小*/
DMA_ConfigStruct.peripheralInc = DMA_PERIPHERAL_INC_DISABLE; /* 当前外设寄存器地址不变(即不自增) */
DMA_ConfigStruct.memoryInc = DMA_MEMORY_INC_ENABLE; /* 当前存储器地址:Disable不变,Enable递增(用于多通道采集) */
DMA_ConfigStruct.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_BYTE; /* 外设数据宽度8位 */
DMA_ConfigStruct.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE; /* 存储器数据宽度8位 */
DMA_ConfigStruct.loopMode = DMA_MODE_NORMAL; /* DMA通道操作模式位环形缓冲模式 */
DMA_ConfigStruct.priority = DMA_PRIORITY_HIGH; /* DMA通道优先级高 */
DMA_ConfigStruct.M2M = DMA_M2MEN_DISABLE; /* 禁止DMA通道存储器到存储器传输 */
DMA_Config(DMA1_Channel4, &DMA_ConfigStruct);
//NVIC_EnableIRQRequest(DMA1_Channel4_IRQn, 1, 1);
//DMA_EnableInterrupt(DMA1_Channel4, DMA_INT_TC);
}
这里是否要使能DMA传输完成中断,用户根据自身需求选择配置,本例使用while方式,等待传输完成。参数中USART1_DR_Address是USART1的数据寄存器地址,查阅手册为0x40013800+0x04,传输方向为DMA_DIR_PERIPHERAL_DST,即由内存到外设,外设地址为目的地址。
以上初始化配置完成之后,下面开始进行传输试验,代码如下:
DMA_ConfigDataNumber(DMA1_Channel4, 10);
DMA_Enable(DMA1_Channel4); //USART1_TX通道
while(!DMA_ReadStatusFlag(DMA1_FLAG_TC4));//等待传输完成
DMA_ClearStatusFlag(DMA1_FLAG_TC4);//清除传输完成标志
DMA_Disable(DMA1_Channel4);
第一行:DMA_ConfigDataNumber(DMA1_Channel4, 10)是配置DMA通道要传输数据的数量的API函数,其中第一个参数是DMA通道,第二个参数是数据的数量;
第二行:DMA_Enable(DMA1_Channel4)是开启DMA,即可自动发送UART_TX_Buff中的数据到USART1的数据寄存器中,此时USART的发送数据也开始启动;
第三行:while(!DMA_ReadStatusFlag(DMA1_FLAG_TC4))是等待DMA1的通道4传输完成;
第四行:DMA_ClearStatusFlag(DMA1_FLAG_TC4)是清除传输完成标志;
第五行:DMA_Disable(DMA1_Channel4)是关闭DMA1的通道4,这一句比较关键,如果DMA1的通道4传输完成后不及时关闭,则USART的发送完成标志(或者中断)一直不会产生,以致于会影响用户判断USART是否已经发送完成。
以上就是APM32F103系列MCU的USART采用DMA方式进行数据传输的例程分享,供大家参考,如有疑问,请及时联系。
|