一、 编写程序的“四步走”战略
在 Keil 中写程序就像盖房子,得先搭架子再填砖瓦:
-
添加图纸 (main.c):右键点击
User栏,新建并添加用户主程序文件main.c。 -
找准工具箱 (头文件):右键引用 51 单片机头文件(如
#include <reg52.h>),这相当于给单片机装上“字典”,让它看得懂你写的 P1 是什么。 -
搭建框架,梳理思路:先写出
void main() { while(1){...} }的基本结构,在脑子里或纸上画出逻辑流程图,再动手填代码。 -
按图索骥 (原理图):代码逻辑必须严格遵守电路原理图的连接方式(比如 LED 接在哪个引脚,就控制哪个引脚)。
二、 变量定义:给数据找个合适的“盒子”
1. 为什么单片机偏爱 unsigned?
比喻:单片机里的数据就像一把“刻度尺”。
-
signed (有符号):尺子的 $0$ 在中间,左边是负数,右边是正数。
-
unsigned (无符号):尺子的 $0$ 在最左端,只能量出正数。
为什么要加 unsigned?
-
硬件更直观:单片机的引脚电平只有“高”和“低”,没有“负电平”,用无符号数最匹配。
-
效率更高:无符号运算对单片机“大脑”来说负担最轻,运行最快。
2. char 与 int 的对比 (存储容量差异)
你可以把变量想象成大小不同的收纳盒:
| 特性 | unsigned char (小盒子) | unsigned int (大箱子) |
|---|---|---|
| 内存占用 | 1 字节 (8 位) | 2~4 字节 (16~32 位) |
| 装载量 | $0 \sim 255$ | 51单片机中通常为 $0 \sim 65535$ |
| 比喻 | 像个存钱罐,存零钱(字节流、颜色值) | 像个保险柜,存大额存款(业务计算) |
| 溢出行为 | 满了就清零 ($255+1 = 0$) | 满了会发生不可预测的错误 |
三、 GPIO:控制硬件的“开关面板”
1. P1 与 P1_01 的关系 (大楼与房间)
单片机的引脚是成组管理的,我们称之为 GPIO 端口。
-
P1 (端口寄存器):
-
比喻:它是整栋 “P1 号宿舍楼”。
-
特性:代表整个 8 位端口。操作
P1会同时控制这栋楼里的所有 8 个房间(引脚)。 -
用法:
P1 = 0x00;相当于“整栋楼一键断电”,8 个灯全灭。
-
-
P1_01 / P1_1 (位定义):
-
比喻:它是这栋楼里的 “101 号房间”。
-
特性:代表其中的某一个引脚。操作它只影响自己,不干扰邻居。
-
用法:
P1_1 = 0;相当于“只关 101 室的灯”。
-
2. 对比总结表
| 特性 | P1 (端口) | P1_x (引脚/位) |
|---|---|---|
| 定义关键字 | sfr (特殊功能寄存器) |
sbit (位定义) |
| 控制范围 | 1 组 8 个引脚 | 1 个特定引脚 |
| 最佳舞台 | 跑流水灯、总线通信 | 开关控制、判断单个按键状态 |
四、 补充概念:什么是寄存器?
比喻:如果把单片机 CPU 比作一个 “厨师”,那么寄存器就是他 “手边的调料盒”。
-
寄存器 (Register):是 CPU 内部读写最快的小存储单元。
-
代码如何控制硬件?:
-
你修改代码中的变量(如
P1 = 0xFE;)。 -
单片机就会去拨动对应的“寄存器开关”。
-
寄存器直接连接着外面的金属引脚,引脚电平随之改变,LED 就亮了!
-
代码学习:
延时函数
void Delay1ms(unsignde int xms){ //@12.000MHz
while(xms --){
unsigned char i, j;
i = 2;
j = 239;
do{
while (--j);
} while (--i);
}
}
流水灯/函数库:
_crol_( ,) //循环左移
_cror_( ,) //循环右移
所属库:<intrins.h>