重生我是嵌入式大能之串口调试UART
什么是串口
串口是一种在数据通讯中广泛使用的通讯接口,通常我们叫做UART (通用异步收发传输器Universal Asynchronous Receiver/Transmitter),其具有数据传输速度稳定、可靠性高、适用范围广等优点。在嵌入式系统中,串口常用于与外部设备进行通讯,如传感器、液晶显示屏、WiFi模块、蓝牙模块等。
串口通信中的 TXD(Transmit Data)和 RXD(Receive Data)是串口通信中的两个重要信号。
TXD是指串口发送端的数据信号,而RXD是指串口接收端的数据信号。在串口通信中,发送端把要发送的数据发送到TXD引脚上,接收端则通过RXD引脚来接收这些数据。
TXD 发送端数据信号 RXD 接收端数据信号
TXD和RXD信号的实现方式取决于使用的芯片或模块。一般来说,它们都是通过芯片或模块的串口功能来实现的,这需要将相应的引脚连接到芯片或模块的串口引脚上。
在发送数据时,需要将要发送的数据通过串口的发送缓冲区发送到TXD引脚上,接收端通过RXD引脚接收这些数据并放入接收缓冲区中。在接收端收到完整的数据后,可以通过相应的处理进行数据的解析和处理。
需要注意的是,TXD和RXD的电平标准也需要一致,一般常见的有TTL电平和RS232电平,如果不一致则需要进行电平转换。同时,在编写程序时也需要注意串口波特率、数据位、停止位等参数的设置,以保证通信的稳定和可靠
以下是STC8H的芯片引脚介绍图

其中有4组Uart通讯口:
| 串口 | RXD | TXD |
| UART1 | P3.0 | P3.1 |
| P3.6 | P3.7 | |
| P1.6 | P1.7 | |
| P4.3 | P4.4 | |
| UART2 | P1.0 | P1.1 |
| P4.6 | P4.7 | |
| UART3 | P0.0 | P0.1 |
| P5.0 | P5.1 | |
| UART4 | P0.2 | P0.3 |
| P5.2 | P5.3 |
串口TTL通讯协议
串口 TTL 通讯协议通常是指通过串行通信接口(TTL UART)进行数据传输的协议。这种协议通常用于连接微控制器、传感器、单片机等设备,以实现数据的收发和控制。串口 TTL 通讯协议通常包括以下几个方面:
-
物理连接:串口 TTL 通常使用一根或多根导线将设备连接在一起,这些导线通常包括信号线(如TX、RX)、地线(GND)和可能的控制线(如RTS、CTS)
-
数据格式:包括数据帧的格式,如起始位、停止位、数据位和校验位。常见的配置包括 8 位数据位、1 位停止位和无校验。
-
波特率:指数据传输的速率,通常以每秒传输的位数(bps)来表示,常见的波特率包括 9600、115200 等。
-
控制协议:有时候需要额外的控制信号或命令来启动、停止或配置通讯。这些控制信号可能包括流量控制(如硬件流控)、命令传输等。
-
异步串行通信:串口 TTL 使用异步串行通信协议,通过将数据分成数据帧并在首尾加上起始位和停止位来传输数据。
-
TTL 电平:串口 TTL 使用 TTL 电平进行数据传输,其电压范围一般是 0 到 5V,需要注意不同设备之间 TTL 电平的兼容性。
TX 用于发送数据,RX 用于接收数据,它们是串口 TTL 通信中最基本的信号
根据具体的应用场景和设备,串口 TTL 通讯协议可能会有所不同,但是通常遵循上述基本原则。例如,一些设备可能需要特定的数据格式或控制信号来实现特定的功能。

串口转USB
串口转USB是一种常见的设备,用于连接使用串口通信协议的设备到计算机或其他设备的USB接口。这种设备通常被称为串口转USB适配器或串口转USB转换器。它的作用是将串口设备的信号转换成USB信号,使得串口设备可以通过USB接口与计算机进行通信。
串口转USB适配器通常包括以下几个部分:
-
串口接口:用于连接串口设备的端口,通常是RS-232或TTL接口。
-
USB接口:用于连接计算机或其他设备的USB端口。
-
转换芯片:用于将串口信号转换成USB信号,以实现串口与USB之间的数据转换和通信。
-
驱动程序:有些串口转USB适配器需要安装特定的驱动程序才能在计算机上正常工作,这些驱动程序通常由适配器的制造商提供。
使用串口转USB适配器可以方便地将传统的串口设备连接到现代的计算机或其他设备上,实现数据传输和通信。这在很多场景下都是非常有用的,特别是在需要连接老旧设备或嵌入式系统时。
STC8H核心板串口调试
原理图

D+D-对应的usb口,和pc主机连接P3.1P3.0对应的芯片- `采用CH340将串口和USB之间进行转换
需求:通过串口调试工具,发送消息给开发板,开发板原封不动的将消息传回。
开发步骤:
- 新建项目
- 导入库函数
- 编写逻辑
串口调试实现
-
新建项目。新建
main.c文件 -
导入函数库。拷贝以下函数库文件到项目目录:
-
代码编写(发送)
#include "Config.h"
#include "GPIO.h"
#include "UART.h"
#include "Delay.h"
#include "NVIC.h"
#include "Switch.h"/************* 功能说明 **************
双串口全双工中断方式收发通讯程序。通过PC向MCU发送数据, MCU收到后通过串口把收到的数据原样返回, 默认波特率:115200,N,8,1.通过开启 UART.h 头文件里面的 UART1~UART4 定义,启动不同通道的串口通信。
******************************************//******************* IO配置函数 *******************/
void GPIO_config(void)
{GPIO_InitTypeDef GPIO_InitStructure; //结构定义GPIO_InitStructure.Pin = GPIO_Pin_0 | GPIO_Pin_1; //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_Inilize(GPIO_P3,&GPIO_InitStructure); //初始化
}/*************** 串口初始化函数 *****************/
void UART_config(void)
{COMx_InitDefine COMx_InitStructure; //结构定义COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3UART1_SW(UART1_SW_P30_P31); //UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}/**********************************************/
void main(void)
{// EAXSFR(); /* 扩展寄存器访问使能 */GPIO_config();UART_config();EA = 1;TX1_write2buff(0x23); // #printf("STC8H8K64U UART1 Test Programme!\r\n"); //UART1发送一个字符串PrintString1("STC8H8K64U UART1 Test Programme!\r\n"); //UART1发送一个字符串while (1){TX1_write2buff(0x2F); // /delay_ms(250);delay_ms(250);delay_ms(250);delay_ms(250);}
}
代码编写(接收并回写)
#include "Config.h"
#include "GPIO.h"
#include "UART.h"
#include "Delay.h"
#include "NVIC.h"
#include "Switch.h"void GPIO_config(void) {GPIO_InitTypeDef GPIO_InitStructure; //结构定义GPIO_InitStructure.Pin = GPIO_Pin_0 | GPIO_Pin_1; //指定要初始化的IO, P30, P31GPIO_InitStructure.Mode = GPIO_PullUp; //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_Inilize(GPIO_P3, &GPIO_InitStructure);//初始化
}void UART_config(void) {COMx_InitDefine COMx_InitStructure; //结构定义COMx_InitStructure.UART_Mode = UART_8bit_BRTx; //模式, UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTxCOMx_InitStructure.UART_BRT_Use = BRT_Timer1; //选择波特率发生器, BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)COMx_InitStructure.UART_BaudRate = 115200ul; //波特率, 一般 110 ~ 115200COMx_InitStructure.UART_RxEnable = ENABLE; //接收允许, ENABLE或DISABLECOMx_InitStructure.BaudRateDouble = DISABLE; //波特率加倍, ENABLE或DISABLEUART_Configuration(UART1, &COMx_InitStructure); //初始化串口1 UART1,UART2,UART3,UART4NVIC_UART1_Init(ENABLE,Priority_1); //中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3UART1_SW(UART1_SW_P30_P31); //UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17,UART1_SW_P43_P44
}void on_uart1_recv() {u8 i;// RX_Cnt收到的数据个数(字节u8 - unsigned char)// 将收到的数据, 按字节逐个循环for(i=0; i<COM1.RX_Cnt; i++) {u8 dat = RX1_Buffer[i]; // 1 1 1 1 0 0 0 0 -> 0xF0TX1_write2buff(dat); //收到的数据原样返回}
}
/**
开启串口调试,接收数据,把收到的数据原样返回**/
void main() {// 初始化IOGPIO_config();// 初始化UARTUART_config();// 开启中断(全局)必须要写!EA = 1;// 写一个字节TX1_write2buff(0x23);// 通过PrintString1输出字符串PrintString1("STC8H8K64U UART1 Test Programme!\r\n"); //UART1发送一个字符串// 通过printf输出字符串printf("STC8H8K64U UART1 Test Programme!\r\n"); //UART1发送一个字符串while(1) {// 超时计数// 一旦收到了一个字节数据,RX_TimeOut会初始化一个值(例如:5)if((COM1.RX_TimeOut > 0) && (--COM1.RX_TimeOut == 0)){ if(COM1.RX_Cnt > 0){// 收到数据了,on_uart1_recv();on_uart1_recv();}// 处理完数据,将数据个数清零COM1.RX_Cnt = 0;}// 注意这里delay代码的位置,属于whiledelay_ms(10);}
}
调试

使用STC-ISP调试工具进行调试。切换好串口助手,选择正确的串口,设置和代码中相同的波特率。
通过发送区进行数据发送,通过接收区观察接收内容。
串口调试重难点
功能配置
- 配置IO的工作模式:如果不配置工作模式,会导致串口不工作。(UART1的当前代码中的引脚
P3.0和P3.1默认是准双向口,可以不配置,但是不要存在侥幸心理,导致其他的串口使用中没有配置准双向口) - 配置UART的串口工作模式
UART_Mode:
-
UART_ShiftRight同步移位输出:按位传输,效率低,通常不用。UART_8bit_BRTx8位数据,可变波特率:常用。发送和接收的数据为8位。UART_9bit9位数据,固定波特率,即无法在运行时动态更改波特率。UART_9bit_BRTx9位数据,可变波特率:发送和接收的数据为9位。最后一位为奇偶校验位。
- 配置UART的波特率
RaudRate:根据实际情况来定,波特率越高,传输越快,但是出现丢帧的概率越高。通常115200就够用。单位是bit/s - 配置UART的波特率发生器
BRT_Use:系统提供了4个发生器,通常一一对应。
-
BRT_Timer1BRT_Timer2BRT_Timer3BRT_Timer4
- 配置UART是否接收
RxEnable:可以获取RXD接收的数据。 - 配置UART波特率加倍
BaudRateDouble:默认不加倍,配置加倍会导致波特率是设定的双倍,过高会导致丢帧。 - 配置UART中断
Interrupt和优先级Priority:UART的数据收发是通过中断实现的,如果不配置,则无法对外发送数据,TXD和RXD不工作。 - 配置UART的端口
P_SW:串口通道可以通过几组引脚来实现,但是需要指明是哪一组。
中断开启
由于uart中的发送是通过中断实现的,需要开启,但是STC8还提供了一个总的开关,如果总开关不打开,一样不起作用。
EA = 1;
UART的接收与发送
关于接收
接收是通过接收缓冲区进行接收。
在死循环中,间隔一定时间到缓冲区中去取数据,有数据,说明就是接收了
关于发送
发送是通过发送缓冲区进行发送。
发送提供了单个字节发送的API:
TX1_write2buff(byte)发送提供了字符串发送的API:
PrintString1(str)
相关文章:
重生我是嵌入式大能之串口调试UART
什么是串口 串口是一种在数据通讯中广泛使用的通讯接口,通常我们叫做UART (通用异步收发传输器Universal Asynchronous Receiver/Transmitter),其具有数据传输速度稳定、可靠性高、适用范围广等优点。在嵌入式系统中,串口常用于与外部设备进…...
【智能优化算法】蜜獾优化算法(Honey Badger Algorithm,HBA)
蜜獾优化算法(Honey Badger Algorithm,HBA)是期刊“MATHEMATICS AND COMPUTERS IN SIMULATION”(IF 3.6)的2022年智能优化算法 01.引言 蜜獾优化算法(Honey Badger Algorithm,HBA)受蜜獾智能觅食行为的启发,从数学上发展出一种求解优化问题的…...
【算法与数据结构】数组
文章目录 前言数组数组的定义数组的基本操作增加元素删除元素修改元素查找元素 C STL 中的数组arrayvector Python3 中的列表访问更改元素值遍历列表检查列表中是否存在某元素增加元素删除元素拷贝列表总结 Python3 列表的常用操作 参考资料写在最后 前言 本系列专注更新基本数…...
【数据结构】队列详解(Queue)
文章目录 有关队列的概念队列的结点设计及初始化队列的销毁判空和计数入队操作出队操作 有关队列的概念 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)入队列:进行插入操作的一端…...
Baumer工业相机堡盟工业相机如何通过NEOAPISDK获取相机的Statistics图像传输统计信息(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPISDK获取相机的Statistics图像传输统计信息(C#) Baumer工业相机Baumer工业相机NEOAPI SDK和相机Statistics图像传输统计信息的技术背景Baumer工业相机通过NEOAPISDK获取相机的Statistics图像传输统计信息技术1.引…...
FreeRTOS标准库例程代码
1.设备STM32F103C8T6 2.工程模板 单片机: 部分单片机的程序例程 - Gitee.comhttps://gitee.com/lovefoolnotme/singlechip/tree/master/STM32_FREERTOS/1.%E5%B7%A5%E7%A8%8B%E6%A8%A1%E6%9D%BF 3.代码 1-FreeRTOS移植模板 #include "system.h" #include "…...
wandb: - 0.000 MB of 0.011 MB uploaded持续出现的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
分布式模式让业务更高效、更安全、更稳定
🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,坚持默默的做事。 🚀 转载自热榜文章🔥:探索设计模式的魅力:分布式模…...
5.11学习记录
20长安杯部分 检材 1 的操作系统版本 CentOS Linux 7.6.1810 (Core) 检材 1 中,操作系统的内核版本是 3.10.0-957.el7.x86_64 检材 1 中磁盘包含一个 LVM 逻辑卷,该 LVM 开始的逻辑区块地址(LBA)是 2099200 物理卷ÿ…...
Java类加载器介绍
在Java中,类加载器是一种动态加载类的机制,它负责在运行时查找、加载和链接类文件。当Java应用程序需要创建某个类的对象时,类加载器会在运行时查找该类对应的.class文件,并将其加载到Java虚拟机中。Java类加载器通常分为三层&…...
VC++ PDH/性能计数器
例子: PID0,缺省为当前进程,但最好是获取当前进程ID传递进去,当然也可以选择其它进程的ID。 PerformanceCounter pc; pc.Open(0, "//Processor(_Total)//% Processor Time"); 源实现: #include <windo…...
C++ 类和对象:面向对象编程基础
目录标题 1. 什么是类?2. 什么是对象?3. 如何定义一个类?4. 如何创建对象?5. 类的构造函数6. 类的析构函数7. 数据封装和访问修饰符8. 示例:一个简单的BankAccount类9. 使用g编译10. 再来一个简单的C程序11. 定义书籍类…...
linux 基础命令使用
命令 su 用于切换到另一个用户身份,通常是超级用户(root)。su命令可以用来在命令行下切换用户,也可以在脚本中使用。 语法: su [选项] [用户名] 选项: - -c:执行完命令后,立即退出su命令;…...
eve 导入linux
mkdir /opt/unetlab/addons/qemu/linux-centos7 cd /opt/unetlab/addons/qemu/linux-centos7 上传hda.qcow2 /opt/unetlab/wrappers/unl_wrapper -a fixpermissions Linux images - (eve-ng.net) Due to very high demand of this section and problems with how to crea…...
vivado新版本兼容老版本,vitis classic兼容sdk教程
new version: vivado版本2023.2 和vitisv classic 2023.2 old version: vivado 2018.3以及之前的版本 打开工程 自动升级到当前版本,选择OK 点击Yes,合并当前的目录架构 点击OK 点击Report IP status 勾选要升级的IP核,点击升级 在项目工程文件夹…...
02.02.返回倒数第k个节点
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。 注意:本题相对原题稍作改动 示例: 输入: 1->2->3->4->5 和 k 2 输出: 4 说明: 给定的 k 保证是有效的。 代码ÿ…...
MongoDB 从部署到掌握
一、docker部署MongoDB ## 通过docker安装MongoDB~~~shell #拉取镜像 docker pull mongo:4.0.3#创建容器 docker create --name mongodb-server -p 27017:27017 -v mongodb-data:/data/db mongo:4.0.3 --auth#启动容器 docker start mongodb-server#进入容器 docker exec -it …...
electron-vite工具打包后通过内置配置文件动态修改接口地址实现方法
系列文章目录 electronvitevue3 快速入门教程 文章目录 系列文章目录前言一、实现过程二、代码演示1.resources/env.json2.App.vue3.main/index.js4.request.js5.安装后修改 前言 使用electron-vite 工具开发项目打包完后每次要改接口地址都要重新打包,对于多环境…...
每日一练2024.5.9
题目: 给定一副牌,每张牌上都写着一个整数。 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组: 每组都有 X 张牌。组内所有的牌上都写着相同的整数。 仅当你可选的 X > 2 时返回 tru…...
P2622 关灯问题
小小注解: 1. vis:表示到达该状态的步数(min)1, 因为我们是从开始状态 穷举,所以每次到一个新状态(之前没有到过的状态)就是最小步数。 如何判断是否是一个新状态呢,…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...
