三位共阴数码管动态显示按键控制加减

      用这个软件也有一两个月了,学习了很多大神的教程代码,让我飞速的进步学习了解电子科技的知识,现在我也想回报大家,慢慢写文章发布我所了解的项目的教程,尽可能写简单通俗,让大部分初学者都能看懂。

fc78c0a185b14f04a4c3086ca15227dc.jpg

 买这东东将近一个月了,工作忙一直没机会学习,就前两天开始研究学习,先从一位的开始学起,就8个引脚,7个分段灯管1个小数点。从0到9我发现很简单就学成了。然后我开始自己设计三位的,我发现这些阳极的引脚都是连通的,只有3个共阴极,我给他们都通GND时个位十位百位上的数字是同步跳动的,从0到9。如下图2eae2aa7552a4a04a3d302c4f8c391a9.jpg

       我试着断开其中十位或者百位的引脚,这时候该位上的数码管不亮,但是用自己设计的程序还是无法使个位十位百位的数分开显示,他们始终是同步的,然后我就去学习两位的数码管动态显示,这下我终于搞明白其中的原理了,让不同位上的数同时闪烁,放闪烁的间隔达到50赫兹(一秒钟闪50下)或者以上的时候,人眼就识别不出来他是闪动的,然后我就根据大佬的代码自行增添了一位百位的编程,然后把代码设计成按键控制加减数,这样自己控制加减进退位感觉更酷也更舒服。基于现在博客还没有大佬发三位共阴数码管的教程,请允许我在这里献上鄙人的拙见。

      首先我们得让他能同时显示三个位的数,并且把显示间隔调成10ms以内,这样肉眼是看不见他的闪动,然后再进行按键设置,外接三个按键,一端分别连接A0A1和A2,另一端都连接gnd。不熟悉按键读取的先学习上拉电阻和上拉输入,将A0A1和A2引脚设置成上拉输入模式后,默认就是接入低电流的高电平,按下按键后读取的就是低电平。根据这个原理可以设计我们的加减分机制。轻触开关的说明和三位共阴数码管的硬件接线图都放下方了

caa224d4d2fa4bbeb5ccba6f6f0fe6f3.jpg

1fb920a1f9374e4a97d1ab738a603432.jpg

 连接好线路后就是这个样子的

296b52fe1f35471eaba3440d3b4dad93.jpg

 左边的按键控制加分,中间的控制清零,右边的控制减分。其中包含了个位十位满十进一,百位满十归零;百位大于0,十位负一百位退一;十位大于0,个位负一十位退一;百位十位均为0,个位负一全部归零的逻辑机制,本人文科生可以自己设计了一下午才完成具体可以看以下代码,个人感觉很精妙,能有鲁班百分之一的巧夺天工技艺吧😌

三位共阴数码管

void gwluoji() { //个位逻辑

  if (g == 10) {

    s++;

    g = 0; //个位满十,十位进一,个位归零

  } else if (g == -1 && s > 0) {

    s--;

    g = 9; //个位负一,十位大于0则退一

  } else if (g == -1 && s == 0 && b == 0) {

    g = 0;

    s = 0; //十位百位均为0,个位负一则均为0(000再减还是显示0)

  }

}

//个位逻辑说明

void swluoji() { //十位逻辑

  if (s == 10) {

    b++;

    s = 0; //十位满十,百位进一,十位归零

  } else if (b > 0 && s == -1) {

    b--;

    s = 9; //百位大于0,十位负一,百位退一

  }

}

//十位逻辑说明

void bwluoji() { //百位逻辑

  if (b == 10) {

    g = 0;

    s = 0;

    b = 0; //百位满十,个十百位归零(数值到达999,再加分后回到000)

  } else if (g == -1 && s == 0 && b > 0) {

    b--;

    s = 9;

    g = 9; //百位大于0,十位为0,个位负一则百位减一,个位十位归9

  }

}

//百位逻辑说明

这些是逻辑代码,不可直接套用,下面献上完整代码,硬件部分按以上图片接,下面就可以直接上传到板子上使用了。

//三位数码管按键控制增减分

/*建立数组num

num[10][8]其中[10]表示在num数组里面有0~9共10个数列,

[8]表示每一个数列里面有8个位,每一位的数字都不一样,

0代表低电平,1代表高电平,我用的数码管是共阴的,所以只有当高电平时,

数码管对应的灯会亮

*/

int num[10][8] = {

  { 1, 1, 1, 1, 1, 1, 0, 0 }, //数字0

  { 0, 1, 1, 0, 0, 0, 0, 0 }, //数字1

  { 1, 1, 0, 1, 1, 0, 1, 0 }, //数字2

  { 1, 1, 1, 1, 0, 0, 1, 0 }, //数字3

  { 0, 1, 1, 0, 0, 1, 1, 0 }, //数字4

  { 1, 0, 1, 1, 0, 1, 1, 0 }, //数字5

  { 1, 0, 1, 1, 1, 1, 1, 0 }, //数字6

  { 1, 1, 1, 0, 0, 0, 0, 0 }, //数字7

  { 1, 1, 1, 1, 1, 1, 1, 0 }, //数字8

  { 1, 1, 1, 1, 0, 1, 1, 0 }, //数字9

};

int g = 0; //定义g为个位变量的值初始化变量为0

int s = 0; //定义s为十位变量的值初始化变量为0

int b = 0; //定义b为百位变量的值初始化变量为0



void setup() //引脚初始化

{

  pinMode(A2, INPUT_PULLUP);//定义A2引脚为上拉输入模式

  pinMode(A1, INPUT_PULLUP);//定义A1引脚为上拉输入模式

  pinMode(A0, INPUT_PULLUP);//定义A0引脚为上拉输入模式

  pinMode(10, OUTPUT); //定义10号引脚为输出模式,用来控制十位公共端供电

  pinMode(11, OUTPUT); //定义11号引脚为输出模式,用来控制个位公共端供电

  pinMode(12, OUTPUT); //定义12号引脚为输出模式,用来控制百位公共端供电

  Serial.begin(9600); //波特率设置9600

  pinMode(2, OUTPUT); //定义2号引脚为输出模式

  pinMode(3, OUTPUT); //定义3号引脚为输出模式

  pinMode(4, OUTPUT); //定义4号引脚为输出模式

  pinMode(5, OUTPUT); //定义5号引脚为输出模式

  pinMode(6, OUTPUT); //定义6号引脚为输出模式

  pinMode(7, OUTPUT); //定义7号引脚为输出模式

  pinMode(8, OUTPUT); //定义8号引脚为输出模式

  pinMode(9, OUTPUT); //定义9号引脚为输出模式

}

void bai() //百位显示的子程序

{

  digitalWrite(12, LOW); //百位公共端通电

  digitalWrite(10, HIGH); //个位公共端断电

  digitalWrite(11, HIGH); //十位公共端断电

  digitalWrite(2, num[b][0]); //2号引脚显示数组里第s个数列里面abcdefgh中的a的值,也就是0这个位的值

  digitalWrite(3, num[b][1]); //3号引脚显示数组里第s个数列里面abcdefgh中的b的值,也就是1这个位的值

  digitalWrite(4, num[b][2]); //4号引脚显示数组里第s个数列里面abcdefgh中的c的值,也就是2这个位的值

  digitalWrite(5, num[b][3]); //5号引脚显示数组里第s个数列里面abcdefgh中的d的值,也就是3这个位的值

  digitalWrite(6, num[b][4]); //6号引脚显示数组里第s个数列里面abcdefgh中的e的值,也就是4这个位的值

  digitalWrite(7, num[b][5]); //7号引脚显示数组里第s个数列里面abcdefgh中的f的值,也就是5这个位的值

  digitalWrite(8, num[b][6]); //8号引脚显示数组里第s个数列里面abcdefgh中的g的值,也就是6这个位的值

  digitalWrite(9, num[b][7]); //9号引脚显示数组里第s个数列里面abcdefgh中的h的值,也就是7这个位的值

  delay(5);                    

}

void shi() //十位显示的子程序

{

  digitalWrite(12, HIGH); //百位公共端断电

  digitalWrite(10, HIGH); //个位公共端断电

  digitalWrite(11, LOW); //十位公共端通电

  digitalWrite(2, num[s][0]); //2号引脚显示数组里第s个数列里面abcdefgh中的a的值,也就是0这个位的值

  digitalWrite(3, num[s][1]); //3号引脚显示数组里第s个数列里面abcdefgh中的b的值,也就是1这个位的值

  digitalWrite(4, num[s][2]); //4号引脚显示数组里第s个数列里面abcdefgh中的c的值,也就是2这个位的值

  digitalWrite(5, num[s][3]); //5号引脚显示数组里第s个数列里面abcdefgh中的d的值,也就是3这个位的值

  digitalWrite(6, num[s][4]); //6号引脚显示数组里第s个数列里面abcdefgh中的e的值,也就是4这个位的值

  digitalWrite(7, num[s][5]); //7号引脚显示数组里第s个数列里面abcdefgh中的f的值,也就是5这个位的值

  digitalWrite(8, num[s][6]); //8号引脚显示数组里第s个数列里面abcdefgh中的g的值,也就是6这个位的值

  digitalWrite(9, num[s][7]); //9号引脚显示数组里第s个数列里面abcdefgh中的h的值,也就是7这个位的值

  delay(5);                   

}

void ge() //个位显示的子程序

{

  digitalWrite(12, HIGH); //百位公共端断电

  digitalWrite(11, HIGH); //十位公共端断电

  digitalWrite(10, LOW); //个位公共端通电

  digitalWrite(2, num[g][0]); //2号引脚显示数组里第g个数列里面abcdefgh中的a的值,也就是0这个位的值

  digitalWrite(3, num[g][1]); //3号引脚显示数组里第g个数列里面abcdefgh中的b的值,也就是1这个位的值

  digitalWrite(4, num[g][2]); //4号引脚显示数组里第g个数列里面abcdefgh中的c的值,也就是2这个位的值

  digitalWrite(5, num[g][3]); //5号引脚显示数组里第g个数列里面abcdefgh中的d的值,也就是3这个位的值

  digitalWrite(6, num[g][4]); //6号引脚显示数组里第g个数列里面abcdefgh中的e的值,也就是4这个位的值

  digitalWrite(7, num[g][5]); //7号引脚显示数组里第g个数列里面abcdefgh中的f的值,也就是5这个位的值

  digitalWrite(8, num[g][6]); //8号引脚显示数组里第g个数列里面abcdefgh中的g的值,也就是6这个位的值

  digitalWrite(9, num[g][7]); //9号引脚显示数组里第g个数列里面abcdefgh中的h的值,也就是7这个位的值

  delay(5);                    

}

void gwluoji() { //个位逻辑

  if (g == 10) {

    s++;

    g = 0; //个位满十,十位进一,个位归零

  } else if (g == -1 && s > 0) {

    s--;

    g = 9; //个位负一,十位大于0则退一

  } else if (g == -1 && s == 0 && b == 0) {

    g = 0;

    s = 0; //十位百位均为0,个位负一则均为0(000再减还是显示0)

  }

}

//个位逻辑说明

void swluoji() { //十位逻辑

  if (s == 10) {

    b++;

    s = 0; //十位满十,百位进一,十位归零

  } else if (b > 0 && s == -1) {

    b--;

    s = 9; //百位大于0,十位负一,百位退一

  }

}

//十位逻辑说明

void bwluoji() { //百位逻辑

  if (b == 10) {

    g = 0;

    s = 0;

    b = 0; //百位满十,个十百位归零(数值到达999,再加分后回到000)

  } else if (g == -1 && s == 0 && b > 0) {

    b--;

    s = 9;

    g = 9; //百位大于0,十位为0,个位负一则百位减一,个位十位归9

  }

}

//百位逻辑说明

void clear() { //清除机制

  int z = digitalRead(A2); //将读取到A2引脚的数值赋值给z

  if (z == 0) {                    

    g = 0;

    s = 0;

    b = 0; //如果z的值为0,则个十百位归零

  }

}

//清除机制

void big() { //加分机制

  int y = digitalRead(A1); //将读取到A1引脚的数值赋值给y

  if (y == 0) {

    delay(5);

    g++; //如果y的值为0,则个位进一

  }

}

//加分机制

void small() { //减分机制

  int x = digitalRead(A0); //将读取到A0引脚的数值赋值给x

  if (x == 0) { 

    delay(5);

    g--; //如果x的值为0,则个位退一

  }

}

//减分机制

void loop() //主程序一直循环

{

  ge(); //调用个位子程序显示

  shi(); //调用十位子程序显示

  bai(); //调用百位子程序显示

  big(); //加分机制

  clear(); //清除机制

  small(); //减分机制

  gwluoji(); //个位逻辑

  swluoji(); //十位逻辑

  bwluoji(); //百位逻辑

}

以上就是完整代码了,如果有什么问题欢迎留言批评指正,我随时都有空哈😜对了最后附上成品视频(视频不知道怎么上传,尴尬)

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
使用矩阵按键控制数码管需要使用到微控制器或者单片机。以下是一种可能的实现步骤: 1. 连接数码管和矩阵按键到微控制器或单片机上。 2. 设置数码管的引脚为输出模式,设置矩阵按键的引脚为输入模式。 3. 初始化数码管和矩阵按键的引脚状态。 4. 在主循环中,检测矩阵按键的状态,如果有按键按下,则获取按键对应的数码,并显示在数码管上。 以下是一个示例代码,使用STM32F103C8T6单片机控制4位数码管和4x4矩阵按键: ```c #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" #define GPIO_PORT_NUM 4 #define GPIO_PIN_NUM 4 GPIO_TypeDef * const GPIO_PORT[GPIO_PORT_NUM] = {GPIOA, GPIOB, GPIOC, GPIOD}; const uint16_t GPIO_PIN[GPIO_PIN_NUM] = {GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2, GPIO_Pin_3}; const uint8_t KEY_MAP[GPIO_PORT_NUM][GPIO_PIN_NUM] = {{1, 2, 3, 10}, {4, 5, 6, 11}, {7, 8, 9, 12}, {14, 0, 15, 13}}; void delay_us(uint32_t us) { uint32_t i; for(i=0; i<us*8; ++i) { __ASM("NOP"); } } void GPIO_Init_All_Out(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure); } void GPIO_Init_Key_In(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure); } uint8_t Get_Key(void) { uint8_t i, j; uint8_t key = 0; for(i=0; i<GPIO_PORT_NUM; ++i) { GPIO_PORT[i]->BSRR = 0xFFFF << GPIO_PIN_NUM; GPIO_PORT[i]->BRR = 1 << GPIO_PIN[i]; for(j=0; j<GPIO_PIN_NUM; ++j) { if((GPIO_PORT[i]->IDR & GPIO_PIN[j]) == 0) { key = KEY_MAP[i][j]; break; } } GPIO_PORT[i]->BSRR = 0xFFFF << GPIO_PIN_NUM; } return key; } void Display_Digit(uint8_t digit) { uint8_t i; for(i=0; i<4; ++i) { GPIO_PORT[i]->BSRR = 0xFFFF << GPIO_PIN_NUM; GPIO_PORT[i]->BRR = (digit & (1 << i)) << GPIO_PIN[i]; } delay_us(500); } int main(void) { uint8_t key = 0; uint8_t digit = 0; GPIO_Init_All_Out(); GPIO_Init_Key_In(); while(1) { key = Get_Key(); if(key > 0 && key <= 9) { digit = key; } else if(key == 10) { digit = 0; } Display_Digit(digit); } } ``` 在上述代码中,使用GPIO口控制数码管和矩阵按键的状态,并轮询检测按键状态。当有按键按下时,获取对应的数字并显示在数码管上。需要注意的是,由于数码管共阴极的,因此在显示数字时需要将对应的引脚设置为低电平,而矩阵按键是带上拉电阻的,因此设置为输入模式时需要启用上拉电阻。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值