×

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

51单片机学习纪实:4.2-控制动态数码管左右滚动显示0-7_【增强实验1】

一哥 一哥 发表于2021-12-22 20:43:05 浏览2498 评论0

抢沙发发表评论

实验要求:

控制两组4位一体动态数码管从左至右滚动显示0-7,然后从右至左滚动显示7-0。


实验思路:

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

2、动态数码管位选线接74HC138译码器控制(简称38译码器),38译码器数据输入管脚A0、A1、A2分别接P1.0、P1.1、P1.2,并用sbit声明为LSA、LSB、LSC。

3、重定义系统数据类型

4、定义一个数组变量gsmg_code,用于定义0-7的段选线码表。

U8 gsmg_code[24]={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
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //段码表后8位置为0x00,用于左右移动时空位熄灭置零
               };

5、定义一个延时函数delay_10us,用于数码管稳定显示字符。

6、定义一个数码管显示函数smg_display(养成良好的编程习惯,模块化更有利于代码移植)


完整代码:

/*****************************程序信息*********************************
* 实验名称:控制动态数码左右滚动显示0-7
* 文件名称:main.c
* 版    本:V1.00
* 日    期:2021-12-22
* 编    著:gefon
* 说    明:使用普中A7开发版,控制两组4位一体数码滚从左至右滚动显示0-7,
            然后从右至左滚动显示7-0

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

#define SMG_A_DP_PORT    P0  //定义动态数码管段选线为P0端口

//定义74HC138D数据输入端口
sbit LSA=P1^0;
sbit LSB=P1^1;
sbit LSC=P1^2;

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

//共阴数码管段选码表
U8 gsmg_code[24]={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
                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //段码表后8位置为0x00,用于左右移动时空位熄灭置零
               };

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

/*******************************子程序*********************************
* 函 数 名   :smg_display
* 函数功能   :动态数码管显示函数
* 输    入   :无
* 输    出   :无
***********************************************************************/
void smg_display()
{
    U8 j=0,i=0;
    for(j=0;j<17;j++)
    {
        //动态数码管字符右移
        for(i=0;i<50;i++)  //变量i表达式2的值,用于控制移动速度
        {
            LSC=1;LSB=1;LSA=1;  //38译码器Y7置低电平,数码管8显示
            SMG_A_DP_PORT=gsmg_code[j]; delay_10us(100); SMG_A_DP_PORT=0x00;  //显示完成后,对SMG_A_DP_PORT置0x00消隐
            LSC=1;LSB=1;LSA=0;  //38译码器Y6置低电平,数码管7显示
            SMG_A_DP_PORT=gsmg_code[j+1]; delay_10us(100); SMG_A_DP_PORT=0x00;
            LSC=1;LSB=0;LSA=1;  //38译码器Y5置低电平,数码管6显示
            SMG_A_DP_PORT=gsmg_code[j+2]; delay_10us(100); SMG_A_DP_PORT=0x00;
            LSC=1;LSB=0;LSA=0;  //38译码器Y4置低电平,数码管5显示
            SMG_A_DP_PORT=gsmg_code[j+3]; delay_10us(100); SMG_A_DP_PORT=0x00;
            LSC=0;LSB=1;LSA=1;  //38译码器Y3置低电平,数码管4显示
            SMG_A_DP_PORT=gsmg_code[j+4]; delay_10us(100); SMG_A_DP_PORT=0x00;
            LSC=0;LSB=1;LSA=0;  //38译码器Y2置低电平,数码管3显示
            SMG_A_DP_PORT=gsmg_code[j+5]; delay_10us(100); SMG_A_DP_PORT=0x00;
            LSC=0;LSB=0;LSA=1;  //38译码器Y1置低电平,数码管2显示
            SMG_A_DP_PORT=gsmg_code[j+6]; delay_10us(100); SMG_A_DP_PORT=0x00;
            LSC=0;LSB=0;LSA=0;  //38译码器Y0置低电平,数码管1显示
            SMG_A_DP_PORT=gsmg_code[j+7]; delay_10us(100); SMG_A_DP_PORT=0x00;
        }
    }
    for(j=23;j>7;j--)
    {
        //动态数码管字符右移
        for(i=0;i<50;i++)  //变量i表达式2的值,用于控制移动速度
        {
            LSC=0;LSB=0;LSA=0;  //38译码器Y0置低电平,数码管1显示
            SMG_A_DP_PORT=gsmg_code[j]; delay_10us(100); SMG_A_DP_PORT=0x00;  //显示完成后,对SMG_A_DP_PORT置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位和后8位要是0x00。当我们数字在滚动的过程中,开始和结束时都会有数字管是要处于熄灭的状态。比如:从左向右滚动时,如果前8位没有0x00,那数字7-0会直接跳出在第1-8号数码管,再开始往右移动。前8位加上0x00,就可以让数字从第1个数码管往右移动。而后面的8位的0x00是为了,当最后一个数字滚动超过第1个数码管后,以保证数码管是熄灭状态。如果后面8位没0x00,当for循环内j的值>8时,无数字显示的数码管会是未知状态,有出现乱码的可能。如:当j=9时,数码管8的值是j+7=9+7=16。而没有后面8位,gsmg_code是没有第16位的,那么数码管的状态就会是未知的。因此这里我们需要给数码管一个状态,以保证程序不乱跑。(从右向左滚动也是同样的道理,只是以我们上面的程序。后8位变成了前8位,前8位变成了后8位)

少长咸集

群贤毕至

访客