STM32之串口字库更新

1.串口通讯介绍

  串口通讯(Serial Communications)是一种通过串口进行数据传输的通讯方式,通过串行口每次传输一个字节的数据,按照约定的协议进行数据的传输和接收。串口通讯的原理是利用串行口的发送和接收线路,将需要传输的数据逐位传输到接收端,然后接收端再将这些数据组合成完整的信息。在传输过程中,数据是按照位(bit)进行发送和接收的,而不是按字节(byte)进行并行传输。

  串口通讯早期就定义了一套标准的串口规约,常见的接口标准包括RS-232、RS-485等。这些标准规定了接口的物理特性、电气特性、信号功能以及传输过程等。其中,RS-232是最常用的标准之一,它规定了使用数据信号线、地线、控制线等进行传输,适用于外设和计算机间的点对点通信。

  在连接方面,串口通讯通常使用DB9(9个引脚)或DB25(25个引脚)等接口进行连接。在这些接口中,GND(地线)、TXD(发送数据)、RXD(接收数据)是最基本的通信线,其他引脚则用于控制信号或握手信号等。

  • 通信参数与模式

  串口通讯需要双方事先约定好通信参数,这些参数包括波特率、数据位、校验位、停止位等。其中,波特率是指每分钟传输二进制的位数,是衡量资料传送速率的指标。数据位则是指一个通信单元发送的有效信息位,一般可选6、7、8、9位。校验位用于检错,有偶校验、奇校验、高校验和低校验等方式。停止位则表示本通信单元结束的标志。

  在通信模式方面,可以是单工、半双工或全双工模式。单工模式的数据传输是单向的,一方固定为发送端,一方固定为接收端。半双工模式则允许数据在两个方向上传输,但在任何时刻只能由其中一方发送数据,另一方接收数据。全双工模式则允许数据同时在两个方向上传输,需要发送设备和接收设备都有独立的接收和发送能力。

  • 特点与应用

  点对点通信:串口通信是一种点对点的通信方式,稳定性高、传输速度快,适用于一些对实时性要求较高的应用场景。

  通信距离短:串口通信的传输距离通常较短,一般在几十米以内,容易受到干扰。不过也有说法认为串口通讯的传输距离较长,可以达到几百米甚至更远(如IEEE488定义的并行通行设备线总长不得超过20米,任意两个设备间的长度不得超过2米,而串口长度可达1200米),这取决于具体的接口标准和传输条件。

  通信速率低:串口通信的传输速率通常较低,一般在几百到几千个比特每秒,难以满足一些高速数据传输的需求。
  硬件接口简单:串口通信使用的是串行接口,接口简单可靠,不需要复杂的硬件支持。

  支持多种通信协议:串口通信可以支持多种通信协议,如RS-232、RS-485、Modbus等,提供了灵活多样的通信方式。

  串口通讯在多个领域中得到广泛应用,包括工业自动化(用于控制和监控机器和生产线)、消费电子产品(如打印机、扫描仪等)、计算机网络(较早的计算机网络中用于连接调制解调器)、科研设备(如示波器、频谱分析器等)以及汽车电子(用于诊断系统)等领域。

2.串口通讯更新字库

  在STM32之LCD屏GBK字库制作与调用中介绍了字库的制作、烧写以及调用方式。但上述使用方法是将字库文件分割为多个数组直接写入。该方法适用于单个字库且字库文件相对较小的情况下进行烧写。本次将介绍利用串口通讯协议,实现串口方式下载更新字库文件。如下图所示:
在这里插入图片描述

2.1 协议介绍

  本协议采用发送–应答方式,每包数据固定4096字节(正文数据),带异或校验;
  协议格式:协议头 + 数据包大小 + 数据标志 + 数据包内容 + 异或校验值。数据均已16进制方式传输;
  协议头:77 62 79 71 --字符串”wbyq”十六进制ASCII值;
  数据包大小:固定两字节,高位在前;
  数据标志:01 —实体内容;
      02 —应答信息;
  数据包内容: 要发送的实际内容,单包数据正文最大4096字节;
  异或校验值:对发送的内容进行异或;
  编码格式:GBK/GB2312

  • 示例1

  • 发送内容:
    在这里插入图片描述

  • 应答信号:
    在这里插入图片描述

  • 示例2

  • 发送内容:
    在这里插入图片描述

  • 应答示例:
    在这里插入图片描述

2.2 协议数据解析示例

  按照文件传输协议格式,解析串口发送的数据内容,通过形参返回解析得到的内容和长度。

/*
串口文件传输数据解析
形参:src --原始内容count --src的字节数据buffer --保存解析的内容buffer_len  --接收的实体内容长度
返回值:0成功,其它值--失败
*/
u8 Usart_DataGet(const u8 *src,u16 count,u8 *buffer,u16 *buffer_len)
{/*77 62 79 71 0 6 1 31 32 33 34 35 36 7 77 62 79 71 --协议头0 6 --内容长度1 --标志符31 32 33 34 35 36 --实际内容7 --异或校验值*/	if(count<8)return 1;//长度错误if(src[0]!='w' || src[1]!='b' || src[2]!='y' || src[3]!='q'){return 2;//协议头错误}u16 len=src[4]<<8|src[5];//数据长度if(len<=0 || len>4096)return 3;//数据内容长度错误*buffer_len=len;u8 xor=0;//保存异或校验值if(src[6]!=0x1)return 4;//数据标志位错误u16 i=0;for(i=0;i<len;i++){xor^=src[7+i];buffer[i]=src[7+i];}if(xor!=src[7+i])return 5;//校验出错return 0;//数据接收正常
}

2.3 应答发送

/*
发送应答
*/
void Usart_SendAck(u8 stat)
{u8 data[10]={0x77,0x62,0x79,0x71,0x0,0x1,0x02};u8 xor=0;//保存异或校验值data[7]=stat;//应答状态xor^=stat;data[8]=xor;//异或校验值Usartx_SendData(USART1,data,9);//发送应答
}

2.4 字库更新

#include "stm32f10x.h"
#include "sys.h"
#include "beep.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include "timer.h"
#include "infrared.h"
#include "w25q64.h"
#include "at24c08.h"
#include "nt35310.h"
u8 Usart_DataGet(const u8 *src,u16 count,u8 *buffer,u16 *buffer_len);
void Usart_SendAck(u8 stat);
u8 buffer[4096];
u16 buffer_len;
int main()
{u8 key=0;Beep_Init();Led_Init();Key_Init();Usartx_Init(USART1,921600,72);TIMx_Init(TIM2,72,20*1000);printf("USART1初始化完成\r\n");u16 id=W25Q64_Init();printf("id=%#x\r\n",id);I2C_Init();//初始化硬件NT35310_Init();LCD_DisplayStr(100,200,16,"GBK Update:",RED);u16 i=0;u8 ret;u32 addr=0;char arr[100];while(1){if(usart1_flag){//usart1_rx_buff[usart1_cnt]='\0';//printf("usart1:%s\r\n",usart1_rx_buff);/*77 62 79 71 0 6 1 31 32 33 34 35 36 7  -->十六进制77 62 79 71 --协议头0 6 --内容长度1 --标志符31 32 33 34 35 36 --实际内容7 --异或校验值*/ret=Usart_DataGet(usart1_rx_buff,usart1_cnt,buffer,&buffer_len);if(ret==0){//将字库信息写入到W25Q64W25Q64_KuaPageProgram_Erase(GBK_24_ADDR+addr,buffer,buffer_len);addr+=buffer_len;snprintf(arr,sizeof(arr),"%.1f KB",addr*1.0/1024);LCD_DisplayStr(100+11*8,200,16,arr,RED);LED1=!LED1;}Usart_SendAck(ret);if(buffer_len<4096){printf("字库更新完成\r\n");LCD_DisplayStr(10,240,24,"串口字库更新应用示例",RED);}//printf("ret=%d\n",ret);usart1_flag=0;usart1_cnt=0;}}
}

2.5 字库更新运行效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3 字库合并

  若一次性需要烧写多个字库,则可以将多个字库合并为一个字库文件,代码实现如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
//字库合并
int main(int argc,char **argv)
{if(argc<3){printf("运行格式:./app <字库文件1>、<字库文件2>、<字库文件3>....\n");return 0;}int i=0;char  *font_file[5];int file_cnt=0;unsigned int font_size[5];unsigned int font_count=0;int ret;for(i=1;i<argc;i++){font_file[file_cnt]=argv[i];struct stat statbuf;ret=stat(font_file[file_cnt],&statbuf);//获取文件大小if(statbuf.st_size<=0 || ret)//保证能正常获取到文件大小{continue;}font_size[file_cnt]=statbuf.st_size;printf("字库文件%d:%s\t大小:%d byte\n",i,font_file[file_cnt],font_size[file_cnt]);file_cnt++;}if(file_cnt<2){printf("合并文件少于2个,请检查要合并的文件是否正常\n");return 0;}const char *dest_file="font.bin";//合并后的目标文件//创建目标文件FILE *dest_fp=fopen(dest_file,"w+b");if(dest_file==NULL){printf("目标文件%s文件创建失败\n",dest_file);return 0;}char buffer[4096];int size=0;int j=0;//打开文件for(i=0;i<file_cnt;i++){FILE *fp=fopen(font_file[i],"rb");if(fp==NULL){printf("%s 文件打开失败,请检查文件是否正常\n",font_file[i]);return 0;}printf("字库文件%d正在写入....\n",i+1);printf("文件大小:%d\t,写入的起始位置:%d\n",font_size[i],font_count);while(1){size=fread(buffer,1,sizeof(buffer),fp);//读取源文件内容fwrite(buffer,size,1,dest_fp);//将内容写入到新文件中font_count+=size;if(size!=sizeof(buffer))break;}if(size%1024)//保证每次写入为1024的倍数{char data=0;//不足1024用0补齐for( j=0;j<1024-size%1024;j++){fwrite(&data,1,1,dest_fp);}font_count+=j;}}printf("文件合并完成,合并后的文件为:%s,\t文件大小:%.1f MB\n",dest_file,font_count*1.0/1024/1024);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/462998.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用

【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用 目录 文章目录 【大语言模型】ACL2024论文-06 探索思维链COT在多模态隐喻检测中的应用目录摘要研究背景问题与挑战如何解决创新点算法模型1. 知识总结模块&#xff08;Knowledge Summarization Module&…

第三十一章 单页与多页应用程序概念

目录 一、概述 ​二、单页与多页对比 一、概述 单页面应用(SPA): 所有功能在一个HTML页面上实现&#xff0c;如网易云音乐。 https://music.163.com/ 多页应用&#xff1a;通过多个HTML页面组合实现整个应用网站的功能。 二、单页与多页对比 单页面应用的主要场景&#xff1…

开源 AI 智能名片 2 + 1 链动模式 S2B2C 商城小程序中积分使用价值的拓展策略

摘要&#xff1a;本文围绕开源 AI 智能名片 2 1 链动模式 S2B2C 商城小程序&#xff0c;深入探讨其积分使用价值的丰富策略。详细分析积分兑换礼品、会员升级、积分抵现等方式在该特定商城小程序环境下的应用特点、存在问题及对用户和商城的影响&#xff0c;旨在为商城的优化运…

C++ | Leetcode C++题解之第526题优美的排列

题目&#xff1a; 题解&#xff1a; class Solution { public:int countArrangement(int n) {vector<int> f(1 << n);f[0] 1;for (int mask 1; mask < (1 << n); mask) {int num __builtin_popcount(mask);for (int i 0; i < n; i) {if (mask &am…

【Linux 25】网络套接字 socket 概念

文章目录 &#x1f308; 一、IP 地址概念⭐ 1. IP 地址的作用⭐ 2. 源 IP 地址和目的 IP 地址 &#x1f308; 二、端口号概念⭐ 1. 源端口号和目的端口号⭐ 2. 端口号范围划分⭐ 3. 端口号 VS 进程 ID⭐ 4. 套接字 socket 的概念 &#x1f308; 三、传输层的典型代表协议⭐ 1. …

利用Docker Compose构建微服务架构

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 利用Docker Compose构建微服务架构 引言 Docker Compose 简介 安装 Docker Compose 创建项目结构 编写 Dockerfile 前端 Dockerf…

【Vue】一个案例带你学会组件通信!!!(1)(父传子props+子传父$emit)

嘿&#xff0c;开发者们&#x1f44b;&#xff01;欢迎来到今天的Vue.js组件通信大冒险。你是否曾在父子组件间的数据同步问题上感到头疼&#xff1f;&#x1f92f; 今天&#xff0c;我们将一起揭开Vue.js父子通信的神秘面纱&#xff0c;学习如何让数据在父子组件间流畅地“跳舞…

在VS中安装chatGPT

2、在VSCode中打开插件窗口 3、输入ChatGPT 4、这里有个ChatGPT中文版&#xff0c;就它了 5、安装 6、这时候侧边栏多了一个chatGPT分页图标&#xff0c;点击它 7、打个招呼 8、好像不行 9、看一下细节描述 10、根据要求按下按下快捷键 Ctrl Shift P 11、切换成国内模式 12、…

3. keil + vscode 进行stm32协同开发

1. 为什么使用vscode 主要还是界面友好&#xff0c;使用习惯问题&#xff0c;vscode 从前端&#xff0c;js, c/c, qt, 仓颉&#xff0c;rust都有很好插件的支持&#xff0c;并且有romote&#xff0c; wsl 等很多插件可以提高效率&#xff0c; 唯一的问题就是要使用插件进行环境…

PostgreSQL 学习笔记:PostgreSQL 主从复制

PostgreSQL 笔记&#xff1a;PostgreSQL 主从复制 博客地址&#xff1a;TMDOG 的博客 在现代应用程序中&#xff0c;数据库的高可用性和扩展性是至关重要的。PostgreSQL 提供了主从复制功能&#xff0c;可以在多个数据库实例之间复制数据&#xff0c;以实现冗余和负载均衡。本…

433、315通信、ev1527、2262编码

目录 ASK介绍EV1527编码芯片介绍模块介绍无线发射芯片无线接收芯片解码程序发射电路原理图 ASK介绍 ASK是幅移键控&#xff0c;通过调幅将数据发送出去&#xff0c;所以发送与接收都是多位二进制数。 ASK如何区分0和1&#xff1f; 0&#xff1a;发送 433.92Mhz 无线波形&…

Python 5个数据容器

列表&#xff08;list&#xff09; 特点&#xff1a;可以被修改 列表的定义 定义空列表&#xff1a; 变量名 [] 或 变量名 list() 定义变量&#xff1a; 变量名 [元素1&#xff0c;元素2&#xff0c;元素3&#xff0c;... ] 取出列表元素 列表名 [下标索引] 从前向…

复习数据库(约束)上篇

目录 约束的分类 分类 注意 主键约束 添加主键约束 1 建表时&#xff0c;添加 1.1创建表&#xff1a;定义列时指定 1.2 创建表&#xff1a;定义列之后独立指定主键&#xff1a; 2 建表后使用alter 关键字添加 删除约束 在主键添加自动增长属性 疑问 1 建表时添加 …

国内短剧源码短剧系统搭建小程序部署H5、APP打造短剧平台

​在当今的互联网时代&#xff0c;短剧作为一种新兴的娱乐形式&#xff0c;受到了越来越多用户的喜爱。为了提供更好的用户体验和满足用户需求&#xff0c;一个好的短剧系统需要具备多元化的功能和优质的界面设计。 本文将介绍国内短剧源码短剧系统搭建小程序部署H5、APP所需的…

Python(数据结构2)

常见数据结构 队列 队列(Queue)&#xff0c;它是一种运算受限的线性表,先进先出(FIFO First In First Out) Python标准库中的queue模块提供了多种队列实现&#xff0c;包括普通队列、双端队列、优先队列等。 1 普通队列 queue.Queue 是 Python 标准库 queue 模块中的一个类…

QT 机器视觉 (3. 虚拟相机SDK、测试工具)

本专栏从实际需求场景出发详细还原、分别介绍大型工业化场景、专业实验室场景、自动化生产线场景、各种视觉检测物体场景介绍本专栏应用场景 更适合涉及到视觉相关工作者、包括但不限于一线操作人员、现场实施人员、项目相关维护人员&#xff0c;希望了解2D、3D相机视觉相关操作…

QT打包Macosx应用发布App Store简易流程

1、QC里编译工程&#xff0c;生成Release版的的app文件&#xff1b; 2、运行macdeployqt把需要的文件打包进app文件中&#xff1b; % ~/Qt/5.15.0/clang_64/bin/macdeployqt {编译的app文件所在路径}/Release/xxxx.app 3、使用codesign对app进行签名&#xff0c;如果要发App…

Android平台RTSP转RTMP推送之采集麦克风音频转发

技术背景 RTSP转RTMP推送&#xff0c;好多开发者第一想到的是采用ffmpeg命令行的形式&#xff0c;如果对ffmpeg比较熟&#xff0c;而且产品不要额外的定制和更高阶的要求&#xff0c;未尝不可&#xff0c;如果对产品稳定性、时延、断网重连等有更高的技术诉求&#xff0c;比较…

网络:ARP的具体过程和ARP欺骗

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》《网络》 《redis学习笔记》 文章目录 前言ARP具体过程ARP欺骗原理总结 前言 本文仅作为ARP具体过程和ARP欺骗的知识总结 硬件类型 &#xff1a;指定发送和接受ARP包的硬件类型&am…

单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构

目录 一、合并两个有序链表 二、链表分割 三、链表的回文结构 u解题的总体思路&#xff1a; 合并两个有序链表&#xff1a;首先创建新链表的头节点&#xff08;哨兵位&#xff1a;本质上是占位子&#xff09;&#xff0c;为了减少一些判断情况&#xff0c;简化操作。然后我们…