stc89c52实现以下程序

大概就是在矩阵键盘输入4个数字到数码管上,然后数字再按照一定的规律进行动态变化。
可有偿代写,难度不大,stc89c52的板子

img


#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int

sbit D1 = P2^0;
sbit D2 = P2^1;
sbit D3 = P2^2;
sbit D4 = P2^3;

uchar code num[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};

void delay(uint x)
{
    uint i, j;
    for(i=x; i>0; i--)
        for(j=110; j>0; j--);
}

void display(uchar i, uchar n)
{
    switch(i)
    {
        case 1:
            D1 = 0; D2 = 1; D3 = 1; D4 = 1;
            P0 = num[n%10];
            break;
        case 2:
            D1 = 1; D2 = 0; D3 = 1; D4 = 1;
            P0 = num[n/10%10];
            break;
        case 3:
            D1 = 1; D2 = 1; D3 = 0; D4 = 1;
            P0 = num[n/100%10];
            break;
        case 4:
            D1 = 1; D2 = 1; D3 = 1; D4 = 0;
            P0 = num[n/1000%10];
            break;
        default:
            break;
    }
}

void main()
{
    uchar i, j, k, l, n1, n2, n3, n4;
    P0 = 0;
    while(1)
    {
        for(i=1; i<=4; i++)
        {
            for(j=0; j<10; j++)
            {
                for(k=0; k<10; k++)
                {
                    for(l=0; l<10; l++)
                    {
                        n1 = num[j];
                        n2 = num[k];
                        n3 = num[l];
                        n4 = num[j];
                        display(1, n1);
                        delay(2);
                        display(2, n2);
                        delay(2);
                        display(3, n3);
                        delay(2);
                        display(4, n4);
                        delay(2);
                    }
                }
            }
        }
    }
}

这里使用了一个数组num来存储数字0到9的七段码值。在display函数中,根据传入的参数i来选择哪个数码管进行显示,根据传入的参数n来选择显示哪个数字。在main函数中,使用四层循环来遍历所有的数字组合,每次调用display函数来显示四个数字。由于循环比较多,因此需要设置一些延时来控制数码管的刷新速度。

以下是使用C语言编写的滚动显示数字的代码示例,适用于STC89C52单片机:

#include <reg52.h>

#define DISPLAY_DELAY 1

// 定义数码管段选和位选引脚
sbit digit1 = P1^0;
sbit digit2 = P1^1;
sbit digit3 = P1^2;
sbit digit4 = P1^3;

sbit segmentA = P2^4;
sbit segmentB = P2^5;
sbit segmentC = P2^6;
sbit segmentD = P2^7;

// 数码管段选码表
unsigned char code segmentCode[] = {
    0x3F,   // 0
    0x06,   // 1
    0x5B,   // 2
    0x4F,   // 3
    0x66,   // 4
    0x6D,   // 5
    0x7D,   // 6
    0x07,   // 7
    0x7F,   // 8
    0x6F    // 9
};

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

// 数码管显示函数
void displayNumber(unsigned int num) {
    unsigned char i;
    unsigned char digitValue[4];

    // 分离数字的每一位
    digitValue[0] = num % 10;
    digitValue[1] = (num / 10) % 10;
    digitValue[2] = (num / 100) % 10;
    digitValue[3] = (num / 1000) % 10;

    // 数码管滚动显示
    for(i = 0; i < 4; i++) {
        // 逐个位选,显示对应数字
        digit1 = i == 0;
        digit2 = i == 1;
        digit3 = i == 2;
        digit4 = i == 3;

        // 设置段选,显示对应数字
        P2 = segmentCode[digitValue[i]];

        // 延时一段时间,控制滚动速度
        delay(DISPLAY_DELAY);
    }
}

void main() {
    unsigned int inputNumber = 2761;  // 输入的数字
    unsigned int tempNumber;
    unsigned char i;

    while(1) {
        tempNumber = inputNumber;

        // 循环滚动显示数字
        for(i = 0; i < 8; i++) {
            displayNumber(tempNumber);

            // 每次滚动将数字右移一位
            tempNumber = (tempNumber / 10) + ((tempNumber % 10) * 1000);

            // 延时一段时间,控制滚动速度
            delay(DISPLAY_DELAY);
        }
    }
}

这段代码使用STC89C52单片机控制4位共阳数码管进行滚动显示输入的数字。你可以根据需要修改inputNumber变量来输入不同的数字,并通过DISPLAY_DELAY常量调整滚动速度。代码中包含详细的注释,以帮助理解每一行代码的作用和功能。请注意,该代码仅供参考,你可能需要根据自己的硬件接口和需求进行适当的修改和调整。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7717872
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:基于STC89C52单片机的多功能智能清洁小车设计
  • 除此之外, 这篇博客: STC89C52单片机数码管介绍以及代码示例中的 其次,我们对多个引脚管进行说明: 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    在这里的显示方式我们简单的归纳为这么几步:位选 段选 清零 位选 段选 清零

    首先说明什么是扫描数码管,我们发现,数码管在构造时为了节省端口(单片机就40个引脚,不能全用来显示数码管吧,嘿嘿)把一排的数码管端口都共用了,所以为了同时显示四个数字,我们是不是得这样:

    1,先在DIG1,DIG2,DIG3,DIG4,选一个

    2,在端口用二进制代码或者十六进制代码显示我们想要显示的字符

    3,最后将端口清零,就是全灭,因为端口是共用的,所以这样可以避免扫描过快时,第二个位置也显示相同的字符;

    最后利用定时器以很快地速度重复这三个步骤,就可以实现数码管的扫描操作了

    然后我们之前解释的显示方式就一一对应了即1就表示位选,2就表示段选,3,就表示清零。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

#include<reg52.h>
#define DataPort P0
sbit we=P2^7;
sbit du=P2^6;
unsigned char code digit[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char irtime;
bit irpro_ok,ir_ok;
unsigned char IRcode[4],IRdata[33];

void TIME0init(void)
{
    TMOD=0x02;
    TH0=0x00;
    TL0=0x00;
    ET0=1;
    TR0=1;    
}

void EX0init()
{
     IT0=1;
    EX0=1;
    EA=1;
}

void TIME0_interrupt(void) interrupt 1 using 1
{
    irtime++;
}

void EX0_interrupt(void) interrupt 0
{
     static unsigned char i;          //接收第几次红外信号处理
    static bit startflag;          //是否开始处理

    if(startflag)
    {
        if(irtime>40&&irtime<60)
             i=0;
        IRdata[i]=irtime;
        irtime=0;
        i++;
        if(i==33)
        {
             ir_ok=1;
            startflag=0;
        }    
    }
    else
    {
         irtime=0;
        startflag=1;
    }
}  

void Ir_work(void)
{
    if (IRcode[0]==0x00&&IRcode[1]==0xFF)
    {
                   switch(IRcode[2])//客户码:00FF
        {
            case 0x45:break;
            case 0x46:break;
            case 0x47:break;
            case 0x44:break;
            case 0x40:break;
            case 0x43:break;
            case 0x07:break;
            case 0x15:break;
            case 0xD9:break;
            case 0x16:DataPort=digit[0];break;
            case 0x19:break;
            case 0x0D:break;

            case 0x0C:DataPort=digit[1];break;
            case 0x18:DataPort=digit[2];break;
            case 0x5E:DataPort=digit[3];break;
            case 0x08:DataPort=digit[4];break;
            case 0x1C:DataPort=digit[5];break;
            case 0x5A:DataPort=digit[6];break;
            case 0x42:DataPort=digit[7];break;
            case 0x52:DataPort=digit[8];break;
            case 0x4A:DataPort=digit[9];break;
            default:break;
        }
    }
}

void Ircodepro(void)
{
    unsigned char i, j, k;
    unsigned char cord,value;
    
    k=1;
    for(i=0;i<4;i++)      //处理4个字节
     {
      for(j=1;j<=8;j++) //处理1个字节8位
         {
          cord=IRdata[k];
          if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
             value|=0x80;
          if(j<8)
            {
             value>>=1;
            }
           k++;
         }
     IRcode[i]=value;
     value=0;     
     } 
     irpro_ok=1;//处理完毕标志位置1
}

void main(void)
{
    EX0init();
    TIME0init();
    we=1;
    DataPort=0xFE;
    we=0;
    du=1;

    while(1)
    {
        if(ir_ok)
        {
            Ircodepro();
            ir_ok=0;
        }

        if(irpro_ok)
        {
             Ir_work();
            irpro_ok=0;
        }
    }

}

示例程序

#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int

uchar KeySta[4] = {0xff, 0xff, 0xff, 0xff}; //初始化键盘状态
uchar KeyValue[16] = {
    0xc, 0x9, 0x3, 0x1,
    0xd, 0xa, 0x6, 0x2,
    0xe, 0xb, 0x7, 0x4,
    0xf, 0x0, 0x8, 0x5,
}; //键值映射表
uchar DispVal[4] = {0, 0, 0, 0}; //初始化数码管显示值
uchar DispPos = 0; //数码管显示位置

//延时函数
void Delay(uint i)
{
    while(i--);
}

//矩阵键盘扫描函数
uchar KeyScan()
{
    uchar i, j;
    uchar keyvalue = 0xff;
    for(i=0; i<4; i++)
    {
        P1 = 0x0f;
        KeySta[i] = (P1 & 0xf0) | 0x0f;
        for(j=0; j<4; j++)
        {
            if(KeySta[i] == KeyValue[i*4+j])
            {
                keyvalue = KeySta[i]; //获取键值
            }
        }
        P1 = 0xf0;
        KeySta[i] = (P1 & 0x0f) | 0xf0;
        for(j=0; j<4; j++)
        {
            if(KeySta[i] == KeyValue[i*4+j])
            {
                keyvalue = KeySta[i]; //获取键值
            }
        }
    }
    return keyvalue;
}

//数码管扫描函数
void ScanDisp()
{
    uchar i, j;
    uint tmp;
    uchar code disptable[] = { //数码管段选表
        0xc0, 0xf9, 0xa4, 0xb0,
        0x99, 0x92, 0x82, 0xf8,
        0x80, 0x90, 0x88, 0x83,
        0xc6, 0xa1, 0x86, 0x8e,
    };
    tmp = DispVal[DispPos]; //获取当前位置的数值
    for(i=0; i<8; i++)
    {
        j = tmp % 10;
        tmp /= 10;
        P0 = 0xff;
        P2 = disptable[j];
        Delay(100); //延时一段时间,保证数码管显示稳定
        P2 = 0x00;
        Delay(100);
    }
}

//主函数
void main()
{
    while(1)
    {
        uchar keyvalue = KeyScan(); //获取键值
        if(keyvalue != 0xff) //判断是否有按键按下
        {
            DispVal[DispPos] = keyvalue & 0x0f; //将键值添加到数码管显示值中
            DispPos++; //更新显示位置
            if(DispPos == 4)
            {
                DispPos = 0; //如果显示的位置超过4,则重新从位置0开始显示
            }
        }
        ScanDisp(); //进行数码管扫描
    }
}

电路图呢?

#include <reg51.h>

// 定义4位数码管的端口连接
sbit digit1 = P2^0;
sbit digit2 = P2^1;
sbit digit3 = P2^2;
sbit digit4 = P2^3;

// 定义4x4矩阵键盘的端口连接
sbit col1 = P0^0;
sbit col2 = P0^1;
sbit col3 = P0^2;
sbit col4 = P0^3;
sbit row1 = P0^4;
sbit row2 = P0^5;
sbit row3 = P0^6;
sbit row4 = P0^7;

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

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

// 读取键盘输入函数
unsigned char getKey() {
    unsigned char key = 0xFF;
    unsigned char col = 0xFF;

    col1 = 0;
    col2 = 1;
    col3 = 1;
    col4 = 1;
    if(row1 == 0) {
        key = 1;
        col = 1;
    }
    else if(row2 == 0) {
        key = 4;
        col = 1;
    }
    else if(row3 == 0) {
        key = 7;
        col = 1;
    }
    else if(row4 == 0) {
        key = 10;
        col = 1;
    }

    col1 = 1;
    col2 = 0;
    col3 = 1;
    col4 = 1;
    if(row1 == 0) {
        key = 2;
        col = 2;
    }
    else if(row2 == 0) {
        key = 5;
        col = 2;
    }
    else if(row3 == 0) {
        key = 8;
        col = 2;
    }
    else if(row4 == 0) {
        key = 0;
        col = 2;
    }

    col1 = 1;
    col2 = 1;
    col3 = 0;
    col4 = 1;
    if(row1 == 0) {
        key = 3;
        col = 3;
    }
    else if(row2 == 0) {
        key = 6;
        col = 3;
    }
    else if(row3 == 0) {
        key = 9;
        col = 3;
    }
    else if(row4 == 0) {
        key = 11;
        col = 3;
    }

    col1 = 1;
    col2 = 1;
    col3 = 1;
    col4 = 0;
    if(row1 == 0) {
        key = 12;
        col = 4;
    }
    else if(row2 == 0) {
        key = 13;
        col = 4;
    }
    else if(row3 == 0) {
        key = 14;
        col = 4;
    }
    else if(row4 == 0) {
        key = 15;
        col = 4;
    }

    return (key + col - 1);
}

void main() {
    unsigned char digit1Val = 0;
    unsigned char digit2Val = 0;
    unsigned char digit3Val = 0;
    unsigned char digit4Val = 0;

    while(1) {
        unsigned char key = getKey();

        if(key >= 1 && key <= 9) {
            // 更新数码管的值
            digit4Val = digit3Val;
            digit3Val = digit2Val;
            digit2Val = digit1Val;
            digit1Val = key;
        }
        else if(key == 0) {
            // 清空数码管的值
            digit1Val = 0;
            digit2Val = 0;
            digit3Val = 0;
            digit4Val = 0;
        }
        else if(key == 12) {
            // 向左移动数码管的值
            unsigned char temp = digit1Val;
            digit1Val = digit2Val;
            digit2Val = digit3Val;
            digit3Val = digit4Val;
            digit4Val = temp;
        }
        else if(key == 13) {
            // 向右移动数码管的值
            unsigned char temp = digit4Val;
            digit4Val = digit3Val;
            digit3Val = digit2Val;
            digit2Val = digit1Val;
            digit1Val = temp;
        }

        // 在数码管上显示值
        digit1 = 1;
        P1 = segTable[digit1Val];
        digit1 = 0;
        delay(5);

        digit2 = 1;
        P1 = segTable[digit2Val];
        digit2 = 0;
        delay(5);

        digit3 = 1;
        P1 = segTable[digit3Val];
        digit3 = 0;
        delay(5);

        digit4 = 1;
        P1 = segTable[digit4Val];
        digit4 = 0;
        delay(5);
    }
}