实验8051+Proteus定时计数器仿真设计.docx
《实验8051+Proteus定时计数器仿真设计.docx》由会员分享,可在线阅读,更多相关《实验8051+Proteus定时计数器仿真设计.docx(32页珍藏版)》请在冰点文库上搜索。
实验8051+Proteus定时计数器仿真设计
实验:
8051+Proteus定时/计数器仿真
一、定时器控制单只LED
/*名称:
定时器控制单只LED
说明:
LED在定时器的中断例程控制下不断闪烁。
*/
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitLED=P0^0;
ucharT_Count=0;
//主程序
voidmain()
{
TMOD=0x00;//定时器0工作方式0
TH0=(8192-5000)/32;//5ms定时
TL0=(8192-5000)%32;
IE=0x82;//允许T0中断
TR0=1;
while
(1);
}
//T0中断函数
voidLED_Flash()interrupt1
{
TH0=(8192-5000)/32;//恢复初值
TL0=(8192-5000)%32;
if(++T_Count==100)//0.5s开关一次LED
{
LED=~LED;
T_Count=0;
}
}
二、TIMER0控制流水灯
/*名称:
TIMER0控制流水灯说明:
定时器控制P0、P2口的LED滚动显示,本例未使用中断函数。
*/
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
//主程序
voidmain()
{
ucharT_Count=0;
P0=0xfe;
P2=0xfe;
TMOD=0x01;//定时器0工作方式1
TH0=(65536-40000)/256;//40ms定时
TL0=(65536-40000)%256;
TR0=1;//启动定时器
while
(1)
{
if(TF0==1)
{
TF0=0;
TH0=(65536-40000)/256;//恢复初值
TL0=(65536-40000)%256;
if(++T_Count==5)
{
P0=_crol_(P0,1);
P2=_crol_(P2,1);
T_Count=0;
}
}
}
}
三、定时器控制4个LED滚动闪烁
/*名称:
定时器控制4个LED滚动闪烁
说明:
4只LED在定时器控制下滚动闪烁。
*/
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitB1=P0^0;
sbitG1=P0^1;
sbitR1=P0^2;
sbitY1=P0^3;
uinti,j,k;
//主程序
voidmain()
{
i=j=k=0;
P0=0xff;
TMOD=0x02;//定时器0工作方式2
TH0=256-200;//200us定时
TL0=256-200;
IE=0x82;
TR0=1;//启动定时器
while
(1);
}
//T0中断函数
voidLED_Flash_and_Scroll()interrupt1
{
if(++k<35)return;//定时中断若干次后执行闪烁
k=0;
switch(i)
{
case0:
B1=~B1;break;
case1:
G1=~G1;break;
case2:
R1=~R1;break;
case3:
Y1=~Y1;break;
default:
i=0;
}
if(++j<300)return;//每次闪烁持续一段时间
j=0;
P0=0xff;//关闭显示
i++;//切换到下一个LED
}
四、T0控制LED实现二进制计数
/*名称:
T0控制LED实现二进制计数
说明:
本例对按键的计数没有使用查询法,没有使用外部中断函数,没有使用定时或计数中断函数。
而是启用了计数器,连接在T0引脚的按键每次按下时,会使计数寄存器的值递增,其值通过LED以二进制形式显示
*/
#include
//主程序
voidmain()
{
TMOD=0x05;//定时器0为计数器,工作方式1,最大计数值65535
TH0=0;//初值为0
TL0=0;
TR0=1;//启动定时器
while
(1)
{
P1=TH0;
P2=TL0;
}
}
五、TIMER0与TIMER1控制条形LED
/*名称:
TIMER0与TIMER1控制条形LED
说明:
定时器T0定时控制上一组条形LED,滚动速度较快
定时器T1定时控制下一组条形LED,滚动速度较慢
*/
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
uchartc0=0,tc1=0;
//主程序
voidmain()
{
P0=0xfe;
P2=0xfe;
TMOD=0x11;//定时器0、定时器1均工作于方式1
TH0=(65536-15000)/256;//定时器0:
15ms
TL0=(65536-15000)%256;
TH1=(65536-50000)/256;//定时器1:
50ms
TL1=(65536-50000)%256;
IE=0x8a;
TR0=1;//启动定时器
TR1=1;
while
(1);
}
//T0中断函数
voidTime0()interrupt1
{
TH0=(65536-15000)/256;//恢复定时器0初值
TL0=(65536-15000)%256;
if(++tc0==10)//150ms转换状态
{
tc0=0;
P0=_crol_(P0,1);
}
}
//T1中断函数
voidTime1()interrupt3
{
TH0=(65536-50000)/256;//恢复定时器1初值
TL0=(65536-50000)%256;
if(++tc1==10)//500ms转换状态
{
tc1=0;
P2=_crol_(P2,1);
}
}
六、10s的秒表
/*名称:
10s的秒表
说明:
首次按键计时开始,再次按键暂停,第三次按键清零。
*/
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitK1=P3^7;
uchari,Second_Counts,Key_Flag_Idx;
bitKey_State;
ucharDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//延时
voidDelayMS(uintms)
{
uchart;
while(ms--)for(t=0;t<120;t++);
}
//处理按键事件
voidKey_Event_Handle()
{
if(Key_State==0)
{
Key_Flag_Idx=(Key_Flag_Idx+1)%3;
switch(Key_Flag_Idx)
{
case1:
EA=1;ET0=1;TR0=1;break;
case2:
EA=0;ET0=0;TR0=0;break;
case0:
P0=0x3f;P2=0x3f;i=0;Second_Counts=0;
}
}
}
//主程序
voidmain()
{
P0=0x3f;//显示00
P2=0x3f;
i=0;
Second_Counts=0;
Key_Flag_Idx=0;//按键次数(取值0,1,2,3)
Key_State=1;//按键状态
TMOD=0x01;//定时器0方式1
TH0=(65536-50000)/256;//定时器0:
15ms
TL0=(65536-50000)%256;
while
(1)
{
if(Key_State!
=K1)
{
DelayMS(10);
Key_State=K1;
Key_Event_Handle();
}
}
}
//T0中断函数
voidDSY_Refresh()interrupt1
{
TH0=(65536-50000)/256;//恢复定时器0初值
TL0=(65536-50000)%256;
if(++i==2)//50ms*2=0.1s转换状态
{
i=0;
Second_Counts++;
P0=DSY_CODE[Second_Counts/10];
P2=DSY_CODE[Second_Counts%10];
if(Second_Counts==100)Second_Counts=0;//满100(10s)后显示00
}
}
七、用计数器中断实现100以内的按键计数
/*名称:
用计数器中断实现100以内的按键计数
说明:
本例用T0计数器中断实现按键技术,由于计数寄存器初值为1,因此
P3.4引脚的每次负跳变都会触发T0中断,实现计数值累加。
计数器的清零用外部中断0控制。
*/
#include
#defineucharunsignedchar
#defineuintunsignedint
//段码
ucharcodeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
ucharCount=0;
//主程序
voidmain()
{
P0=0x00;
P2=0x00;
TMOD=0x06;//计数器T0方式2
TH0=TL0=256-1;//计数值为1
ET0=1;//允许T0中断
EX0=1;//允许INT0中断
EA=1;//允许CPU中断
IP=0x02;//设置优先级,T0高于INT0
IT0=1;//INT0中断触发方式为下降沿触发
TR0=1;//启动T0
while
(1)
{
P0=DSY_CODE[Count/10];
P2=DSY_CODE[Count%10];
}
}
//T0计数器中断函数
voidKey_Counter()interrupt1
{
Count=(Count+1)%100;//因为只有两位数码管,计数控制在100以内(00~99)
}
//INT0中断函数
voidClear_Counter()interrupt0
{
Count=0;
}
八、100000s以内的计时程序
/*名称:
100000s以内的计时程序
说明:
在6只数码管上完成0~99999.9s。
*/
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
//段码
ucharcodeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//6只数码管上显示的数字
ucharDigits_of_6DSY[]={0,0,0,0,0,0};
ucharCount;
sbitDot=P0^7;
//延时
voidDelayMS(uintms)
{
uchart;
while(ms--)for(t=0;t<120;t++);
}
//主程序
voidmain()
{
uchari,j;
P0=0x00;
P3=0xff;
Count=0;
TMOD=0x01;//计数器T0方式1
TH0=(65536-50000)/256;//50ms定时
TL0=(65536-50000)%256;
IE=0x82;
TR0=1;//启动T0
while
(1)
{
j=0x7f;
//显示Digits_of_6DSY[5]~Digits_of_6DSY[0]的内容
//前面高位,后面低位,循环中i!
=-1亦可写成i!
=0xff
for(i=5;i!
=-1;i--)
{
j=_crol_(j,1);
P3=j;
P0=DSY_CODE[Digits_of_6DSY[i]];
if(i==1)Dot=1;//加小数点
DelayMS
(2);
}
}
}
//T0中断函数
voidTimer0()interrupt1
{
uchari;
TH0=(65536-50000)/256;//恢复初值
TL0=(65536-50000)%256;
if(++Count!
=2)return;
Count=0;
Digits_of_6DSY[0]++;//0.1s位累加
for(i=0;i<=5;i++)//进位处理
{
if(Digits_of_6DSY[i]==10)
{
Digits_of_6DSY[i]=0;
if(i!
=5)Digits_of_6DSY[i+1]++;//如果0~4位则分别向高一位进位
}
elsebreak;//若某低位没有进位,怎循环提前结束
}
}
九、定时器控制数码管动态显示
/*名称:
定时器控制数码管动态显示
说明:
8个数码管上分两组动态显示年月日与时分秒,本例的位显示延时用定时器实现。
*/
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
//段码,最后一位是“-”的段码
ucharcodeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
//待显示的数据:
09-12-25与23-59-58(分两组显示)
ucharcodeTable_of_Digits[][8]={{0,9,10,1,2,10,2,5},{2,3,10,5,9,10,5,8}};
uchari,j=0;
uintt=0;
//主程序
voidmain()
{
P3=0x80;//位码初值
TMOD=0x00;//计数器T0方式0
TH0=(8192-4000)/32;//4ms定时
TL0=(8192-4000)%32;
IE=0x82;
TR0=1;//启动T0
while
(1);
}
//T0中断函数控制数码管刷新显示
voidDSY_Show()interrupt1
{
TH0=(8192-4000)/32;//恢复初值
TL0=(8192-4000)%32;
P0=0xff;//输出位码和段码
P0=DSY_CODE[Table_of_Digits[i][j]];
P3=_crol_(P3,1);
j=(j+1)%8;//数组第i行的下一字节索引
if(++t!
=350)return;//保持刷新一段时间
t=0;
i=(i+1)%2;//数组行i=0时显示年月日,i=1时显示时分秒
}
十、用定时器设计的门铃
/*名称:
用定时器设计的门铃
说明:
按下按键时蜂鸣器发出叮咚的门铃声。
*/
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitKey=P1^7;
sbitDoorBell=P3^0;
uintp=0;
//主程序
voidmain()
{
DoorBell=0;
TMOD=0x00;//T0方式0
TH0=(8192-700)/32;//700us定时
TL0=(8192-700)%32;
IE=0x82;
while
(1)
{
if(Key==0)//按下按键启动定时器
{
TR0=1;
while(Key==0);
}
}
}
//T0中断控制点阵屏显示
voidTimer0()interrupt1
{
DoorBell=~DoorBell;
p++;
if(p<400)//若需要拖长声音,可以调整400和800
{
TH0=(8192-700)/32;//700us定时
TL0=(8192-700)%32;
}
elseif(p<800)
{
TH0=(8192-1000)/32;//1ms定时
TL0=(8192-1000)%32;
}
else
{
TR0=0;
p=0;
}
}
十一、演奏音阶
/*名称:
演奏音阶
说明:
本例使用定时器演奏一段音阶,播放由K1控制。
*/
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitK1=P1^0;
sbitSPK=P3^4;
uinti=0;//音符索引
//14个音符放在方式2下的定时寄存器(TH0,TL0)
ucharcodeHI_LIST[]={0,226,229,232,233,236,238,240,241,242,244,245,246,247,248};
ucharcodeLO_LIST[]={0,4,13,10,20,3,8,6,2,23,5,26,1,4,3};
//定时器0中断函数
voidT0_INT()interrupt1
{
TL0=LO_LIST[i];
TH0=HI_LIST[i];
SPK=~SPK;
}
//延时
voidDelayMS(uintms)
{
uchart;
while(ms--)for(t=0;t<120;t++);
}
//主程序
voidmain()
{
TMOD=0x00;//T0方式0
IE=0x82;
SPK=0;
while
(1)
{
while(K1==1);//未按键等待
while(K1==0);//等待释放
for(i=1;i<15;i++)
{
TR0=1;//播放一个音符
DelayMS(500);//播放延时
TR0=0;
DelayMS(50);
}
}
}
十二、按键控制定时器选播多段音乐
/*名称:
按键控制定时器选播多段音乐
说明:
本例内置3段音乐,K1可启动停止音乐播放,K2用于选择音乐段。
*/
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitK1=P1^0;//播放和停止键
sbitSPK=P3^7;//蜂鸣器
ucharSong_Index=0,Tone_Index=0;//当前音乐段索引,音符索引
//数码管段码表
ucharcodeDSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//标准音符频率对应的延时表
ucharcodeHI_LIST[]={0,226,229,232,233,236,238,240,241,242,244,245,246,247,248};
ucharcodeLO_LIST[]={0,4,13,10,20,3,8,6,2,23,5,26,1,4,3};
//三段音乐的音符
ucharcodeSong[][50]=
{
{1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,3,5,6,5,3,5,3,2,1,2,1,-1},
{3,3,3,4,5,5,5,5,6,5,3,5,3,2,1,5,6,53,3,2,1,1,-1},
{3,2,1,3,2,1,1,2,3,1,1,2,3,1,3,4,5,3,4,5,5,6,5,3,5,3,2,1,3,2,1,1,-1}
};
//三段音乐的节拍
ucharcodeLen[][50]=
{
{1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,2,1,2,-1},
{1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,2,2,-1},
{1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,1,1,2,1,1,2,2,-1}
};
//外部中断0
voidEX0_INT()interrupt0
{
TR0=0;//播放结束或者播放中途切换歌曲时停止播放
Song_Index=(Song_Index+1)%3;//跳到下一首的开头
Tone_Index=0;
P2=DSY_CODE[Song_Index];//数码管显示当前音乐段号
}
//定时器0中断函数
voidT0_INT()interrupt1
{
TL0=LO_LIST[Song[Song_Index][Tone_Index]];
TH0=HI_LIST[Song[Song_Index][Tone_Index]];
SPK=~SPK;
}
//延时
voidDelayMS(uintms)
{
uchart;
while(ms--)for(t=0;t<120