Arduino驱动Max7219四位数码管显示时间

#define MO 2
#define CS 3
#define CLK 4
static int time_h = 21, time_m =25, time_s = 30; //此刻时间:时,分,秒
int alarm_clock_h = 8, alarm_clock_m = 00; //闹钟时间
unsigned long time = 0;
unsigned char buffer_led[5] = { 0x00,};//缓存
void SPI_init(void) //初始化SPI引脚
{
  pinMode(CLK, OUTPUT);
  pinMode(MO, OUTPUT);
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  digitalWrite(CLK, LOW);
  digitalWrite(MO, HIGH);
}
void SPI_send(unsigned char reg, unsigned char data) //spi单向16位数据发送
{
  int x;
  /*
  Serial.print("reg = ");
  Serial.print(reg, HEX);
  Serial.print("   data = ");
  Serial.println(data, HEX);
  */
  digitalWrite(CS, LOW);
  for (x = 0; x < 8; x++)
  {
    digitalWrite(MO, 0x80 & (reg << x)); //高位在前
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
  }
  for (x = 0; x < 8; x++)
  {
    digitalWrite(MO, 0x80 & (data << x)); //高位在前
    digitalWrite(CLK, HIGH);
    digitalWrite(CLK, LOW);
  }
  digitalWrite(CS, HIGH);
}
void lcd_init(void)//初始化Max7219配置
{
  SPI_send(0x0b, 0x07); //scan-limit
  SPI_send(0x09, 0xff); //decode mode all
  SPI_send(0x0c, 0x01); //shutdown off
  SPI_send(0x0f, 0x00); //off display test
  SPI_send(0x0a, 0x04); //intensity
  delay(100);
}
void clear(void)//清除显示
{
  for (int i = 1; i <= 8; i++)
  {
    SPI_send(i, 0x0F);
  }
}
void led_display(void)//显示时间
{
  char cache = 0x00;
  if ((time_h / 10) == 0)buffer_led[0] = 0x00;
  else  buffer_led[0] = time_h / 10;
  buffer_led[1] = time_h % 10 | 0x01;
  buffer_led[2] = time_m / 10;
  buffer_led[3] = time_m % 10;
  SPI_send(8, buffer_led[0]);
  SPI_send(7, buffer_led[1]);
  
  SPI_send(6, 0x0a);
  
  SPI_send(5, buffer_led[2]);
  SPI_send(4, buffer_led[3]);
  
  SPI_send(3, 0x0a);
  SPI_send(2, time_s / 10);
  SPI_send(1, time_s % 10);
}
void get_time()//获取时间并更新显示
{
  static char ss = 1;
  static unsigned long time_cc = 0;
  if ((millis() - time_cc) > 1000 | millis() < 150)//秒
  {
    if (millis() <= 200) //若系统计时器溢出时时间,time_cc重计
    {
      time_cc = millis();
      time_s ++;
      delay(150);
    }
    else if (millis() > 200)//秒
    {
      time_s += (millis() - time_cc) / 1000;
      //    time_cc = millis()-990; //时间快进
      time_cc = millis();
      buffer_led[4] = (0x01 & ss) << 5;
      ss = ~ss;
    }
    if (time_s > 59) //分
    {
      if (time_s - 60 > 1)//如果有延时间隔导致秒钟大于60秒,进行分钟缺失补偿
      {
        time_m += time_s / 60;
        if (time_s % 60 == 0)time_m--;
        time_s = time_s - (time_s / 60) * 60;
      }
      else time_s = 0;
      time_m++;
      buffer_led[4] = 0x80;
      if (time_m > 59)//时
      {
        time_h++;
        time_m = (time_m - 60);
        buffer_led[4] = 0xf0;
      }
      if (time_h > 23)
      {
        time_h = 0;
        time_s += 5; //时间误差补偿
      }
    }
    //    Serial.print("millis=");
    //    Serial.print(time_cc);
    //    Serial.print("  time=");
    //    Serial.print(time_h);
    //    Serial.print(":");
    //    Serial.print(time_m);
    //    Serial.print(":");
    //    Serial.println(time_s);
    led_display();//刷新数码管显示
  }
}
void setup()
{
  Serial.begin(9600);
  SPI_init();
  lcd_init();
  clear();
}
void loop()
{
  get_time();
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注