文章目录

  • 1、逻辑分析仪下的串口数据
  • 2、数字转字符串函数
  • 3、字符串转整数
  • 4、字符串转浮点数
  • 5、测试转换方法
  • 6、空闲中断DMA接收不定长数据
  • 7、高频数据收发测试

本文总结下串口通信的一些小技巧

1、逻辑分析仪下的串口数据

首先我们还是先配置一个串口,一般正常情况下都默认是可以的

上面参数的意思:

  • 波特率 115200
  • 字长 8
  • 校验 无校验
  • 停止位 1位

那我们先来看下串口通信具体是什么样的,串口的数据包组成如下:

我们在来看下用串口发下数据到逻辑i分析仪里面读取的数据,相关说明我已经在图片中标出来了

这是我串口发送的数据

那我们再来看下波特率,这里我们选的波特率是115200,那就是1秒钟可以发送115200byte的数据,那一个数据的时间可以计算如下所示:

而我们可以在逻辑分析仪中测量下这个时间的准确性,可以看到是非常准确的(废话,这用的不是硬件串口吗,哈哈哈

这样就可以帮我么更清楚的认识串口了!

2、数字转字符串函数

通信过程中一般都是发送字符串偏多,因为字符串就是char类型的,可以直接匹配串口的数据,方便转化,所以一个常用的小工具就是数字转字符串了!

u32 Pow(u32 num,u8 count)
{u8 i;u32 result = 0;if(count == 0){num = 1;return num;}else{result = num;for(i = 0;i<count-1;i++){result *= num;   }}return result;
}void NumToString(u32 num,u8 numbit,u8 *string)
{u8 i=0,z=0;u32 temp = 0;u8 changestart = 0;u8 j = numbit-1;for(i = 0;i<numbit;i++){temp = num/Pow(10,j);if(changestart){string[z++] = temp+0x30;}if((temp>0)&&(changestart == 0)){string[z++] = temp+0x30;    changestart = 1;}temp = Pow(10,j);num %= temp;j--;}string[z] = 0;
}

那么如果是浮点数怎么办呢,就只能是先转为整数在处理了,就是先把他变为整数,再用这个函数来处理!

更好的办法还可以采用官方函数的方法,可以无视整数和浮点数的差异,该函数的用法如下所示,因为后面一个参数是格式化的数据,那%d就是整形数据,%f就是单精度浮点型了。

3、字符串转整数

这也是比较常用的一种数据类型,有很多时候接收到的数据是以字符串的方式发过来的,我们要获取其中的整形数据,就可以用这个方法,flag是分隔符,比如一组数据13,23,23这样就是以,为分隔符了

int32_t str2int(uint8_t * str, uint8_t flag, uint8_t no)
{uint8_t No = 1;uint8_t * Str = str;uint8_t NumTemp[TempIntLen];while(No!=no){if(*Str == flag)No++;Str++;}No = 0;while(*Str != flag && *Str != '\r' && *Str != '\n' && *Str != '\0' && No < (TempIntLen - 1)){NumTemp[No] = *Str;Str++;No++;}NumTemp[No] = '\0';return atoi(NumTemp);
}

4、字符串转浮点数

这个就是获取其中的浮点型数据了,flag是分隔符

void str2double(uint8_t * str, uint8_t flag, uint8_t no, double * Output)
{uint8_t No = 1;uint8_t * Str = str;uint8_t NumTemp[TempDoubleLen];uint8_t NumTemp_int[TempDoubleLen];double OutputNum;while(No!=no){if(*Str == flag)No++;Str++;}No = 0;while(*Str != flag && *Str != '\r' && *Str != '\n' && *Str != '\0' && No < (TempDoubleLen - 1)){NumTemp[No] = *Str;Str++;No++;}NumTemp[No] = '\0';NumTemp[(TempDoubleLen - 1)] = 0;No = 0;while(NumTemp[NumTemp[(TempDoubleLen - 1)]] != '\0' && NumTemp[(TempDoubleLen - 1)] < (TempDoubleLen - 1)){if(NumTemp[NumTemp[(TempDoubleLen - 1)]] == '.'){NumTemp[(TempDoubleLen - 1)]++;NumTemp_int[(TempDoubleLen - 1)] = NumTemp[(TempDoubleLen - 1)];}NumTemp_int[No] = NumTemp[NumTemp[(TempDoubleLen - 1)]];No++;NumTemp[(TempDoubleLen - 1)]++;}NumTemp_int[No]='\0';NumTemp[(TempDoubleLen - 1)] = NumTemp_int[(TempDoubleLen - 1)]++;OutputNum = (double)atoi(NumTemp_int);while(NumTemp[NumTemp[(TempDoubleLen - 1)]] != '\0'){OutputNum /= 10;NumTemp[(TempDoubleLen - 1)] ++;}*Output = OutputNum;
}

5、测试转换方法

以上四种转换方法的测试如下所示:

int num=1253423456;
u8 str[20]= {0};
char str1[]="112,233,41";
char str2[]="112.32,233.34,343.45";
double dat[3];int main(void)
{NumToString(num,10,str);printf("%s\n",str);printf("%d\n%d\n%d\n",str2int(str1,',',1),str2int(str1,',',2),str2int(str1,',',3));str2double(str2,',',1,dat);str2double(str2,',',2,dat+1);str2double(str2,',',3,dat+2);printf("%f\n%f\n%f",dat[0],dat[1],dat[2]);
}

打印结果如下所示,可以看到,结果是非常顺利的!

6、空闲中断DMA接收不定长数据

在需要接收大量数据的情况下这个是比较常用的,比如解析物联网开发时候云下发的json命令,一般数据梁都比较大而且不是固定长度的数据,这个时候这个东西就变得很有必要了

开启串口,并设置参数,一般情况默认即可

配置中断和DMA

配置DMA发送和接收函数模式


初始化中开启串口空闲中断

对中断函数进行处理

空闲中断处理函数如下所示

源代码如下:

UART_DMA.c

/** UART_DMA.c**  Created on: Mar 18, 2022*      Author: LX*/#include "UART_DMA.h"#include "string.h"
#include "stdarg.h"
#include "stdio.h"#define USART_DMA_TX_BUFFER_MAXIMUM         128    // DMA缓冲区大小
#define USART_DMA_RX_BUFFER_MAXIMUM         128    // DMA缓冲区大小extern DMA_HandleTypeDef hdma_usart1_rx;
extern DMA_HandleTypeDef hdma_usart1_tx;extern UART_HandleTypeDef huart1; //UART句柄
uint8_t usart1_rx_buffer[USART_DMA_RX_BUFFER_MAXIMUM]; //串口1的DMA接收缓冲区
uint8_t usart1_tx_buffer[USART_DMA_TX_BUFFER_MAXIMUM]; //串口1的DMA发送缓冲区
uint16_t usart1_rx_len; //DMA一次空闲中断接收到的数据长度
uint8_t receive_data[USART_DMA_RX_BUFFER_MAXIMUM];    //DMA接收数据缓存区void HAL_UART_ReceiveIdle(UART_HandleTypeDef *huart)
{//当触发了串口空闲中断if((__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)){if(huart->Instance == USART1){__HAL_UART_CLEAR_IDLEFLAG(huart);HAL_UART_DMAStop(huart);usart1_rx_len = USART_DMA_RX_BUFFER_MAXIMUM - (__HAL_DMA_GET_COUNTER(&hdma_usart1_rx));memcpy(receive_data, usart1_rx_buffer, USART_DMA_RX_BUFFER_MAXIMUM);memset(usart1_rx_buffer,0,128);while (HAL_UART_Receive_DMA(&huart1,(uint8_t *)usart1_rx_buffer, USART_DMA_RX_BUFFER_MAXIMUM)!=HAL_OK);//      Debug_printf("%s",receive_data); // 是否添加回环检测函数}//下面添加其他串口的处理函数}
}
void UART1_TX_DMA_Send(uint8_t *buffer, uint16_t length)
{while(HAL_DMA_GetState(&hdma_usart1_tx) != HAL_DMA_STATE_READY);//while(__HAL_DMA_GET_COUNTER(&hdma_usart1_tx));__HAL_DMA_DISABLE(&hdma_usart1_tx);HAL_UART_Transmit_DMA(&huart1, buffer, length);
}void Debug_printf(const char *format, ...)
{uint32_t length = 0;va_list args;va_start(args, format);length = vsnprintf((char *)usart1_tx_buffer, sizeof(usart1_tx_buffer), (char *)format, args);UART1_TX_DMA_Send(usart1_tx_buffer, length);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{if (huart->Instance == USART1){__HAL_DMA_CLEAR_FLAG(&hdma_usart1_tx, DMA_FLAG_TC4);
//    HAL_UART_DMAStop(&huart1);}
}

UART_DMA.h

#include "main.h"void HAL_UART_ReceiveIdle(UART_HandleTypeDef *huart);
void UART1_TX_DMA_Send(uint8_t *buffer, uint16_t length);
void Debug_printf(const char *format, ...);

7、高频数据收发测试

下面可以对数据接收进行暴力测试:

在串口助手中设置高频率的大量数据进行发送,并在单片机端设置数据回传,测试结果如下:

正常情况下回环接收

周期加大会开始出现错误

经过测试我得到的结论大概如下:

  • 不要把数据发送频率设置的过高。115200的波特率数据量上去50hz的频率都受不了
  • 提高波特率可以在更高的频率下进行数据收发,我这里用的92个数据,在100khz的情况下是没有什么问题的,提高到200khz出现了部分数据不完整的现象
  • 这只是个测试,单片机仅仅只是跑了一个程序,实际情况下可能会出现比如其他程序中断的问题等等,都会对接收效果造成影响

串口通信中一些常用的小工具相关推荐

  1. SPCOMM控件在Delphi7.0串口通信中的应用

    ====================================================== 注:本文源代码点此下载 ================================= ...

  2. xmodem java_Xmodem XMODEM协议是一种串口通信中广泛用到的异步文件传输协议 联合开发网 - pudn.com...

    Xmodem 所属分类:串口编程 开发工具:Java 文件大小:3KB 下载次数:6 上传日期:2017-11-02 21:50:52 上 传 者:雄霸天下19 说明:  XMODEM协议是一种串口通 ...

  3. 计算机给文件重命名快捷键,实用电脑小技巧:批量重命名文件常用的小工具也可以设快捷键...

    沪江小编:对于很多人来说,电脑应该算是使用频率最高的工具了,可是你真的会用电脑么?实用电脑小技巧,用最简单明了的方式给你无比有趣的电脑使用新体验. [视觉遗像]注视图形中央的四个黑点30秒,然后闭眼仰 ...

  4. STM32串口通信中使用printf发送数据配置方法 开发环境 Keil

    STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK) 已有 12456 次阅读2011-6-29 23:29 | 在STM32串口通信程序中使用printf发送数据, ...

  5. 串口通信中ReadFile和WriteFile的超时详解!

    源:串口通信中ReadFile和WriteFile的超时详解! 在用ReadFile和WriteFile读写串行口时,需要考虑超时问题.如果在指定的时间内没有读出或写入指定数量的字符,那么ReadFi ...

  6. Arduino中Serial.print()与Serial.write()函数的区别,以及串口通信中十六进制与字符串的收发格式问题和转换过程详解

    1.串口通信中十六进制和字符数据的区别 串口收发数据时字符.十六进制.二进制格式详细区分 ASCII码查询表格 在使用串口发送数据时可以选择字符串(ASCII)发送或者十六进制(Hex)发送,通常情况 ...

  7. c语言中延时时间计算,能精确计算C语言延时程序中延时时间的小工具(转)

    能精确计算C语言延时程序中延时时间的小工具 Emu51Form是一个软仿真计时器 具体使用方法为: 1.打开 keil\tools,ini 文件,在它的c51栏中加入 AGSI9=Emu51Form. ...

  8. C#解决串口通信中接收数据时延迟处理与缓存处理的方法

    转载连接: http://blog.csdn.net/yaoliang11/article/details/6885768 C#解决串口通信中接收数据时延迟处理与缓存处理的方法 时间:2011-1-2 ...

  9. 测试工作中常用在线小工具-初级篇

    背景 测试过程中经常需要用到一些工具来校验数据的正确性,并且可以帮助测试人员更好的定位问题,所以我总结了我这个初级测试小白日常测试使用的小工具~ 1.在线json转换: http://www.bejs ...

最新文章

  1. python入门到实践-Python编程从入门到实践(基础入门)
  2. elasticsearch查询
  3. 样本距离计算、向量范数、矩阵范数
  4. 计算机社团嘉年华的游戏,社团嘉年华,游戏大乱斗!
  5. Surface Pro 4 和 Surface Book 使用名为 Surface UEFI(统一可扩展固件接口)的新固件接口...
  6. 重要的动态路由OSPF(多区)
  7. Java Web应用程序的反跨站点脚本(XSS)过滤器
  8. TCP—三次握手和四次挥手详解
  9. Windows下链接boost库及应用实例
  10. python selenium安装失败_python:学习selenium遇到的坑
  11. Java小题,通过JNI调用本地C++共享库中的对应方法实现杨辉三角的绘制
  12. python简单地实现几个小代码
  13. 51单片机驱动TM1640实现多个LED灯控制
  14. ffmpeg 再编译使用 ffmpeg-gl-transition
  15. TIFF图像文件格式详解——转载
  16. COSC1076_assignment2_221
  17. c++new时赋初值_智慧树知到_C/C++程序设计案例实战_作业题库答案
  18. 【洛谷】3957 跳房子
  19. 计算机网络共享打不开,电脑只要打开共享提示“无法启用共享访问”如何解决...
  20. JS正则表达式匹配手机号

热门文章

  1. 完全用 GNU/Linux 工作(转)
  2. 浅析支付宝钱包支付流程
  3. win7 隐藏受保护的操作系统文件 消失
  4. 计算机网络笔记及思维导图(1)——概述
  5. Identity-Aware Textual-Visual Matching with Latent Co-attention文章翻译学习(ICCV)
  6. 使用Python实现键盘记录器和邮箱自动通知
  7. Wine零知识学习1 —— 介绍
  8. Adobe 安装程序无法初始化,请下载Adobe Support Advisor检测该问题
  9. 0.91英寸OLED初始化程序
  10. 嵌入式linux pam,Linux PAM 之cracklib模块