點矩陣MAX7219 8X8

回覆文章
cajhbb
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

點矩陣MAX7219 8X8

文章 cajhbb »

列(Row)、 行(Column)(直行橫列)
點矩陣MAX7219 8X8 箭號由左向右
https://atceiling.blogspot.com/2020/11/ ... 8-led.html 參考網址
https://xantorohara.github.io/led-matrix-editor/ 原始網址
https://sites.google.com/jes.mlc.edu.tw ... 97/max7219 吉哥-MAX7219 8x8 LED矩陣
https://swf.com.tw/?p=738 超圖解
https://atceiling.blogspot.com/2019/07/ ... 2-led.html 時鐘串連
LED矩陣說明.jpg
LED矩陣說明.jpg (63.25 KiB) 已瀏覽 90 次
2025-01-13_145815.jpg
2025-01-13_145815.jpg (57.09 KiB) 已瀏覽 112 次
setLed(int addr, int row, int col, boolean state);//單顆顯示
clearDisplay(int addr);//清除裝置
lc.setColumn(0,4,B01111110);//代表第4"行"通電,"列"則依據"數值"顯示
lc.setRow(0,4,B01111110);//代表第4"列"通電,"行"則依據"數值"顯示
位移三格的做法
for(int row=0;row<8;row++){
byte mover=(Hour_Tens1[row]>>3);
lc.setColumn(1,row,mover);
2025-01-27_121116.jpg
2025-01-27_121116.jpg (46.84 KiB) 已瀏覽 41 次

代碼: 選擇全部

#include <LedControl.h>
// Pin 12:Data in, Pin 11: Clock,  Pin 10: CS(Load)
LedControl display = LedControl(12,11,10,1);
 
const uint64_t R_IMAGES[] = {   //往右箭頭
  0x0000000100000000,
  0x0000010301000000,
  0x0001030703010000,
  0x0103070f07030100,
  0x02060f1f0f060200,
  0x040c1f3f1f0c0400,
  0x08183f7f3f180800,
  0x08183f7f3f180800,
  0x10307fff7f301000,
  0x2060fefefe602000,
  0x40c0fcfcfcc04000,
  0x8080f8f8f8808000,
  0x0000f0f0f0000000,
  0x0000e0e0e0000000,
  0x0000c0c0c0000000,
  0x0000808080000000,
  0x0000000000000000
};
const int R_IMAGES_LEN = sizeof(R_IMAGES)/8;

void setup()
{
  display.clearDisplay(0);    // 清除螢幕
  display.shutdown(0, false);  // 關閉省電模式
  display.setIntensity(0, 10); // 設定亮度為 8 (介於0~15之間)

}
void displayImage(uint64_t image) {
  for (int i = 0; i < 8; i++) {
    byte row = (image >> i * 8) & 0xFF;
    for (int j = 0; j < 8; j++) {
      display.setLed(0, i, j, bitRead(row, j));
    }
  }
}

int i = 0;

void loop() {
   displayImage(R_IMAGES[i]);
  if (++i >= R_IMAGES_LEN ) {
    i = 0;
  }
  delay(100); 
}
cajhbb
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

Re: 點矩陣MAX7219 8X8

文章 cajhbb »

寫一個arduino程式,讓一顆MAX7219 LED Matrix 8x8模組,逐顆點燈LED燈,間隔0.3秒

代碼: 選擇全部

#include <LedControl.h>

// 定义连接到 MAX7219 的引脚
const int DIN_PIN = 12;
const int CS_PIN = 11;
const int CLK_PIN = 10;

// 定义 LedControl 对象
LedControl lc = LedControl(DIN_PIN, CLK_PIN, CS_PIN, 1);

// 初始化函數
void setup() {
  // 初始化 MAX7219
  lc.shutdown(0, false);
  lc.setIntensity(0, 8); // 設置亮度
  lc.clearDisplay(0); // 清除显示
}

void loop() {
  // 循环遍历每个 LED 并逐个点亮
  for (int row = 0; row < 8; row++) {
    for (int col = 0; col < 8; col++) {
      lc.setLed(0, row, col, true); // 点亮 LED
      delay(300); // 间隔 0.3 秒
      lc.setLed(0, row, col, false); // 熄灭 LED
    }
  }
}
讓2顆MAX7219 LED Matrix 8x8模組,一顆負責個位數,另一顆負責拾位數,當計數器從00數到99,00~99變化一次間隔0.3秒!
接線方法
以下引腳的連接需要根據你的硬件進行調整:
MAX7219 DIN(數據輸入)連接到 Arduino D12
MAX7219 CS(片選)連接到 Arduino D11
MAX7219 CLK(時鐘)連接到 Arduino D10
MAX7219 VCC 連接到 Arduino 5V
MAX7219 GND 連接到 Arduino GND
兩個矩陣串聯連接:
第一個矩陣的 DOUT(數據輸出)連接到第二個矩陣的 DIN(數據輸入)

代碼: 選擇全部

#include <LedControl.h>

// 定義連接到 MAX7219 的引腳
const int DIN_PIN = 12;
const int CS_PIN = 11;
const int CLK_PIN = 10;

// 定義 LedControl 對象
LedControl lc = LedControl(DIN_PIN, CLK_PIN, CS_PIN, 2); // 2 表示有兩個設備

// 初始化函數
void setup() {
  // 初始化兩個 MAX7219
  for (int i = 0; i < 2; i++) {
    lc.shutdown(i, false);
    lc.setIntensity(i, 8); // 設置亮度
    lc.clearDisplay(i); // 清除顯示
  }
}

void loop() {
  // 從 00 數到 99 的循環
  for (int number = 0; number < 100; number++) {
    int tens = number / 10; // 取拾位數
    int ones = number % 10; // 取個位數

    // 在第一個 MAX7219 上顯示個位數
    lc.setDigit(0, 0, ones, false);

    // 在第二個 MAX7219 上顯示拾位數
    lc.setDigit(1, 0, tens, false);

    delay(300); // 間隔 0.3 秒
  }
}

cajhbb
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

Re: 點矩陣MAX7219 8X8

文章 cajhbb »

2025-01-15_103442.jpg
2025-01-15_103442.jpg (6.91 KiB) 已瀏覽 94 次
兩條固定,一條左右跑

代碼: 選擇全部

#include <LedControl.h>

const int DIN_PIN = 12;
const int CS_PIN = 10;
const int CLK_PIN = 11;

const uint64_t IMAGES[] = {
  0xff000001010000ff, 0xff000003030000ff, 0xff000006060000ff,
  0xff00000c0c0000ff, 0xff000018180000ff, 0xff000030300000ff,
  0xff000060600000ff, 0xff0000c0c00000ff, 0xff000080800000ff,
  0xff0000c0c00000ff, 0xff000060600000ff, 0xff000018180000ff,
  0xff00000c0c0000ff, 0xff000006060000ff, 0xff000003030000ff,
  0xff000001010000ff
};
const int IMAGES_LEN = sizeof(IMAGES)/8;


LedControl display = LedControl(DIN_PIN, CLK_PIN, CS_PIN);


void setup() {
  display.clearDisplay(0);
  display.shutdown(0, false);
  display.setIntensity(0, 3);
}

void displayImage(uint64_t image) {
  for (int i = 0; i < 8; i++) {
    byte row = (image >> i * 8) & 0xFF;
    for (int j = 0; j < 8; j++) {
      display.setLed(0, i, j, bitRead(row, j));
    }
  }
}

int i = 0;

void loop() {
  displayImage(IMAGES[i]);
  if (++i >= IMAGES_LEN ) {
    i = 0;
  }
  delay(100);
}
cajhbb
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

七段顯示器-點矩陣MAX7219 8X8

文章 cajhbb »

https://atceiling.blogspot.com/2020/09/ ... 19-87.html
單獨點亮一顆燈

代碼: 選擇全部

#include <LedControl.h>

// CLK (SCK) 接腳定義
const int CLK = 13;
// DATA (DIN) 接腳定義
const int DATA = 11;
// CS (LOAD) 接腳定義
const int CS = 10;

// 初始化 LedControl 物件
LedControl lc = LedControl(DATA, CLK, CS, 1);

void setup() {
  // 啟動 MAX7219
  lc.shutdown(0, false);
  // 設定亮度 (0-15)
  lc.setIntensity(0, 8);
  // 清空顯示
  lc.clearDisplay(0);
}

void loop() {
  // 設定第0列,第0行的LED亮起 (左上角)
  lc.setLed(0, 0, 0, true);
  delay(1000);
}

在這個程式碼中,lc.setLed(0, 0, 0, true); 的第一個參數是設備編號(對於單個顯示器為 0),第二個參數是列號,第三個參數是行號,最後一個參數是狀態(true 表示亮起,false 表示熄滅)。你可以修改列號和行號來控制不同位置的LED,例如 lc.setLed(0, 7, 7, true); 將會點亮右下角的LED。
gotop_8x8_font01.zip
(1.2 KiB) 已下載 2 次
反向顯示+一個矩陣有兩位數
附加檔案
數字.jpg
數字.jpg (213.54 KiB) 已瀏覽 64 次
倒置數字.jpg
倒置數字.jpg (189.81 KiB) 已瀏覽 64 次
cajhbb
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

顯示12:25

文章 cajhbb »

代碼: 選擇全部

#include <LedControl.h>
LedControl lc=LedControl(12,11,10,2);//DIN=12 CS=10 CLK=11 2個裝置
int Led_Delay=2;
  int row;//列
#define T_PUSH 2;//第D2腳位
unsigned long Time_Get = 0;
//-----------------------------------------------------------------
//---分鐘個位數 Min_Single
 byte Min_Single0[8]={0x07,0x07,0x05,0x05,0x05,0x05,0x07,0x07};
 byte Min_Single1[8]={0x07,0x02,0x02,0x02,0x02,0x02,0x06,0x02};
 byte Min_Single2[8]={0x07,0x04,0x04,0x07,0x07,0x01,0x01,0x07};
 byte Min_Single3[8]={0x07,0x01,0x01,0x07,0x07,0x01,0x01,0x07};
 byte Min_Single4[8]={0x01,0x01,0x01,0x07,0x07,0x05,0x05,0x05};
 byte Min_Single5[8]={0x07,0x01,0x01,0x07,0x07,0x04,0x04,0x07};
 byte Min_Single6[8]={0x07,0x05,0x05,0x07,0x07,0x04,0x04,0x04};
 byte Min_Single7[8]={0x01,0x01,0x01,0x01,0x05,0x05,0x07,0x07};
 byte Min_Single8[8]={0x07,0x05,0x05,0x07,0x07,0x05,0x05,0x07};
 byte Min_Single9[8]={0x07,0x01,0x01,0x07,0x07,0x05,0x05,0x07};
//---分鐘拾位數 Min_Tens
 byte Min_Tens0[8]={0x70,0x70,0x50,0x50,0x50,0x50,0x70,0x70};
 byte Min_Tens1[8]={0x70,0x20,0x20,0x20,0x20,0x20,0x60,0x20};
 byte Min_Tens2[8]={0x70,0x40,0x40,0x70,0x70,0x10,0x10,0x70};
 byte Min_Tens3[8]={0x70,0x10,0x10,0x70,0x70,0x10,0x10,0x70};
 byte Min_Tens4[8]={0x10,0x10,0x10,0x70,0x70,0x50,0x50,0x50};
 byte Min_Tens5[8]={0x70,0x10,0x10,0x70,0x70,0x40,0x40,0x70};
 byte Min_Tens6[8]={0x70,0x50,0x50,0x70,0x70,0x40,0x40,0x40};
 byte Min_Tens7[8]={0x10,0x10,0x10,0x10,0x50,0x50,0x70,0x70};
 byte Min_Tens8[8]={0x70,0x50,0x50,0x70,0x70,0x50,0x50,0x70};
 byte Min_Tens9[8]={0x70,0x10,0x10,0x70,0x70,0x50,0x50,0x70};
//---小時個位數 Hour_Single
 byte Hour_Single0[8]={0x0E,0x0E,0x0A,0x0A,0x0A,0x0A,0x0E,0x0E};
 byte Hour_Single1[8]={0x0E,0x04,0x04,0x04,0x04,0x04,0x0C,0x04};
 byte Hour_Single2[8]={0x0E,0x08,0x08,0x0E,0x0E,0x02,0x02,0x0E};
 byte Hour_Single3[8]={0x0E,0x02,0x02,0x0E,0x0E,0x02,0x02,0x0E};
 byte Hour_Single4[8]={0x02,0x02,0x02,0x0E,0x0E,0x0A,0x0A,0x0A};
 byte Hour_Single5[8]={0x0E,0x02,0x02,0x0E,0x0E,0x08,0x08,0x0E};
 byte Hour_Single6[8]={0x0E,0x0A,0x0A,0x0E,0x0E,0x08,0x08,0x08};
 byte Hour_Single7[8]={0x02,0x02,0x02,0x02,0x0A,0x0A,0x0E,0x0E};
 byte Hour_Single8[8]={0x0E,0x0A,0x0A,0x0E,0x0E,0x0A,0x0A,0x0E};
 byte Hour_Single9[8]={0x0E,0x02,0x02,0x0E,0x0E,0x0A,0x0A,0x0E};
//---小時拾位數 Hour_Tens 
 byte Hour_Tens0[8]={0xE0,0xE0,0xA0,0xA0,0xA0,0xA0,0xE0,0xE0};
 byte Hour_Tens1[8]={0xE0,0x40,0x40,0x40,0x40,0x40,0xC0,0x40};
 byte Hour_Tens2[8]={0xE0,0x80,0x80,0xE0,0xE0,0x20,0x20,0xE0};
 byte Hour_Tens3[8]={0xE0,0x20,0x20,0xE0,0xE0,0x20,0x20,0xE0};
 byte Hour_Tens4[8]={0x20,0x20,0x20,0xE0,0xE0,0xA0,0xA0,0xA0};
 byte Hour_Tens5[8]={0xE0,0x20,0x20,0xE0,0xE0,0x80,0x80,0xE0};
 byte Hour_Tens6[8]={0xE0,0xA0,0xA0,0xE0,0xE0,0x80,0x80,0x80};
 byte Hour_Tens7[8]={0x20,0x20,0x20,0x20,0xA0,0xA0,0xE0,0xE0};
 byte Hour_Tens8[8]={0xE0,0xA0,0xA0,0xE0,0xE0,0xA0,0xA0,0xE0};
 byte Hour_Tens9[8]={0xE0,0x20,0x20,0xE0,0xE0,0xA0,0xA0,0xE0};
//-----------------------------------------------------------------

void setup() {
  for(int i=0;i<2;i++){ //2個矩陣LED初始設定
    lc.shutdown(i,false);//
    lc.setIntensity(i,1);//
    lc.clearDisplay(i);//
  }
}

void loop() {
  
//  byte A2[3]={0xFD,0x8C,0x8F};
//--------------------------------------------------------
//  byte A9[8]={0x70,0x10,0x10,0x70,0x70,0x50,0x50,0x70};
//--------------------------------------------------------
//  byte C0[8]={A1[0]|A9[0],A1[1]|A9[1],A1[2]|A9[2],A1[3]|A9[3],A1[4]|A9[4],A1[5]|A9[5],A1[6]|A9[6],A1[7]|A9[7]};
  for(int row=0;row<8;row++){
    lc.setColumn(0,row,Min_Tens2[row]|Min_Single5[row]);//第一裝置 分用OR過濾另外半部 
    lc.setColumn(1,row,Hour_Tens1[row]|Hour_Single2[row]);//第二裝置 分用OR過濾另外半部 
    lc.setLed(0, 0, 5, true);//裝置0 上午秒點
    lc.setLed(1, 7, 5, true);//裝置1 上午秒點
    lc.setLed(0, 0, 2, true);//裝置0 下午秒點
    lc.setLed(1, 7, 2, true);//裝置1 下午秒點
//    lc.setColumn(1,row,A2[row]);//第二裝置
    //Time_Get=millis();
    delay(90);;
  }
}
顯示12:00用move 位移方法

代碼: 選擇全部

#include <LedControl.h>
LedControl lc=LedControl(12,11,10,2);//DIN=12 CS=10 CLK=11 2個裝置
int Led_Delay=2;
  int row;//列
#define T_PUSH 2;//第D2腳位

unsigned long Time_Get = 0;
//-----------------------------------------------------------------
//---時間字型---
 byte T_Font0[8]={0xE0,0xE0,0xA0,0xA0,0xA0,0xA0,0xE0,0xE0};
 byte T_Font1[8]={0xE0,0x40,0x40,0x40,0x40,0x40,0xC0,0x40};
 byte T_Font2[8]={0xE0,0x80,0x80,0xE0,0xE0,0x20,0x20,0xE0};
 byte T_Font3[8]={0xE0,0x20,0x20,0xE0,0xE0,0x20,0x20,0xE0};
 byte T_Font4[8]={0x20,0x20,0x20,0xE0,0xE0,0xA0,0xA0,0xA0};
 byte T_Font5[8]={0xE0,0x20,0x20,0xE0,0xE0,0x80,0x80,0xE0};
 byte T_Font6[8]={0xE0,0xA0,0xA0,0xE0,0xE0,0x80,0x80,0x80};
 byte T_Font7[8]={0x20,0x20,0x20,0x20,0xA0,0xA0,0xE0,0xE0};
 byte T_Font8[8]={0xE0,0xA0,0xA0,0xE0,0xE0,0xA0,0xA0,0xE0};
 byte T_Font9[8]={0xE0,0x20,0x20,0xE0,0xE0,0xA0,0xA0,0xE0};

void setup() {
  for(int i=0;i<2;i++){ //2個矩陣LED初始設定
    lc.shutdown(i,false);//
    lc.setIntensity(i,1);//
    lc.clearDisplay(i);//
  }
}

void loop() {
  for(int row=0;row<8;row++){
   byte Hour_Tens=(T_Font1[row]);
   byte Hour_Single=(T_Font2[row]>>4);
   byte Min_Tens=(T_Font0[row]>>1);
   byte Min_Single=(T_Font0[row]>>5);
    lc.setColumn(1,row,Hour_Tens|Hour_Single);//第1裝置 分用OR過濾另外半部 
    lc.setColumn(0,row,Min_Tens|Min_Single);//第0裝置 分用OR過濾另外半部 
    lc.setLed(0, 0, 5, true);//裝置0 上午秒點
    lc.setLed(1, 7, 5, true);//裝置1 上午秒點
    lc.setLed(0, 0, 2, true);//裝置0 下午秒點
    lc.setLed(1, 7, 2, true);//裝置1 下午秒點
    //Time_Get=millis();
    delay(90);;
  }
}
cajhbb
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

示範用arduino 寫 byte T_Font[10][8]陣列傳一個2維陣列值

文章 cajhbb »

deepseek回答
示範用arduino 寫 byte T_Font[10][8]陣列傳一個2維陣列值

代碼: 選擇全部

// 定義一個 10x8 的二維陣列
byte T_Font[10][8] = {
  {0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00, 0x00}, // 字元 0
  {0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00}, // 字元 1
  {0x42, 0x61, 0x51, 0x49, 0x46, 0x00, 0x00, 0x00}, // 字元 2
  {0x21, 0x41, 0x45, 0x4B, 0x31, 0x00, 0x00, 0x00}, // 字元 3
  {0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 0x00, 0x00}, // 字元 4
  {0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x00, 0x00}, // 字元 5
  {0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00, 0x00, 0x00}, // 字元 6
  {0x01, 0x71, 0x09, 0x05, 0x03, 0x00, 0x00, 0x00}, // 字元 7
  {0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00, 0x00}, // 字元 8
  {0x06, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00, 0x00}  // 字元 9
};

// 函式用於顯示二維陣列的內容
void displayFont(byte fontArray[10][8]) {
  for (int i = 0; i < 10; i++) {
    Serial.print("字元 ");
    Serial.print(i);
    Serial.print(": ");
    for (int j = 0; j < 8; j++) {
      Serial.print("0x");
      if (fontArray[i][j] < 0x10) {
        Serial.print("0"); // 補零以保持兩位數格式
      }
      Serial.print(fontArray[i][j], HEX);
      Serial.print(" ");
    }
    Serial.println();
  }
}

void setup() {
  Serial.begin(9600); // 初始化串口通信
  displayFont(T_Font); // 呼叫函式並傳遞二維陣列
}

void loop() {
  // 主循環不需要做任何事情
}
字元 0: 0x3E 0x51 0x49 0x45 0x3E 0x00 0x00 0x00
字元 1: 0x00 0x42 0x7F 0x40 0x00 0x00 0x00 0x00
字元 2: 0x42 0x61 0x51 0x49 0x46 0x00 0x00 0x00
...
字元 9: 0x06 0x49 0x49 0x29 0x1E 0x00 0x00 0x00
cajhbb
系統管理員
文章: 993
註冊時間: 2018年 6月 30日, 02:16

Clock-ok

文章 cajhbb »

代碼: 選擇全部

/* Timer1(16bits)最大值65535計時1秒,將針腳13LED反相 
石英振盪=16MHz + 設定CTC模式(Clear Timer on Compare Match)
TCCR1A要設-->WGM11=0 WGM10=0
TCCR1B要設-->WGM13=0 WGM12=1 (除頻256-->CS12=1 CS11=0 CS10=0)
<註>1.CS12=1 CS11=0 CS10=0 查表:除256
<註>2.使用除頻器除256,16M/256=62500Hz
<註>3.OCR1A=(目標時間*計數頻率)-1-->OCR1A=(1秒*62500)-1=62499次
<註>4.比較器中斷法,數值不可以超過65535,否則要換方法
<註>5.比較中斷62499次,才可以得到1秒!
*/
#include<avr/interrupt.h>//載入中斷函式
#include <LedControl.h>//載入MAX7219控制函式
#define PINLED 13 //內建第13腳位的LED燈
#define ChangTime_PUSH 2//第D2腳位
#define SetTime_PUSH 4//第D4腳位
//<註>中斷次數值(volatile的宣告方式適合中斷後,計數不會被更改)
volatile bool stateLED=LOW;//LED目前為(滅)
volatile bool dot=false,flag1s=false;//旗熛判斷(是否達1秒)
volatile byte Sec_Now=0,Min_Single_Now=0,Min_Tens_Now=0,Hour_Single_Now=0,Hour_Tens_Now=0;//計算用時間格式
uint32_t preTime,curTime;//前次時間,目前時間
unsigned long Time_Get = 0;
int row;//列
LedControl lc=LedControl(12,11,10,2);//DIN=12 CS=10 CLK=11 2個裝置
volatile boolean lastButtonState,inButton=false;//inButton進入處理旗標
byte tMin_Single_Now=0,tMin_Tens_Now=0,tHour_Single_Now=0,tHour_Tens_Now=0;//暫時轉換時間格式
byte MHour_Tens,MHour_Single,MMin_Tens,MMin_Single;//矩陣時間格式
byte SetFlag=0,Change_Flag=0,ctrl_Flag=0;//設定旗摽
//-----------------時間字型----------------
byte T_Font[10][8]={{0x00,0xE0,0xA0,0xA0,0xA0,0xA0,0xA0,0xE0},
                    {0x00,0xE0,0x40,0x40,0x40,0x40,0xC0,0x40},
                    {0x00,0xE0,0x80,0x80,0xE0,0x20,0x20,0xE0},
                    {0x00,0xE0,0x20,0x20,0xE0,0x20,0x20,0xE0},
                    {0x00,0x20,0x20,0x20,0xE0,0xA0,0xA0,0xA0},
                    {0x00,0xE0,0x20,0x20,0xE0,0x80,0x80,0xE0},
                    {0x00,0xE0,0xA0,0xA0,0xE0,0x80,0x80,0x80},
                    {0x00,0x20,0x20,0x20,0x20,0x20,0x20,0xE0},
                    {0x00,0xE0,0xA0,0xA0,0xE0,0xA0,0xA0,0xE0},
                    {0x00,0x20,0x20,0x20,0xE0,0xA0,0xA0,0xE0}};
byte Z_Font[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//空白字型
//---------------程式初始設定---------------------
void setup() {
//Serial.begin(9600);// 初始化序列埠
//按鈕輸入設定
pinMode(ChangTime_PUSH, INPUT_PULLUP);//D2腳位上拉電阻-設定鈕
pinMode(SetTime_PUSH, INPUT_PULLUP);//D4腳位上拉電阻-確定鈕
//矩陣LED初始:兩個裝置矩陣初始設定
  for(int i=0;i<2;i++){ 
    lc.shutdown(i,false);
    lc.setIntensity(i,1);//亮度
    lc.clearDisplay(i);//清除燈號
  }
 //   Adjust();//初始先調整時間
    init_timer1_CTC();//啟用Timer1比較中斷模式
    curTime=micros();//擷取開機後至目前時間
    DisPlayLED(0);//正常顯示開始
}
//----------初始設定Timer1設為CTC模式比較中斷模式 ------------
void init_timer1_CTC(){
 // 設置Timer1以CTC模式運行
 TCCR1A=TCCR1A &(~(1<<WGM11))&(~(1<<WGM10));//設為0
 TCCR1B=TCCR1B &(~(1<<WGM13));//設為0
 TCCR1B=TCCR1B |((1<<WGM12));//設為1
//暫存器TCCR1B(CS12=1,CS11=0,CS10=0)設置預分頻為256
 TCCR1B=TCCR1B &(~(1<<CS11))&(~(1<<CS10));//
 TCCR1B=TCCR1B |((1<<CS12));// 
 OCR1A = 62499;   // 設置比較值為62500 - 1
 TIMSK1 |= (1 << OCIE1A);//啓用比較中斷
 sei();//啟動中斷功能
}
//---------------迴圈開始--------------------
void loop() {
// 等待D2 ChangTime_PUSH按鈕按下-->inButton設為true進入時間設定迴圈
  if (digitalRead(ChangTime_PUSH) == LOW && !inButton) {
    delay(50);  // 簡單的除抖動處理
    if (digitalRead(ChangTime_PUSH) == LOW) {
      inButton = true;// 進入調整時間函式的迴圈
	    Change_Flag=true;//改變4種時間位格
//      Serial.println("進入函式");
	  //將現在時間代入,暫時代數值
	    tHour_Tens_Now=Hour_Tens_Now,tHour_Single_Now=Hour_Single_Now,tMin_Tens_Now=Min_Tens_Now,tMin_Single_Now=Min_Single_Now;
	  Adjust();//呼叫調整函式
						}
	}
}
//-------以下為比較中斷服務函式----------------------------
//計數器1
ISR(TIMER1_COMPA_vect){
    Sec_Now++;//累計秒數
//    Serial.print(Min_Tens_Now);Serial.print(Hour_Single_Now);Serial.print(Min_Tens_Now);Serial.print(Min_Single_Now);Serial.println(Sec_Now);
                  //-----秒燈下午-----
                  if((Hour_Tens_Now==1 && Hour_Single_Now>=2)|Hour_Tens_Now==2){
                    if(inButton==false){
                    lc.setLed(0, 0, 2, dot);//裝置0 下午秒點
                    lc.setLed(1, 7, 2, !dot);//裝置1 下午秒點
                    dot=!dot;}
                  }
                  //-----秒燈上午-----
                  else{ 
                    if(inButton==false){
                    lc.setLed(0, 0, 5, dot);//裝置0 上午秒點
                    lc.setLed(1, 7, 5, !dot);//裝置1 上午秒點
                    dot=!dot;}
                  }
    if(Sec_Now==60){ //達到1秒鐘
      Sec_Now=0; Min_Single_Now++; if(inButton==false){DisPlayLED(4);}//累計"分個位"
      if(Min_Single_Now==10){//"分個位"逢10進位
         Min_Single_Now=0; Min_Tens_Now++; DisPlayLED(3);//累計"分拾位"
		        if(Min_Tens_Now==6){//"分拾位"逢6進位
		    			Min_Tens_Now=0; Hour_Single_Now++; DisPlayLED(2); DisPlayLED(3);//累計"時個位"
		            if((Hour_Tens_Now<=1)&&(Hour_Single_Now==10)){ //如果時拾位=0~1,時個位,逢10進位
                          Hour_Single_Now=0; Hour_Tens_Now++; DisPlayLED(1); DisPlayLED(2);}//累計"時拾位"
					if((Hour_Tens_Now==2)&&(Hour_Single_Now==4)){ //如果時拾位=2,時個位,逢4歸0
					      Hour_Single_Now=0; Hour_Tens_Now=0; DisPlayLED(1); DisPlayLED(2);}	  
                      }
                    }
                  }
}
//-------------調整鈕被按下-調整時間----------------
void Adjust(){
//Serial.print("Change_Flag:");
//Serial.println(Change_Flag);
for(int i=0;i<3;i++){
  lc.clearDisplay(1);lc.clearDisplay(0);delay(180);DisPlayLED(0);DisPlayLED(0);delay(180);//閃爍3次預備設定時間
                }
  lc.clearDisplay(1);lc.clearDisplay(0);//清除螢幕
  ChangeLED(1);
   while (inButton) {//如果 inButton一直為"真"就在迴圈內,直到4格時間設定完成
 // 檢查D2 ChangTime_PUSH是否按下(累加任務)
    if (digitalRead(ChangTime_PUSH) == LOW) {//
      delay(50);  // 簡單的除抖動處理
      if (digitalRead(ChangTime_PUSH) == LOW){
        if(Change_Flag==1){tHour_Tens_Now++; //累計'時拾'
							if(tHour_Tens_Now==3){tHour_Tens_Now=0;}
							ChangeLED(1);
							}//超過3歸0
		if(Change_Flag==2){ tHour_Single_Now++;//累計'時個'
							if(tHour_Tens_Now<=2){
							if(tHour_Tens_Now==2 && tHour_Single_Now>=4)
							{tHour_Single_Now=0; ChangeLED(1);}
							if(tHour_Single_Now==10){tHour_Single_Now=0;}//超過10歸0
												}
						    ChangeLED(1);
						  }
		if(Change_Flag==3){tMin_Tens_Now++;  //累計'分拾'
							if(tMin_Tens_Now==6){tMin_Tens_Now=0;}
							ChangeLED(0);
						  }//超過6歸0
		if(Change_Flag==4){tMin_Single_Now++; //累計'分個'
							if(tMin_Single_Now==10){tMin_Single_Now=0;}
						   ChangeLED(0);
						  }//超過10歸0
//        Serial.print("計數器: ");Serial.print(tHour_Tens_Now);Serial.print(tHour_Single_Now);Serial.print(tMin_Tens_Now);Serial.println(tMin_Single_Now);
        while (digitalRead(ChangTime_PUSH) == LOW);  // 等待按鈕釋放
      }
    }
//	Serial.print("SetFlag:");
//	Serial.println(SetFlag);
    // 檢查D4設定鈕是否按下(累計SetTime_PUSH+跳出函式)
    if (digitalRead(SetTime_PUSH) == LOW) {
      delay(50);  // 簡單的除抖動處理
	//-------------------------------------
      if (digitalRead(SetTime_PUSH) == LOW) {
		SetFlag++;
        if(Change_Flag==1){
			Hour_Tens_Now=tHour_Tens_Now;
			if(tHour_Tens_Now==2 && tHour_Single_Now>=4){tHour_Single_Now=0;ChangeLED(2);}
			else{ChangeLED(2);}}//時拾寫入
		if(Change_Flag==2){
			Hour_Single_Now=tHour_Single_Now;ChangeLED(3);}//時個寫入
		if(Change_Flag==3){
			Min_Tens_Now=tMin_Tens_Now;ChangeLED(4);}//分拾寫入
		if(Change_Flag==4){
			Min_Single_Now=tMin_Single_Now;}//分個寫入	
		  Change_Flag++;
	//判斷是否完成4格時間設定,是(歸0,跳出迴圈)
	    if(SetFlag==4){
			inButton = false;  // 跳出函式
			Change_Flag=0;
			SetFlag=0;//旗標歸0
      Sec_Now=0;
//      Serial.println("跳出函式");
      }
	//--------------------------------	
	while (digitalRead(SetTime_PUSH) == LOW);  // 等待按鈕釋放
      }
    }
  }
 lc.clearDisplay(1);lc.clearDisplay(0);delay(100);//清除螢幕
 DisPlayLED(0);
}
//----DisPlayLED正常顯示-----
void DisPlayLED(byte time_value){
       if(time_value==0){
			  for(int row=0;row<8;row++){
				byte Hour_Tens=(T_Font[Hour_Tens_Now][row]);
				byte Hour_Single=(T_Font[Hour_Single_Now][row]>>4);
				byte Min_Tens=(T_Font[Min_Tens_Now][row]>>1);
				byte Min_Single=(T_Font[Min_Single_Now][row]>>5);
				lc.setColumn(1,row,Hour_Tens|Hour_Single);//第1裝置 分用OR過濾另外半部 
				lc.setColumn(0,row,Min_Tens|Min_Single);//第0裝置 分用OR過濾另外半部 
				                          }
       }
	    if(time_value==4|time_value==3){
      for(int row=0;row<8;row++){
				byte Min_Tens=(T_Font[Min_Tens_Now][row]>>1);
				byte Min_Single=(T_Font[Min_Single_Now][row]>>5);
				lc.setColumn(0,row,Min_Tens|Min_Single);//第0裝置 分用OR過濾另外半部
                                }
				}
	     if(time_value==2|time_value==1){
        for(int row=0;row<8;row++){
				byte Hour_Tens=(T_Font[Hour_Tens_Now][row]);
				byte Hour_Single=(T_Font[Hour_Single_Now][row]>>4);
				lc.setColumn(1,row,Hour_Tens|Hour_Single);//第1裝置 分用OR過濾另外半部
				                        }
       }   
}
//----ChangeLED調整顯示-----
void ChangeLED(boolean tmp_value){
       for(int row=0;row<8;row++){
        byte MHour_Tens=(T_Font[tHour_Tens_Now][row]);
        byte MHour_Single=(T_Font[tHour_Single_Now][row]>>4);
        byte MMin_Tens=(T_Font[tMin_Tens_Now][row]>>1);
        byte MMin_Single=(T_Font[tMin_Single_Now][row]>>5);
        if(inButton==true && SetFlag==0){
		        lc.setColumn(1,row,MHour_Tens);}//第1裝置 分用OR過濾另外半部 
        if(inButton==true && SetFlag==1){
		        lc.setColumn(1,row,MHour_Tens|MHour_Single);}//第1裝置 分用OR過濾另外半部
        if(inButton==true && SetFlag==2){
		        lc.setColumn(1,row,MHour_Tens|MHour_Single);//第1裝置 分用OR過濾另外半部
            lc.setColumn(0,row,MMin_Tens);}//第0裝置 分用OR過濾另外半部
        if(inButton==true && SetFlag==3){
		        lc.setColumn(1,row,MHour_Tens|MHour_Single);//第1裝置 分用OR過濾另外半部
            lc.setColumn(0,row,MMin_Tens|MMin_Single);}//第0裝置 分用OR過濾另外半部
		}
}

      //  lc.setLed(0, 0, 5, true);//裝置0 上午秒點
      //  lc.setLed(1, 7, 5, true);//裝置1 上午秒點
      //  lc.setLed(0, 0, 2, true);//裝置0 下午秒點
      //  lc.setLed(1, 7, 2, true);//裝置1 下午秒點      
回覆文章