×

51单片机笔记 51单片机学习纪实

51单片机学习纪实:4.3-控制动态数码管向左不间断滚动显示0-7_【增强实验2】

一哥 一哥 发表于2021-12-26 17:06:42 浏览2297 评论0

抢沙发发表评论

实验要求:

控制两组4位一体共阴动态数码管向左不间断滚动显示0-7。


实验思路:

1、动态数码管段选线接P0端口(段选a-dp分别接P0.0-P0.7),宏定义P0端口为SMG_A_DP_PORT。

2、动态数码管位选线接74H138译码器(1-8位分别接Y0-Y7),38译码器数据输入管脚A0、A1、A2分别接P1.0、P1.1、P1.2管脚,使用sbit声明为LSA、LSB、LSC。

3、重定义系统数据类型。定义一个延时函数delay_10us(用于数码管稳定显示数字)

4、定义一个数组变量gsmg_code,用于定义数码管显示0-7的段选码表。段选码表的前8位为“0x00”,用于滚动开始时,字符从第8位数码开始往左滚动。段选码表后8位重复一遍0-7的16进制代码,用以不断滚动显示0-7,而不导致段选线不跑空或溢出段码表。

U8 gsmg_code[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  //段码表前8位0x00,用于控制初始显示时空位状态,不跑乱码。
                0x3F, // 0
                0x06, // 1
                0x5B, // 2
                0x4F, // 3
                0x66, // 4
                0x6D, // 5
                0x7D, // 6
                0x07, // 7
                0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07  //段码表后8位0-7,用于不间断滚动显示0-7
               };

5、定义一个数码管显示函数smg_display(养成模块化程度的习惯,便于后期移植)


完整代码:

/*****************************程序信息*********************************
* 实验名称:控制动态数码管向左不间断滚动显示0-7
* 文件名称:main.c
* 版    本:V1.00
* 日    期:
* 编    著:gefon
* 说    明:使用普中A7开发版,控制两组4位一体动态数码管,向左不间断滚动
            显示数字0-7

*******************************声明区*********************************/
#include "reg52.h"

#define SMG_A_DP_PORT    P0  //重定义P0端口

//定义74HC138数据输入管脚
sbit LSA=P1^0;
sbit LSB=P1^1;
sbit LSC=P1^2;

//重定义系统数据类型
typedef unsigned char U8;
typedef unsigned int U16;

//共阴动态数码管段选码表
U8 gsmg_code[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  //段码表前8位0x00,用于控制初始显示时空位状态,不跑乱码。
                0x3F, // 0
                0x06, // 1
                0x5B, // 2
                0x4F, // 3
                0x66, // 4
                0x6D, // 5
                0x7D, // 6
                0x07, // 7
                0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07  //段码表后8位0-7,用于不间断滚动显示0-7
               };

/*******************************子程序*********************************
* 函 数 名   :delay_10us
* 函数功能   :延时函数,当传入变量ten_us=1时,约延时10us
* 输    入   :ten_us
* 输    出   :无
***********************************************************************/
void delay_10us(U16 ten_us)
{
    while(ten_us--);
}

/*******************************子程序*********************************
* 函 数 名   :smg_display
* 函数功能   :动态数码管显示
* 输    入   :无
* 输    出   :无
***********************************************************************/
void smg_display()
{
    U8 j,i;
    if (j<8)  //段码表前8位为0x00(即熄灭),仅初始滚动前需要。第二次循环时7后面直接显示0,不停滚动。
    {
        for(j=0;j<8;j++)  //动态数码管位选线控制
        {
            for(i=0;i<50;i++)  //控制动态数码管滚动显示速度
            {
                LSC=0;LSB=0;LSA=0;  //38译码器Y0置低电平,动态数码管1显示
                SMG_A_DP_PORT=gsmg_code[j];  delay_10us(100);  SMG_A_DP_PORT=0x00;  //显示完成后,段选线置0x00消隐
                LSC=0;LSB=0;LSA=1;  //38译码器Y1置低电平,动态数码管2显示
                SMG_A_DP_PORT=gsmg_code[j+1];  delay_10us(100);  SMG_A_DP_PORT=0x00;
                LSC=0;LSB=1;LSA=0;  //38译码器Y2置低电平,动态数码管3显示
                SMG_A_DP_PORT=gsmg_code[j+2];  delay_10us(100);  SMG_A_DP_PORT=0x00;
                LSC=0;LSB=1;LSA=1;  //38译码器Y3置低电平,动态数码管4显示
                SMG_A_DP_PORT=gsmg_code[j+3];  delay_10us(100);  SMG_A_DP_PORT=0x00;
                LSC=1;LSB=0;LSA=0;  //38译码器Y4置低电平,动态数码管5显示
                SMG_A_DP_PORT=gsmg_code[j+4];  delay_10us(100);  SMG_A_DP_PORT=0x00;
                LSC=1;LSB=0;LSA=1;  //38译码器Y5置低电平,动态数码管6显示
                SMG_A_DP_PORT=gsmg_code[j+5];  delay_10us(100);  SMG_A_DP_PORT=0x00;
                LSC=1;LSB=1;LSA=0;  //38译码器Y6置低电平,动态数码管7显示
                SMG_A_DP_PORT=gsmg_code[j+6];  delay_10us(100);  SMG_A_DP_PORT=0x00;
                LSC=1;LSB=1;LSA=1;  //38译码器Y7置低电平,动态数码管8显示
                SMG_A_DP_PORT=gsmg_code[j+7];  delay_10us(100);  SMG_A_DP_PORT=0x00;
            }
        }
    }
    for(j=8;j<16;j++)  //动态数码管位选线控制
    {
        for(i=0;i<50;i++)  //控制动态数码管滚动显示速度
        {
            LSC=0;LSB=0;LSA=0;  //38译码器Y0置低电平,动态数码管1显示
            SMG_A_DP_PORT=gsmg_code[j];  delay_10us(100);  SMG_A_DP_PORT=0x00;  //显示完成后,段选线置0x00消隐
            LSC=0;LSB=0;LSA=1;  //38译码器Y1置低电平,动态数码管2显示
            SMG_A_DP_PORT=gsmg_code[j+1];  delay_10us(100);  SMG_A_DP_PORT=0x00;
            LSC=0;LSB=1;LSA=0;  //38译码器Y2置低电平,动态数码管3显示
            SMG_A_DP_PORT=gsmg_code[j+2];  delay_10us(100);  SMG_A_DP_PORT=0x00;
            LSC=0;LSB=1;LSA=1;  //38译码器Y3置低电平,动态数码管4显示
            SMG_A_DP_PORT=gsmg_code[j+3];  delay_10us(100);  SMG_A_DP_PORT=0x00;
            LSC=1;LSB=0;LSA=0;  //38译码器Y4置低电平,动态数码管5显示
            SMG_A_DP_PORT=gsmg_code[j+4];  delay_10us(100);  SMG_A_DP_PORT=0x00;
            LSC=1;LSB=0;LSA=1;  //38译码器Y5置低电平,动态数码管6显示
            SMG_A_DP_PORT=gsmg_code[j+5];  delay_10us(100);  SMG_A_DP_PORT=0x00;
            LSC=1;LSB=1;LSA=0;  //38译码器Y6置低电平,动态数码管7显示
            SMG_A_DP_PORT=gsmg_code[j+6];  delay_10us(100);  SMG_A_DP_PORT=0x00;
            LSC=1;LSB=1;LSA=1;  //38译码器Y7置低电平,动态数码管8显示
            SMG_A_DP_PORT=gsmg_code[j+7];  delay_10us(100);  SMG_A_DP_PORT=0x00;
        }
    }
}

/*******************************主程序*********************************
* 函 数 名   :main
* 函数功能   :主函数
* 输    入   :无
* 输    出   :无
***********************************************************************/
void main()
{
    while(1)
    {
        smg_display();
    }
}


实验分析:

1、段选码表为何前段要加8个0x00,后段为要重复一遍0-7的16进制代码?前面加8个0x00在前面51单片机学习纪实:4.2有说明,后面重复一遍0-7的16进制代码,是为了不间断的滚动显示数字0-7.

2、第一个for循环之所以放在一个if语句内,是为了让前8位的0x00只跑一遍,满足if表达式j<8才会执行第一个for循环。当第一个for循环退出时,执行第二个for循环退出后j=15,j的值是>8的,因此会跳过第一个for,开始执行第二个for循环。第二个for循环初始给j赋值j=8,循环结束后j的值一直是>8。因此会不断的进行跳过第一个for循环,执行第二个for循环的过程。这样就可以做到0-7不间断的滚动显示。

3、为何第二个for循环的判断条是j<16呢?当j=8时,8个数码管依次显示的是0,1,2,3,4,5,6,7。当j=16时,8个数码管依次显示的也是0,1,2,3,4,5,6,7。第二点我们有讲过,第一个for循环只是最开始执行一次,后面都是不断的执行第二个for循环的过程。因此如果判断条件设置成j<17,执行完j=16跳回j=8时,会对0,1,2,3,4,5,6,7有两次显示。视觉上看到的就会是第8个数码管显示的7会时间长一点才再次滚动出现0,就像运行到7卡了一下样。判断条件设置为j<16就不会多显示一次0,1,2,3,4,5,6,7。这样就不会看到7卡一下再显示0,而是自然的过渡到0。

少长咸集

群贤毕至

访客