51单片机006:利用动态扫描和定时器1在数码管上显示出从765开始以1/10秒的速度往下递减直至321并保持显示此数,与此同时利用定时器0以500MS速度进行流水灯从上至下移动,当数码管上数减到……
题目:利用动态扫描和定时器1在数码管上显示出从765开始以1/10秒的速度往下递减直至321并保持显示此数,与此同时利用定时器0以500MS速度进行流水灯从上至下移动,当数码管上数减到停止时,实验板上流水灯也停止然后全部开始闪烁,3秒后(用T0定时)流水灯全部关闭、数码管上显示出“HAO”。到此保持住。
思路:
1、“从765开始以1/10秒的速度往下递减直至321并保持显示此数”:
定义num变量,初始值为765,定时器定时0.1s,num--,完成向下递减效果,保持显示此数,可以通过控制TCON中的TR0/TR1运行控制寄存器,使定时器停止计时,num就不会向下递减。
2、“利用定时器0以500MS速度进行流水灯从上至下移动”:
一个简单的利用定时器实现流水灯
3、“当数码管上数减到停止时,实验板上流水灯也停止然后全部开始闪烁,3秒后(用T0定时)流水灯全部关闭、数码管上显示出“HAO”。到此保持住。”
数码管和LED可分为以下几个阶段:
阶段一:数码管数字递减,LED为流水灯
阶段二:数码管显示321,LED闪烁三秒
阶段三:数码管显示HAO,LED关闭
定义两个状态变量,flag和flag_led。
当flag == 0,flag_led == 0时:数码管递减,LED效果为流水灯
当flag == 1,flag_led == 0时:数码管显示为321,LED效果为闪烁3s
当flag_led == 1,flag == 1时:数码管显示为HAO,LED效果为关闭
原理图:
代码:
说明:由于进行数码管位选时和LED的引脚有些冲突,所以只选取了后三位LED灯进行流水灯演示。
#include "reg52.h"
#include <intrins.h>
//定义数码管位选信号控制脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
//定义LED位选信号控制脚
sbit led5=P2^5;
sbit led6=P2^6;
sbit led7=P2^7;
//共阴极数码管显示0~F的段码数据
unsigned char gsmg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0-9
0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x76,0x3f}; //a-f , h ,o
unsigned int num = 765;
unsigned int flag = 0;
unsigned int flag_led = 0;
unsigned int count_10ms; //定义10ms计时变量
unsigned int count_50ms; //定义50ms计时变量
//延时函数
void delay_10us(unsigned int ten_us)
{
while(ten_us--);
}
/*****************************数码管*****************************/
void shumaguan(unsigned char location,number)
{
P0=0x00;
switch(location)
{
case 8:LSC=0;LSB=0;LSA=0;break;
case 7:LSC=0;LSB=0;LSA=1;break;
case 6:LSC=0;LSB=1;LSA=0;break;
case 5:LSC=0;LSB=1;LSA=1;break;
case 4:LSC=1;LSB=0;LSA=0;break;
case 3:LSC=1;LSB=0;LSA=1;break;
case 2:LSC=1;LSB=1;LSA=0;break;
case 1:LSC=1;LSB=1;LSA=1;break;
}
P0=gsmg_code[number];
}
void smg_display(unsigned int num)
{
if(flag == 0)
{
shumaguan(1,num/100);
delay_10us(100);
shumaguan(2,(num/10)%10);
delay_10us(100);
shumaguan(3,num%10);
delay_10us(100);
}
if(flag_led == 1)
{
shumaguan(1,17); //H
delay_10us(100);
shumaguan(2,10); //A
delay_10us(100);
shumaguan(3,18); //O
delay_10us(100);
}
}
/****************************定时器********************************/
/*****定时器1********/
void time1_init(void)
{
TMOD|=0X10; //选择为定时器1模式,工作方式1
TH0=(65535-10000)/256; //10ms循环10次
TL0=(65535-10000)%256;
ET1=1; //打开定时器1中断允许
EA=1; //打开总中断
TR1=1; //打开定时器
}
void time1() interrupt 3 //定时器1中断函数
{
TH0=(65535-10000)/256; //10ms循环10次
TL0=(65535-10000)%256;
count_10ms++;
}
/*******定时器0**********/
void time0_init(void)
{
TMOD|=0X01; //选择为定时器0模式,工作方式1
TH0=(65535-50000)/256; //50ms定时10次
TL0=(65535-50000)%256;
ET0=1; //打开定时器0中断允许
EA=1; //打开总中断
TR0=1; //打开定时器
}
void time0() interrupt 1 //定时器0中断函数
{
TH0=(65535-50000)/256; //50ms定时10次
TL0=(65535-50000)%256;
count_50ms++;
}
void main()
{
time0_init();
time1_init();
while(1)
{
smg_display(num);
if(count_10ms == 10)
{
count_10ms = 0;
num--;
smg_display(num);
if(num == 321)
{
TR1 = 0; //停止计时
flag = 1;
smg_display(num);
}
}
if(flag == 0) //流水灯
{
flag_led = 0;
if(count_50ms==10) //500ms
{
led5=0;led6=1;led7=1;
}
if(count_50ms==20) //500ms
{
led5=1;led6=0;led7=1;
}
if(count_50ms==30) //500ms
{
led5=1;led6=1;led7=0;
count_50ms = 0;
}
}
else //led闪烁
{
if(count_50ms <= 60)
{
led5=1;led6=1;led7=1; //全部熄灭
delay_10us(10);
led5=0;led6=0;led7=0; //全部点亮
delay_10us(10);
}
//到了3s
else
{
TR0 = 0;
flag_led = 1;
led5=1;led6=1;led7=1; //全部熄灭
}
}
}
}