动态数码管与独立按键

1.按下复位键,数码管从左到右显示自己的学号后三位
2.按下一个独立按键,数码管间隔一位显示1357。
3.按下一个独立按键,数码管显示最右边数字加一,且蜂鸣器响起。若该到9则清零。

基于Monster 组和GPT的调写:

#include <reg52.h>

sbit btn_reset = P1^0;      // 复位按键
sbit btn_display = P1^1;    // 显示按键
sbit btn_increment = P1^2;  // 数字增加按键
sbit buzzer = P2^3;         // 蜂鸣器

unsigned char seg_code[10] = {
    0x3F,  // 0
    0x06,  // 1
    0x5B,  // 2
    0x4F,  // 3
    0x66,  // 4
    0x6D,  // 5
    0x7D,  // 6
    0x07,  // 7
    0x7F,  // 8
    0x6F   // 9
};

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

void display(unsigned char digit) {
    P0 = seg_code[digit];
    delay(100);
    P0 = 0x00;
}

void main() {
    unsigned char num = 0;

    while(1) {
        if (btn_reset == 0) {  // 复位按键按下
            display(2);  // 显示学号后三位
            display(1);
            display(5);
            delay(1000);
            P0 = 0x00;
        }
        else if (btn_display == 0) {  // 显示按键按下
            display(1);  // 显示 1 3 5 7
            delay(100);
            P0 = 0x00;
            delay(100);
            display(3);
            delay(100);
            P0 = 0x00;
            delay(100);
            display(5);
            delay(100);
            P0 = 0x00;
            delay(100);
            display(7);
            delay(100);
            P0 = 0x00;
        }
        else if (btn_increment == 0) {  // 数字增加按键按下
            num++;
            if (num == 10) {  // 如果数字到达 10,则清零
                num = 0;
            }
            display(num);
            buzzer = 1;  // 蜂鸣器响起
            delay(100);
            buzzer = 0;
            delay(1000);
            P0 = 0x00;
        }
    }
}

用 P0 口控制数码管的显示,使用 P1 口控制按键的输入,使用 P2 口控制蜂鸣器的输出。

在主函数中,使用一个无限循环来不断检测按键的状态。如果复位按键按下,则显示学号后三位;如果显示按键按下,则显示 1 3 5 7;如果数字增加按键按下,则数字加一并显示,同时蜂鸣器响起,如果数字到达 10,则清零。

该回答引用ChatGPT

如果运行报错,可以回复我


#include <reg52.h>
#include <intrins.h>

// 延时函数
void delay(unsigned int x)
{
    while(x--);
}

// 数码管位选函数
void display(unsigned char num)
{
    unsigned char i;
    for(i = 0; i < 8; i++)
    {
        P0 = i;
        P2 = num % 10;
        num /= 10;
        delay(100);
        P2 = 0x0f;  // 关闭数码管
    }
}

void main()
{
    unsigned char num = 123;  // 学号后三位
    unsigned char flag1 = 0;  // 第一个按键标志
    unsigned char flag2 = 0;  // 第二个按键标志
    unsigned char count = 0;  // 计数器

    P1 = 0xff;  // 设置P1口为输入口
    P2 = 0x0f;  // 关闭数码管

    while(1)
    {
        if(P1 != 0xff)  // 检测按键是否按下
        {
            delay(10);  // 延时去抖
            if(P1 != 0xff)  // 确认按键按下
            {
                if(P1 == 0xfe)  // 第一个按键
                {
                    flag1 = ~flag1;
                    flag2 = 0;
                    if(flag1 == 1)  // 间隔一位显示1357
                    {
                        display(1357);
                    }
                    else
                    {
                        P2 = 0x0f;  // 关闭数码管
                    }
                }
                else if(P1 == 0xfd)  // 第二个按键
                {
                    flag1 = 0;
                    flag2 = ~flag2;
                    if(flag2 == 1)  // 最右边数字加一
                    {
                        count++;
                        if(count > 9)
                        {
                            count = 0;  // 清零
                        }
                        P2 = count;
                        // 蜂鸣器响一声
                        P3 |= 0x10;
                        delay(1000);
                        P3 &= ~0x10;
                    }
                    else
                    {
                        P2 = 0x0f;  // 关闭数码管
                    }
                }
            }
        }

        if(flag1 == 0 && flag2 == 0)  // 复位键
        {
            display(num);
        }
    }
}

程序一直处于死循环中,不断检测按键是否按下。如果按下,就根据不同的按键标志位执行不同的操作。复位键执行显示学号后三位的操作,第一个按键执行显示1357的操作,第二个按键执行最右边数字加一并响蜂鸣器的操作。

img

以下答案基于ChatGPT与GISer Liu编写:

下面是一个可以实现你所描述的功能的 C 语言代码。该代码使用了单片机的外部中断和定时器中断,以实现动态数码管显示和独立按键的检测:

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit beep = P1^5;        // 蜂鸣器接口
sbit k1 = P3^2;          // 独立按键1
sbit k2 = P3^3;          // 独立按键2
sbit rst = P3^4;         // 复位按键
sbit dula = P2^6;        // 数码管段选1
sbit wela = P2^7;        // 数码管位选

uchar code duanma[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};   // 共阳极数码管段码表
uchar num1[4] = {0};                                                            // 显示学号后三位
uchar num2[4] = {1, 3, 5, 7};                                                   // 显示 1357
uchar num3[4] = {0};                                                            // 显示计数值
uint cnt = 0;                                                                   // 计数器

// 定时器中断服务函数,每隔 10ms 执行一次
void timer0() interrupt 1 {
    TH0 = 0xFC;             // 重置定时器初值
    TL0 = 0x67;
    cnt++;                  // 增加计数器
    if(cnt >= 100) {        // 计数器达到 100 时清零
        cnt = 0;
        num3[3]++;          // 右数第一位加一
        if(num3[3] > 9) {   // 判断是否需要进位
            num3[3] = 0;
        }
        beep = 1;           // 蜂鸣器响
    }
    if(cnt % 2 == 0) {      // 数码管动态扫描,每隔 20ms 扫描一次
        dula = 1;           // 显示数码管左边一位
        P0 = duanma[num1[3]];
        wela = 0;
        wela = 1;
        dula = 0;           // 显示数码管右边一位
        P0 = duanma[num2[3]];
        wela = 0;
        wela = 1;
        dula = 1;           // 显示数码管左边二位
        P0 = duanma[num3[2]];
        wela = 0;
        wela = 1;
        dula = 0;           // 显示数码管右边二位
        P0 = duanma[num3[3]];
        wela = 0;
        wela = 1;
    }
}

参考GPT和自己的思路,以下是基于STC89C52单片机的C语言示例代码,实现上述动态数码管与独立按键的功能。代码中使用了中断服务函数,需要设置相应的中断向量和优先级。

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

sbit beep=P1^5;  // 定义蜂鸣器输出引脚
sbit KEY1=P3^2;  // 定义按键1输入引脚
sbit KEY2=P3^3;  // 定义按键2输入引脚

uchar code table[]={
  // 数码管显示码表,分别对应数字0~9
  0x3f, 0x06, 0x5b, 0x4f, 0x66,
  0x6d, 0x7d, 0x07, 0x7f, 0x6f
};

uchar num[4]={0, 0, 0, 0};  // 存放数码管的数字

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

void display()  // 数码管显示函数
{
  uchar i;
  for(i=0; i<4; i++)
  {
    P0=table[num[i]];  // 数码管赋值
    P2=0x0f^(1<<i);  // 选择数码管位
    delay(1);  // 稍作延时
    P2=0x0f;  // 关闭数码管
  }
}

void init_timer()  // 定时器初始化函数
{
  TMOD=0x01;  // 定时器0工作在模式1
  TH0=0x3c;  // 定时器初值高8位
  TL0=0xb0;  // 定时器初值低8位
  ET0=1;  // 开启定时器0中断
  EA=1;  // 开启总中断
  TR0=1;  // 启动定时器0
}

void timer0() interrupt 1  // 定时器0中断服务函数
{
  static uchar cnt=0;  // 计数器,用于控制定时周期
  cnt++;
  if(cnt==20)  // 定时周期为20ms
  {
    cnt=0;
    display();  // 数码管显示函数
  }
}

void main()
{
  KEY1=1;  // 初始化按键1输入状态
  KEY2=1;  // 初始化按键2输入状态
  init_timer();  // 定时器初始化

  while(1)
  {
    if(KEY1==0)  // 按键1被按下
    {
      num[0]=6;  // 显示自己的学号后三位,示例为"006"
      num[1]=0;
      num[2]=0;
      num[3]=6;
      delay(1000);  // 稍作延时,防止按键抖动
     

如果对您有帮助,请给与采纳,谢谢。