STM32
直播中

颜立歆

7年用户 922经验值
擅长:控制/MCU
私信 关注
[问答]

如何去实现stm32f405串口DMA+空闲中断不定长数据收发代码

如何去实现STM32f405串口DMA+空闲中断不定长数据收发代码?

回帖(1)

余煌木

2021-12-8 14:57:13
stm32f405串口 DMA+空闲中断 不定长数据收发代码

#include "sys.h"
#include "usart.h"
#include
#include "led.h"
//
//
/*
//1,串口通信
UART1_TX PA9  DMA2_Stream7
UART1_RX PA10 DMA2_Stream2
UART2_TX PA2  DMA1_Stream6
UART2_RX PA3  DMA1_Stream5
UART3_TX PB10 DMA1_Stream3
UART3_RX PB11 DMA1_Stream1
UART4_TX PC10 DMA1_Stream4
UART4_RX PC11 DMA1_Stream2
UART5_TX PC12 DMA1_Stream7
UART5_RX PD2  DMA1_Stream0
UART6_TX PC6  DMA2_Stream6
UART6_RX PC7  DMA2_Stream1
*/
#define DMA2_Stream7_Tx1 DMA2_Stream7
#define DMA2_Stream2_Rx1 DMA2_Stream2

#define DMA1_Stream6_Tx2 DMA1_Stream6
#define DMA1_Stream5_Rx2 DMA1_Stream5

#define DMA1_Stream3_Tx3 DMA1_Stream3
#define DMA1_Stream1_Rx3 DMA1_Stream1

#define DMA1_Stream4_Tx4 DMA1_Stream4
#define DMA1_Stream2_Rx4 DMA1_Stream2

#define DMA1_Stream7_Tx5 DMA1_Stream7
#define DMA1_Stream0_Rx5 DMA1_Stream0

#define DMA2_Stream6_Tx6 DMA2_Stream6
#define DMA2_Stream1_Rx6 DMA2_Stream1
//
//

//串口1数据
uint8_t g_RxBuffer1[UART_BUF_SIZE1];  //接收缓冲1
uint8_t g_TxBuffer1[UART_BUF_SIZE1];  //发送缓冲1
uint8_t volatile  g_UartState1;   //UART1工作状态标记

//通讯1数据缓存
u8 Ctr_Rx_Buffer1[UART_BUF_SIZE1];    //通信用缓冲区
u8 Ctr_Tx_Buffer1[UART_BUF_SIZE1];    //通信用缓冲区
uint16_t Ctr_DataLength1;


///
///
void DMA_Configuration1(void);
void uart1_dma_init(uint16_t BaudRate)
{
    GPIO_InitTypeDef    GPIO_InitStructure;
    USART_InitTypeDef   USART_InitStructure;
    NVIC_InitTypeDef    NVIC_InitStructure;
       
    /* 1.使能PA口时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
       
    /* 2.管脚映射 */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); /* GPIOA9复用为USART2 */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); /* GPIOA10复用为USART2 */

    /* 4.配置串口1的PA9和PA10管脚 */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  /* TXIO */

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  /* RXIO */

    /* 5.配置串口工作模式 */
                USART_DeInit(USART1);
    USART_InitStructure.USART_BaudRate            = BaudRate*100;//接电机控制
    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);

    /* 6.设置中断 */
    NVIC_InitStructure.NVIC_IRQChannel                   = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

                /* 7.配置串口中断 */
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//    USART_ITConfig(USART1, USART_IT_TC,   DISABLE);
//    USART_ITConfig(USART1, USART_IT_TXE,  DISABLE);
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);/* 使能IDLE中断 */
                /* 8.使能串口 */
    USART_Cmd(USART1, ENABLE);//使能串口
               
                /* 9.DMA配置*/
                DMA_Configuration1();
               
                 g_UartState1 = UART_IDLE1;
}

///
//*********************串口1DMA设置********************//
//#define DMA2_Stream7_Tx1 DMA2_Stream7
//#define DMA2_Stream2_Rx1 DMA2_Stream2
//uint8_t g_RxBuffer1[UART_BUF_SIZE1];  //接收缓冲1
//uint8_t g_TxBuffer1[UART_BUF_SIZE1];  //发送缓冲1
//uint8_t volatile  g_UartState1;   //UART1工作状态标记

void DMA_Configuration1(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    /* 1.使能DMA2时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
       

    /* 2.配置使用DMA发送数据 */
    DMA_DeInit(DMA2_Stream7_Tx1);

    DMA_InitStructure.DMA_Channel             = DMA_Channel_4;               /* 配置DMA通道 */
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t)(&(USART1->DR));   /* 目的 */
    DMA_InitStructure.DMA_Memory0BaseAddr     = (uint32_t)g_TxBuffer1;             /* 源 雷达的数据*/
    DMA_InitStructure.DMA_DIR                 = DMA_DIR_MemoryToPeripheral;    /* 方向 */
    DMA_InitStructure.DMA_BufferSize          = UART_BUF_SIZE1;                                                            /* 长度 */
    DMA_InitStructure.DMA_PeripheralInc       = DMA_PeripheralInc_Disable;    /* 外设地址是否自增 */
    DMA_InitStructure.DMA_MemoryInc           = DMA_MemoryInc_Enable;         /* 内存地址是否自增 */
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_MemoryDataSize_Byte;      /* 目的数据带宽 */
    DMA_InitStructure.DMA_MemoryDataSize      = DMA_MemoryDataSize_Byte;      /* 源数据宽度 */
    DMA_InitStructure.DMA_Mode                = DMA_Mode_Normal;              /* 单次传输模式/循环传输模式 */
    DMA_InitStructure.DMA_Priority            = DMA_Priority_VeryHigh;             /* DMA优先级 */
    DMA_InitStructure.DMA_FIFOMode            = DMA_FIFOMode_Disable;          /* FIFO模式/直接模式 */
    DMA_InitStructure.DMA_FIFOThreshold       = DMA_FIFOThreshold_HalfFull; /* FIFO大小 */
    DMA_InitStructure.DMA_MemoryBurst         = DMA_MemoryBurst_Single;       /* 单次传输 */
    DMA_InitStructure.DMA_PeripheralBurst     = DMA_PeripheralBurst_Single;

    /* 3. 配置DMA */
    DMA_Init(DMA2_Stream7_Tx1, &DMA_InitStructure);
    /* 4.使能DMA中断 */
//    DMA_ITConfig(DMA2_Stream7_Tx1, DMA_IT_TC, ENABLE);
//                DMA_ITConfig(DMA2_Stream7_Tx1, DMA_IT_TE, ENABLE);
    /* 5.使能串口的DMA发送接口 */
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    /* 7.不使能DMA */
    DMA_Cmd(DMA2_Stream7_Tx1, DISABLE);
               

    /* 2.配置使用DMA接收数据 */
    DMA_DeInit(DMA2_Stream2_Rx1);

    DMA_InitStructure.DMA_Channel             = DMA_Channel_4;                       /* 配置DMA通道 */
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t)(&(USART1->DR));           /* 目的 */
    DMA_InitStructure.DMA_Memory0BaseAddr     = (uint32_t)g_RxBuffer1;   /* 源 雷达的数据*/
    DMA_InitStructure.DMA_DIR                 = DMA_DIR_PeripheralToMemory;   /* 方向 */
    DMA_InitStructure.DMA_BufferSize          = UART_BUF_SIZE3;             /* 长度 */
    DMA_InitStructure.DMA_PeripheralInc       = DMA_PeripheralInc_Disable;    /* 外设地址是否自增 */
    DMA_InitStructure.DMA_MemoryInc           = DMA_MemoryInc_Enable;         /* 内存地址是否自增 */
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_MemoryDataSize_Byte;      /* 目的数据带宽 */
    DMA_InitStructure.DMA_MemoryDataSize      = DMA_MemoryDataSize_Byte;      /* 源数据宽度 */
    DMA_InitStructure.DMA_Mode                = DMA_Mode_Normal;              /* 单次传输模式/循环传输模式 */
    DMA_InitStructure.DMA_Priority            = DMA_Priority_High;             /* DMA优先级 */
    DMA_InitStructure.DMA_FIFOMode            = DMA_FIFOMode_Disable;          /* FIFO模式/直接模式 */
    DMA_InitStructure.DMA_FIFOThreshold       = DMA_FIFOThreshold_HalfFull;    /* FIFO大小 */
    DMA_InitStructure.DMA_MemoryBurst         = DMA_MemoryBurst_Single;        /* 单次传输 */
    DMA_InitStructure.DMA_PeripheralBurst     = DMA_PeripheralBurst_Single;

    /* 3. 配置DMA */
    DMA_Init(DMA2_Stream2_Rx1, &DMA_InitStructure);
    /* 4.使能DMA中断 */
//    DMA_ITConfig(DMA2_Stream2_Rx1, DMA_IT_TC, ENABLE);
//                DMA_ITConfig(DMA2_Stream2_Rx1, DMA_IT_TE, ENABLE);
//                DMA_ITConfig(DMA2_Stream2_Rx1, DMA_IT_HT, ENABLE);
    /* 5.使能串口的DMA发送接口 */
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
    /* 7.使能DMA */
    DMA_Cmd(DMA2_Stream2_Rx1, ENABLE);
}

//
//
extern u32 wcntCK_uartrx_over[6];//接收超时
extern u8  uflagCK_uartrx_over[6];//接收超时
u8  uflagCK_Ctr_Modbus[6];//接收超时

void Ctr_Modbus1(void);
//空闲中断
void USART1_IRQHandler(void)
{
    u16 data, i;

    if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
                        //读SR后读DR清除Idle,下面2行代码不能少,也不能用USART_ClearITPendingBit(USART1, USART_IT_IDLE);来代替
                        data = USART1->SR;
                        data = USART1->DR;
                       
                        //关闭DMA,防止处理其间有数据
      DMA_Cmd(DMA2_Stream2_Rx1, DISABLE); //关闭DMA,防止处理其间有数据
                        //读数据
                        Ctr_DataLength1 =UART_BUF_SIZE1 - DMA_GetCurrDataCounter(DMA2_Stream2_Rx1);
      //处理数据
                        if (Ctr_DataLength1 > 0)
      {
            for (i = 0; i < Ctr_DataLength1; i++) //将数据送DMA存储地址
            {
                Ctr_Rx_Buffer1 = g_RxBuffer1;
            }
      }
                        //重新开始接受DMA数据
                        DMA_Cmd(DMA2_Stream2_Rx1, DISABLE); //改变datasize前先要禁止通道工作
                        DMA_ClearFlag(DMA2_Stream2_Rx1, DMA_FLAG_TCIF2 | DMA_FLAG_FEIF2 | DMA_FLAG_DMEIF2 | DMA_FLAG_TEIF2 | DMA_FLAG_HTIF2); //清除DMA2_Steam7传输完成标志
                        DMA_SetCurrDataCounter(DMA2_Stream2_Rx1, UART_BUF_SIZE1);
                        DMA_Cmd(DMA2_Stream2_Rx1, ENABLE);
                       
                        g_UartState1 = UART_RECV1;
                       
//                        Ctr_Modbus1();//控制通讯 放入主定时循环里
                }

}

//
//#define DMA2_Stream7_Tx1 DMA2_Stream7
//#define DMA2_Stream2_Rx1 DMA2_Stream2
//发送完成中断
void DMA2_Stream7_IRQHandler(void)
{
    u16 data, i;
    //清除标志
    if(DMA_GetFlagStatus(DMA2_Stream7_Tx1, DMA_FLAG_TCIF7) != RESET) //等待DMA2_Steam7传输完成
    {
        DMA_ClearFlag(DMA2_Stream7_Tx1, DMA_FLAG_TCIF7); //清除DMA2_Steam7传输完成标志
    }
}

//接收通道中断
void DMA2_Stream2_IRQHandler(void)
{
    u16 data, i;
    //清除标志
    if(DMA_GetFlagStatus(DMA2_Stream2_Rx1, DMA_FLAG_TCIF2) != RESET) //等待DMA2_Steam7传输完成
    {
        DMA_ClearFlag(DMA2_Stream2_Rx1, DMA_FLAG_TCIF2); //清除DMA2_Steam7传输完成标志
    }
}


//
//dma数据发送
//#define DMA2_Stream7_Tx1 DMA2_Stream7
//#define DMA2_Stream2_Rx1 DMA2_Stream2
void uart1_send_dma(uint8_t *buf, uint8_t len)
{
    DMA_InitTypeDef DMA_InitStructure;
    /* 1.使能DMA1时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
       
          /* 2.配置使用DMA发送数据 */
    DMA_DeInit(DMA2_Stream7_Tx1);
    DMA_InitStructure.DMA_Channel             = DMA_Channel_4;               /* 配置DMA通道 */
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t)(&(USART1->DR));   /* 目的 */
    DMA_InitStructure.DMA_Memory0BaseAddr     = (uint32_t)buf;//数据            /* 源 雷达的数据*/
    DMA_InitStructure.DMA_DIR                 = DMA_DIR_MemoryToPeripheral;    /* 方向 */
    DMA_InitStructure.DMA_BufferSize          = len;//长度                                                   /* 长度 */
    DMA_InitStructure.DMA_PeripheralInc       = DMA_PeripheralInc_Disable;    /* 外设地址是否自增 */
    DMA_InitStructure.DMA_MemoryInc           = DMA_MemoryInc_Enable;         /* 内存地址是否自增 */
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_MemoryDataSize_Byte;      /* 目的数据带宽 */
    DMA_InitStructure.DMA_MemoryDataSize      = DMA_MemoryDataSize_Byte;      /* 源数据宽度 */
    DMA_InitStructure.DMA_Mode                = DMA_Mode_Normal;              /* 单次传输模式/循环传输模式 */
    DMA_InitStructure.DMA_Priority            = DMA_Priority_High;             /* DMA优先级 */
    DMA_InitStructure.DMA_FIFOMode            = DMA_FIFOMode_Disable;          /* FIFO模式/直接模式 */
    DMA_InitStructure.DMA_FIFOThreshold       = DMA_FIFOThreshold_HalfFull; /* FIFO大小 */
    DMA_InitStructure.DMA_MemoryBurst         = DMA_MemoryBurst_Single;       /* 单次传输 */
    DMA_InitStructure.DMA_PeripheralBurst     = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream7_Tx1, &DMA_InitStructure);
               
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
    DMA_ITConfig(DMA2_Stream7_Tx1, DMA_IT_TC, ENABLE);
    DMA_Cmd(DMA2_Stream7_Tx1, ENABLE);
}

//
//DMA发送多字节
//开启一次DMA传输
//数据:g_TxBuffer1
//#define DMA2_Stream7_Tx1 DMA2_Stream7
//#define DMA2_Stream2_Rx1 DMA2_Stream2
void uart1_dma_tx(void)
{
        u8 len=50;
        u8 crc=0x33;
        u8 i;
        //******数据发送位******
        //包头
        g_TxBuffer1[0]=0xBB;
        g_TxBuffer1[1]=0x66;
        g_TxBuffer1[2]=0x15;
        g_TxBuffer1[3]=len;
        //数据区
        //包尾
        g_TxBuffer1[49]=crc;
        //******数据发送******
        uart1_send_dma(g_TxBuffer1, len);
}

//
//
void Ctr_Modbus1(void)
{
    u8 i;
    u8 Command = 0;
          u8 board=0;
          u8 Cmd_length=0;
       
    if (g_UartState1 == UART_RECV1) //接收完成
    {
        i = Ctr_DataLength1;//10长度
                                /*******包头*****/
        if( (Ctr_Rx_Buffer1[0] != 0xBB) || (Ctr_Rx_Buffer1[1] != 0x66))
            return ;
                                /*******板子连接类型*****/
                                board=Ctr_Rx_Buffer1[2];//长度
                                /*******cmd*****/
                                Command =  Ctr_Rx_Buffer1[3];//指令
                                Cmd_length=Ctr_Rx_Buffer1[4];//长度
        switch (Command)
        {
                               
                                }
                }
                g_UartState1 = UART_IDLE1;
}
e1 = UART_IDLE1;}  
举报

更多回帖

发帖
×
20
完善资料,
赚取积分