Proteus入门单片机(3)例程分析

2023-04-04 03:30   268   0  

e87c2066-ac51-11ed-bcd2-b8ca3a6cb5c4.webp


74HC573详解:


e87c2067-ac51-11ed-bcd2-b8ca3a6cb5c4.webp


/*


调试环境:Proteus 7.8  AT89S52单片机  8位共阴数码管


功能为:实现数码管1秒~99秒倒计时,    12M晶振


*/




#include

#define uchar unsigned char

sbit LED1=P1^1;                           //连的是LED1

#define MAX_NUM     13                //最大倒计时数1~99可设

#define SEGPORT         P0           //定义数码管连接端口

sbit LE_DUAN         = P2^0;           //定义573锁存使能端口 段锁存

sbit LE_WEI         = P2^1;           //定义573锁存使能端口 位锁存


unsigned char code Seg_Duan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴数码管显示段码值 0~9

unsigned char code Seg_Wei[]  = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};                 //数码管的位码,低电平有效。


static uchar second=MAX_NUM,count;    //99只是一个数,可以任意改,因为这里只学习怎样实现倒计时


uchar shiwei;

uchar gewei;


void delay(unsigned int cnt)

{

        while(--cnt);

}


void main()

{

        TMOD|=0x01;       //定时器设置 16位

        TH0=(65536-50000)/256;  //定时时间   50ms

        TL0=(65536-50000)%256;

        EA=1;

        ET0=1;

        TR0=1;

        SEGPORT = 0;//P0等于0,段码位码均为零

        LE_DUAN = 0;//74HC573锁

        LE_WEI = 0;//74HC573锁

        while(1)

        {

                shiwei=second/10;  //数码管10位

                gewei=second%10;   //数码管个位

                       //下面四句送段码,

                SEGPORT=0;    //清空数据,防止有交替重影

                LE_DUAN=1;      //段锁存

                LE_DUAN=0;

                delay(30);


                SEGPORT = Seg_Wei[1];     //先送位码值

                LE_WEI = 1;           //573高电平锁存

                LE_WEI = 0;

                SEGPORT = Seg_Duan[shiwei];    //再送段码值,这里为 2~9

                LE_DUAN = 1;                //573高电平锁存

                LE_DUAN = 0;

                delay(300);



                SEGPORT = Seg_Wei[0];           //先送位码值

                LE_WEI = 1;           //573高电平锁存

                LE_WEI = 0;

                SEGPORT = Seg_Duan[gewei]; //再送段码值,这里为 2~9

                LE_DUAN = 1;                //573高电平锁存

                LE_DUAN = 0;

                delay(300);

        }

}


void tim(void) interrupt 1    //定时器0中断    

{

        TH0=(65536-50000)/256;     //定时时间   50ms

        TL0=(65536-50000)%256;

        count++;

    if(count==20)     //50毫秒定时,50*20=1000(毫秒)=1秒

    {

       count=0;

       second--;

       if(second==0xff)/*无符号char型数值,-1为:0xff,0之后,显示最大倒计数。*/

       {

         LED1=~LED1;      //这里让LED1反转一下,表现倒计时一周。

         second=MAX_NUM;   //回到最大倒计数值,再次倒计,当然,可以加入其他的控制

       }

         

    }

}


分析:在死循环里,一直重复着以下三个操作

第一:分离second的十位和个位,消隐

第二:十位送到十位

第三:个位送到个位


什么导致second的变化?

答:通过定时器与中断,在定时时间到在中断子程序中改变计数值。


实验有什么问题?

首先硬件连接了8颗LED,这里只用了一颗,动态数码管也没有发挥他的功能,然后在进中断时程序的位置无法确定,不能做到精准倒计时。


如何改进?

使用38译码器可以进一步节省代码,将led改为静态数码管可以记录倒计时次数。


学到了什么?

74HC573可以用来控制动态数码管,38译码器可以节省引脚。



登录icspec成功后,会自动跳转查看全文
博客评论
还没有人评论,赶紧抢个沙发~
发表评论
说明:请文明发言,共建和谐网络,您的个人信息不会被公开显示。