请选择 进入手机版 | 继续访问电脑版

 找回密码
 立即注册
查看: 738|回复: 1

新手学STC单片机 实验二 动态数码管的显示

[复制链接]
  • TA的每日心情

    2024-1-8 16:35
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    10

    主题

    18

    回帖

    344

    积分

    中级会员

    积分
    344
    发表于 2023-2-28 18:20:26 | 显示全部楼层 |阅读模式
    本帖最后由 sbk100 于 2023-3-1 15:25 编辑

    先上电路

    新手学STC单片机 实验二 动态数码管的显示-1.png


        在本次实验中,采用了 8 位数码管动态扫描显示,其硬件原理图如图 2-1 所示。它将所有数码管的 8 个段线相应的连接到 JP81,程序中我们将 JP81 连接到单片机
    的 P0 口,由 P0 口控制字段输出。而各位数码管的共阴极由单片机的 P1 控制 SL0-SL7 来实现 8 位数码管的位输出控制。

        这样,对于一组数码管动态扫描显示需要由两组信号来控制:一组是用来控制显示的字形,称为段码;另一组用来选择第几位数码管工作,称为位码。

        由于各位数码管的段线是连接到一起的,所以段码的输出对各位数码管来说都是相同的。因此,在同一时刻如果各位数码管的位选线都处于选通状态的话,8位数码管
    将显示相同的字符。若要各位数码管能够显示出与本位相应的字符,就必须采用扫描显示方式。即在某一时刻,只让某一位的位选线处于导通状态,而其它各位的位选线处
    于关闭状态。同时,段线上输出相应位要显示字符的字型码。这样在同一时刻,只有选通的那一位显示出字符,而其它各位则是熄灭的,如此循环下去,就可以使各位数码
    管显示出将要显示的字符。虽然这些字符是在不同时刻出现的,而且同一时刻,只有一位显示,其它各位熄灭,但由于人眼有视觉暂留效应,只要每秒扫描的次数足够多,
    就能看到连续稳定地显示。




        数码管是由 7 个条形的 LED 和右下方一个圆形的 LED 组成,这样一共有 8 个段线,恰好适用于 8 位的并行系统。数码管有共阴极和共阳极两种,共阴极数码管的公共
    阴极接地(如图 2-2),当各段阳极上的电平为“1”时,该段点亮,电平为“0”时,该段熄灭。(本次实验采用共阴极数码管)


    新手学STC单片机 实验二 动态数码管的显示-1.png


        共阳极数码管的公共阳极接+5V,当各段阴极上的电平为“0”时,该段点亮,电平为“1”时,该段熄灭。


    新手学STC单片机 实验二 动态数码管的显示-2.png



        共阴极数码管的字型代码如图 2-4。


    新手学STC单片机 实验二 动态数码管的显示-3.png



    新手学STC单片机 实验二 动态数码管的显示-4.png


        以上的常规编码仅在共阴数码管,且 I/O 口的 0-7 对应数码管的 a-dp 时使用,如果是非常规编码需要将数码管对应的 a-dp 按照 I/O 接口的顺序重新排列,编码
    例如:将 b 与 c 对调。



    I/O 口工作模式
    I/O 口配置
        STC15 系列单片机最多有 46 个 I/O 口:P0.0~P0.7,P1.0~P1.7,P2.0~P2.7,P3.0~P3.7,P4.0~P4.7,P5.0~P5.5。其所有 I/O 口均可由软件配置成 4 种工作类
    型之一,如下表所示。4 种类型分别为:准双向口/弱上拉(标准 8051 输出模式)、推挽输出/强上拉、仅为输入(高阻)或开漏输出功能。每个 I/O 口由 2 个标准寄
    存器中的相应位控制每个引脚的工作类型。STC15 系列单片机的 I/O 口上电复位后准双向/弱上拉(传统 8051 的 I/O 口)模式。每个 I/O 口驱动能力均可达到 20mA,
    但 40-pin 及 40-pin 以上单片机的整个芯片最大不要超过 120mA,20-pin 以上及32-pin 以下(含 32)单片机的整个芯片不要超过 90mA。
    例:P0 口设定<P0.0~P0.7>(P0 口地址:80H)
    新手学STC单片机 实验二 动态数码管的显示-1.png

    举例:MOV P0M1,#10100000B
    P0.7 为开漏,P0.6 为强推挽输出,P0.5 为高阻输入,其他为准双向口。


    实验测试
    连接:
    P0 端口接动态数码管的段选 JP81
    P1 端口接动态数码管的位选 JP82
    实验现象:8 位数码管上分别显示 0-7 数字


    /************************************************
    * * 程序功能:动态数码管的显示
    * * 接线说明:P0端口接动态数码管的段选JP81
    *            P1端口接动态数码管的位选JP82
    * * 实验现象:8位数码管上分别显示0-7数字
    * *************************************************/
    #include "hal.h"
    #define DataPort P0
    #define PosPort P1
    //数码管字形表,供显示时查询
    uchar code disptable[18]=
    { //定义表格一定要使用code,这样会做到程序存储区中
        0x3F, //"0"的字形表,0B00111111
        0x06, //"1"的字形表,0B00000110
        0x5B, //"2"的字形表,0B01011011
        0x4F, //"3"的字形表,0B01001111
        0x66, //"4"的字形表,0B01100110
        0x6D, //"5"的字形表,0B01101101
        0x7D, //"6"的字形表,0B01111101
        0x07, //"7"的字形表,0B00000111
        0x7F, //"8"的字形表,0B01111111
        0x6F, //"9"的字形表,0B01101111
        0x77, //"A"的字形表,0B01110111
        0x7c, //"b"的字形表,0B01111100
        0x39, //"C"的字形表,0B00111001
        0x5e, //"d"的字形表,0B01011110
        0x79, //"E"的字形表,0B01111001
        0x71, //"F"的字形表,0B01110001
        0x00 // 全灭消隐
    };

    /*共阴数码管位选编码*/
    uchar code Position[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
    uchar dos =0; //数码管位选
    uchar dis_1ms_ok = 0; //扫描标志位
    /*******************************************************
    * //函数名称:Timer0Init()
    * //函数功能:定时器0初始化函数 1毫秒@12MHz
    * //入口参数:无
    * //返回参数:无
    * ********************************************************/
    void Timer0Init(void)
    {
        TIMER_CLK_DIV(0,1); //设置定时器0时钟12T模式
        TIMER_TIME(0); //设置定时器0定时模式
        TIMER_MODE(0,0); //设置定时器0模式0
        TL0 = 0x18; //设置定时初值
        TH0 = 0xFC; //设置定时初值
        CLR_TIMER_FLAG(0); //清除TF0标志
    }
    /*******************************************************
      * 函数名称:Timer0_ISR()
      * 函数功能:定时器0中断服务程序
      * 入口参数:无
      * 返回参数:无
      * ********************************************************/
    void Timer0_ISR() interrupt T0_VECTOR using 1
    {
         dis_1ms_ok = 1; //扫描时间1ms到
    }

    /*******************************************************
    * 函数名称:dispaly()
    * 函数功能:数码管动态扫描显示0-7
    * 入口参数:无
    * 返回参数:无
    * ********************************************************/
    void display()
    {
        PosPort = 0xff;//消隐
        DataPort = disptable[dos];//送数据段
        PosPort = Position[dos]; //送位选
        dos++;
        if(dos>=8) //判断位选是否超过8
        {
            dos=0; //清零
        }
    }
        数码管显示子程序:首先为消除上一位显示对当前显示的影响,先在位码上输出全 0,完成消隐。然后输出当前显示位的段码和位码完成一位的显示。轮流显示
    8 位数码管,就可以完成 8位数码管的显示。为了无闪烁并且亮度足够需要每个 LED灯每秒至少点亮 25 次,并采用推挽输出模式。这里我们每位点亮 1ms,即8位扫描
    完一次需要 8ms,1s 扫描 125 次。
    void main()
    {
        IO_PORT_SET(0,0xff, IO_OUT);//P0口设置为推挽输出
        Timer0Init(); //定时器0的初始化
        TIMER_INT_EN(0,ON); //开启定时器0中断
        INT_GLOBAL_ENABLE(ON); //开启全局中断
        TIMER_RUN(0,START); //定时器0开始计时
        while(1)
        {
           if(dis_1ms_ok)
           {
               dis_1ms_ok = 0;
               display();
           }
        }
    }





    回复 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 10:22
  • 签到天数: 86 天

    [LV.6]常住居民II

    68

    主题

    539

    回帖

    1788

    积分

    超级版主

    积分
    1788
    QQ
    发表于 2023-3-1 15:41:34 | 显示全部楼层
    很棒!精神可嘉,官方必须送个实验箱,期待更多笔记给新人们分享
    热线19952583534
    www.STCAI.com
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-4-17 00:12 , Processed in 0.087396 second(s), 36 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表