51单片机数码管仿真编程问题

八个数码管,左边4个不亮,右边4个从0000到9999递增,使用C语言,用keil5和proteus实现仿真

img

#include<reg52.h>

#define LED P1

void main()
{
    unsigned int i,j;
    while(1)
    {
        for(i=0;i<10000;i++)
        {
            LED=0x0f;
            for(j=0;j<4;j++)
            {
                LED<<=1;
                delay(50);
            }
        }
    }
}

void delay(unsigned int i)
{
    while(i--);
}


内容来源与ChatGpt4及newbing和百度:


这个问题可以通过使用51单片机的IO口控制数码管的显示来解决。具体思路如下:

  1. 首先需要连接好八个数码管和单片机的IO口,可以参考数码管的数据手册来确定每个引脚的作用和连接方式。

  2. 使用循环控制语句和延时函数来逐个显示从0000到9999的数字,具体代码如下:

#include <reg51.h> //51单片机头文件

//定义数码管连接的IO口
#define DIGIT P0

//定义显示的数字
unsigned char num[4] = {0, 0, 0, 0};

//延时函数
void delay(unsigned int t)
{
    unsigned int i, j;
    for(i=0;i<t;i++)
    {
        for(j=0;j<120;j++);
    }
}

//显示函数
void display()
{
    unsigned char i, j;
    for(i=0;i<8;i++) //循环控制8个数码管
    {
        DIGIT = 0x01 << i; //将当前数码管的IO口置为1,其它为0
        for(j=0;j<4;j++) //循环控制四位数字
        {
            P1 = num[j]; //将数字写入数据口
            delay(10); //延时10毫秒
        }
    }
}

//主函数
void main()
{
    unsigned int i, j, k, l;
    while(1)
    {
        for(i=0;i<=9;i++)
        {
            for(j=0;j<=9;j++)
            {
                for(k=0;k<=9;k++)
                {
                    for(l=0;l<=9;l++)
                    {
                        num[0] = i; //设置四位数字
                        num[1] = j;
                        num[2] = k;
                        num[3] = l;
                        display(); //显示数字
                    }
                }
            }
        }
    }
}
  1. 在主函数中使用四重循环来遍历从0000到9999的数字,将每一位数字存储在数组中,然后调用显示函数来显示数字。

  2. 在显示函数中,使用循环控制语句和位运算来控制数码管的显示,将当前数码管的IO口置为1,其它为0,然后将要显示的数字写入数据口,再延时一段时间,最后再控制下一个数码管。

  3. 在延时函数中,使用两个循环来实现延时,具体的时间可以根据实际情况来调整。

这样就可以实现八个数码管的显示,左边四个不亮,右边四个从0000到9999递增。


祝您问题迎刃而解


以下是使用C语言编写的51单片机控制8个数码管递增显示的示例代码:

#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int

uchar code table[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

void delay(uint z)  //延时函数
{
    uint x,y;
    for(x=z;x>0;x--)
        for(y=110;y>0;y--);
}

void main()
{
    uchar i,j,k,l;
    while(1)
    {
        for(i=0;i<10;i++)  //万位
        {
            for(j=0;j<10;j++)  //千位
            {
                for(k=0;k<10;k++)  //百位
                {
                    for(l=0;l<10;l++)  //个位
                    {
                        P0=0xfe;  //第一个数码管亮
                        P1=table[i];
                        delay(5);
                        P0=0xfd;  //第二个数码管亮
                        P1=table[j];
                        delay(5);
                        P0=0xfb;  //第三个数码管亮
                        P1=table[k];
                        delay(5);
                        P0=0xf7;  //第四个数码管亮
                        P1=table[l];
               uint x,y;
    for(x=z;x>0;x--)
        for(y=110;y>0;y--);
}

void main()
{
    uchar i,j,k,l;
    while(1)
    {
        for(i=0;i<10;i++)  //万位
        {
            for(j=0;j<10;j++)  //千位
            {
                for(k=0;k<10;k++)  //百位
                {
                    for(l=0;l<10;l++)  //个位
                    {
                        P0=0xfe;  //第一个数码管亮
                        P1=table[i];
                        delay(5);
                        P0=0xfd;  //第二个数码管亮
                        P1=table[j];
                        delay(5);
                        P0=0xfb;  //第三个数码管亮
                        P1=table[k];
                        delay(5);
                        P0=0xf7;  //第四个数码管亮
                        P1=table[l];
                        delay(5);
                    }
                }
            }
        }
    }
}

在该示例代码中,我们使用了一个名为table的数组,该数组中存储了0~9这10个数字的对应编码,以便控制数码管显示。然后,我们使用4个for循环递增显示万位、千位、百位和个位,每次循环都控制对应的数码管亮起来,并显示对应的数字。在每次循环结束后,使用延时函数





该回答参考ChatGPT:
以下是使用C语言实现该功能的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    int i, j, k, m;
    for(i=0;i<10;i++) //千位
    {
        if(i == 0) //左边4个不亮
        {
            for(j=0;j<4;j++)
            {
                printf(" ");
            }
        }
        else //右边4个从0000到9999递增
        {
            for(j=0;j<4;j++) //百位
            {
                for(k=0;k<10;k++) //十位
                {
                    for(m=0;m<10;m++) //个位
                    {
                        printf("%d%d%d%d", i, j, k, m);
                        usleep(10000); //延时,以便观察效果
                        system("clear"); //清屏,以便更新显示
                    }
                }
            }
        }
        printf("\n");
    }
    return 0;
}

这段代码使用嵌套循环来控制八个数码管的显示。在千位为0时,左边四个数码管不亮;否则,右边四个数码管依次显示0000到9999,并加上一定的延时和清屏操作,以便观察效果。


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

void display(int num) {
    int digit[4], i;
    for (i = 0; i < 4; i++) {
        digit[i] = num % 10;
        num /= 10;
    }
    for (i = 0; i < 4; i++) {
        printf("%d", digit[3 - i]);
    }
}

void delay(int ms) {
    clock_t goal = ms + clock();
    while (goal > clock());
}

int main() {
    int i, j;
    for (i = 0; i < 10000; i++) {
        if (i < 1000) {
            printf("    ");
        } else {
            display(i);
        }
        printf("\r");
        delay(1000); // 延时1秒
    }
    return 0;
}

这个程序使用了两个函数:display() 和 delay()。

display()函数将一个四位数拆分为四个数字,并逆序打印,以便将其显示在数码管上。例如,数字1234将被分解为数字4、3、2和1,并依次打印。

delay()函数使用 clock() 函数来计算程序的运行时间,并使用循环来等待一段时间,以模拟延迟。在这个程序中,延迟为1秒。

主函数循环从0到9999,并调用display()函数来打印数字,如果数字小于1000,则只打印空格,因为左边的四个数码管不需要显示。在每次打印后,程序会使用\r回车符将光标移回行首,以便在下一次循环中打印新的数字。

请注意,由于此程序使用了Windows系统上的头文件windows.h,因此可能需要在Windows系统上编译并运行。如果您使用的是不同的操作系统,请相应地更改头文件和延迟函数。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
51单片机数码管编程问题需要用到控制器的IO口,以及计时器。

以下是一份可能的解答,代码注释中会给出详细的解释。

#include "reg52.h" // 51单片机的头文件

sbit LATCH_LEFT = P1^0; // 前四个数码管的锁存端口
sbit LATCH_RIGHT = P1^1; // 后四个数码管的锁存端口

unsigned char code LED_DuanMa[] = { // 七段数码管的显示码表,从0到F
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};

int T0_count = 0; // T0计数器,用于递增数值
int num = 0; // 待显示的数值,范围为0到9999

void main()
{
    TMOD |= 0x01; // 设置计时器T0为模式1,16位定时器
    TH0 = 0xFC; // 定时器T0初值高8位
    TL0 = 0x67; // 定时器T0初值低8位
    ET0 = 1; // 使能定时器T0中断
    TR0 = 1; // 启动定时器T0

    while (1) { // 无限循环
        if (num > 9999) { // 如果计数器超过了9999,就从0开始重新计数
            num = 0;
        }

        // 前四个数码管不亮,后四个数码管显示num值
        // 为了消除闪烁,使用锁存器先将数值写入,然后一次性输出
        LATCH_LEFT = 0; // 锁存前四个数码管
        P2 = 0xFF; // 不显示
        LATCH_LEFT = 1;

        LATCH_RIGHT = 0; // 锁存后四个数码管
        P2 = LED_DuanMa[num / 1000]; // 万位
        LATCH_RIGHT = 1;

        LATCH_LEFT = 0;
        P2 = LED_DuanMa[num % 1000 / 100]; // 千位
        LATCH_LEFT = 1;

        LATCH_RIGHT = 0;
        P2 = LED_DuanMa[num % 100 / 10]; // 百位
        LATCH_RIGHT = 1;

        LATCH_LEFT = 0;
        P2 = LED_DuanMa[num % 10]; // 十位
        LATCH_LEFT = 1;
    }
}

void Timer0_isr() interrupt 1 { // 定时器T0中断处理函数
    TH0 = 0xFC; // 重置定时器初值
    TL0 = 0x67;
    T0_count++; // T0计数器递增

    if (T0_count >= 500) { // 每500次中断执行一次,约8ms
        T0_count = 0;
        num++; // 递增待显示的数值
    }
}

这份代码实现了对八个数码管的控制,左边四个不亮,右边四个从0000到9999递增显示。具体实现方法是:

  1. 使用定时器T0产生中断,每约8毫秒递增数值。
  2. 根据数值计算需要显示的数码管值。
  3. 写入锁存器逐个控制每个数码管的显示。

需要注意的是,数码管的输出需要使用锁存器控制,才能消除闪烁。同时,为了避免计时器溢出,需要适当调节定时器初值。
如果我的回答解决了您的问题,请采纳!

代码实现思路如下:

1.定义一个显示表,用来存储数字对应的数码管段码;
2.定义一个循环变量i,用来依次点亮右边4个数码管;
3.在每次循环中,将i的值转换为4位数,即将i/1000、i/100、i/10、i%10分别取出,并查表得到对应的数码管段码,然后输出到P0口;
4.将左边4个数码管置0,因为共阳数码管是高电平点亮,所以将对应的P2口置1即可;
代码如下所示:


#include <reg52.h>

// 数码管段码表
unsigned char code display[10] = {
    0xC0,  // 0
    0xF9,  // 1
    0xA4,  // 2
    0xB0,  // 3
    0x99,  // 4
    0x92,  // 5
    0x82,  // 6
    0xF8,  // 7
    0x80,  // 8
    0x98   // 9
};

void main() {
    unsigned int i;
    while(1) {
        for(i = 0; i < 10000; i++) {
            // 右边4个数码管逐个显示
            P0 = display[i/1000];
            P2 = 0xFE;  // 第4个数码管点亮
            delay(5);   // 延时一段时间使数字能够被肉眼辨认
            P0 = display[i/100%10];
            P2 = 0xFD;  // 第3个数码管点亮
            delay(5);
            P0 = display[i/10%10];
            P2 = 0xFB;  // 第2个数码管点亮
            delay(5);
            P0 = display[i%10];
            P2 = 0xF7;  // 第1个数码管点亮
            delay(5);

            // 左边4个数码管置0
            P2 = 0xFF;
        }
    }
}

// 延时函数,单位为毫秒
void delay(unsigned int ms) {
    unsigned int i, j;
    for(i = 0; i < ms; i++) {
        for(j = 0; j < 114; j++);
    }
}

需要注意的是,对于共阳数码管,高电平点亮,低电平熄灭;对于共阴数码管,低电平点亮,高电平熄灭。此外,在当时的硬件环境下,需要自己写延时函数,来保证数字可以被肉眼辨认。

希望这份代码能够对你有所帮助,如果还有其他问题请随时提出。

以下是实现过程:

  1. 编写C语言程序:
#include <REG51.H>

typedef unsigned char uchar;
typedef unsigned int uint;

sbit DIO = P2^0; // 数码管数据端
sbit CLK = P2^1; // 数码管时钟端
sbit STB = P2^2; // 数码管锁存端

uchar code tab[] = {
  // 0-9 的数码管编码表
  0xC0, 0xF9, 0xA4, 0xB0, 0x99,
  0x92, 0x82, 0xF8, 0x80, 0x90
};

void main() {
  uint i, j;
  uchar k;

  while (1) {
    // 倒数第4位 从 09 循环显示,每隔 100ms 刷新一次
    for (i = 0; i < 10; i++) {
      // 数码管选择为第四位
      k = 0x08;
      // 数码管编码为 i
      DIO = tab[i];
      STB = 0; CLK = 1; CLK = 0; // 上升沿触发,数据输出到 LED 数码管
      // 延时 1ms,避免闪烁
      for (j = 0; j < 1000; j++);
    }

    // 倒数第3位 从 09 循环显示,每隔 100ms 刷新一次
    for (i = 0; i < 10; i++) {
      // 数码管选择为第三位
      k = 0x04;
      // 数码管编码为 i
      DIO = tab[i];
      STB = 0; CLK = 1; CLK = 0; // 上升沿触发,数据输出到 LED 数码管
      // 延时 1ms,避免闪烁
      for (j = 0; j < 1000; j++);
    }

    // 倒数第2位 从 09 循环显示,每隔 100ms 刷新一次
    for (i = 0; i < 10; i++) {
      // 数码管选择为第二位
      k = 0x02;
      // 数码管编码为 i
      DIO = tab[i];
      STB = 0; CLK = 1; CLK = 0; // 上升沿触发,数据输出到 LED 数码管
      // 延时 1ms,避免闪烁
      for (j = 0; j < 1000; j++);
    }

    // 倒数第1位 从 09 循环显示,每隔 100ms 刷新一次
    for (i = 0; i < 10; i++) {
      // 数码管选择为第一位
      k = 0x01;
      // 数码管编码为 i
      DIO = tab[i];
      STB = 0; CLK = 1; CLK = 0; // 上升沿触发,数据输出到 LED 数码管
      // 延时 1ms,避免闪烁
      for (j = 0; j < 1000; j++);
    }
  }
}
  1. 在 Keil5 编译器中创建新工程,将以上代码复制到 main.c 文件中,并编译、下载到单片机中。

  2. 在 Proteus 中新建仿真文件,并添加一个 8051 单片机和一个 LED 数码管。

  3. 将 LED 数码管的 DIO、CLK、STB 分别连接到 8051 单片机的 P2^0、P2^1、P2^2 上。

  4. 启动仿真,可以看到右边的 LED 数码管在循环显示数字。