当初初学51单片机写实操代码,最折磨人的问题就是搞懂c51支持的数据类型有哪些,习惯性照搬电脑端标准C语言的写法,结果次次编译异常、设备运行错乱,白白浪费了好几天调试时间。
就这看似基础的知识点,新手几乎全员踩坑。
最开始一直默认C51和普通C语言的数据类型完全通用,写变量定义时随心所欲,char、int、float随便套用在单片机IO口、寄存器、状态标记上,完全没意识到51内核是8位低端单片机,Keil C51编译器做了专门裁剪和适配,很多标准C的用法在这里根本行不通。照着通用教程写的传感器采集代码,编译通过后烧录开发板,数据传输一直紊乱,端口电平飘忽不定,排查了电路、延时函数、逻辑语法,全都找不出问题,折腾好久才搞明白,根源全是变量类型用错了。
C51首先兼容一套固定位数的基础数据类型,这是日常编程最常用的核心部分。char类型占8位字节,分有符号char和无符号unsigned char,取值范围固定,是51单片机里使用率最高的类型,用来存储字符、小范围数值、端口数据最合适。int类型为16位整型,负责存储中等数值数据,long是32位长整型,适配超大数值场景。还有float浮点类型,同样是32位,能处理小数数值,但这个类型在C51里实用性很低,因为51没有硬件浮点运算单元,所有浮点计算都是软件模拟,会大幅拖慢程序运行速度,还会占用大量内存,我之前写温湿度小数显示程序,用了float之后,单片机响应直接卡顿半秒,换成整型放大数值运算后才恢复正常。
浮点类型基本能不用就不用。
除了通用基础类型,C51真正区别于标准C的,是四款专属单片机数据类型,这也是新手最容易忽略的关键。bit类型,仅占用1位存储空间,只能存储0和1,专门用来做开关状态、标志位判断,比如判断按键是否按下、设备是否触发,用它替代char能极大节省单片机稀缺的内存资源,我之前不懂,全程用char存开关状态,做多模块联动项目时直接内存溢出报错。
sbit是引脚位定义类型,可以直接绑定单片机的单个IO引脚地址,精准操作独立引脚电平。最开始控制LED灯、继电器,一直用普通整型变量间接赋值,代码冗长还容易出错,改用sbit单独定义P1.0、P2.1这类引脚后,一行代码就能控制引脚状态,代码简洁度直接翻倍。sfr用于定义单片机内部8位特殊功能寄存器,比如定时器、中断寄存器,sfr16则专门适配16位的寄存器,比如定时计数器的组合寄存器,这两个类型是操作单片机底层硬件的核心,没有它们就无法实现硬件功能配置。
很多人写不好51程序,根本不是逻辑不行,就是没摸透这些专属类型的用法。
试过无数次错误搭配后才清楚,C51的数据类型没有标准C那么繁杂,所有支持的类型都是为8位单片机硬件量身定制的,舍弃了冗余类型,新增了硬件适配专属类型,适配场景极度固定,根本不需要胡乱套用电脑端的编程逻辑。
那天深夜改完所有变量定义,删掉了所有多余的float变量,替换了所有状态标记的char为bit,重新编译烧录程序,开发板的传感器数据终于稳定定格,LED指示灯的闪烁节奏也变得均匀规整。