2017年06月15日 16:54:16

阅读数:13692

方法1:串口接受数据,定时器来判断超时是否接受数据完成。

方法2:DMA接受+IDLE中断

实现思路:采用STM32F103的串口1,并配置成空闲中断IDLE模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。那么初始化完成之后,当外部给单片机发送数据的时候,假设这帧数据长度是200个字节,那么在单片机接收到一个字节的时候并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区里面。当整帧数据发送完毕之后串口才会产生一次中断,此时可以利用DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。

应用对象:适用于各种串口相关的通信协议,如:MODBUS,PPI ;还有类似于GPS数据接收解析,串口WIFI的数据接收等,都是很好的应用对象。

关键代码分析:

  1. void uart_init(u32 bound);

  2. void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);

  3. #endif

  4. usart.C

  5. //初始化IO 串口1

  6. //bound:波特率

  7. void uart_init(u32 bound)

  8. {

  9. //GPIO端口设置

  10. GPIO_InitTypeDef GPIO_InitStructure;

  11. USART_InitTypeDef USART_InitStructure;

  12. NVIC_InitTypeDef NVIC_InitStructure;

  13. DMA_InitTypeDef DMA_InitStructure;

  14. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE); //使能USART1,GPIOA时钟

  15. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输

  16. RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟

  17. USART_DeInit(USART1); //复位串口1

  18. //USART1_TX PA.9

  19. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9

  20. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  21. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出

  22. GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9

  23. //USART1_RX PA.10

  24. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

  25. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入

  26. GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10

  27. //Usart1 NVIC 配置

  28. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

  29. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3

  30. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3

  31. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

  32. NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

  33. //USART 初始化设置

  34. USART_InitStructure.USART_BaudRate = bound;

  35. USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式

  36. USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位

  37. USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位

  38. USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None;//无硬件数据流控制

  39. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式

  40. USART_Init(USART1, &USART_InitStructure); //初始化串口

  41. USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启空闲中断

  42. USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //使能串口1 DMA接收

  43. USART_Cmd(USART1, ENABLE); //使能串口

  44. //相应的DMA配置

  45. DMA_DeInit(DMA1_Channel5); //将DMA的通道5寄存器重设为缺省值 串口1对应的是DMA通道5

  46. DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR; //DMA外设usart基地址

  47. DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DMA_Rece_Buf; //DMA内存基地址

  48. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从外设读取发送到内存

  49. DMA_InitStructure.DMA_BufferSize = DMA_Rec_Len; //DMA通道的DMA缓存的大小

  50. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器不变

  51. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增

  52. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度为8位

  53. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度为8位

  54. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常缓存模式

  55. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级

  56. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输

  57. DMA_Init(DMA1_Channel5, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道

  58. DMA_Cmd(DMA1_Channel5, ENABLE); //正式驱动DMA传输

  59. }

  60. //重新恢复DMA指针

  61. void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)

  62. {

  63. DMA_Cmd(DMA_CHx, DISABLE ); //关闭USART1 TX DMA1所指示的通道

  64. DMA_SetCurrDataCounter(DMA_CHx,DMA_Rec_Len);//DMA通道的DMA缓存的大小

  65. DMA_Cmd(DMA_CHx, ENABLE); //打开USART1 TX DMA1所指示的通道

  66. }

  67. //发送len个字节

  68. //buf:发送区首地址

  69. //len:发送的字节数

  70. void Usart1_Send(u8 *buf,u8 len)

  71. {

  72. u8 t;

  73. for(t=0;t<len;t++) //循环发送数据

  74. {

  75. while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

  76. USART_SendData(USART1,buf[t]);

  77. }

  78. while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

  79. }

  80. //串口中断函数

  81. void USART1_IRQHandler(void) //串口1中断服务程序

  82. {

  83. if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)

  84. {

  85. USART_ReceiveData(USART1);//读取数据注意:这句必须要,否则不能够清除中断标志位。

  86. Usart1_Rec_Cnt =DMA_Rec_Len-DMA_GetCurrDataCounter(DMA1_Channel5); //算出接本帧数据长度

  87. //***********帧数据处理函数************//

  88. printf ("Thelenght:%d\r\n",Usart1_Rec_Cnt);

  89. printf ("The data:\r\n");

  90. Usart1_Send(DMA_Rece_Buf,Usart1_Rec_Cnt);

  91. printf ("\r\nOver! \r\n");

  92. //*************************************//

  93. USART_ClearITPendingBit(USART1,USART_IT_IDLE); //清除中断标志

  94. MYDMA_Enable(DMA1_Channel5); //恢复DMA指针,等待下一次的接收

  95. }

  96. }

stm32-串口接受不定长数据方法(3种)相关推荐

  1. 基于HAL库STM32串口驱动不定长数据接收

    STM32串口驱动不定长数据接收带环形缓冲区 最新框架代码 使用方法 源码 串口接口文件 环形缓冲区接口文件 移植图示 使用涉及4个文件, UART_Port.c UART_Port.h Circul ...

  2. STM32串口接收不定长数据原理与源程序

    **STM32串口接收不定长数据原理与源程序**CSDN上有很多关于STM32串口接收不定长数据的文章,但实际使用后发现照搬他们的代码,程序根本就不能正确接收数据,其中最关键的一句有问题.其余内容完全 ...

  3. 串口接收不定长数据的几种方式

    在阅读本文前,你需要先做到串口成功接收一个数据(相信这一点是很简单的)  这几天简单总结了一下用串口怎么接收一帧数据的办法,个人使用的有三种,下面逐一介绍: 第一种:使用中断的方式: 这种在数据接收不 ...

  4. stm32串口接收不定长数据_基于STM32之UART串口通信协议--接收

    一.前言 1.简介 回顾上一篇UART发送当中,已经讲解了如何实现UART的发送操作了,接下来这一篇将会继续讲解如何实现UART的接收操作. 2.UART简介 嵌入式开发中,UART串口通信协议是我们 ...

  5. ZYNQ进阶之路14--PS端uart串口接收不定长数据

    ZYNQ进阶之路14--PS端uart串口接收不定长数据 导语 ZYNQ串口简介 实现步骤 导语 繁忙的博主又来了,本节我们实现一个比较简单的东西:串口.之前的章节中我们也有使用PS端的串口进行收发数 ...

  6. openmv串口数据 串口助手_STM32 串口接收不定长数据 STM32 USART空闲检测中断

    编者注: 单片机串口接收不定长数据时,必须面对的一个问题为:怎么判断这一包数据接收完成了呢?常见的方法主要有以下两种: 1.在接收数据时启动一个定时器,在指定时间间隔内没有接收到新数据,认为数据接收完 ...

  7. 处理串口接收不定长数据的另一种解决方法

    开发平台:Keil 5 库函数版本:V3.5 芯片:STM32F103CBT6 之前我在我的另一篇博客中介绍过使用串口空闲中断+DMA的方式来处理不定长数据,没有看过的同学可以点击这里查看.今天要介绍 ...

  8. HAL库的串口基础学习(包含串口接收不定长数据的实现)

    HAL库的串口基础学习(1) HAL库有一个特点就是对于许多外设的初始化以及功能操作,都提供有一个weak版本的函数,这是充分的展现出库名字的含义(Hardware Abstraction Layer ...

  9. HAL库实践记录之串口接收不定长数据

    串口1接收不定长数据 实验板是原子mini板 一开始使用官方库,只能接受定长数据.把数据长度设置为1时,发送多字节数据时又会丢数.所以自己重写串口中断处理函数. 首先搞一下Cube配置用法:Mode选 ...

最新文章

  1. 美妙的Python又来了
  2. 使用Git命令时出现fatal: this operation must be run in a work tree提示,该如何解决
  3. bgi::detail::path_intersection用法的测试程序
  4. css文件的MIME错误引发的Jquery Mobile绘制错误
  5. OkHttp3的连接池及连接建立过程分析
  6. c语言考试常考试卷,c语言面试最必考的十道试题,求职必看!!!
  7. mac下安装caffe
  8. php编写大型网站问题集
  9. @程序员,你处在食物链哪级?有人跑车游轮到处玩,有人被房价羞辱,被平庸折磨...
  10. TheFatRat生成免杀木马(powershell)报错问题
  11. 老徐和阿珍的故事:CAP是什么?超级爱放P吗?
  12. 用k-mer分析进行基因组调查:(六)用KmerGenie一步实现
  13. 剑指21.调整数组顺序使奇数位于偶数前面 python leetcode
  14. react具名插槽与作用域插槽
  15. pytorch基于GAN生成对抗网络的数据集扩充
  16. #bzoj2240#积木游戏(DP? 贪心?)
  17. C++进阶笔记001:static 静态生存期 和 动态生存期
  18. 服务器上显示存储脱机,使存储空间直通服务器脱机以进行维护
  19. 写一场爱情离散的词句
  20. 查看七牛云生成qiniuUploadToken的过期时间

热门文章

  1. MySQL性能突发事件问题排查技巧
  2. 软件开发中的开源协议详解!
  3. 微服务架构如何保障双11狂欢下的99.99%高可用
  4. 一起来造一个RxJava,揭秘RxJava的实现原理
  5. maven可选依赖(Optional Dependencies)和依赖排除(Dependency Exclusions)
  6. spring boot应用启动原理分析
  7. 【Python】青少年蓝桥杯_每日一题_9.03_画三角形和半圆相切
  8. 响应格式html,设置响应格式的HTML邮件
  9. python爬虫专家_Python爬虫入门教程 27-100 微医挂号网专家团队数据抓取pyspider
  10. 主程序与子程序不在同一程序模块中_深度解析S7200系列PLC带参数子程序用法