STM32F429标准库使用DMA实现串口收发

STM32F429标准库使用DMA实现串口收发

自己使用的代码

全局变量

uint8_t USART1SendBuff[128];
uint8_t USART1ReceiveBuff[128];
uint8_t USART1ReceiveBuffSize;//串口接收数据的长度

uint8_t USART1_Tx_Flage = 0;//串口使用DMA发送数据标志位,1:正在通信;0:通信结束
uint8_t USART1_Rx_Flage = 0;//串口使用DMA接收数据标志位,1:收到数据;0:没有数据

串口初始化

void USART_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    
    //配置GPIO口为复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    //选择具体的复用功能
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
    
    //配置USART参数
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    
    //配置中断
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);    //开启检测串口空闲状态中断,用在接收不定长数据
    USART_ClearITPendingBit(USART1, USART_IT_TC);
    USART_Cmd(USART1, ENABLE);
    
    //配置NVIC
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//优先级低于对应的DMA优先级(1)
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

对应的DMA初始化

void USART_DMA_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    
    //USART1_TX
    DMA_DeInit(DMA2_Stream7);
    while(DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);//确保DMA数据流复位完成
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;//设置DMA源为串口数据寄存器地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART1SendBuff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_BufferSize = sizeof(USART1SendBuff);
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream7, &DMA_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
    DMA_ClearFlag(DMA2_Stream7, DMA_IT_TC);
    USART1_Tx_Flage = 0;
    
    //USART1_RX
    DMA_DeInit(DMA2_Stream2);
    while(DMA_GetCmdStatus(DMA2_Stream2) != DISABLE);//确保DMA数据流复位完成
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;//设置DMA源为串口数据寄存器地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART1ReceiveBuff;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_BufferSize = sizeof(USART1ReceiveBuff);
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream2, &DMA_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    DMA_Cmd(DMA2_Stream2, ENABLE);//初始时打开
    while(DMA_GetCmdStatus(DMA2_Stream2) != ENABLE);
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
    USART1_Rx_Flage = 0;
}

串口重定向

void USART1_Printf(char *format, ...)
{
    uint32_t length;
    va_list arg_ptr;

    while(USART1_Tx_Flage);//等待上一次传输结束

    va_start(arg_ptr, format);
    length = vsnprintf((char*)USART1SendBuff, sizeof(USART1SendBuff)+1, (char*)format, arg_ptr);
    va_end(arg_ptr);
    
    DMA_SetCurrDataCounter(DMA2_Stream7, length);//设置DMA传输的长度
    USART1_Tx_Flage = 1;
    DMA_Cmd(DMA2_Stream7, ENABLE);//开始DMA传输,触发DMA的TC中断
    while(DMA_GetCmdStatus(DMA2_Stream7) != ENABLE);
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
}

串口发送的DMA传输完成中断函数

void DMA2_Stream7_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA2_Stream7, DMA_IT_TCIF7) == SET)
    {
        DMA_Cmd(DMA2_Stream7, DISABLE);//关闭DMA通道
        while(DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);//DMA只有在关闭的时候才能设置一些参数
        DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7 | DMA_IT_HTIF7);
        USART_DMACmd(USART1, USART_DMAReq_Tx, DISABLE);
        USART1_Tx_Flage = 0;
    }
}

串口接收完成中断函数

void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_IDLE) == SET)//接收不定长数据,需要保证接收的数据长度小于DMA的设置长度
    {
        USART_ReceiveData(USART1);
        USART_ClearITPendingBit(USART1, USART_IT_IDLE);//这个中端标志位清除比较特殊,看手册

        DMA_Cmd(DMA2_Stream2, DISABLE);//要先关闭DMA才能触发DMA的标志位
        while(DMA_GetCmdStatus(DMA2_Stream2) != DISABLE);//等待关闭完成
        DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2 | DMA_IT_HTIF2);
        
        USART1ReceiveBuffSize = sizeof(USART1ReceiveBuff) - DMA_GetCurrDataCounter(DMA2_Stream2);//计算获取数据点长度
        USART1_Rx_Flage = 1;

        DMA_SetCurrDataCounter(DMA2_Stream2, sizeof(USART1ReceiveBuff));
        
        DMA_Cmd(DMA2_Stream2, ENABLE);
        while(DMA_GetCmdStatus(DMA2_Stream2) != ENABLE);//等待打开完成
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值