
C语言学习笔记
文章平均质量分 72
分享在学习C语言的过程中遇到的问题及解决方法
嵌入式@hxydj
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
IAR软件中测量函数执行时间
摘要:本文介绍了在IAR开发环境中测量代码执行时间的两种方法。第一种通过ST-LINK的Data Log Summary工具,在调试时记录断点前后的时间差(如测量到200.996ms延时)。第二种利用CYCLECOUNTER寄存器差值计算指令周期数,再结合CPU时钟频率(如170MHz)换算为实际时间(34,169,410周期对应200.996ms)。两种方法均可准确测量代码段执行时长,适用于不同调试需求。原创 2025-08-06 19:30:00 · 198 阅读 · 0 评论 -
IAR软件中变量监控的几种方法
IAR软件中分别使用watch、live watch、Locals、printf()、Debug log这几种显示需要实时监控的变量值。原创 2025-08-05 17:25:00 · 891 阅读 · 0 评论 -
使用Simulink和STM32Cube联合生成LED闪烁程序
本文详细介绍了如何将Simulink仿真模型生成的代码集成到STM32单片机工程中。主要内容包括:1)设置仿真参数与代码生成路径;2)建立状态机模型并设置状态转移条件;3)创建数据字典定义参数和信号变量;4)绑定模型与数据字典,配置仿真参数;5)设置符号变量和输出端口。通过这一系列步骤,可实现Simulink模型到嵌入式代码的完整转换流程,为嵌入式开发提供可视化建模支持。原创 2025-07-17 08:46:36 · 497 阅读 · 0 评论 -
在STM32CubeMonitor中使用j-link显示变量曲线
本文介绍了使用J-Link连接STM32F103C8T6开发板并通过STM32CubeMonitor监控变量波形的方法。首先将工程中的ST-Link模块替换为J-Link模块,配置J-Link参数并添加MCU型号。加载工程中的.axf文件后选择需要监控的变量,部署成功后即可显示波形曲线。文中还详细说明了如何调整波形显示的时间坐标轴,并通过重新部署使设置生效。整个过程展示了从硬件连接到软件配置的完整流程,实现了与ST-Link相同的变量监控功能。原创 2025-06-30 09:38:14 · 393 阅读 · 0 评论 -
使用STM32CubeMonitor实时修改变量值
本文演示了使用STM32CubeMonitor实时修改变量值及存储数据的方法。在原有代码基础上,通过添加write panel控件实现对max和max1变量的动态修改,从而控制time_cnt和time_cnt1的计数上限。操作步骤包括:连接控件输入输出、配置变量组、设置目标变量,部署后通过界面直接修改数值并观察波形变化。此外,还展示了将time_cnt变量值保存为CSV文件的功能,通过single value控件筛选数据,写入文件控件指定存储路径。实验结果表明,该方法能有效实现运行时的变量修改和数据记录,原创 2025-06-27 17:55:32 · 735 阅读 · 2 评论 -
使用STM32CubeMonitor仪表显示功能
本文介绍了如何使用STM32CubeMonitor实现变量数据的仪表盘可视化监控。通过STM32代码生成三个测试变量:两个线性递增变量(time_cnt和time_cnt1)和一个正弦变量(sin_value),详细演示了在CubeMonitor中配置仪表(gauge)和文本(text)显示模块的方法。文章包含完整的配置步骤:从变量添加、模块布局调整到显示效果优化,最终实现了波形曲线与仪表盘的协同显示。通过调整模块尺寸和布局,获得了清晰直观的监控界面,为嵌入式系统实时数据可视化提供了实用参考方案。原创 2025-06-26 11:37:11 · 511 阅读 · 0 评论 -
使用STM32CubeMonitor实时监控变量曲线
STM32CubeMonitor实时变量观测指南 摘要:本文介绍使用ST官方工具STM32CubeMonitor实时观测单片机变量的方法。首先从官网下载安装软件,配置工程路径并选择.axf文件,添加需要观测的变量。通过ST-LINK连接硬件后,在Dashboard界面启动波形显示,可调整时间轴范围(默认10秒可改为100秒)。演示了同时观测两个变量(自增和自减变量)的方法,并提醒修改程序时需先停止波形显示再下载,避免ST-LINK连接失败。该工具为STM32调试提供了便捷的实时数据可视化方案。原创 2025-06-25 17:53:49 · 555 阅读 · 0 评论 -
PIC16F1936单片机HEX文件问题
开始还以为是编译器出问题了,最后经过查找资料才发现,在PIC16F1xxx系列单片机中,单指令的长度是14bit,是由2个8bit的字节拼起来的,所以hex文件中的地址是实际地址的两倍。这样编译器中的地址 0x7D1 * 2 = 0xFA2, hex文件中的地址 0xFC2 / 2 = 0x7E1。可以看到程序地址从0FA2开始存储,但是在编译器中查看程序数据时发现,0FA2地址中开始的值全是默认值。通过地址换算,然后对比地址中的数据,可以相互对应。说明hex文件中的地址和程序中的地址确实是2倍关系。原创 2025-03-25 16:17:22 · 244 阅读 · 0 评论 -
PIC单片机设置bootloader程序和app程序地址方法
但是app的程序就能不能通过烧写器下载了,否则在下载app的程序时,boot loader的程序就会被擦除掉。第一行的数据存储地址是 0x2000,第2行的数据的存储地址就跳到了0xFF74,这个地址是由编译器自动分配的。这里的ROM ranges就是设置boot loader代码的存放地址,这个地址的范围也可根据自己代码的情况设置。APP的地址地址为0x2000,芯片的最大地址是0xFFFF,所以代码的存储范围就是0x2000到0xFFFF,可以打开编译好的hex文件查看。是由编译器自动分配的。原创 2025-01-21 17:04:51 · 1382 阅读 · 1 评论 -
PIC单片机HEX文件格式分析
04 表示后面的地址为扩展地址,因为数据地址只有2个字节,最大值只能表示到0xFFFF,如果地址超过0xFFFF,就需要用到扩展地址,表示将后面的地址值左移16位,如图中11行所示,后面的地址为0x0030,前面的数据为04,地址值就要左移16位,所以实际的地址值就是0x0300 0000。第16行是跳转到地址0x00F0 0000地址处,这个地址在芯片手册上未找到相关资料,不过根据17行的数据可以看出,在这个地址上写入的值是0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F。原创 2025-01-21 15:06:46 · 1007 阅读 · 0 评论 -
PIC单片机生成HEX文件中代码地址问题分析
这时候代码的存储位置变了,但是不是从0地址开始存储,而是从7FF地址前面了。当程序中没有中断的时候,代码存储的位置是编译器自动存放的,不一定是按照顺序从0开始存放的。以前使用STM32单片机的时候,生成的HEX文件,代码存储都是从0地址开始依次递增存储的,但是最近再使用PIC单片机的时候却发现这个单片机有点不一样。可以看到默认生成的代码存放地址都是从0x1000开始的,如果要修改存储地址的话需要再编译器项目属性里面设置ROM的地址范围。如果要设置代码的偏移地址的话,也可以在项目属性中设置。原创 2025-01-11 09:20:20 · 747 阅读 · 0 评论 -
嵌入式编程时如何分层设计代码
代码量少的话还可以,如果代码里比较多,需要在一堆代码中去找这些需要的代码也很费时间,假如某一个功能需要升级了,代码需要修改了,那么每个产品都需要找到对于的代码去修改,那工作量岂不是很大。串口数据接收的函数,由统一的一个函数就被分离成了 串口中断----->数据接收 两个部分,如果后面还需要对接收到的数据进行内部解析,按照这种思维再抽象一个协议解析的函数。将接收函数的参数,由一个修改为2个。将接收到的数据存储到数组中,并使用一个值来标记接收到数据的状态和接收到数据个数,如果收到回车换行符,就结束数据接收。原创 2024-12-22 13:59:28 · 902 阅读 · 0 评论 -
STM32CubeMX生成代码后汉字乱码解决方法
总的来说汉字乱码的原因就是UTF-8和GB2312这两种格式再IAR这个编译器中不会自动转换,需要使用vscode软件手动转换代码格式。这是由于,STM32CubeMX生成的代码默认的是UTF-8格式,这里虽然把编译器的编码格式改了,但是代码本身其实还是UTF-8格式。这个打印函数是在main.c文件中,在VScode 使用UTF-8格式打开,然后编码格式另存为GB2312。此时代码中的汉字是正常的,接着再点击右下角的编码格式。此时代码的注释是汉字,但是使用IAR软件打开之后汉字是乱码。原创 2024-12-19 21:55:14 · 2385 阅读 · 0 评论 -
IAR中如何而将定义的数组放在指定的位置
注意添加的第一行代码中内存地址的范围要在RAM地址范围之内,否则就会出错。使用这种方法的话,就不需要修改 stm32f103xb_flash.icf 这个文件内容了,直接使用默认的内容就行。但是这个方法在IAR中是用不了的,通过网上查找各种资料,发现了两种可用的方法。我这里测试的单片机是stm32f103c8t6,其他单片机的操作方法是一样的。这里要注意一个问题,如果使用第2种方法的时候,数组大小必须是4的倍数,否则编译会报错。好了,这两种方法就分享到这,如果后面发现了其他新的方法再补充。原创 2024-12-19 21:04:35 · 651 阅读 · 0 评论 -
关于CAN通信中同步机制的通俗理解
所以在上升沿或者下降沿的过程中有识别你是0,也有可能识别你是1,这样判断你的电平的时候就可以引起误差。现在唯一确定的时间就是你数数是1秒钟变化1次的,那么在你变化的一瞬间我就开始对你计时,然后在对比我自己数数的计时,这样就可以知道我和你的时间差是多少,如果我比你慢,那么下次我就提前变,如果我比你快,我就晚一点变。比如上图中的状态,当你从0变为1的时候,我开始计时,我这边开始变的时候我也计下时间,此时我就发现了,你比我快了0.1秒,那我我此时就可以推算出,如果你到了1秒钟变化的时候,我才数到0.9秒。原创 2024-12-14 16:35:40 · 835 阅读 · 0 评论 -
STM32F103单片机HAL库串口通信卡死问题解决方法
所以分析造成串口卡死或者数据丢失的原因主要原因应该是直接在接收中断中直接发送数据,由于是接收一个字节,立即发送一个字节,如果每次发送几十个字节的时候,每两个字节之间的时间是很短的。在接收回调函数中接收到数据之后先存放到数组之中,当收到回车换行符之后结束接收,然后在main函数中检测接收标志位,如果接收完成,再将接收的数据打印出来。在网上查资料发现造成这个原因主要是HAL的流程问题,当串口在发送数据的时候,如果又接收到了数据,程序中就会出现死锁的情况。所以就将正点原子的串口接收方法移植过来。原创 2024-12-09 21:40:58 · 2002 阅读 · 0 评论 -
STM32F103单片机使用STM32CubeMX创建IAR串口工程
最后编译下载程序,在串口回调函数中打个断点,使用USB转TTL连接单片机的PA10和PA9引脚,使用串口工具发送一个字母q,可以看到串口中断已经进去了,接收到的数据也是q。接下来设置时钟,选择时钟配置,左下角时钟源选择HSE,然后在HCLK的位置直接输入需要输出的时钟值,这里设置72,按回车键。接下里设置串口参数,这里直接使用默认值,波特率115200,8位数据位,1位停止位,无校验位,发送和接收模式。接下来设置工程名,选择工程存储的位置,设置编译器的类型,和编译器最低版本。这里的编译器选择为IAR。原创 2024-12-08 18:03:42 · 862 阅读 · 0 评论 -
STM32F103单片机使用STM32CubeMX新建IAR工程步骤
STM32F103单片机上,使用STM32CubeMX生成IAR工程设置步骤。原创 2024-12-07 22:24:34 · 878 阅读 · 0 评论 -
使用CCS软件查看PID曲线
这是因为取消延时后,图形显示的刷新率太低,不能实时捕获到每个数据,所以直接显示变量的曲线就看不出来细节了,而数组显示比较完整,是因为代码中将过程中的所有数据都先存储到了数组中,然后根据数组中的数据来绘制曲线。这是两种很典型的PID算法,一个位置式,一个增量式。此时又增加了一个显示窗口,但是这两个窗口重叠在了一起,看起来不方便,在窗口标题处按住鼠标左键,拖动窗口,将两个图形显示调节到合适的位置。添加完成之后,将黄色箭头的图标选中,这个是实时刷新功能,这样在代码全速运行的时候,就可实时看到变量值在变化。原创 2024-04-17 22:45:00 · 2571 阅读 · 1 评论 -
STM32F407单片机HAL库CAN2不能接收数据解决方法
下面就就是can的时钟,这里要注意一个就是使用can1的时候,开启can1的时钟就行,但是使用can2的时候,也必须开启can1的时钟。在can的控制器中,存储访问控制器是由can1控制的,当使用can2的时候,can2要访问存储访问控制器时,必须通过can1才能访问,所以使用can2的时候,can1为主机,can2为从机。当使用can2的时候,直接将值设置为14。的值就很关键了,这个值的含义是,从机滤波器的起始地址,那么当使用can2时,can2就是从机,那么这个值就是can2滤波器的起始地址,而上面。原创 2023-05-27 17:08:41 · 4037 阅读 · 6 评论 -
PSIM软件BUCK转换数字控制官方例程
在使用PSIM软件仿真开关电源时,大多数都是模拟电路,纯数字电路的仿真很少。无意间发现了在PSIM 2021版本中有官方的数字控制BUCK电路仿真。电路使用简单C模块编写的代码来控制电路。 由于下载的2021版是演示版,不能直接仿真,为了能够彻底的学习,于是将电路图和程序移植到了9.1版本中。现在将电路和代码分享出来。 2021版官方例程 由于软件是演示版,有限制,所以不能仿真。 于是将电路图和代码移植到 PSIM 9.1 版本上 硬件电路如下: 首先使用电路传感器读取电原创 2022-03-01 16:44:02 · 6701 阅读 · 4 评论 -
C语言学习笔记---字符函数isalnum()和iscntrl()
isalnum() 函数用于检查所传的字符是否是字母或者十进制数字。它的函数原型如下: _CRTIMP int __cdecl isalnum(int _C); 返回值为非零(真)表示参数c是字母或者十进制数字,返回值为零(假)表示参数c既不是十进制数字,也不是字母。 下面通过一个简单的例子来演示它的用法。#include <stdio.h>#include <ctype.h>int main(){ int var1 = 'a'; int va原创 2022-02-17 08:45:45 · 502 阅读 · 2 评论 -
C语言学习笔记---浮点函数floor()和ceil()和浮点数四舍五入
在上一篇文章中已经了解了浮点数在计算机中的存储原理,同时也介绍对浮点数取整和取余的函数.在C语言标准库里面还提供了对于浮点数取整的两个函数。函数原型如下: double __cdecl ceil(double _X); double __cdecl floor(double _X); ceil函数返回大于或等于 x 的最小的整数值。下面通过一个简单的例子,演示一下ceil函数的用法。#include <stdio.h>#include <math.h>int原创 2022-02-17 08:43:59 · 1749 阅读 · 0 评论 -
C语言学习笔记---浮点函数modf()和fmod()
modf函数可以提取出浮点数的整数部分和小数部分。fmod函数可以返回两个浮点数相除的余数。它们的函数原型如下: double __cdecl modf(double _X,double *_Y); double __cdecl fmod(double _X,double _Y); 这两个函数的功能看起来都挺简单的,但是为什么在C语言库中还要专门搞一个函数来计算呢?在使用这两个函数之前,首先看一个简单的浮点数相关的例子。int main (){ int i; float j=1.0原创 2022-02-17 08:42:42 · 4513 阅读 · 0 评论 -
C语言学习笔记---三角函数
在C语言标准库里面提供了常用的三角函数,在头文件math.h里面可以看到函数的相关定义。 double __cdecl sin(double _X); double __cdecl cos(double _X); double __cdecl tan(double _X); double __cdecl asin(double _X); double __cdecl acos(double _X); double __cdecl atan(double _X); double原创 2022-02-17 08:41:18 · 21701 阅读 · 4 评论 -
C语言学习笔记---字符串转浮点函数
字符串不仅可以转换为整数,也可以转换为浮点数,字符串转浮点数函数原型如下: float __cdecl __mingw_strtof (const char * __restrict__, char ** __restrict__); double __cdecl __mingw_strtod (const char * __restrict__, char ** __restrict__); strtof函数返回值是一个单精度浮点数,strtod返回值是一个双精度浮点数。原创 2022-02-17 08:40:24 · 15777 阅读 · 3 评论 -
C语言学习笔记---字符串转换函数
字符串转整数 字符串转换为整数的函数有两个,他们的函数原型如下: int __cdecl atoi(const char *_Str); long __cdecl atol(const char *_Str); 这两个函数的用法都很简单,atoi函数将字符串转换为整数int型,atol函数将字符串转换为长整形long int型。如果转换无效,返回值都为0,下面通过一个简单的例子看一下这两个函数的用法。#include <stdio.h>#include <stdlib原创 2022-02-17 08:36:43 · 1185 阅读 · 0 评论 -
C语言学习笔记---时间函数strftime()
strftime函数主要用于时间格式化,它的函数原型如下:size_t __cdecl strftime(char * __restrict__ _Buf,size_t _SizeInBytes,const char * __restrict__ _Format,const struct tm * __restrict__ _Tm);它有4个参数:_Buf, 表示返回的时间字符串_SizeInBytes, 要写入的字节的最大数量_Format, 这是 C 字符串,包含了普通字符和特殊格式说明符原创 2022-02-16 13:56:30 · 2003 阅读 · 0 评论 -
C语言学习笔记---时间函数mktime()和difftime()
这两个函数原型如下: __CRT_INLINE time_t __cdecl mktime(struct tm *_Tm); __CRT_INLINE double __cdecl difftime(time_t _Time1,time_t _Time2);mktime函数 mktime函数会把参数把 timeptr 所指向的结构转换为自 1970 年 1 月 1 日以来持续时间的秒数,如果发生错误时则返回-1。 参数结构体原型如下:struct tm { int tm_sec;原创 2022-02-16 13:55:15 · 1423 阅读 · 0 评论 -
C语言学习笔记---时间函数ctime()和gmtime()
函数原型如下: __CRT_INLINE char *__cdecl ctime(const time_t *_Time); __CRT_INLINE struct tm *__cdecl gmtime(const time_t *_Time);ctime函数 ctime函数可以将当前时间值转换为字符串格式返回。返回的字符串格式为:Www Mmm dd hh:mm:ss yyyy 其中,Www 表示星期几,Mmm 是以字母表示的月份,dd 表示一月中的第几天,hh:mm:ss 表示时间,yy原创 2022-02-16 13:54:08 · 1131 阅读 · 0 评论 -
C语言学习笔记---时间函数asctime()和localtime()
这两个时间函数原型如下: char *__cdecl asctime(const struct tm *_Tm); __CRT_INLINE struct tm *__cdecl localtime(const time_t *_Time);asctime函数 asctime函数可以将时间结构体转换为时间字符串格式。它的参数是一个时间结构体。结构体原型如下:struct tm { int tm_sec; /* 秒,范围从 0 到 59原创 2022-02-16 13:52:49 · 3780 阅读 · 0 评论 -
C语言学习笔记---时间函数clock()和time()
时间函数在编写代码的时候会经常用到,下面就来总结一下clock和time函数的用法,函数原型如下: clock_t __cdecl clock(void); __CRT_INLINE time_t __cdecl time(time_t *_Time); clock函数 clock函数返回程序从运行开始到当前调用函数位置处CPU所使用的时间,通过这个函数就可以计算某段代码运行时所使用的时间。 下面通过一段简单的代码测试一下:#include <stdio.h>#i原创 2022-02-16 13:51:42 · 2090 阅读 · 0 评论 -
C语言学习笔记---随机数rand()函数
在生活中很多场景下都需要产生随机数,比如抽奖,打牌,游戏等场景下就需要使用随机数。在C语言标准库函数里面有专门用来产生随机数的函数rand,它的函数原型如下: int __cdecl rand(void); rand函数没有参数,它的返回值就是随机数。下面通过一个简单的例子来测试一下rand函数。#include <stdio.h>#include <stdlib.h>int main(int argc, char** argv) { int i;原创 2022-02-16 13:50:09 · 1542 阅读 · 0 评论 -
C语言学习笔记---abs()函数和div()函数
C语言库中提供了许多函数,这样需要计算的时候,可以直接借助库函数,而不用自己重新编写函数。今天就来看一下C语言标准库函数里面的整型函数。 int __cdecl abs(int _X); long __cdecl labs(long _X); div_t __cdecl div(int _Numerator,int _Denominator); ldiv_t __cdecl ldiv(long _Numerator,long _Denominator); abs函数用来计算整数的绝原创 2022-02-16 13:48:58 · 789 阅读 · 0 评论 -
C语言学习笔记---常见的动态内存错误
在使用动态内存分配时,经常会出现许多错误。这些错误包括对NULL指针进行操作,对分配内存操作时越过边界,释放非动态内存分配的内存,一块动态内存被释放后继续使用等。 动态分配内存最常见的错误就是忘记检查所请求的内存是否分配成功。为了避免每次分配内存后忘记检查,现在通过一段代码来有效的避免这个问题。#define MALLOC(num,type) (type *)alloc( (num) * sizeof(type))void *alloc(size_t size) { void *new_me原创 2022-02-16 13:47:44 · 637 阅读 · 0 评论 -
C语言学习笔记---动态内存分配calloc()和realloc()
动态内存分配函数除了常用的malloc函数以外,还有calloc函数和realloc函数,这两个函数的原型如下:void *__cdecl calloc(size_t _NumOfElements,size_t _SizeOfElements);void *__cdecl realloc(void *_Memory,size_t _NewSize);calloc函数 calloc函数用于动态的分配内存,并初将其始化为0。它有两个参数,第一个参数用于设置连续空间的数量,第二个参数用于设置每个原创 2022-02-16 13:46:37 · 658 阅读 · 0 评论 -
C语言学习笔记---动态内存分配
数组在内存中时存储在连续的位置上,当声明一个数组的时候,编译器就会在内存中分配它所需要的空间,但是有时候还需要使用动态内存为数组分配空间。 比如现在要同统计一个班级学生的成绩,可以申请一个固定大小的数组,但是班级学生的人数时会变动的,当这个固定大小的数组设置的太小时,有可能不能完全放下所有学生的数据,当这个数组设置的太大时,不一定每次每次都能用到这么大的空间。导致系统空间的浪费。 为了使程序更加灵活,同时更加有效的利用内存空间,通常使用动态内存分配来解决这个问题,C库函数里面提供了两个函数mal原创 2022-02-16 13:45:11 · 501 阅读 · 1 评论 -
IAR软件中直接查看编译后代码大小
在使用IAR软件编译代码时,编译后往往看不到编译后代码的大小情况。在调试程序的时候还是比较麻烦的。下面就总结两种最简单的方法在IAR编译器中查看代码大小。通过输出的编译信息查看 IAR默认的编译信息输出很少,基本就只能查看一下错误和警告的数量。 如果想要输出更多的编译信息,在这个Messages信息框中,单击鼠标右键选择All。 这时再重新编译一次代码。 此时就可以看到编译信息输出了很多,其中就包括了代码占用空间情况。这样通过一个简单的设置就可直接在编译器输出信息中查看代码的大小原创 2021-12-06 11:44:52 · 6218 阅读 · 1 评论 -
STM8单片机串口同时识别自定义协议和Modbus协议
在单片机开发中,串口是最常用的和外界交换数据的渠道,要使用串口,那必不可少的就是通信协议,通信协议就是单片机和外界通信的语言,要想正常和其他设备正常交流,首先语言必须相通。 在实际开发过程中由于各种原因,导致很多时候单片机和外界其他设备协议不兼容,在使用的时候就比较麻烦。比如单片机要和两个设备通信,但是这两个设备的通信协议的不一样,在使用时单片机就必须使用两个串口分别和两个设备通信。如果这两个设备同时使用时还不感觉到资源浪费,如果每次只接一个设备,那么另一个串口也不能作为其他功能使用,还得留着备用。原创 2021-12-03 21:16:58 · 6448 阅读 · 6 评论 -
在STM8单片机中自己实现 printf()函数功能
由于STM8单片机本身内存比较小,而系统自带的printf()函数又比较占据空间,所以在稍微大一点的工程中有时候一使用 printf() 函数就会导致单片机内存不足,于是想着能不能自己写一个比较小的函数来实现类似printf()函数的功能。经过网上查找资料和总结终于找到了一个占用内存比较小,又能实现串口打印功能的方法。 现在将自己的方法分享出来,这里使用 STM8S003F3P6单片机测试。 首先新建一个工程,专门用来测试串口功能。 串口部分相关代码如下://串口void Uart1_I原创 2021-12-03 15:58:39 · 3266 阅读 · 0 评论