![](https://img-blog.csdnimg.cn/20201014180756738.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C语言学习笔记
文章平均质量分 71
嵌入式@hxydj
这个作者很懒,什么都没留下…
展开
-
使用CCS软件查看PID曲线
这是因为取消延时后,图形显示的刷新率太低,不能实时捕获到每个数据,所以直接显示变量的曲线就看不出来细节了,而数组显示比较完整,是因为代码中将过程中的所有数据都先存储到了数组中,然后根据数组中的数据来绘制曲线。这是两种很典型的PID算法,一个位置式,一个增量式。此时又增加了一个显示窗口,但是这两个窗口重叠在了一起,看起来不方便,在窗口标题处按住鼠标左键,拖动窗口,将两个图形显示调节到合适的位置。添加完成之后,将黄色箭头的图标选中,这个是实时刷新功能,这样在代码全速运行的时候,就可实时看到变量值在变化。原创 2024-04-17 22:45:00 · 1447 阅读 · 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 · 2688 阅读 · 2 评论 -
PSIM软件BUCK转换数字控制官方例程
在使用PSIM软件仿真开关电源时,大多数都是模拟电路,纯数字电路的仿真很少。无意间发现了在PSIM 2021版本中有官方的数字控制BUCK电路仿真。电路使用简单C模块编写的代码来控制电路。 由于下载的2021版是演示版,不能直接仿真,为了能够彻底的学习,于是将电路图和程序移植到了9.1版本中。现在将电路和代码分享出来。 2021版官方例程 由于软件是演示版,有限制,所以不能仿真。 于是将电路图和代码移植到 PSIM 9.1 版本上 硬件电路如下: 首先使用电路传感器读取电原创 2022-03-01 16:44:02 · 5014 阅读 · 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 · 398 阅读 · 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 · 1404 阅读 · 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 · 2765 阅读 · 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 · 17138 阅读 · 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 · 13303 阅读 · 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 · 1005 阅读 · 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 · 1744 阅读 · 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 · 1142 阅读 · 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 · 1022 阅读 · 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 · 3050 阅读 · 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 · 1891 阅读 · 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 · 1435 阅读 · 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 · 639 阅读 · 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 · 474 阅读 · 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 · 578 阅读 · 0 评论 -
C语言学习笔记---动态内存分配
数组在内存中时存储在连续的位置上,当声明一个数组的时候,编译器就会在内存中分配它所需要的空间,但是有时候还需要使用动态内存为数组分配空间。 比如现在要同统计一个班级学生的成绩,可以申请一个固定大小的数组,但是班级学生的人数时会变动的,当这个固定大小的数组设置的太小时,有可能不能完全放下所有学生的数据,当这个数组设置的太大时,不一定每次每次都能用到这么大的空间。导致系统空间的浪费。 为了使程序更加灵活,同时更加有效的利用内存空间,通常使用动态内存分配来解决这个问题,C库函数里面提供了两个函数mal原创 2022-02-16 13:45:11 · 416 阅读 · 1 评论 -
IAR软件中直接查看编译后代码大小
在使用IAR软件编译代码时,编译后往往看不到编译后代码的大小情况。在调试程序的时候还是比较麻烦的。下面就总结两种最简单的方法在IAR编译器中查看代码大小。通过输出的编译信息查看 IAR默认的编译信息输出很少,基本就只能查看一下错误和警告的数量。 如果想要输出更多的编译信息,在这个Messages信息框中,单击鼠标右键选择All。 这时再重新编译一次代码。 此时就可以看到编译信息输出了很多,其中就包括了代码占用空间情况。这样通过一个简单的设置就可直接在编译器输出信息中查看代码的大小原创 2021-12-06 11:44:52 · 4512 阅读 · 1 评论 -
STM8单片机串口同时识别自定义协议和Modbus协议
在单片机开发中,串口是最常用的和外界交换数据的渠道,要使用串口,那必不可少的就是通信协议,通信协议就是单片机和外界通信的语言,要想正常和其他设备正常交流,首先语言必须相通。 在实际开发过程中由于各种原因,导致很多时候单片机和外界其他设备协议不兼容,在使用的时候就比较麻烦。比如单片机要和两个设备通信,但是这两个设备的通信协议的不一样,在使用时单片机就必须使用两个串口分别和两个设备通信。如果这两个设备同时使用时还不感觉到资源浪费,如果每次只接一个设备,那么另一个串口也不能作为其他功能使用,还得留着备用。原创 2021-12-03 21:16:58 · 6092 阅读 · 6 评论 -
在STM8单片机中自己实现 printf()函数功能
由于STM8单片机本身内存比较小,而系统自带的printf()函数又比较占据空间,所以在稍微大一点的工程中有时候一使用 printf() 函数就会导致单片机内存不足,于是想着能不能自己写一个比较小的函数来实现类似printf()函数的功能。经过网上查找资料和总结终于找到了一个占用内存比较小,又能实现串口打印功能的方法。 现在将自己的方法分享出来,这里使用 STM8S003F3P6单片机测试。 首先新建一个工程,专门用来测试串口功能。 串口部分相关代码如下://串口void Uart1_I原创 2021-12-03 15:58:39 · 2357 阅读 · 0 评论 -
C语言学习笔记---可变参数
在C语言中有些函数传递进入的参数数量是不固定的,最常见的就是**printf()**函数,它就是利用可变参数来实现任意格式的数据打印功能。 我们自己也可以编写一个参数可变的函数,每次动态的检测传入的参数,然后执行相应的动作。...原创 2021-11-12 20:41:20 · 1126 阅读 · 0 评论 -
C语言学习笔记---数据拷贝函数memcpy()和memmove()函数
在C语言中拷贝字符串的时候通常可以使用strcpy()函数和strncpy()函数,这两个函数是专门针对字符串拷贝的。如果想要拷贝其他类型数组的话,可以使用memcpy()和memmove()函数。下面就来看一下这两个函数的使用方法。memcpy()函数 函数原型如下:void * __cdecl memcpy(void * __restrict__ _Dst,const void * __restrict__ _Src,size_t _Size) 这个函数有三个参数,第一个是目标数组的原创 2021-11-12 14:05:41 · 2312 阅读 · 0 评论 -
C语言学习笔记---断言函数assert()
在C语言库函数中提供了一个辅助调试程序的小型库,它是由assert()宏组成,接收一个整形表达式作为参数。如果表达式的值为假(非零),则assert()宏就在标准错误流(stderr)中写入一条错误信息,并调用abort()函数终止程序。 下面通过一个简单的例子来看一下assert()的用法。int main(){ int n = 1; assert(n>=0); printf("%d \r\n",n); system("pause"); return 0;} 在asse原创 2021-11-12 11:09:05 · 2990 阅读 · 4 评论 -
C语言学习笔记---C库排序函数qsort()
在处理数据的时候,由于排序方法会经常用到,所以C语言的库函数里面自带了快速排序的函数qsort(),对大型数据而言,“快速排序”方法是最有效的排序方法之一。它是把数组不断的分成更小的数组,直到变成单元素数组。首先把数据分成两部分,一部分的值都小于另一部分的值。这个过程一直持续到数组完全排好序为止。 其函数原型如下所示:void __cdecl qsort(void *_Base,size_t _NumOfElements,size_t _SizeOfElements,int (__cdecl *_原创 2021-11-11 16:40:29 · 1032 阅读 · 0 评论 -
C语言学习笔记---位字段
在C语言中通常操作只有真假两种状态的的数据时使用布尔bool变量比较多,如果需要同时观察多个状态,这时候选择位操作效率会更高,用一个字节的8位分别表示8种状态。比较节省内存,处理起来效率更高。但是这种方法有一个缺点,就是看起来不直观,比如0x5C要想知道每一位的状态还得换算一下,同时要操作某一个单独位时,还必须使用位操作运算,比如位与、位或、异或。 如果熟悉单片机的就会想到,能不能在C语言中像操作寄存器那样直接操作一个字节的单独一位呢? 比如这是一个单片机的端口方向配置寄存器,每一个端口原创 2021-11-10 13:16:24 · 1872 阅读 · 0 评论 -
C语言学习笔记---指向函数的指针
在内存中函数的存放也是一段连续的内存,函数名就是指向改内存中的首地址,所以也可以将这个函数的首地址赋给一个指针变量,这样通过指针变量就可以访问改函数。 那么为什么要通过指针来访问函数呢?下面通过一个简单的例子来演示一下。int (*fun)(int m,int n);int Add(int x,int y){ return x + y;}int Sub(int x,int y){ return x - y;}int Mul(int x,int y){ return x *原创 2021-11-09 15:48:33 · 895 阅读 · 0 评论 -
C语言学习笔记---typedef 简介
在单片机和操作系统中 typedef 会经常用到,它可以为某一个类型自定义名称。和#define比较类似。但是又有不同的地方。typedef 创建的符号只能用于数据类型,不能用于值。而#define 创建的符号可以用于值。typedef 是由编译器来解释,而不是预处理器。typedef 使用起来更加灵活。 下面使用typedef定义一个数据类型int main(){ typedef unsigned char BYTE; BYTE c = 10; printf("%d \r原创 2021-11-08 17:20:28 · 3260 阅读 · 1 评论 -
C语言学习笔记---枚举类型enum
枚举类型通常用来存放整形常量。可以使用enum关键字来创建一个"新的类型",用来表示一组关系比较密切的整形常量。 可以这样声明:enum spectrum { red,orange,yellow,green,blue,violet };enum spectrum color; 第一条语句声明创建了spectrum 作为标记名,允许把enum spectrum作为一个类型名使用。第二条语句声明了将 color作为该类型的变量。在第一条语句中依次列举了spectrum 变量可能有的值,因此co原创 2021-11-08 15:31:08 · 1010 阅读 · 0 评论 -
C语言学习笔记---结构体中的字符数组和字符指针
在结构体中可以使用字符数组来存储字符串,也可以使用字符指针来存储字符串。比如:struct str { char s1[5]; char s2[5]; }; struct str str1= {"123","abc"};或者 struct str { char *s1; char *s2; }; struct str str1= {"123","abc"}; 通过这两种方式定义的结构体都可以正常运行,输出结果也都是一样的。 那么这两种方式在内存中存储是原创 2021-11-08 14:17:15 · 2228 阅读 · 0 评论 -
C语言学习笔记---结构体作为函数参数和返回值
结构体不仅可以作为函数的参数传递,也可以作为函数的返回值。现在就分别来看一下这两种情况。结构体作为参数struct score{ int chinese; int math; int english;};int sum(struct score p){ return (p.chinese + p.math + p.english);}int main(){ int total = 0; struct score s= { 80,90,85 }; total =原创 2021-11-08 13:20:28 · 9052 阅读 · 4 评论 -
C语言学习笔记---向函数传递结构信息
传递值 在向函数传递参数的时候,可以直接将结构体成员的值传递给函数。如下面的例子:int sum(int x,int y,int z){ return (x + y + z);}int main(){ int total = 0; struct score { int chinese; int math; int english; }; struct score s= { 80,90,85 }; total = sum(s.chinese,s.math,s原创 2021-11-08 10:45:17 · 947 阅读 · 0 评论 -
C语言学习笔记---结构体指针
既然结构体是一种数据类型,那么除了使用变量本身来访问结构体之外,也可以使用指针来访问结构体。下面通过一个简单的例子来演示一下:struct Date { int year; int month; int day; }; struct book { char title[30]; char author[30]; float value; struct { int year; int month; int day; }; }; 首原创 2021-11-08 09:29:10 · 1332 阅读 · 0 评论 -
C语言学习笔记---嵌套结构体
结构体不仅可以单独使用,也可以在结构体中嵌套另一个结构体。如下面的例子:struct Date{ int year; int month; int day; }; struct book { char title[30]; char author[30]; float value; struct Date date; }; 首先声明一个book结构体,在这个结构体里面描述了书本的标题、作者、价格、出版日期。由于出版日期里面有包含了年月日信息,为了方便管理,就原创 2021-11-05 09:24:54 · 16202 阅读 · 7 评论 -
C语言学习笔记---结构体数组初始化
既然结构体是一种数据类型,那么它也可以定义为数组的形式。比如要描述一本书的信息,可以将书的名称,作者,价格这些信息用一个结构体来描述,在使用的过程中不可能只描述一本书,所以就需要使用一个结构体数组来描述多本书的信息。 首先声明一个结构体。struct book { char title[30]; char author[30]; float value; }; 接下来定义结构变量,直接定义一个结构数组,在定义的时候初始化。struct book books[3]={原创 2021-11-04 17:11:49 · 23941 阅读 · 4 评论 -
C语言学习笔记---结构体的定义和初始化
在C语言中结构体通常用来将不同类型的变量打包在一起,方便对对象的统一管理。结构体定义 要使用结构体时,首先要进行结构体的声明。声明的形式如下:struct 结构体名{结构体所包含的变量}; 比如现在要描述一本书的标题,作者,价格。声明格式如下:struct book{ char title[30]; char author[30]; float value; }; 用字符数组来存储书的标题和作者,用浮点型来存储书的价格。声明完成之后,此时在内存中并没有分配存原创 2021-11-04 14:53:55 · 676 阅读 · 0 评论 -
C语言学习笔记---fseek()函数和ftell()函数
fseek()函数 fseek()函数简单的理解,功能就是用来设置打开文件中光标的位置。比如默认打开一个文件后,光标在文件的最开始位置,但是好多时候操作文件的时候,不一定都是从最开始位置操作的。有时候需要在文件中间某个位置开始操作,有时候需要从文件结尾处开始操作。所以就需要一个专门设置文件中光标位置的函数。fseek()函数有三个参数,第一个参数是需要操作的文件指针,第二个参数是光标的偏移量,第三个参数为确定起点模式,也就是设置在文件中光标的起点位置。有以下几种情况: 下面通过代码来演示fsee原创 2021-11-01 17:26:06 · 7563 阅读 · 0 评论 -
C语言学习笔记---fgets()函数和fputs()函数
fgets()函数 fgets()函数和gets()函数一样,都是读取字符串,不过gets()函数通常用来从键盘读取输入的字符串,fgets()函数可以通过文件来读取字符串。下面通一个例子来演示fgets()函数的使用方法。int main(){ FILE *in,*out; int ret; char ch; char str1[30],str2[30],str3[30]; /* 打开文件 */ in = fopen("123.txt","r"); if(in == NULL)原创 2021-11-01 15:33:59 · 513 阅读 · 1 评论 -
C语言学习笔记---fprintf()函数和fscanf()函数
fprintf()函数 在C语言中常用使用的打印函数是printf()函数,这个多用于给控制台打印数据,如果需要将内容直接打印到某个文件中的时候,可以使用fprintf()函数。它有两个参数,第一个参数为待写入的文件指针,第二个参数为待写入的内容。下面通过一个简单的例子来演示它的用法。int main(){ FILE *in,*out; int ret; char ch; /* 打开文件 */ in = fopen("123.txt","a+"); if(in == NULL)原创 2021-11-01 14:39:22 · 883 阅读 · 0 评论