51单片机流水灯跑马灯程序设计 (STC89C52RC)
本文针对虾米I代单片机开发板
单片机C编程和普通C编程的区别是基于硬件编程。因此,在编程时经常要看电路原理图。
一般用低电平来点亮LED
多看原理图和实物板子,把图记在脑子里,一边回忆图一边写代码。回忆图形是运用右脑的记忆方法。我们不光是学习单片机,还要借这个机会训练右脑。
用STC ISP下载程序到单片机时,先点击"Download/下载"按钮,然后单片机电源慢慢开到on,如果开太快,可能下载不进去。
把单片机正放身前,左下是USB转串口,右上是数码管,LED。
看板子个的LED,从右到左分别是LED2-LED9, 然后看51开发板原理图,LED2-LED9分别通到DB0-DB7。再查DB0-DB7对应的IO口,分别是P0.0到 P0.7. 要点亮LED2,也就是右边第一个LED,一般情况代码如下:
#include <reg52.h>
sbit LED0 = P0^0;
void turnLED()
{
while(1)
{
LED0 = 0;
}
}
int main(void)
{
turnLED();
return 0;
}
但是此开发板因为IO紧张,用74HC138进行了端口复用。必须先设置74HC138,切换到LED2-LED9才能点亮所需LED。
再次查看原理图,8个LED的共阳极和PNP三极管的集电极连接,三极管的基极接到LEDS6,只有LEDS6是低电平时,三极管电路才会导通。查看74HC138的电路,LEDS6对应于74HC138的Y6.
查看74HC138的手册,要Y0-Y7要输出低电平,必须G1=H, G2=L, 要Y6输出低电平,必须C=H, B=H,A=L. 发现此表很有规律,CBA组成三位二进制数,C高位,H表示1. HHL也就是二进制的6, 所以Y6输出低电平。
接下来要找到51单片机开发板上,74HC138和开发板上的IO的对应关系。还是查开发板原理图。
G1=ADDR3=P1.3
G2=ENLED=P1.4
C=ADDR2=P1.2
B=ADDR1=P1.1
A=ADDR0=P1.0
于是我们可以写出下面函数让LEDS6输出低电平(如果你的板子没有用到138译码器,下面代码可以略过):
sbit enableG1 = P1^3;
sbit enableG2 = P1^4;
sbit selectC = P1^2;
sbit selectB = P1^1;
sbit selectA = P1^0;
void hc138()
{
enableG1 = 1;
enableG2 = 0;
selectC = 1;
selectB = 1;
selectA = 0;
}
现在,点亮LED2的完整代码如下:
#include <reg52.h>
sbit enableG1 = P1^3;
sbit enableG2 = P1^4;
sbit selectC = P1^2;
sbit selectB = P1^1;
sbit selectA = P1^0;
//74HC138译码器
void hc138()
{
enableG1 = 1;
enableG2 = 0;
selectC = 1;
selectB = 1;
selectA = 0;
}
//点亮LED
void turnLED()
{
while(1)
{
P0 = 254;
}
}
int main(void)
{
hc138();
turnLED();
return 0;
}
注意,点亮LED2的代码我们写成了P0=254, 这是一次设置1 byte的方法。1 byte最大的数字是255,第1位变成0,就是254了。用16进制赋值更简单: P0 = 0xFE
下面变换些花样,我只给出turnLED函数,其他代码同前:
typedef unsigned char uint8;
typedef unsigned int uint16;
//6种单片机LED流水灯跑马灯示例代码
void turnLED()
{
uint8 i = 0;
uint16 j = 0;
while(1)
{
//P0 = 1 << i++; //一熄灭灯从右到左
//P0 = ~(1 << i++); //一灯从右到左
//P0 = ~(0x80 >> i++); //一灯从左到右
//P0 = ~(0xC0 >> i++); //二灯从左到右
//左右来回振荡
/*
P0 = ~(0x80 >> i++); //一灯从左到右
for(j = 0; j < 33000; j++); //延时不要太短,以看得更清楚
if( i == 8 )
{
i -= 2;
while(i > 0)
{
P0 = ~(0x80 >> i--);
for(j = 0; j < 33000; j++); //延时不要太短,以看得更清楚
}
}
*/
P0 = ~(0x80 >> i++); //一灯从左到右
for(j = 0; j < 33000; j++); //延时不要太短,以看得更清楚
i %= 8;
}
}
|