任务:
1、控制LED,手打代码,
2、单片机上电,关闭所有外设LED,蜂鸣器,继电器,数码管;
3、然后LED全部一起闪烁8次,间隔300ms;
4,然后在while1里面,不断LED1闪烁5次,间隔500ms,然后LED全部关/1秒;
5、然后LED5慢闪5次,间隔1000ms;然后全部关闭1秒;
6、然后LEDbuf=0xBD,P0输出这个数据,等待5秒;
7、然后判断LED6是不是等于1,如果等于1,熄灭的状态,那么让LED7快闪5次,间隔200ms;如果等于0,点亮的状态,那么让LED8快闪5次;然后所有的LED关闭1秒钟。
关键代码:
选择不同的573的函数;
设置一个全局变量,负责LED的状态,LEDbuf,unsigned char类型;
让某一个位等于1,其他位保持不变;或1等于1,或0保持不变;
让某一个位等于0,其他位保持不变;与0清0,与1保持不变;
判断某一个位,是0还是1,;右移N位,再与0x01等结果
取反某个LED的状态,其他位保持不变,异或1取反,异或0保持不变。
理论看我的LQB原来的视频。或者先记着。现场问我。
关闭全部外设:
LED是等于1,熄灭,等于0点亮;
蜂鸣器和继电器都是等于0不响,不导通,等于1就是点亮,导通;
数码管是共阳数码管,COM口等于0x00,ABC数据口等于0xFF;
#include <stc15.h>
#include <intrins.h>
//类型定义,在stcISP软件复制过来的,提高编程效率,比如用u8代替unsigned char,不用打这么多字
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
//宏定义,注意不要有分号在后面
#define LED 4
#define ULN 5
#define COM 6
#define ABC 7
//***********全局变量
u8 LEDbuf=0xFF;//这个数据等于0xFF,那么后面输出给P0,LED会全部熄灭
u8 ULNbuf=0x00;//ULN2003是反相器,0出1,输出给P0,蜂鸣器继电器都会不反应
//******************************背出来
void Select(u8 x)
{
switch(x)
{
//0001 1111
case 0:P2=P2&0x1F;break;//选择74HC138的Y0闲置口,相当于不选择任何一个支路
case LED:P2=(P2&0x1F)|0x80;break; //选择Y4,LED通道支路
case ULN:P2=(P2&0x1F)|0xA0;break; //选择Y5,ULN通道支路
case COM:P2=(P2&0x1F)|0xC0;break; //选择Y6,COM通道支路
case ABC:P2=(P2&0x1F)|0xE0;break; //选择Y7,ABC通道支路
}
}
//延时1ms,stcISP软件生成,nop函数注意在KEIL的help文件里面搜索,得到头文件是intrins.h
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
//自己变成,用for循环进行多次一个毫秒的循环,注意括号最好用u16类型,因为可能超过1000数字,大于8位256数字
void delayms(u16 nms)
{
u16 i=0;
for(i=0;i<nms;i++)
{
Delay1ms();
}
}
//*****************************main
void main()
{
//局部变量
u8 i=0;
//关闭外设 ,初始化动作
//选择通道,更新数据,输出数据,关闭通道
Select(LED); LEDbuf=0xFF; P0=LEDbuf; Select(0);//LED通道,关闭熄灭LED
Select(ULN);ULNbuf=0x00;P0=ULNbuf;Select(0);
//ULN2003芯片,反相器,0x00经过ULN2003之后,数据是0xFF,输出后,蜂鸣器继电器熄灭
Select(COM);P0=0x00;Select(0);//选择数码管COM通道,这没有缓冲字节,因为数码管我们不需要随时读取哪个点亮
Select(ABC);P0=0xFF;Select(0);//选择数码管ABC段码通道,这没有缓冲字节,因为数码管我们不需要随时读取亮的是什么
//开机之后,全部数码管闪烁8次,快速闪烁
for(i=0;i<8;i++)
{
Select(LED); LEDbuf=0x00; P0=LEDbuf; Select(0);
delayms(300);
Select(LED); LEDbuf=0xFF; P0=LEDbuf; Select(0);
delayms(300);
}
while(1)
{
//让LED1闪烁8次,,注意为什么用取反0x01,目的是为了简化,
//方便理解。0000 0001取反等于1111 1110,bit0与0等于0,其他位与1保持不变
for(i=0;i<8;i++)
{
Select(LED); LEDbuf=LEDbuf &(~0x01) ; P0=LEDbuf; Select(0);
//~0x01,对0x01进行取反,得到1111 1110,LEDbuf与1111 1110,将最低位清0,其他位保持不变,
//目的是让LED1=0,点亮LED1;为什么我这里要采用取反的方法呢,主要是为了方便记忆,我们习惯用1进行计算,当然你也
//可以不采用这种方法;而直接采用LEDbuf=LEDbuf &0xFE;(开发板没有LED0,而是从LED1开始的。。)
delayms(500);
//或0x01,将最低LED1=1,其他位保持不变,熄灭LED1;
Select(LED); LEDbuf=LEDbuf |0x01; P0=LEDbuf; Select(0);
delayms(500);
}
//让LED5闪烁8次,注意为什么用取反0x10,目的是为了简化,方便理解。
for(i=0;i<8;i++)
{
//~0x10,对0x10进行取反,得到1110 1111,LEDbuf与1110 1111,将LED5=0,其他位保持不变,
//目的是让LED5=0,点亮LED5;为什么我这里要采用取反的方法呢,主要是为了方便记忆,我们习惯用1进行计算,当然你也
//可以不采用这种方法;而直接采用LEDbuf=LEDbuf &0xFE;(开发板没有LED0,而是从LED1开始的。。)
Select(LED); LEDbuf=LEDbuf &(~0x10) ; P0=LEDbuf; Select(0); //0001 0000
delayms(1000);
Select(LED); LEDbuf=LEDbuf |0x10; P0=LEDbuf; Select(0);
delayms(1000);
}
//关闭LED灯一秒钟
Select(LED); LEDbuf=0xFF; P0=LEDbuf; Select(0);
delayms(1000);
LEDbuf=0xBD;
//学会判断哪一位是0还是1?
//判断LED7是不是1;等于1,让LED7闪烁5次;
//将LEDbuf右移7位,原来右边的7位移动右边,没有了,左边补0,得到的数,和0x01与,只剩下最后一位,可以判断了。
//如LEDbuf假如是0xa7=1010 0111,LED7是bit6位,因为开发板没有LED0,而是从LED1开始的;
//bit7----bit0,bit6=0,右边移动6位,00000010,和0x01与,与0得到0,与1保持不变,所以结果就是剩下最后的bit6位。
//假如判断哪一位,右移x位,再与0x01,记住了吗?
if(((LEDbuf>>6)&0x01)==1)
{
for(i=0;i<5;i++)
{
//0x40=0100 0000
Select(LED); LEDbuf=LEDbuf &(~0x40) ; P0=LEDbuf; Select(0); //0100 0000
delayms(300);
Select(LED); LEDbuf=LEDbuf |0x40; P0=LEDbuf; Select(0);
delayms(300);
}
}
//等于0,让LED8闪烁5次
else
{
for(i=0;i<5;i++)
{
Select(LED); LEDbuf=LEDbuf &(~0x80) ; P0=LEDbuf; Select(0); //0100 0000
delayms(300);
Select(LED); LEDbuf=LEDbuf |0x80; P0=LEDbuf; Select(0);
delayms(300);
}
}
//关闭所有的LED灯;
Select(LED); LEDbuf=0xFF; P0=LEDbuf; Select(0);
delayms(1000);
}
}