《中学生C51单片机易学实战入门教程》
第三课 8 LED玩花样实验准备:使用第一课已装配好的实验板 LED 增加7只 电阻 10k ,增加7只 课程内容:一、 接完整8只LED 电路参照原理图,类似在P1.0上接LED的方法,把P1.1到P1.7的7只LED和电阻也接好。 这时,为实验板加电,可见到只有P1.0对应的D1这只LED在闪,如果按之前的编程思路,就是使用如下的程序方式: sbit P10= P1^0; sbit P11= P1^1; sbit P12= P1^2; sbit P13= P1^3; sbit P14= P1^4; sbit P15= P1^5; sbit P16= P1^6; sbit P17= P1^7; 同时main()程序中使用 P10=!P10; P11=!P11; P12=!P12; P13=!P13; P14=!P14; P15=!P15; P16=!P16; P17=!P17; 这方式可行吗?当然可行,只要能达到效果,哪一种方式都行,其实这也是编程最先采用的方法,就是先用最容易理解,最简单的实现方法去编程,达到要求结果后,再去做程序优化,否则没达到结果 什么精简高效的程序都是没用的。 好了,现在可以同时控制8 LED了,但看上去很繁,那么就做优化。 单片机虽然只认0与1,但可以一次同时处理多个位,例如C51系列就是8位单片机,同时可以处理8位,更高级的处理器可以同时处理16位、32位、64位或128位等等。 89C52单片机可一次同时处理8位,这单片机把控制数据输入输出的管脚(简称IO口)分成4组,每组8个IO口,分别命名为P1、P2、P3、P4,这在 reg52.h 文件中预先做好定义,方便我们直接操控。 本次实验中8 只LED接在P1的8个IO口处,所以,可以直接一次性控制8只LED。 修改控制,只须改到一行代码。 主程序main()中,把 P10=!P10; 改成 P1=~P1; 下载,观看实验效果,可以见到8只LED同时闪动。 上一课中所用的运算符号!,只对一位数起效,不能同时控制8位,如果把 P1=~P1; 改成 P1=!P1; 那么只有LED1闪,其他不闪,这个可以下载实践下。 而运算符~则是8位同时运算 00000000 做~取反,对每个位取反,结果就是11111111 同理,11111111 做~取反,对每个位取反,结果就是00000000 二、十六进制与二进制如果8个LED灯想玩下花样,做出特效,有的LED发光,有的不发光,或者做流水灯等广告效果,这时,需要对不同的LED控制它所在位设0或设1,于是 11110000,10101010等这样的结果就出现了,这些数不方便记忆,也不方便编程,于是采用『数制』来实验简化。11110000或10101010这纯机器码表现形式你为二进制数,每位只能是0或1,逢2进1,与平常用的10进制数类似,10进制每位可用0至9个数,逢10进1。还有十六进制的数,成语『半斤八两』中所用的是十六进制,中国古代的重量计量方式是一斤是十六两。 二进制数太长不好写不好记,一般采用十六进制方式表示, 二进制11110000 ---> 十六进制 0xF0 二进制10101010 ---> 十六进制 0xAA 注意,每个十六制数前要加 0x,如果不加,是当成10进制数的。 如果转换,很简单,电脑中有只工具软件『计算器』能帮我们。 在电脑程序附件中可以找到『计算器』这个工具软件。 可以通过 查看 – 科学型 ,切换到 数制转换模式 点二进制,输入11110000,再点十六进制,就自动显示F0 三、8 LED 花样控制现在,可以实验LED花样特效了, 间闪效果一:(这里仅修改主程序main()) void main() { P1=0xAA;//二进制对应是 10101010 mDelay(200); P1=0x55;//二进制对应是 01010101 mDelay(200); } 间闪效果二:(这里仅修改主程序main()) void main() { P1=0x36;//二进制对应是 01101101 mDelay(200); P1=0x5B;//二进制对应是 10110110 mDelay(200); P1=0xDB;//二进制对应是 11011011 mDelay(200); } 四、 新花样:单点LED轮转#include 'reg52.h' #define uchar unsigned char #define uint unsigned int sbit P10=P1^0; void mDelay(uint Delay) { uint i; for(;Delay>0;Delay--) for(i=0;i<> } void main() { uchar a = 0x01; // 二进制00000001 for(;;) { P1 = ~a; // 首次循环时把a取反的值给P1,11111110 //控制P1.0的LED,注意这时 a 值本身是没有变化的 a = a < 1;="" 首次循环时="" a左移一位,a值变成=""> if (a==0x00) a=0x01; //如果 a 变成了00000000,那么设成00000001 mDelay(200); //延时,之后继续循环 分别控制 各只LED } } 程序分析: 第一:uchar 定义的数据,刚好是8位,直接适用于IO的控制。 第二:< 左移运算符,a中的8个位同时向左移,最后一个用0补上。(同理="">>右移运算类似), a=a<1;>1;> 第三:if (a==0x00) a=0x01;这是判断结构,if 就是『如果』,由于循环结构for(;;)是无限循环,所以其中 a 每左移8次后会变成0,这时让a设成0x01,可以让重新让第一位的LED受控。 注意if (a==0x00)中的 a==0x00 是两个等于号,这是C语言中的,判断运算符中的一个,类似,还有 >=(小于或等于)、<><(小于)、>( 大于)、!=(不等于) 这些运算符。 五、 程序优化C51单片机开发的前辈已编有一些方便我们使用的功能模块,我们直接按需调用,于是程序可以再简化。在文件intrins.h中定义有循环左移位函数_crol_(),使用方法直接看以下修改后的程序。(类似有循环右移位函数_cror_()) #include 'reg52.h' #include 'intrins.h' #define uchar unsigned char #define uint unsigned int sbit P10=P1^0; void mDelay(uint Delay) { uint i; for(;Delay>0;Delay--) for(i=0;i<> } void main() { uchar a = 0x01; // 二进制00000001 for(;;) { P1 = ~a; // 首次循环时把a取反的值给P1,11111110 //控制P1.0的LED,注意这时 a 值本身是没有变化的 a = _crol_(a,1); // a 循环左移位,左边移出的放回右边的移空位 mDelay(200); //延时,之后继续循环 分别控制 各只LED } } 注意: 1.增加了 #include 'intrins.h' 这一行, 2.循环左移位函数 _crol_(),函数名前面与后面是下划线。 (小于)、> |
|