OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3320|回复: 10

DMA串口接收丢数据,全部积分奉上

[复制链接]

13

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2016-8-15
在线时间
52 小时
发表于 2020-2-23 11:55:39 | 显示全部楼层 |阅读模式
45金钱
本帖最后由 carvenl 于 2020-2-25 11:23 编辑

配好了串口DMA接收,发现总是不规律的丢数据。我写了一段测试程序,没有用中断,由串口助手给STM32发数据,然后在DEBUG里观察DMA缓存里的接收情况。
发现串口接收是正常,串口DR里总能收到发来的最后一个字节,问题就在DMA经常没有完整的传输数据。
测试情况如下,接收数组长度为10。

1.手动发单个字节,DMA传输无误,没有出现丢包。
Inked手动发10个_LI.jpg

2.两个字节一起发,手动发了5次,CNDTR才记录2次。
发现DMA读不到最后一个字节0x36,但是串口里是收到了的。
多次测试,前面一个0x90也有大概率会丢。
Inked手动发5个_LI.jpg

3.三个字节一起发,也是最后一个字节收不到,前两个字节有一定概率会丢包。
Inked手动发3个_LI.jpg

4.四个字节一起发,最魔幻的情况出现了,串口是能收到数据的,但是DMA一个都没有?CNDTR还是10?
Inked手动发n个_LI.jpg

串口和DMA配置如下。

DMA和串口配置的代码如下
  1. #define DMA1_USART1_TX_CHANNEL  DMA1_Channel4
  2. #define DMA1_USART1_RX_CHANNEL  DMA1_Channel5
  3. uint8_t DMA1TxBuf[10];
  4. uint8_t DMA1RxBuf[10];

  5. static void DMA1Init(void)
  6. {
  7.     RCC->AHBENR |= RCC_AHBENR_DMA1EN;//开启DMA1时钟

  8.     /* USART1_TX_DMA Channel4 */
  9.     DMA1_USART1_TX_CHANNEL->CPAR = (uint32_t)(&USART1->TDR);//设置外设地址
  10.     DMA1_USART1_TX_CHANNEL->CMAR = (uint32_t)(&DMA1TxBuf);//设置DMA存储器地址

  11.     DMA1_USART1_TX_CHANNEL->CCR |= DMA_CCR_DIR;//从内存到外设
  12.     DMA1_USART1_TX_CHANNEL->CCR |= DMA_CCR_MINC;//存储器地址增量模式
  13.     DMA1_USART1_TX_CHANNEL->CCR |= DMA_CCR_PL_0;//通道优先级:中

  14.     /* USART1_RX_DMA Channel5 */
  15.     DMA1_USART1_RX_CHANNEL->CPAR = (uint32_t)(&USART1->RDR);//设置外设地址
  16.     DMA1_USART1_RX_CHANNEL->CMAR = (uint32_t)(&DMA1RxBuf);//设置DMA存储器地址

  17.     DMA1_USART1_RX_CHANNEL->CCR |= DMA_CCR_MINC;//存储器地址增量模式
  18.     DMA1_USART1_RX_CHANNEL->CCR |= DMA_CCR_PL_1;//通道优先级:高
  19. }

  20. static void USART1Init(void)
  21. {
  22.     RCC->APB2ENR |= RCC_APB2ENR_USART1EN;//使能usart1时钟,PCLK=72M

  23.     gpioInit(USART1_TX_PORT,USART1_TX_PIN,MODER_AF,OTYPER_PP,OSPEEDR_HIG,PUPDR_PU);//复用,上拉
  24.     gpioAF(USART1_TX_PORT,USART1_TX_PIN,7);
  25.     gpioInit(USART1_RX_PORT,USART1_RX_PIN,MODER_AF,OTYPER_PP,OSPEEDR_HIG,PUPDR_PU);//复用,上拉
  26.     gpioAF(USART1_RX_PORT,USART1_RX_PIN,7);

  27.     USART1->CR1 |= USART_CR1_TE;//TE:发送使能
  28.     USART1->CR1 |= USART_CR1_RE;//RC:接收器使能
  29.     USART1->BRR |= 0x271;//波特率115200

  30.     DMA1Init();
  31.     USART1->CR3 |= USART_CR3_DMAT;//DMA发送使能
  32.     USART1->CR3 |= USART_CR3_DMAR;//DMA接收使能

  33.     USART1->CR1 |= USART_CR1_UE;//串口使能
  34.     DMA1Enable(DMA1_USART1_RX_CHANNEL,10);//开启接收,缓存总长度为USART1_BUF_LEN+1
  35. }

  36. void DMA1Enable(DMA_Channel_TypeDef *DMA1_Channelx,uint16_t len)
  37. {
  38.     DMA1_Channelx->CCR &= ~DMA_CCR_EN;//关闭DMA
  39.     while(DMA1_Channelx->CCR & DMA_CCR_EN);//等待DMA传输完
  40.     DMA1_Channelx->CNDTR = len;//传输数量设置为len个,每传输一个字节CNDTR就会减1
  41.     DMA1_Channelx->CCR |= DMA_CCR_EN;//开启DMA
  42. }
复制代码


最佳答案

查看完整内容[请看2#楼]

解决了,我换了一块板就好了,估计是stm32坏了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2016-8-15
在线时间
52 小时
 楼主| 发表于 2020-2-23 11:55:40 | 显示全部楼层
解决了,我换了一块板就好了,估计是stm32坏了
回复

使用道具 举报

3

主题

1155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7462
金钱
7462
注册时间
2015-1-15
在线时间
1367 小时
发表于 2020-2-23 15:19:11 | 显示全部楼层
自己初始化设置有问题,自己照着手册找原因
一分耕耘一分收获。
回复

使用道具 举报

13

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2016-8-15
在线时间
52 小时
 楼主| 发表于 2020-2-23 16:08:44 | 显示全部楼层
yklstudent 发表于 2020-2-23 15:19
自己初始化设置有问题,自己照着手册找原因

感谢回复,愿闻其详。我刚重新看了一下手册,除了中断,其他的我都配置了。

Reception using DMA
DMA mode can be enabled for reception by setting the DMAR bit in USART_CR3 register.
Data is loaded from the USART_RDR register to a SRAM area configured using the DMA
peripheral (refer to Section 12: Direct memory access controller (DMA) on page 183)
whenever a data byte is received. To map a DMA channel for USART reception, use the
following procedure:
1. Write the USART_RDR register address in the DMA control register to configure it as
the source of the transfer. The data is moved from this address to the memory after
each RXNE event.
2. Write the memory address in the DMA control register to configure it as the destination
of the transfer. The data is loaded from USART_RDR to this memory area after each
RXNE event.
3. Configure the total number of bytes to be transferred to the DMA control register.
4. Configure the channel priority in the DMA control register
5. Configure interrupt generation after half/ full transfer as required by the application.
6. Activate the channel in the DMA control register.
When the number of data transfers programmed in the DMA Controller is reached, the DMA
controller generates an interrupt on the DMA channel interrupt vector.
回复

使用道具 举报

5

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
115
金钱
115
注册时间
2017-10-31
在线时间
24 小时
发表于 2020-2-24 09:43:13 | 显示全部楼层
你显示出来得是什么。usart接收到了配置没错。上位机显示出来是你发送得?还是单片机发出来得?你没清那个缓冲区吗
回复

使用道具 举报

13

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2016-8-15
在线时间
52 小时
 楼主| 发表于 2020-2-24 10:43:55 | 显示全部楼层
ioremap 发表于 2020-2-24 09:43
你显示出来得是什么。usart接收到了配置没错。上位机显示出来是你发送得?还是单片机发出来得?你没清那个 ...

左边上位机显示是我发给STM32的,最右边DMA1RxBuf数组是STM32的DMA接收缓存,就会丢数据
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2020-2-24 23:17:50 | 显示全部楼层
论坛有相关帖子,可以参考一下
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

13

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2016-8-15
在线时间
52 小时
 楼主| 发表于 2020-2-25 11:22:16 | 显示全部楼层
正点原子 发表于 2020-2-24 23:17
论坛有相关帖子,可以参考一下

看过很多贴,问题普遍存在,却没有找到解决方法
回复

使用道具 举报

11

主题

95

帖子

0

精华

高级会员

Rank: 4

积分
598
金钱
598
注册时间
2017-3-19
在线时间
116 小时
发表于 2020-2-25 14:58:29 | 显示全部楼层
试下清除DMA接收中断标志位,类似于下面
/****************************************************
函数功能:串口接收DMA重启-单次模式
****************************************************/
void RX_DMA_Restart(void)
{
        DMA_Cmd(DMA1_Stream1, DISABLE );
        while (DMA_GetCmdStatus(DMA1_Stream1) != DISABLE){}
                       
        DMA_ClearFlag(DMA1_Stream1,DMA_FLAG_TCIF1);/*不能删除*/
        DMA_Cmd(DMA1_Stream1, ENABLE);           //开启DMA传输               
}
回复

使用道具 举报

3

主题

1155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
7462
金钱
7462
注册时间
2015-1-15
在线时间
1367 小时
发表于 2020-2-25 15:37:36 | 显示全部楼层
uint8_t m_dma_recv_buf[eUSARTn][USART_DMA_RECV_SIZE];
uint8_t m_dma_send_buf[eUSARTn][USART_DMA_SEND_SIZE];

const usart_type usart_handlers[eUSARTn] =
{
    [eUSART1] =
    {
        .irq_vector                     = USART1_IRQn,
        .mpriority                      = 1,
        .spriority                      = 1,
        .port                           = USART1,
        .pin_tx                         = &gpio_handlers[eUSART1Tx],
        .pin_rx                         = &gpio_handlers[eUSART1Rx],
        .pin_cts                        = NULL,
        .pin_rts                        = NULL,
                .pin_en                                                        = &gpio_handlers[eUSART1En],
                .pin_en_config                                  = &pin_config_handlers[eUSART1En],
        .tx_dma_config =
        {
            .irq_vector                 = DMA2_Stream7_IRQn,
            .mpriority                  = 2,
            .spriority                  = 1,
            .controller                 = DMA2,
            .stream                     = DMA2_Stream7,
            .channel                    = DMA_Channel_4,
            .complete_flags             = DMA_IT_TCIF7,
            .error_flags                = 0,
        },
        .rx_dma_config =
        {
            .irq_vector                 = DMA2_Stream2_IRQn,
            .mpriority                  = 2,
            .spriority                  = 1,
            .controller                 = DMA2,
            .stream                     = DMA2_Stream2,
            .channel                    = DMA_Channel_4,
            .complete_flags             = DMA_IT_TCIF2,
            .error_flags                = 0,
        },
    },
    [eUSART2] =
    {
        .irq_vector                     = USART2_IRQn,
        .mpriority                      = 1,
        .spriority                      = 1,
        .port                           = USART2,
        .pin_tx                         = &gpio_handlers[eUSART2Tx],
        .pin_rx                         = &gpio_handlers[eUSART2Rx],
        .pin_cts                        = NULL,
        .pin_rts                        = NULL,
                .pin_en                                                        = &gpio_handlers[eUSART2En],
                .pin_en_config                                  = &pin_config_handlers[eUSART2En],
        .tx_dma_config =
        {
            .irq_vector                 = DMA1_Stream6_IRQn,
            .mpriority                  = 2,
            .spriority                  = 1,
            .controller                 = DMA1,
            .stream                     = DMA1_Stream6,
            .channel                    = DMA_Channel_4,
            .complete_flags             = DMA_IT_TCIF6,
            .error_flags                = 0,
        },
        .rx_dma_config =
        {
            .irq_vector                 = DMA1_Stream5_IRQn,
            .mpriority                  = 2,
            .spriority                  = 1,
            .controller                 = DMA1,
            .stream                     = DMA1_Stream5,
            .channel                    = DMA_Channel_4,
            .complete_flags             = DMA_IT_TCIF5,
            .error_flags                = 0,
        },
    },
    [eUSART3] =
    {
        .irq_vector                     = USART3_IRQn,
        .mpriority                      = 1,
        .spriority                      = 1,
        .port                           = USART3,
        .pin_tx                         = &gpio_handlers[eUSART3Tx],
        .pin_rx                         = &gpio_handlers[eUSART3Rx],
        .pin_cts                        = NULL,
        .pin_rts                        = NULL,
                .pin_en                                                        = &gpio_handlers[eUSART3En],
                .pin_en_config                                  = &pin_config_handlers[eUSART3En],
        .tx_dma_config =
        {
            .irq_vector                 = DMA1_Stream3_IRQn,
            .mpriority                  = 2,
            .spriority                  = 1,
            .controller                 = DMA1,
            .stream                     = DMA1_Stream3,
            .channel                    = DMA_Channel_4,
            .complete_flags             = DMA_IT_TCIF3,
            .error_flags                = 0,
        },
        .rx_dma_config =
        {
            .irq_vector                 = DMA1_Stream1_IRQn,
            .mpriority                  = 2,
            .spriority                  = 1,
            .controller                 = DMA1,
            .stream                     = DMA1_Stream1,
            .channel                    = DMA_Channel_4,
            .complete_flags             = DMA_IT_TCIF1,
            .error_flags                = 0,
        },
    },
    [eUSART6] =
    {
        .irq_vector                     = USART6_IRQn,
        .mpriority                      = 1,
        .spriority                      = 1,
        .port                           = USART6,
        .pin_tx                         = &gpio_handlers[eUSART6Tx],
        .pin_rx                         = &gpio_handlers[eUSART6Rx],
        .pin_cts                        = NULL,
        .pin_rts                        = NULL,
                .pin_en                                                        = &gpio_handlers[eUSART6En],
                .pin_en_config                                  = &pin_config_handlers[eUSART6En],
        .tx_dma_config =
        {
            .irq_vector                 = DMA2_Stream6_IRQn,
            .mpriority                  = 2,
            .spriority                  = 1,
            .controller                 = DMA2,
            .stream                     = DMA2_Stream6,
            .channel                    = DMA_Channel_5,
            .complete_flags             = DMA_IT_TCIF6,
            .error_flags                = 0,
        },
        .rx_dma_config =
        {
            .irq_vector                 = DMA2_Stream1_IRQn,
            .mpriority                  = 2,
            .spriority                  = 1,
            .controller                 = DMA2,
            .stream                     = DMA2_Stream1,
            .channel                    = DMA_Channel_5,
            .complete_flags             = DMA_IT_TCIF1,
            .error_flags                = 0,
        },
    },
};

const usart_config_type usart_config_handlers[eUSARTn] =
{
    [eUSART1] = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED, 0},
    [eUSART2] = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED, 0},
    [eUSART3] = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED, 0},
    [eUSART6] = {115200, DATA_WIDTH_8BIT, NO_PARITY, STOP_BITS_1, FLOW_CONTROL_DISABLED, 0},
};

static const uint8_t usart_alternate_functions[eUSARTn] =
{
    [eUSART1] = GPIO_AF_USART1,
    [eUSART2] = GPIO_AF_USART2,
    [eUSART3] = GPIO_AF_USART3,
    [eUSART6] = GPIO_AF_USART6,
};

static const mico_peripheral_clock_function_type usart_peripheral_clock_functions[eUSARTn] =
{
    [eUSART1] = RCC_APB2PeriphClockCmd,
    [eUSART2] = RCC_APB1PeriphClockCmd,
    [eUSART3] = RCC_APB1PeriphClockCmd,
    [eUSART6] = RCC_APB2PeriphClockCmd,
};

static const uint32_t usart_peripheral_clocks[eUSARTn] =
{
    [eUSART1] = RCC_APB2Periph_USART1,
    [eUSART2] = RCC_APB1Periph_USART2,
    [eUSART3] = RCC_APB1Periph_USART3,
    [eUSART6] = RCC_APB2Periph_USART6,
};

usart_driver_type usart_drivers[eUSARTn] =
{
    [eUSART1] =
    {
                .uFrameFlag        = false,
        .peripheral = (usart_type*)&usart_handlers[eUSART1],
                .uFrameObj  =
                {
                        .event        = eUSART1,
                        .rxbuf        = &m_dma_recv_buf[eUSART1][0],
                        .txbuf        = &m_dma_send_buf[eUSART1][0],
                        .rxlen        = 0,
                        .txlen        = 0,
                },
        .tx_buf     = &m_dma_send_buf[eUSART1][0],
        .rx_buf     = &m_dma_recv_buf[eUSART1][0],
        .tx_size    = 0,
        .rx_size    = 0,
    },
    [eUSART2] =
    {
                .uFrameFlag        = false,
        .peripheral = (usart_type*)&usart_handlers[eUSART2],
                .uFrameObj  =
                {
                        .event        = eUSART2,
                        .rxbuf        = &m_dma_recv_buf[eUSART1][0],
                        .txbuf        = &m_dma_send_buf[eUSART1][0],
                        .rxlen        = 0,
                        .txlen        = 0,
                },
        .tx_buf     = &m_dma_send_buf[eUSART2][0],
        .rx_buf     = &m_dma_recv_buf[eUSART2][0],
        .tx_size    = 0,
        .rx_size    = 0,
    },
    [eUSART3] =
    {
                .uFrameFlag        = false,
        .peripheral = (usart_type*)&usart_handlers[eUSART3],
                .uFrameObj  =
                {
                        .event        = eUSART3,
                        .rxbuf        = &m_dma_recv_buf[eUSART1][0],
                        .txbuf        = &m_dma_send_buf[eUSART1][0],
                        .rxlen        = 0,
                        .txlen        = 0,
                },
        .tx_buf     = &m_dma_send_buf[eUSART3][0],
        .rx_buf     = &m_dma_recv_buf[eUSART3][0],
        .tx_size    = 0,
        .rx_size    = 0,
    },
    [eUSART6] =
    {
                .uFrameFlag        = false,
        .peripheral = (usart_type*)&usart_handlers[eUSART6],
                .uFrameObj  =
                {
                        .event        = eUSART6,
                        .rxbuf        = &m_dma_recv_buf[eUSART1][0],
                        .txbuf        = &m_dma_send_buf[eUSART1][0],
                        .rxlen        = 0,
                        .txlen        = 0,
                },
        .tx_buf     = &m_dma_send_buf[eUSART6][0],
        .rx_buf     = &m_dma_recv_buf[eUSART6][0],
        .tx_size    = 0,
        .rx_size    = 0,
    },
};

static uint8_t usart_port_number(USART_TypeDef *usart)
{
    switch( (uint32_t)usart )
    {
        case USART1_BASE:
            return 0;
        case USART2_BASE:
            return 1;
        case USART3_BASE:
            return 2;
        case USART6_BASE:
            return 3;
        default:
            return 0xFF;
    }
}

void sUSARTx_DMA_Configuration(usart_driver_type *driver, const usart_type *peripheral, const usart_config_type *config)
{
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    uint8_t usart_number = usart_port_number(driver->peripheral->port);

    driver->rx_size = 0;
    driver->tx_size = 0;
    driver->peripheral = (usart_type*)peripheral;

    usart_peripheral_clock_functions[usart_number](usart_peripheral_clocks[usart_number], ENABLE);

    /* Enable DMA peripheral clock */
    if ( peripheral->tx_dma_config.controller == DMA1 )
    {
        RCC->AHB1ENR |= RCC_AHB1Periph_DMA1;
    }
    else
    {
        RCC->AHB1ENR |= RCC_AHB1Periph_DMA2;
    }

    gpio_set_alternate_function(peripheral->pin_tx->port, peripheral->pin_tx->pin_number, GPIO_OType_PP, GPIO_PuPd_UP, usart_alternate_functions[ usart_number ] );
    gpio_set_alternate_function(peripheral->pin_rx->port, peripheral->pin_rx->pin_number, GPIO_OType_PP, GPIO_PuPd_UP, usart_alternate_functions[ usart_number ] );

    if ( ( peripheral->pin_cts != NULL ) && ( config->flow_control == FLOW_CONTROL_CTS || config->flow_control == FLOW_CONTROL_CTS_RTS ) )
    {
        gpio_set_alternate_function( peripheral->pin_cts->port, peripheral->pin_cts->pin_number, GPIO_OType_PP, GPIO_PuPd_NOPULL, usart_alternate_functions[ usart_number ] );
    }

    if ( ( peripheral->pin_rts != NULL ) && ( config->flow_control == FLOW_CONTROL_RTS || config->flow_control == FLOW_CONTROL_CTS_RTS ) )
    {
        gpio_set_alternate_function( peripheral->pin_rts->port, peripheral->pin_rts->pin_number, GPIO_OType_PP, GPIO_PuPd_NOPULL, usart_alternate_functions[ usart_number ] );
    }

        if(driver->peripheral->pin_en != NULL)
        {
                gpio_init(peripheral->pin_en, *peripheral->pin_en_config);
                gpio_low(peripheral->pin_en);
        }
       
    /* Initialise USART peripheral */
    USART_DeInit(peripheral->port);

    /* Enable the USART OverSampling by 8 */
    USART_OverSampling8Cmd(peripheral->port, ENABLE);  

    /* USARTx configuration ----------------------------------------------------*/
    /* USARTx configured as follows:
        - BaudRate = 5250000 baud
                   - Maximum BaudRate that can be achieved when using the Oversampling by 8
                     is: (USART APB Clock / 8)
                         Example:
                            - (USART3 APB1 Clock / 8) = (42 MHz / 8) = 5250000 baud
                            - (USART1 APB2 Clock / 8) = (84 MHz / 8) = 10500000 baud
                   - Maximum BaudRate that can be achieved when using the Oversampling by 16
                     is: (USART APB Clock / 16)
                         Example: (USART3 APB1 Clock / 16) = (42 MHz / 16) = 2625000 baud
                         Example: (USART1 APB2 Clock / 16) = (84 MHz / 16) = 5250000 baud
        - Word Length = 8 Bits
        - one Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
    */
    USART_InitStructure.USART_Mode       = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_BaudRate   = config->baud_rate;
    USART_InitStructure.USART_WordLength = ( ( config->data_width == DATA_WIDTH_9BIT ) || ( ( config->data_width == DATA_WIDTH_8BIT ) && ( config->parity != NO_PARITY ) ) ) ? USART_WordLength_9b : USART_WordLength_8b;
    USART_InitStructure.USART_StopBits   = ( config->stop_bits == STOP_BITS_1 ) ? USART_StopBits_1 : USART_StopBits_2;

    switch ( config->parity )
    {
        case NO_PARITY:
            USART_InitStructure.USART_Parity = USART_Parity_No;
            break;
        case EVEN_PARITY:
            USART_InitStructure.USART_Parity = USART_Parity_Even;
            break;
        case ODD_PARITY:
            USART_InitStructure.USART_Parity = USART_Parity_Odd;
            break;
        default:
            break;
    }

    switch ( config->flow_control )
    {
        case FLOW_CONTROL_DISABLED:
            USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
            break;
        case FLOW_CONTROL_CTS:
            USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_CTS;
            break;
        case FLOW_CONTROL_RTS:
            USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS;
            break;
        case FLOW_CONTROL_CTS_RTS:
            USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;
            break;
        default:
            break;
    }

    USART_Init(peripheral->port, &USART_InitStructure);

    /* Disable USART */
        USART_Cmd(peripheral->port, DISABLE);

    /* Enable the USART Receive interrupt: this interrupt is generated when the
     USART receive data register is not empty */
    //USART_ITConfig(driver->peripheral->port, USART_IT_RXNE, ENABLE);
    //USART IDLE Interrupt
        USART_ITConfig(peripheral->port, USART_IT_IDLE, ENABLE);

    /* Enable USART */
    USART_Cmd(peripheral->port, ENABLE);

    /* Clear USART TC Flag */
    USART_ClearFlag(peripheral->port, USART_FLAG_TC);

    /*Enable the USART Interrupt*/
        NVIC_InitStructure.NVIC_IRQChannel                   = peripheral->irq_vector;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = peripheral->mpriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority                 = peripheral->spriority;
        NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

    // FOR USART DMA RX
    NVIC_InitStructure.NVIC_IRQChannel                                         = peripheral->rx_dma_config.irq_vector;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = peripheral->rx_dma_config.mpriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority                 = peripheral->rx_dma_config.spriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd                                 = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // FOR USART DMA TX
    NVIC_InitStructure.NVIC_IRQChannel                                         = peripheral->tx_dma_config.irq_vector;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = peripheral->tx_dma_config.mpriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority                 = peripheral->tx_dma_config.spriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd                                 = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

        reload_usart_dma_rx(driver, (uint8_t*)&m_dma_recv_buf[usart_number][0], USART_DMA_RECV_SIZE);
}

/*RX*/
void reload_usart_dma_rx(usart_driver_type *driver, uint8_t *p_data, uint16_t rx_size)
{
    DMA_InitTypeDef     DMA_InitStructure;
    uint8_t usart_number = usart_port_number(driver->peripheral->port);

        /* Configure DMA controller to manage USART TX DMA request ----------*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&driver->peripheral->port->DR);
        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_VeryHigh;
        DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Enable;
        DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;

        DMA_DeInit(driver->peripheral->rx_dma_config.stream);
        DMA_InitStructure.DMA_Channel = driver->peripheral->rx_dma_config.channel;
        DMA_InitStructure.DMA_DIR     = DMA_DIR_PeripheralToMemory;

        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)p_data;
        DMA_InitStructure.DMA_BufferSize      = (uint16_t)rx_size;
        DMA_Init(driver->peripheral->rx_dma_config.stream, &DMA_InitStructure);

        DMA_ClearITPendingBit(driver->peripheral->rx_dma_config.stream, driver->peripheral->rx_dma_config.complete_flags);
        DMA_ITConfig(driver->peripheral->rx_dma_config.stream, DMA_IT_TC, ENABLE);

        /* Enable the USART Rx DMA request */
        USART_DMACmd(driver->peripheral->port, USART_DMAReq_Rx, ENABLE);
        /* Enable the DMA RX Stream */
        DMA_Cmd(driver->peripheral->rx_dma_config.stream, ENABLE);
}

/*TX*/
void reload_usart_dma_tx(usart_driver_type *driver, uint8_t *p_data, uint16_t tx_size)
{
    DMA_InitTypeDef     DMA_InitStructure;
    uint8_t usart_number = usart_port_number(driver->peripheral->port);

        /* Configure DMA controller to manage USART TX DMA request ----------*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&driver->peripheral->port->DR);
        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_Enable;
        DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
        DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;

        DMA_DeInit(driver->peripheral->tx_dma_config.stream);
        DMA_InitStructure.DMA_Channel = driver->peripheral->tx_dma_config.channel;
        DMA_InitStructure.DMA_DIR     = DMA_DIR_MemoryToPeripheral;

        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)p_data;
        DMA_InitStructure.DMA_BufferSize      = (uint16_t)tx_size;
        DMA_Init(driver->peripheral->tx_dma_config.stream, &DMA_InitStructure);

        DMA_ClearITPendingBit(driver->peripheral->tx_dma_config.stream, driver->peripheral->tx_dma_config.complete_flags);
        /* Enable the DMA Stream Interrupt */
        DMA_ITConfig(driver->peripheral->tx_dma_config.stream, DMA_IT_TC, ENABLE);

        /* Enable the USART DMA requests */
        USART_DMACmd(driver->peripheral->port, USART_DMAReq_Tx, ENABLE);

        /* Clear the TC bit in the SR register by writing 0 to it */
        USART_ClearFlag(driver->peripheral->port, USART_FLAG_TC);

        /* Enable the DMA TX Stream */
        DMA_Cmd(driver->peripheral->tx_dma_config.stream, ENABLE);
}

void usart_send_data_packet(usart_driver_type *driver, uint8_t* p_cmd, uint16_t cmd_len)
{
        if(0 == cmd_len)
                return;
    uint8_t usart_number = usart_port_number(driver->peripheral->port);

        if(driver->peripheral->pin_en != NULL)
                gpio_high(driver->peripheral->pin_en);
       
        memcpy((uint8_t*)&m_dma_send_buf[usart_number][0], p_cmd, cmd_len);
       
        reload_usart_dma_tx(driver, &m_dma_send_buf[usart_number][0], cmd_len);
}

/*TX*/
void sDMA_StreamTx_Interrupt(usart_driver_type *driver)
{
    uint8_t usart_number = usart_port_number(driver->peripheral->port);

        //TX Interrupt
        if(DMA_GetITStatus(driver->peripheral->tx_dma_config.stream, driver->peripheral->tx_dma_config.complete_flags) != RESET)
        {
        DMA_Cmd(driver->peripheral->tx_dma_config.stream, DISABLE);
                DMA_ITConfig(driver->peripheral->tx_dma_config.stream, DMA_IT_TC, DISABLE);
                USART_ITConfig(driver->peripheral->port, USART_IT_TC, ENABLE);
                DMA_ClearITPendingBit(driver->peripheral->tx_dma_config.stream, driver->peripheral->tx_dma_config.complete_flags);
        }
}
/*RX*/
void sDMA_StreamRx_Interrupt(usart_driver_type *driver)
{
    uint8_t usart_number = usart_port_number(driver->peripheral->port);

    //RX Interrupt
        if(DMA_GetITStatus(driver->peripheral->rx_dma_config.stream, driver->peripheral->rx_dma_config.complete_flags) != RESET)
        {
                reload_usart_dma_rx(driver, (uint8_t*)&m_dma_recv_buf[usart_number][0], USART_DMA_RECV_SIZE);
                DMA_ClearITPendingBit(driver->peripheral->rx_dma_config.stream, driver->peripheral->rx_dma_config.complete_flags);
        }
}

void sUSART_DMA_Interrupt(usart_driver_type *driver)
{
        Comm_Type *pEvt = NULL;
    uint8_t usart_number = usart_port_number(driver->peripheral->port);

    if(driver->peripheral->port->SR & 0x00000008) driver->peripheral->port->SR |= 0x00000008;

        if(USART_GetITStatus(driver->peripheral->port, USART_IT_IDLE) != RESET)
        {
                //USART_ClearITPendingBit(driver->peripheral->port, USART_IT_IDLE);
        DMA_Cmd(driver->peripheral->rx_dma_config.stream, DISABLE);
                driver->uFrameFlag = true;
                pEvt = &driver->uFrameObj;
                if(pEvt != NULL)
                {
                        memset(pEvt, 0x00, sizeof(Comm_Type));
                        pEvt->event = usart_number;
                        pEvt->rxlen = USART_DMA_RECV_SIZE - DMA_GetCurrDataCounter(driver->peripheral->rx_dma_config.stream);
                        pEvt->rxbuf = (uint8_t*)&m_dma_recv_buf[usart_number][0];
                        pEvt->txbuf = (uint8_t*)&m_dma_send_buf[usart_number][0];
                }
                USART_ReceiveData(driver->peripheral->port);
                DMA_SetCurrDataCounter(driver->peripheral->rx_dma_config.stream, USART_DMA_RECV_SIZE);
                DMA_Cmd(driver->peripheral->rx_dma_config.stream, ENABLE);
        }
       
        if(USART_GetITStatus(driver->peripheral->port, USART_IT_TC) != RESET)
        {
                if(driver->peripheral->pin_en != NULL)
                        gpio_low(driver->peripheral->pin_en);
                USART_ITConfig(driver->peripheral->port, USART_IT_TC, DISABLE);
                USART_ClearITPendingBit(driver->peripheral->port, USART_IT_TC);
        }
}

以上代码楼主可以参考
一分耕耘一分收获。
回复

使用道具 举报

13

主题

41

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2016-8-15
在线时间
52 小时
 楼主| 发表于 2020-2-26 16:56:32 | 显示全部楼层
123将321 发表于 2020-2-25 14:58
试下清除DMA接收中断标志位,类似于下面
/****************************************************
函数功 ...

感谢回复。DMA中断标志位应该是在DMA传输完后才置1,然后再手动清除。然而我的情况,DMA是在传输过程中丢了数据,导致没有用完所设定的长度,也就不会触发中断。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-7 19:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表