原理图如图:
编程工具:Keil uVision4
烧录软件:stc-isp-15xx-v6.86I
编译语言:c51
1.打开软件,点击project新建工程,命名为英文(使用中文会出现一些奇怪的错误)。
2.选择单片机型号为AT89C52。
3.新建main.c文件添加进工程。
4.配置魔术棒工具卡,在output选项卡勾选crete hex,这样在程序运行完成就会产生一个hex文件用于烧录。
1.选择单片机型号stc89c52。
2.点击打开程序文件,在工程中找到hex文件。
3.点击下载编程,按下单片机开关。
要点亮D1,就要把P20置0.
代码如下
reg52.h是51单片机的头文件。
延时问题:可以让程序进入一个i–的循环,通过设置i的大小来控制延时的时间。
这个i设置的值要大一点。。我开始设置在100,1000观察不到闪烁现象。。调整到5000可以观察到很快的闪烁。
要实现的是D1到D8逐渐亮起,每当后一个灯点亮,前一个灯熄灭。
当对P2口赋值时,以十六进制赋值,比如赋0x01,转化为二进制就是00000001,1在P2的最低位即为P2.0,此时D1亮,其他都灭。
第一个灯亮了之后,给他一定的延时,然后下一个灯亮,这个时候可以可以设置P2为二级制值为00000010的16进制,之后逐个设置。。但还有一个简单的方法,使用左右移函数。
crol(led,1)即为左移函数,使用后小灯从最低位向高位移动,右移函数将crol改为cror即可。
**
直接用单片机的io口驱动蜂鸣器很困难,这里通过三极管将电流放大后再进行驱动。
单片机的蜂鸣器是无源蜂鸣器,需要一个有一定频率的脉冲信号(高低电平不断转换)使他发声。
动态显示分为段选和位选。这里使用74HC245驱动实现段选,由于数码管是共阴极接法当输入是高电平时对应位置亮。使用74HC318扩展io口实现位选,将输入的三位二进制转换为十进制即可得到位置,例如输入为101转化为二进制即为5对用Y5输出选中LED6为低电平。
#include
typedef unsigned int u16;
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 code smgduan[9]={0x06,0x4f,0x06,0x66,0x40,0x6d,0x5b,0x3f
};
void delay(u16 i)
{
while(i--);
}
void DigDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=1;LSB=1;LSC=1; break;//显示第0位
case(1):
LSA=0;LSB=1;LSC=1; break;//显示第1位
case(2):
LSA=1;LSB=0;LSC=1; break;//显示第2位
case(3):
LSA=0;LSB=0;LSC=1; break;//显示第3位
case(4):
LSA=1;LSB=1;LSC=0; break;//显示第4位
case(5):
LSA=0;LSB=1;LSC=0; break;//显示第5位
case(6):
LSA=1;LSB=0;LSC=0; break;//显示第6位
case(7):
LSA=0;LSB=0;LSC=0; break;//显示第7位
}
P0=smgduan[i];//发送段码
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}
void main()
{
while(1)
{
DigDisplay(); //数码管显示函数
}
}
数码管显示1314-520,如果把延迟调大到24ms左右可以观察到逐个显示,我直接调到10000观察到很明显的逐个显示现象。
#include
typedef unsigned int u16;
typedef unsigned char u8;
sbit k1=P3^1;
sbit led=P2^0;
void delay(u16 i)
{
while(i--);
}
void krun()
{
if(k1==0)
{
delay(1000); //防抖动
if(k1==0)
{
led=~led;
}
}
while(!k1);//检查是否松开
}
void main()
{
while(1)
{
krun();
}
}
按键防抖动和检查按键是否松开是应该注意的地方;烧录后,按下k1小灯状态改变。
要实现判断哪个按键被按下并返回他的序号到数码管上。
采用行列扫描法检测,先行后列或先列后行确定按键位置。
#include
typedef unsigned int u16;
typedef unsigned char u8;
#define key P1
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 keyvalue;
u8 code duan[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
void delay(u16 i)
{
while(i--);
}
void DigDisplay()
{
u8 i;
for(i=0;i<2;i++)
{
if(i==1)
{
LSA=1;LSB=1;LSC=1;
P0=~duan[1];//发送段码
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
else
{
LSA=0;LSB=1;LSC=1;
P0=~duan[keyvalue-10];//发送段码
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}
}
void find()
{
u16 a=0;
key=0x0f;
if(key!=0x0f)
{
delay(1000);
if(key!=0x0f)
{
key=0x0f;
switch(key)
{
case(0x07): keyvalue=1;break;
case(0x0b): keyvalue=2;break;
case(0x0d): keyvalue=3;break;
case(0x0e): keyvalue=4;break;
}
key=0xf0;
switch(key)
{
case(0x70): keyvalue=keyvalue;break;
case(0xb0): keyvalue=keyvalue+4;break;
case(0xd0): keyvalue=keyvalue+8;break;
case(0xe0): keyvalue=keyvalue+12;break;
}
}
}
while((key!=0xf0)&&(a<50))
{
delay(10);
a++;
}
}
void main()
{
while(1)
{
find();
if(keyvalue>=10)
{
DigDisplay();
}
else
{
P0=~duan[keyvalue];//因为上面的段码用的是共阳。。所以这里取反
}
}
}
原先设置的检测松手为每次延时100,发现这样当显示10以上位置时会闪烁。。在松手检测中设置a=50时跳出是为了防止程序陷入死等待机。。对为什么要做松手检测有些迷惑。。查找资料
烧录后,按下按键,1-9在数码管第一位显示,10-16在数码管第一第二位显示。