OpenEdv-开源电子网

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

hal库+rtos的串口空闲中断+DMA接收 分享

[复制链接]

9

主题

30

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2017-3-2
在线时间
26 小时
发表于 2017-6-17 14:01:29 | 显示全部楼层 |阅读模式
hal库初学感觉好多没有标准库顺手,这个弄了一天,为了避免少走弯路,分享给大家。
基于F407,串口1,数据发送到串口,串口利用dma接收后产生中断,然后通过消息队列方式在线程中取出并再通过串口1返回。

RTOS_1.rar

5.36 MB, 下载次数: 1004

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2017-5-15
在线时间
22 小时
发表于 2017-7-7 11:48:32 | 显示全部楼层
我的为什么不能进入空闲中断啊,无操作系统

/* USART3 init function */
void USART3_UART_Init(uint32_t bound)
{

  huart3.Instance = USART3;
  huart3.Init.BaudRate = bound;  //115200
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  HAL_UART_Init(&huart3);
  __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
}


void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  if(huart->Instance==USART3)
  {
  /* USER CODE BEGIN USART3_MspInit 0 */

  /* USER CODE END USART3_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_GPIOC_CLK_ENABLE();                        //使能GPIOC时钟
    __USART3_CLK_ENABLE();
  
    /**USART3 GPIO Configuration   
    PC10     ------> USART3_TX
    PC11     ------> USART3_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* Peripheral interrupt init*/
    HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART3_IRQn);
  /* USER CODE BEGIN USART3_MspInit 1 */

  /* USER CODE END USART3_MspInit 1 */
  }

}


void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,uint32_t chx)
{
        if((uint32_t)DMA_Streamx>(uint32_t)DMA2)//得到当前stream是属于DMA2还是DMA1
        {
        __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能       
        }else
        {
        __HAL_RCC_DMA1_CLK_ENABLE();//DMA1时钟使能
        }

  /* DMA interrupt init */
  HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
  
  /* Peripheral DMA init*/
  hdma_usart3_rx.Instance = DMA_Streamx;                             //数据流选择
  hdma_usart3_rx.Init.Channel = chx;                                 //通道选择
  hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;              //存储器到外设
  hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;                  //外设非增量模式
  hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;                      //存储器增量模式
  hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;     //外设数据长度:8位
  hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;        //存储器数据长度:8位
  hdma_usart3_rx.Init.Mode = DMA_CIRCULAR;                           //外设循环模式
  hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;                   //低优先级
  hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;               
  hdma_usart3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;      
  hdma_usart3_rx.Init.MemBurst = DMA_MBURST_SINGLE;                  //存储器突发单次传输
  hdma_usart3_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;               //外设突发单次传输
  HAL_DMA_DeInit(&hdma_usart3_rx);
  HAL_DMA_Init(&hdma_usart3_rx);

  __HAL_LINKDMA(&huart3,hdmarx,hdma_usart3_rx);  
  HAL_UART_Receive_DMA(&huart3,rx_buffer,BUFFER_SIZE);
}


void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
  uint32_t tmp_flag = 0;
        uint32_t temp;
  tmp_flag =  __HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE);
        if((tmp_flag != RESET))
  {
                        __HAL_UART_CLEAR_IDLEFLAG(&huart3);
                        temp = huart3.Instance->SR;  
                        temp = huart3.Instance->DR;
                        HAL_UART_DMAStop(&huart3);
                        temp  = hdma_usart3_rx.Instance->NDTR;
                        rx_len =  BUFFER_SIZE - temp;
                  recv_end_flag = 1;
                        HAL_UART_Receive_DMA(&huart3,rx_buffer,BUFFER_SIZE);
               
  }
回复 支持 反对

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2017-5-15
在线时间
22 小时
发表于 2017-7-7 11:48:45 | 显示全部楼层
求大神解答
回复 支持 反对

使用道具 举报

9

主题

30

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2017-3-2
在线时间
26 小时
 楼主| 发表于 2017-7-7 12:11:32 | 显示全部楼层

你要不先试试把我的程序初始化的部分拿去修改修改
回复 支持 反对

使用道具 举报

2

主题

13

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2017-5-15
在线时间
22 小时
发表于 2017-7-7 15:01:20 | 显示全部楼层
zhen8838 发表于 2017-7-7 12:11
你要不先试试把我的程序初始化的部分拿去修改修改

初始化没啥问题啊
我是用串口助手给单片机随便发个东西就进入 USART3_IRQHandler(void)
然后__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)这个函数读取不到标志位

然后程序不停进入 USART3_IRQHandler 中断服务函数,继续检测不到__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE)又退出中断服务函数,不停循环
回复 支持 反对

使用道具 举报

9

主题

30

帖子

0

精华

新手上路

积分
41
金钱
41
注册时间
2017-3-2
在线时间
26 小时
 楼主| 发表于 2017-7-7 16:26:16 | 显示全部楼层
绿洲 发表于 2017-7-7 15:01
初始化没啥问题啊
我是用串口助手给单片机随便发个东西就进入 USART3_IRQHandler(void)
然后__HAL_UART ...

是不是你的dma要设置为单次模式,不能设置为循环模式
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-7-8 22:52:22 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

7

主题

36

帖子

0

精华

初级会员

Rank: 2

积分
157
金钱
157
注册时间
2017-3-24
在线时间
42 小时
发表于 2017-7-11 17:14:10 | 显示全部楼层
多谢分享,
回复 支持 反对

使用道具 举报

31

主题

130

帖子

0

精华

高级会员

Rank: 4

积分
790
金钱
790
注册时间
2015-6-28
在线时间
139 小时
发表于 2018-9-21 11:22:23 | 显示全部楼层
zhen8838 发表于 2017-7-7 16:26
是不是你的dma要设置为单次模式,不能设置为循环模式

初始化不应该配置为循环模式吗
回复 支持 反对

使用道具 举报

2

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
140
金钱
140
注册时间
2014-8-31
在线时间
33 小时
发表于 2019-7-3 10:20:11 | 显示全部楼层
最近也在调试这个, 谢谢分享
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-11 07:20

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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