【嵌入式成长1】STC89C51点亮LED|GPIO原理、闪烁、流水灯实战教程
一、LED实际应用场景LED即发光二极管生活中随处可见显示屏、广告牌、指示灯、装饰灯带。单片机最基础、经典的入门实验就是点亮LED。二、LED点灯基础原理插件LED灯珠长引脚正极短引脚负极。LED只有两端形成电压差、流过合适大小电流的时候才会发光。⚠️LED不能直接接电源必须串联限流电阻电流过大直接烧毁灯珠。限流电阻计算公式RVCC−VLEDIR\frac{V_{CC}-V_{LED}}{I}RIVCC−VLED插件LED常规工作电流20mA贴片LED常规工作电流5mA红/黄光压降约1.8V蓝/白光压降约3V举个例子3.3V供电、黄色贴片LEDR(3.3−1.8)/0.005300ΩR(3.3-1.8)/0.005300ΩR(3.3−1.8)/0.005300Ω实际产品指示灯经常选用几千欧的大电阻牺牲亮度换取更低功耗。三、单片机GPIO控制LEDGPIO全称General‑purpose input/output通用输入输出引脚可以配置输出高低电平以此控制LED亮灭。STC89C51的IO分组P0口P0.0~P0.7P1口P1.0~P1.7P2口P2.0~P2.7P3口P3.0~P3.7P4口P4.0~P4.6两种硬件接法IO口直接输出高电平点亮LED不推荐单片机IO输出驱动能力弱亮度不足VCC供电LED负极接IO引脚IO输出低电平点亮LED开发板标准接法本实验开发板硬件LED1、LED2、LED3分别接P2.7、P2.6、P2.5引脚输出低电平 → LED点亮方式1整体操作IO寄存器直接给整个端口寄存器赋值一次性控制8个引脚电平P20x53;0x53是十六进制对应二进制0101 0011对应控制P2口8个引脚电平。进制简单科普十进制0‑9逢十进一适合人阅读二进制只有0、1对应硬件高低电平但是数字太长不好写十六进制0‑9、A‑F0x前缀紧凑表达二进制单片机代码最常用一键点亮P2口全部LED示例代码#includereg52.hvoidmain(){P20x00;//全部输出低电平while(1){}}while(1)死循环单片机程序运行到这里永久停留方式2单独控制某一个引脚(sbit位定义)sbit是C51编译器独有的关键字可以单独操作寄存器其中某一个IO引脚语法格式sbit led1P2^7;代表把P2.7引脚别名定义为led1后续代码直接操作led1即可控制引脚电平。单颗LED点亮完整代码#includereg52.hsbit ledP2^7;voidmain(void){led0;//输出低电平点亮LEDwhile(1){}}四、LED闪烁实验闪烁逻辑点亮 →延时一段时间 →熄灭 →延时一段时间循环往复。51单片机时间基础概念时钟周期晶振频率的倒数12M晶振时钟周期1/12 us机器周期51单片机默认12时钟周期 1个机器周期指令周期CPU执行一条汇编指令花费的总机器周期软件延时原理让CPU空循环消耗时间达到延时效果通用毫秒延时函数(12M晶振)voiddelay_ms(unsignedintxms)//12MHz{unsignedinti,j;for(ixms;i0;i--){for(j124;j0;j--){}}}也可以使用STC‑ISP软件自动生成精准延时代码省去手动计算LED闪烁完整可运行代码#includereg52.hsbit ledP2^7;//带参延时函数 12M晶振voiddelay_ms(unsignedintxms){unsignedinti,j;for(ixms;i0;i--){for(j124;j0;j--){}}}voidmain(){while(1){led0;delay_ms(500);//亮500msled1;delay_ms(500);//灭500ms}}五、流水灯实现硬件LED1(P2.7)、LED2(P2.6)、LED3(P2.5)依次循环点亮版本1单独位操作写法可读性高#includereg52.h#includeintrins.hsbit LED1P2^7;sbit LED2P2^6;sbit LED3P2^5;voidDelay1000ms()//11.0592MHz{unsignedchari,j,k;_nop_();i8;j1;k243;do{do{while(--k);}while(--j);}while(--i);}voidmain(){while(1){LED10;LED21;LED31;Delay1000ms();LED20;LED11;LED31;Delay1000ms();LED30;LED11;LED21;Delay1000ms();}}版本2端口寄存器整体赋值写法代码简洁#includereg52.hvoiddelay_ms(unsignedintxms){unsignedinti,j;for(ixms;i0;i--){for(j124;j0;j--)}}voidmain(){while(1){P20xDF;//1101 1111 P2.7输出低delay_ms(500);P20xBF;//1011 1111 P2.6输出低delay_ms(500);P20x7F;//0111 1111 P2.5输出低delay_ms(500);}}版本3位运算封装函数扩展性最强#includereg52.hvoiddelay_ms(unsignedintxms){unsignedinti,j;for(ixms;i0;i--){for(j124;j0;j--)}}//点亮指定P2端口引脚voidopen_led(unsignedintnum){P20xFF~(1num);}voidmain(){while(1){open_led(7);delay_ms(500);open_led(6);delay_ms(500);open_led(5);delay_ms(500);}}六、拓展知识点 bit / sbit / sfr区别bitC51扩展基础数据类型1位布尔变量值只能是0或1在单片机RAM空间分配存储空间类似boolbit flag0;sbit位别名定义用来直接操作特殊寄存器的某一个引脚不占用RAM内存直接绑定硬件地址sbit OVPSW^2;sbit三种标准写法sbit OV0xd2;sbit OVPSW^2;sbit OV0xD0^2;sfr定义8位特殊功能寄存器直接绑定硬件寄存器地址reg52.h头文件内部大量使用sfr定义P0‑P3等端口sfr P10x90;七、本章小结1、LED必须串联限流电阻防止烧毁2、可以整体赋值寄存器或者sbit单独控制单个IO引脚3、软件空循环实现延时完成LED闪烁效果4、流水灯可以使用3种不同编码思路实现下一章预告独立按键检测软件消抖原理与代码实现