串口输出乱码问题的解决方法汇总(持续更新):

2023-05-16

平时工作中程序员在调试时总会用到串口打印数据以及一些标志位查看程序是否出现问题。但是在使用时总会遇到各种各样的问题,最常见的就是输出乱码问题(指的是有收到数据但数据显示的是一堆不认识的汉字或字符),下面就我遇到过的串口乱码问题的相关几种解决方法:

方法一:检查GND线连接情况

电子系统接地非常重要,接地不当往往导致电子系统不能稳定工作。

在串口通信时地线是必须接的,比如串行数据通信接口标准(RS—232)的3线TX、RX、GND。虽然在使用RS-485总线工业标准时接两线TX、RX也能实现通信,但接Gnd 有利抑制干扰。RS-485的前身RS—422也一样。

一般建议在使用串口通信时需要把GND连接上,尤其是在长距离传输时。

方法二:查看串口助手和源程序就传输协议设置是否一致

串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。在使用串口时这些参数必须要保持一致。下面大致介绍一些这些参数的意义:

一、波特率

波特率(bandrate)是衡量符号传输速率的参数,指的是串口通信的速率,也就是串口通信时每秒钟可以传输多少个二进制位。比如串口常用波特率9600指的是串口每秒钟可以传输9600个二进制(传输一个二进制位需要的时间是1/9600秒,也就是104us)。

注意波特率和比特率的区别:

情形一:一个信号码元有且仅有两种状态:0或1

此时每种状态含一位二进制数(0或1),在这种情况下比特率值=波特率值

情形二:一个码元有4种不同的状态:01、11、00或10

此时每种状态含两位二进制数(00、01、10、11),在这种情况下比特率值=波特率值×2

以此类推可以得到:比特率=波特率 * 单个调制状态对应的二进制位数

二、数据位

数据位是衡量通信中实际数据的参数。当计算机发送一个信息包,实际的数据不一定是8位的(标准的值是6、7和8位),如何设置取决于你想传送的信息。

比如,标准的ASCII码是0~127(7位),扩展的ASCII码是0~255(8位)。如果数据使用标准 ASCII码,那么每个数据包使用7位数据;如果数据使用扩展 ASCII码,那么每个数据包使用8位数据(每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位)。

三、停止位

停止位是用于表示单个包的最后一位。典型的值为1,1.5和2位。

由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也相应越慢。

四、奇偶校验位

奇偶校验位是串口通信中在数据位后面加一位用于简单地检查数据发送是否有错。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。

对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。

例如,如果传输的数据是011,那么对于偶校验(校验位为0),则此时数据位 + 校验位的数据为:0110,保证逻辑高的位数是偶数个。如果是奇校验(校验位为1),则此时数据位 + 校验位的数据为:0110,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步。

在实际使用中要确保这四个参数在源程序和助手设置是一致的。

方法三:在源程序中查看主频设置是否有误

上面两个是一般会出现乱码的原因,除此之外在源程序里面也会出现一些大意操作导致串口乱码(最难且不容易想到的出错点)。我目前尚未遇到过这种情况导致串口乱码的但在不少大佬的博客和文章中看见有遇到过,这里也引用下来大家可以看看是否能解决你的串口乱码问题。

STM32F407系统时钟配置不准确导致串口发送数据乱码、定时器定时不准问题

https://blog.csdn.net/lqj11/article/details/108058008

stm32f407等芯片(HAL库)时钟频率修改(乱码)

https://blog.csdn.net/bulefire2009/article/details/119633701?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-119633701-blog-108058008.pc_relevant_recovery_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-119633701-blog-108058008.pc_relevant_recovery_v2&utm_relevant_index=2

方法四:Printf重定向函数

关于重定向导致数据输出乱码我遇到过几次,关于重定向引用一篇大佬的文章printf重定向原文链接:https://blog.csdn.net/RONG_YAO/article/details/115746940。这能解决大家关于重定向的一些疑惑。但我遇到过另外一种重定向导致输出乱码的情况。

在调试一个项目时一直出现乱码问题,虽然能接到数据但一直显示“IIIIIIIt”,看着不像乱码但与实际要显示的内容天差地别(不管输出的是汉字还是ASCII都一样),前面几个解决方法都检查过没有问题,但乱码现象依然没有改变。后面仔细研究源代码发现问题出在printf重定向上,不是没有添加重定向函数,而是添加了两个重定向函数(分别添加在了sys.c和usart.c中)

在sys.c函数中定义了一次:

#pragma import(__use_no_semihosting)                             
struct __FILE { 
    int handle; 
}; 

#if( defined  DEBUG)
int fputc( int c, FILE *f )
{
#if  DEBUG == Debug_UART0
  while( R8_UART0_TFC == UART_FIFO_SIZE );                        /* 等待数据发送 */
  R8_UART0_THR = c;                                               /* 发送数据 */
#elif DEBUG == Debug_UART1       
  while( R8_UART1_TFC == UART_FIFO_SIZE );                        /* 等待数据发送 */
  R8_UART1_THR = c;                                               /* 发送数据 */
#elif DEBUG == Debug_UART2       
  while( R8_UART2_TFC == UART_FIFO_SIZE );                        /* 等待数据发送 */
  R8_UART2_THR = c;                                               /* 发送数据 */
#elif DEBUG == Debug_UART3       
  while( R8_UART3_TFC == UART_FIFO_SIZE );                        /* 等待数据发送 */
  R8_UART3_THR = c;                                               /* 发送数据 */
#endif
  return( c );
}
#endif

在usart.c中又重复添加了一个重定向函数:

#pragma import(__use_no_semihosting)                             
struct __FILE { 
    int handle; 
}; 


FILE __stdout;          
void _sys_exit(int x) 
{ 
    x = x; 
}

int fputc(int ch, FILE *f)
{      
    while(R8_UART1_TFC != UART_FIFO_SIZE)
    {
            R8_UART1_THR = ch;
    }       
    return ch;
}

有人会觉得两次重定向了程序应该会报错,但不好意思程序真没报错。将sys.c中下面这段代码删除后再测试串口收发数据正常。

#pragma import(__use_no_semihosting)                             
struct __FILE { 
    int handle; 
}; 

目前就遇到过这么几种常见(或不常见)的情况,后面会持续更新遇到的串口问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

串口输出乱码问题的解决方法汇总(持续更新): 的相关文章

随机推荐

  • 51单片机之智能小车(避障、跟随、循迹)

    目录 基本概述 硬件组成 功能 关键字 模块介绍 电机模块L9110S 循迹模块 xff08 TCRT5000传感器 xff09 红外避障模块 测速模块 小车 移动小车 xff08 控制电机转动 xff0c 使小车前进 后退 左转 右转 x
  • PX4开发环境搭建(Ubuntu1804+QGC+Qt Creator )

    文章目录 前言一 安装环境二 PX4环境搭建1 在虚拟机中安装Ubuntu2 安装PX4环境 1 下载PX4源码 xff1a 2 安装工具链 3 jMAVSim仿真 4 编译验证 三 安装QGC四 安装Qt Creator五 镜像分享 前言
  • ESP8266————AT指令+网络透传

    一 AT指令 ESP8266可以通过串口的AT指令和其他设备进行通讯或控制 刚开始我以为AT指令是ESP8266本就封装好的 xff0c 直接就可以用 xff0c 结果不是 xff0c 需要自己安装AT固件 xff0c 安装好固件之后直接用
  • 修改pip安装路径的方法

    当我们需要安装python的第三方库时 xff0c 通常都是打开cmd输入pip install xxx去安装 但是默认安装路径在C盘 xff0c 极大占用空间 xff0c 看看我的C盘空间 xff0c 已经不足了 xff01 xff01
  • 详细介绍如何在华为云调用SDK的Python代码(以文字识别OCR技术实现身份证识别为例)

    文章目录 1 保存信息2 安装SDK3 生成代码 1 保存信息 首先我们在首页的产品一栏输入OCR xff0c 找到文字识别OCR 然后找到证件类 xff0c 并点击 xff0c 然后点击立即使用 进入到文字识别 控制台 xff0c 找到身
  • 还是搞不懂Anaconda是什么?读这一篇文章就够了

    文章目录 1 Anaconda介绍2 conda介绍3 安装Anaconda4 Anaconda的使用配置Anaconda源 5 创建虚拟环境并使用5 1 创建虚拟环境5 2 查看所有环境5 3 激活环境5 4 安装包5 4 1 conda
  • 安装tensorflow的GPU版本(详细图文教程)--CUDA11.6的安装

    文章目录 TensorFlow简介TensorFlow是什么tensorflow版本变迁tensorflow 2 0 架构 安装过程常用IDE安装python3 9的安装Anaconda的安装 CUDA安装cuda软件安装cuDNN神经网络
  • 解决visual studio C++ build tools时安装包缺失或损坏的问题(亲测绝对有用!!!)

    安装visual studio C 43 43 build tools时遇到安装包缺失或损坏的问题 这个问题真的困扰我好久 xff0c 尝试过很多种办法都失败了 xff0c 我真的很无语 我尝试过卸载掉visual studio重新下载 用
  • ROS1学习笔记:tf坐标系广播与监听的编程实现(ubuntu20.04)

    参考B站古月居ROS入门21讲 xff1a tf坐标系广播与监听的编程实现 基于VMware Ubuntu 20 04 Noetic版本的环境 文章目录 一 创建功能包二 创建代码2 1 以C 43 43 为例2 1 1 配置代码编译规则2
  • Ubuntu上使用Qt Creator编译、下载PX4代码

    文章目录 一 创建工程文件二 Qt 加载工程文件三 工程的配置四 编译工程五 下载程序六 连接QGC验证 一 创建工程文件 在命令行执行以下几条命令 xff1a span class token function cd span src F
  • ROS1学习笔记:launch启动文件的使用方法

    参考B站古月居ROS入门21讲 xff1a launch启动文件的使用方法 基于VMware Ubuntu 20 04 Noetic版本的环境 文章目录 一 launch的文件结构二 launch的文件语法2 1 根元素2 2 参数设置2
  • ROS1学习笔记:常用可视化工具的使用(ubuntu20.04)

    参考B站古月居ROS入门21讲 xff1a 常用可视化工具的实现 基于VMware Ubuntu 20 04 Noetic版本的环境 文章目录 一 日志输出工具 xff1a rqt console二 绘制数据曲线 xff1a rqt plo
  • 笔记(STM32篇)day1——工程创建、操作寄存器点灯

    目录 一 STM32F103VET6 二 创建工程 1 主要文件 2 生成文件 三 操作寄存器点灯 前言 这一年 xff0c 从调剂到各种找工作面试 去实习 xff0c 感受总结下来就是 出走半生 xff0c 归来仍是萌新 xff0c 作为
  • 手把手教CMake编译Qt5工程

    一 新建CMakeLists txt 可以在工程目录下新建一个名为CMakeLists txt文件 xff0c 亦或是 xff0c 在Qtcreator中 xff0c 右键项目 xff0c 添加新文件 xff0c 选择General中的Em
  • Arduino学习篇 FreeRtos的使用

    ESP32 Arduino中的FreeRTOS使用 在platformio中不需要引入FreeRTOS的头文件 xff0c 直接可用 FreeRTOS使用第一步 xff1a 任务的创建与删除 下面的代码启用了两个任务 xff0c 并且在执行
  • 创建Ubuntu18.04的工作空间、环境变量与增强功能

    一 编译环境变量 在主目录旁显示隐藏文件 xff0c 找到 bashc文件打开来 在最后面加上以下几句代码 source opt ros melodic setup bash source catkin ws devel setup bas
  • Linux内核下gitee的使用

    一 什么是git git是一个开源的分布式版本控制系统 xff0c 用于敏捷高效地处理任何或小或大的项目 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件 Git 与常用的版本控
  • c++ 中 char 与 string 之间的相互转换问题

    首先必须了解 xff0c string可以被看成是以字符为元素的一种容器 字符构成序列 xff08 字符串 xff09 有时候在字符序列中进行遍历 xff0c 标准的string类提供了STL容器接口 具有一些成员函数比如begin end
  • 四旋翼 PID 控制

    文章目录 一 PID 原理二 四旋翼串级双闭环 PID 控制1 外环2 内环 一 PID 原理 偏差控制 xff0c 利用目标值 xff08 期望值 xff09 与实际测量值构成的偏差 xff08 误差 xff09 对被控对象进行线性的控制
  • 串口输出乱码问题的解决方法汇总(持续更新):

    平时工作中程序员在调试时总会用到串口打印数据以及一些标志位查看程序是否出现问题 但是在使用时总会遇到各种各样的问题 xff0c 最常见的就是输出乱码问题 xff08 指的是有收到数据但数据显示的是一堆不认识的汉字或字符 xff09 xff0