打印
[STM32F4]

【STM32F469I试用】+串口DMA接收不定长数据+任务轮询系统

[复制链接]
4934|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 karaxiaoyu 于 2015-12-24 16:10 编辑

   记得在活动开始的第一天我就提交了申请,看了STM32F469官方的介绍视频我就很想拥有一块板子,这里感谢21IC。拿到板子后,感觉板子的造型去掉下巴就像几年前的一部手机了,板子特殊的部分在于同时集成了适用于Flash存储器的ART Accelerator™和适用于结合LCD-TFT和MIPI-DSI显示接口进行图形处理的Chrom-ART Accelerator™,能够为高要求的实时处理提供足够资源和高级用户界面。
硬件方面,原理图由STM32F469NIH6U、AUDIO、LCD、数字麦克风、SD卡、USB_OTG、128M外部SDRAM、Arduino接口、外部引脚、ST_LINK、Power供电11个块组成。PCB不是AD格式的,为什么用AD画原理图,Cadence Allegro画PCB呢,AD画6层板没问题呀,好吧,硬件就简单说到这里。
下面会送上Cadence Allegro的百度网盘下载链接和原理图PCB文件

下面实现用CubeMX实现串口DMA接收不定长数据
先说下串口实现的3种方式,可以用轮询、中断以及DMA实现,轮询模式为堵塞模式,必须在设定的时间内接收到设定的数据长度才会正确接收;中断模式为非堵塞模式,也是平时用的比较多的,但在HAL库中必须在每次接完之后就要重新开启接收中断,这样在接收不确定长度数据就不好处理;最后发现有一个比较好的方法那就是用串口的空闲中断+DMA实现串口数据的接收,在接收一帧数据只需要中断一次,这样就可以接收不定长数据了,下面介绍具体过程:

首先查阅官方原理图知道Arduino接口的串口是使用USART6
在STM32CubeMX  Pinout中选择USART6为 Asynchronous,
然后设置定时器3
接下来设置时钟,时钟配置真是方便,主频肯定是180MHz啦,定时器3是挂载在APB1上的,
波特率115200bit/s,8位数据位,无奇偶校验,1位停止位,其它默认
这里配置USART的DMA,选择USART6_RX为DMA Request,DMA2通道1,其它默认
使能USART6中断
接下来配置定时器,89分频,定时10ms中断一次
使能定时器3中断
把这个勾上代码层次比较好

打开生成的代码后,首先定义BUFFER_SIZE,接收到数据的长度,接收完标志,接收数组
#define BUFFER_SIZE 128
uint8_t rx_len=0;
uint8_t recv_end_flag=0;
uint8_t rx_buffer[BUFFER_SIZE];
然后再开启串口空闲中断和定时器中断
__HAL_UART_ENABLE_IT(&huart6,UART_IT_IDLE);
  HAL_TIM_Base_Start_IT(&htim3);
在串口6的中断函数中,,写入如下代码
  uint32_t tmp_flag = 0;
         uint32_t temp;
  tmp_flag =  __HAL_UART_GET_FLAG(&huart6,UART_FLAG_IDLE);
         if((tmp_flag != RESET))
  {
         __HAL_UART_CLEAR_IDLEFLAG(&huart6);
        temp = huart6.Instance->SR;
         temp = huart6.Instance->DR;
        HAL_UART_DMAStop(&huart6);
        temp  = hdma_usart6_rx.Instance->NDTR;
        rx_len =  BUFFER_SIZE - temp;               
       recv_end_flag = 1;               
  }
        
首先判断是不是空闲中断,然后清除标志位,暂停DMA传输后得到剩余的空间大小,通过总大小减去剩余的就是此次接收到的数据长度。在接收完成标志位置一之后,就可以在主函数中处理了

把接收到的数据发出去,重新开启DMA接收
if(recv_end_flag==1)
{
       HAL_UART_Transmit(&huart6,rx_buffer,rx_len,10);
       rx_len=0;
       recv_end_flag=0;
       HAL_UART_Receive_DMA(&huart6,rx_buffer,BUFFER_SIZE);
}
这样就可以通过串口DMA接收不定长串口数据了。

在定时器中断回调函数中加入如下代码
voidHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
   if(htim->Instance== TIM3)
   {
      static  uint16_t tim3_cnt = 0;
      if(tim3_cnt== 100)
     {
         tim3_cnt= 0;
         HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_6);
     }
     else
     {
         tim3_cnt++;
     }
   }
}
实现定时器中断翻转IO口状态。
下面加入任务轮询系统:
1:初始化定时器,这里设定定时中断为10ms,中断太频繁效率低
2:设计一个结构体
         //任务结构
typedef struct _TASK_COMPONENTS
{
              unsigned char Run;                 //任务运行标记  0-不运行 1-运行
              unsigned int Timer;               //计时器
              unsigned int ItvTime;             //任务运行时间间隔
              void (*TaskHook)(void);            //要运行的任务函数
}TASK_COMPONENTS;                      //任务定义
3:任务运行标志
void TaskRemarks(void)
{
   unsignedchar i;
   for(i=0;i<TASK_MAX; i++)    //逐个时间处理
   {
     if(TaskComps.Timer)    //时间不为0
     {
         TaskComps.Timer--;  //减去一个节拍
          if(TaskComps.Timer == 0)
          {
             TaskComps.Timer =TaskComps.ItvTime;  //恢复计时器值
             TaskComps.Run = 1;   //任务可以运行
          }
      }
   }
}
4:任务处理
voidTaskProcess(void)
{
       unsigned char i;
       for(i=0; i<TASK_MAX; i++)            //逐个任务时间处理
       {
              if(TaskComps.Run)
              {
                     TaskComps.TaskHook();     //运行任务
                     TaskComps.Run = 0;        //标志清零
              }
              __delay_cycles(100);
       }
}
这个架构只需要在定时器中调用TaskRemarks(),定义自己的任务数之后,在主程序中调用TaskProcess()就行。

这也是一个小小的个人认为不错的框架,暂时就先写这么多,之后准备上FreeRTOS,等玩了更高级的功能之后再分享给大家,谢谢!

stm32f469i-disco_sch.zip

3.46 MB

原理图和PCB

Cadence Allegro--百度网盘链接.rar

165 Bytes

Cadence Allegro

沙发
发在天涯| | 2015-12-24 14:59 | 只看该作者
HAL库困扰我很久了,终于看到大神支招了串口空闲中断+DMA接收数据的方式,还有后面那个小的任务轮询系统很实用,谢谢大神分享

使用特权

评论回复
板凳
mjun5210| | 2016-6-21 17:57 | 只看该作者
楼主在吗?我DMA收数据的程序完全按照您的来写的,但是收不到数据,我的片子是429的

使用特权

评论回复
地板
mjun5210| | 2016-6-22 09:13 | 只看该作者
找到问题了,是我的串口有问题,换了个串口试就没问题了。硬件问题。

使用特权

评论回复
5
炳程| | 2017-5-21 14:18 | 只看该作者
Cadence Allegro--百度网盘链接已失效

使用特权

评论回复
6
232321122| | 2017-5-21 22:57 | 只看该作者
这个不用中断了吗?

使用特权

评论回复
7
232321122| | 2017-5-21 22:59 | 只看该作者
楼主的工程文件在哪里下载?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

72

帖子

3

粉丝