这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【分享评测,赢取加热台】+Arduino下基于TM1638驱动的数码管模块显示

共2条 1/1 1 跳转至

【分享评测,赢取加热台】+Arduino下基于TM1638驱动的数码管模块显示

专家
2024-05-04 19:08:33   被打赏 50 分(兑奖)     打赏

前面帖子中介绍了TM1638的工作特点,本帖就以一个以TM1638驱动的数码管模块为例,编程驱动显示和键盘扫描处理。

这个数码管显示、键盘扫描模块的电路图如下:

图片1.png

使用的是共阴数码管3461BS。

本帖只处理显示部分的代码,根据电路图和TM1638的工作特性,每次要显示一组8位数据的时候,需要把8个数码管相同位置的字段数据组织起来传给TM1638的显示寄存器。以下是处理程序:

/**
 驱动TM1638的数码管模块
 数码管 - 共阴数码管 3461BS
 数码管笔段(4位数码管)   TM1638  Pin
 --------------------------------------
 a                      GR1    24
 b                      GR2    23
 c                      GR3    22
 d                      GR4    21
 e                      GR5    20
 f                      GR6    19
 g                      GR7    17
 dp                     GR8    16
第一组数码管D1
g1(数码管1)             SG1    5 
g2(数码管2)             SG2    6 
g3(数码管3)             SG3    7
g4(数码管4)             SG4    8
第二组数码管D2
g1(数码管1)             SG5    9
g2(数码管2)             SG6    10
g3(数码管3)             SG7    11
g4(数码管4)             SG8    12
*/
#define STB 16
#define CLK 5
#define DIO 4
// 数码管显示的值
unsigned char tab[]={
  0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,      // 0-9,       索引:0-9
  0x77,0x7C,0x39,0x5E,0x79,0x71,                          // A, b, C, d, E,F        索引:10-15
  0xbf,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xeF,     // 0. - 9.  , 索引:16-25
  0xF7,0xFC,0xB9,0xDE,0xF9,0xF1,                          // A., b., C., d., E.,F.  索引:26-31
  0x00,0x40,0x08, 0x37, 0x7C, 0x73, 0x80                  // 空白,-,_, N, o, P, 点        索引:32-38
};
// 写数据函数
void TM1638_Write(unsigned char DATA) {
  unsigned char i;
  // 发送字节,每个字节8位
  for(i=0;i<8;i++) {
    // 准备上升沿脉冲
    digitalWrite(CLK, LOW);
    // 根据输出位,使DIO为高电平或者低电平
    // 输出按照先低后高的顺序
    if(DATA&0X01)
      digitalWrite(DIO, HIGH);
    else
      digitalWrite(DIO, LOW);
    // 移位到下一个Bit位
    DATA>>=1;
    // 产生上升沿
    digitalWrite(CLK, HIGH);
  }
}
// 读数据函数
unsigned char TM1638_Read(void) {
  unsigned char i;
  unsigned char temp=0;
  // 为了正常输入,拉高输入口
  digitalWrite(DIO, HIGH);
  //设置为输入
  pinMode(DIO, INPUT);
  for(i=0;i<8;i++) {
    temp>>=1;
    digitalWrite(CLK, LOW);
    if(digitalRead(DIO)>0)
      temp|=0x80;
    digitalWrite(CLK, HIGH);
  }
  return temp;
}
// 发送命令字
void Write_CMD(unsigned char cmd) {
  // 使DIO转换为输出模式
  pinMode(DIO, OUTPUT);
  // 选通模块,允许读写
  digitalWrite(STB, LOW);
 
  // 发送指令
  TM1638_Write(cmd);
  // 关闭选通
  digitalWrite(STB, HIGH);
}
// 读取按键
unsigned char Read_key(void) {
  unsigned char c[4],i,key_value=0;
  // 选通模块,允许读写
  digitalWrite(STB, LOW);
  // 输出指令:0x42 - 
  TM1638_Write(0x42);
  // 延迟100ms
  delay(100);
 
  // 为了正常输入,拉高输入口
  digitalWrite(DIO, HIGH);
  pinMode(DIO, INPUT);
  // 取得输入数据
  for(i=0;i<4;i++)
    c[i]=TM1638_Read();
 
   digitalWrite(STB, HIGH);
  // 判断键值
  if(c[0]==0x04) key_value=1;
  if(c[0]==0x40) key_value=2;
  if(c[1]==0x04) key_value=3;
  if(c[1]==0x40) key_value=4;
  if(c[2]==0x04) key_value=5;
  if(c[2]==0x40) key_value=6;
  if(c[3]==0x04) key_value=7;
  if(c[3]==0x40) key_value=8;
  if(c[0]==0x02) key_value=9;
  if(c[0]==0x20) key_value=10;
  if(c[1]==0x02) key_value=11;
  if(c[1]==0x20) key_value=12;
  if(c[2]==0x02) key_value=13;
  if(c[2]==0x20) key_value=14;
  if(c[3]==0x02) key_value=15;
  if(c[3]==0x20) key_value=16;
 
  // 延迟100ms
  delay(100);
  // 返回键值
  return (key_value);
}
// 显示处理
void LedDisplay(unsigned char Num7,unsigned char Num6,unsigned char Num5,unsigned char Num4,
                unsigned char Num3,unsigned char Num2,unsigned char Num1,unsigned char Num0)
{
  unsigned char  seg_a,seg_b,seg_c,seg_d,seg_e,seg_f,seg_g,seg_dp;
  // 转换为笔段数据
  seg_a=(tab[Num0]&0x01)+((tab[Num1]&0x01)<<1)+((tab[Num2]&0x01)<<2)+((tab[Num3]&0x01)<<3)+((tab[Num4]&0x01)<<4)
    +((tab[Num5]&0x01)<<5)+((tab[Num6]&0x01)<<6)+((tab[Num7]&0x01)<<7);
  seg_b=((tab[Num0]&0x02)>>1)+((tab[Num1]&0x02))+((tab[Num2]&0x02)<<1)+((tab[Num3]&0x02)<<2)+((tab[Num4]&0x02)<<3)
    +((tab[Num5]&0x02)<<4)+((tab[Num6]&0x02)<<5)+((tab[Num7]&0x02)<<6);
  seg_c=((tab[Num0]&0x04)>>2)+((tab[Num1]&0x04)>>1)+((tab[Num2]&0x04))+((tab[Num3]&0x04)<<1)+((tab[Num4]&0x04)<<2)
    +((tab[Num5]&0x04)<<3)+((tab[Num6]&0x04)<<4)+((tab[Num7]&0x04)<<5);
  seg_d=((tab[Num0]&0x08)>>3)+((tab[Num1]&0x08)>>2)+((tab[Num2]&0x08)>>1)+((tab[Num3]&0x08))+((tab[Num4]&0x08)<<1)
    +((tab[Num5]&0x08)<<2)+((tab[Num6]&0x08)<<3)+((tab[Num7]&0x08)<<4);
  seg_e=((tab[Num0]&0x10)>>4)+((tab[Num1]&0x10)>>3)+((tab[Num2]&0x10)>>2)+((tab[Num3]&0x10)>>1)+((tab[Num4]&0x10))
    +((tab[Num5]&0x10)<<1)+((tab[Num6]&0x10)<<2)+((tab[Num7]&0x10)<<3);
  seg_f=((tab[Num0]&0x20)>>5)+((tab[Num1]&0x20)>>4)+((tab[Num2]&0x20)>>3)+((tab[Num3]&0x20)>>2)+((tab[Num4]&0x20)>>1)
    +((tab[Num5]&0x20))+((tab[Num6]&0x20)<<1)+((tab[Num7]&0x20)<<2);
  seg_g=((tab[Num0]&0x40)>>6)+((tab[Num1]&0x40)>>5)+((tab[Num2]&0x40)>>4)+((tab[Num3]&0x40)>>3)+((tab[Num4]&0x40)>>2)
    +((tab[Num5]&0x40)>>1)+((tab[Num6]&0x40))+((tab[Num7]&0x40)<<1);
  seg_dp=((tab[Num0]&0x80)>>7)+((tab[Num1]&0x80)>>6)+((tab[Num2]&0x80)>>5)+((tab[Num3]&0x80)>>4)+((tab[Num4]&0x80)>>3)
    +((tab[Num5]&0x80)>>2)+((tab[Num6]&0x80)>>1)+((tab[Num7]&0x80));
 
  // 开显示,设置脉冲宽度为4/16
  Write_CMD(0x8A);
  // 写数据到显示寄存器的指令
  Write_CMD(0x40);
  // 选通模块,允许读写
  digitalWrite(STB, LOW);  
  // 写地址命令:0xC0 - 从显示地址0x00开始
  TM1638_Write(0xC0);
 
  // 输出组合后的笔段数据(00H~0FH,共计16字节单元)
  // 见《三、显示寄存器地址》中数据设置的说明
  TM1638_Write(seg_a);  TM1638_Write(0x80);
  TM1638_Write(seg_b);  TM1638_Write(0x00);
  TM1638_Write(seg_c);  TM1638_Write(0x00);
  TM1638_Write(seg_d);  TM1638_Write(0x00);
  TM1638_Write(seg_e);  TM1638_Write(0x00);
  TM1638_Write(seg_f);  TM1638_Write(0x00);
  TM1638_Write(seg_g);  TM1638_Write(0x00);
  TM1638_Write(seg_dp); TM1638_Write(0x00);
  digitalWrite(STB, HIGH);  
  delay(100);
}
// 显示字符串
// 获取字符对应的索引值,根据索引值,执行显示
void LedDispString(unsigned char *str) {
  unsigned char ch=0, idx=0, i=0;
  unsigned char dispIndex[8]={32,32,32,32,32,32,32,32};
  for (i=0; ;i++) {
    ch=*(str+i);
    if (ch=='\0') {
      break;
    }
    if (i==0 && ch=='.') {
      //dispIndex[i]=38;
      dispIndex[0]=16;
      idx++;
      continue;
    }
    switch(ch) {
      case '0': dispIndex[idx]=0;idx++;break;
      case '1': dispIndex[idx]=1;idx++;break;
      case '2': dispIndex[idx]=2;idx++;break;
      case '3': dispIndex[idx]=3;idx++;break;
      case '4': dispIndex[idx]=4;idx++;break;
      case '5': dispIndex[idx]=5;idx++;break;
      case '6': dispIndex[idx]=6;idx++;break;
      case '7': dispIndex[idx]=7;idx++;break;
      case '8': dispIndex[idx]=8;idx++;break;
      case '9': dispIndex[idx]=9;idx++;break;
      case 'A':
      case 'a': dispIndex[idx]=10;idx++;break;
      case 'B':
      case 'b': dispIndex[idx]=11;idx++;break;
      case 'C':
      case 'c': dispIndex[idx]=12;idx++;break;
      case 'D':
      case 'd': dispIndex[idx]=13;idx++;break;
      case 'E':
      case 'e': dispIndex[idx]=14;idx++;break;
      case 'F':
      case 'f': dispIndex[idx]=15;idx++;break;
      case '.': dispIndex[idx-1]=dispIndex[idx-1]+16;break;
      case ' ': dispIndex[idx]=32;idx++;break;
      case '-': dispIndex[idx]=33;idx++;break;
      case '_': dispIndex[idx]=34;idx++;break;
      case 'N':
      case 'n': dispIndex[idx]=35;idx++;break;
      case 'O':
      case 'o': dispIndex[i]=36;break;
      case 'P':
      case 'p': dispIndex[i]=37;break;
    }
    if (idx>=8) {
      break;
    }
  }
  LedDisplay(dispIndex[0], dispIndex[1], dispIndex[2], dispIndex[3],
             dispIndex[4], dispIndex[5], dispIndex[6], dispIndex[7]);
}
void setup() {
  unsigned char i = 0;
  unsigned char idx[8]={32,32,32,32,32,32,32,32};
  // 初始化接口为输出模式
  pinMode(STB,OUTPUT);
  pinMode(CLK,OUTPUT);
  pinMode(DIO, OUTPUT);
  Serial.begin(115200);
  //LedDisplay(7,6,5,4,3,2,1,0);
  //LedDispString((unsigned char *)"3.1415926");
  // 0从第一位到第八位移位显示
  for (i=0; i < 8; i++) {
    idx[i] = 0;
    LedDisplay(idx[0], idx[1], idx[2], idx[3],
               idx[4], idx[5], idx[6], idx[7]);
    idx[i]=32;
    delay(500);
  }
}
long cnt=0;
void loop() {
  char str[16];
  // 转换为8位长的字符串
  sprintf(str, "%8d", cnt);
  // 数码管显示
  LedDispString((unsigned char *)str);
 
  // 自动加1
  if (cnt>=99999999) {
    cnt=0;
  } else {
    cnt++;
  }
  delay(10);
}

以上程序在ESP8266开发板上测试通过。

微信图片_20240504190841.jpg




关键词: Arduino     TM1638     数码管    

高工
2024-05-04 20:39:29     打赏
2楼

谢谢分享 


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]