Arduinoで16x16 LEDドットマトリックスを利用する(6)
前回の続きです。
スクロール表示の動作検証および、日本語フォントROM GT20L16J1Yを使ってみました。
割り込み処理とSPI通信の併用を心配していましたが、まったく問題なしでした。
表示しています。
スクロールをちょと速めにしてもちゃんと表示出来ています。
GT20L16J1Yは3.3V駆動なので、CD4050を使って5V -> 3.3Vのレベル調整をしました。
LED表示部は前回と変わらずですが、清書しました。
清書してD9接続の74HC595とTB62706のLATCHのタイミングが違うことに初めて気づきました。
まあ、動作しているのでOKということで..(タイミング的にも大丈夫なはず)。
プロフラムソースはこんな感じです。
// // TB62706を使ったLEDの点灯サンプル //#include <arduino.h> #include <MsTimer2.h> #include <string.h> #include <SPI.h> /// #define ASC8x16S 255968 // 8x16 ASCII 粗体字符(半角) #define ASC8x16N 257504 // 8x16 ASCII 日文假名(半角) #define DATAPIN (7) // TB62706のSERIAL-INへ #define LATCHPIN (9) // TB62706のLATCHへ #define CLOCKPIN (8) // TB62706のCLOCKへ #define ENABLEPIN (6) // TB62706のENABLEへ uint16_t fbuf[16]; // 表示パターンバッファデータ byte rowdata[32]; // 漢字ROM読み取り用バッファ // 文字データ "こんにちは埼玉県" uint16_t fnt[11][16]= { {// "" 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff }, {// こ 0x0000,0x0000,0x1ff8,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x2000,0x3000,0x1c00,0x07fc,0x0000,0x0000 }, {// ん 0x0200,0x0200,0x0600,0x0400,0x0c00,0x0800,0x0800,0x1b80, 0x1440,0x1840,0x3040,0x2042,0x2046,0x604c,0x4038,0x0000 }, {// に 0x0000,0x1000,0x1000,0x31fc,0x2000,0x2000,0x2000,0x2000, 0x2000,0x2000,0x2200,0x2200,0x2b00,0x31fe,0x1000,0x0000 }, {// ち 0x0100,0x0100,0x0100,0x7ffc,0x0200,0x0600,0x0400,0x0ff0, 0x1808,0x3004,0x0004,0x0004,0x000c,0x0038,0x07e0,0x0000 }, {// は 0x0000,0x2020,0x2020,0x6020,0x47fe,0x4020,0x4020,0x4020, 0x4020,0x4020,0x43e0,0x4438,0x542c,0x6466,0x23c0,0x0000 }, {// 埼 0x2020,0x2020,0x23fe,0x2050,0xf8d8,0x218c,0x2000,0x27ff, 0x2004,0x21e4,0x3924,0x6124,0xc124,0x01e4,0x0004,0x001c}, {// 玉 0x0000,0x7ffe,0x0100,0x0100,0x0100,0x0100,0x0100,0x3ffc, 0x0100,0x0100,0x0118,0x010c,0x0104,0x0100,0xffff,0x0000 }, {// 県 0x07f8,0x2408,0x2408,0x27f8,0x2408,0x2408,0x27f8,0x2408, 0x2408,0x27f8,0x2000,0x3fff,0x0888,0x188c,0x7087,0x0080 }, {// "" 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 }, {// "" 0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555, 0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555,0xAAAA,0x5555 } }; //いろは歌(JISコード文字列) uint16_t iroha[] = { 0x3f27,0x244f,0x244b,0x245b,0x2458,0x2449,0x3b36,0x246a,//1 0x244c,0x246b,0x2472,0x3266,0x242c,0x4024,0x243f,0x246c,//2 0x243e,0x3e6f,0x244a,0x2469,0x2460,0x4d2d,0x3059,0x244e,//3 0x317c,0x3b33,0x3a23,0x467c,0x315b,0x2428,0x2446,0x4075,//4 0x242d,0x4c34,0x382b,0x2438,0x3f6c,0x2452,0x2462,0x243b,//5 0x243a }; // 漢字ROM GT20L16J1Y用 // 全角JISコードからフォント格納先頭アドレスを求める // GT20L16J1Y データシート VER 4.0 2013-3のサンプルを参照した // (サンプルでは区点コードからの変換であることに注意) unsigned long calcAddr(unsigned short jiscode) { unsigned long MSB; unsigned long LSB; unsigned long Address; char buf[32]; // 上位、下位を区点コードに変換 MSB = (jiscode >> 8) - 0x20; LSB = (jiscode & 0xff) -0x20; // データ格納アドレスを求める if(MSB >=1 && MSB <= 15 && LSB >=1 && LSB <= 94) Address =( (MSB - 1) * 94 + (LSB - 01))*32; else if(MSB >=16 && MSB <= 47 && LSB >=1 && LSB <= 94) Address =( (MSB - 16) * 94 + (LSB - 1))*32+43584; else if(MSB >=48 && MSB <=84 && LSB >=1 && LSB <= 94) Address = ((MSB - 48) * 94 + (LSB - 1))*32+ 138464; else if(MSB ==85 && LSB >=0x01 && LSB <= 94) Address = ((MSB - 85) * 94 + (LSB - 1))*32+ 246944; else if(MSB >=88 && MSB <=89 && LSB >=1 && LSB <= 94) Address = ((MSB - 88) * 94 + (LSB - 1))*32+ 249952; return Address; } // 漢字ROM GT20L16J1Y用 // JISコードからキャラクタデータを得る void getCharData(unsigned short code) { byte data; unsigned long addr=0; byte n; if (code > 0xFF) { // 全角 addr =calcAddr(code); n = 32; } else { // 半角 addr = ASC8x16N + (code<<4); n = 16; } digitalWrite(10, HIGH); //delayMicroseconds(10); digitalWrite(10, LOW); SPI.transfer(0x03); SPI.transfer((addr>>16) & 0xff); SPI.transfer((addr>>8) & 0xff); SPI.transfer(addr & 0xff); SPI.setBitOrder(LSBFIRST); for(byte i = 0;i< n; i++) rowdata[i] = SPI.transfer(0x00); SPI.setBitOrder(MSBFIRST); digitalWrite(10, HIGH); } // 漢字ROM GT20L16J1Y用 // 漢字ROMフォントを表示用形式に変換する void rowtofont(uint16_t* fnt) { for (byte i=0; i <16; i++) fnt[i]=0; for (byte i=0;i<8;i++) for (byte j=0; j<16; j++) { fnt[7-i] |= (rowdata[j] & 0x1<<i ? 0x8000: 0) >>j; fnt[15-i] |= (rowdata[j+16] & 0x1<<i ? 0x8000: 0) >>j; } } // 漢字ROM GT20L16J1Y用 // JIS漢字コートに対応するフォントデータの取得 // void loadfontdata(uint16_t *fnt, unsigned short code) { getCharData(code); rowtofont(fnt); } // 漢字ROM GT20L16J1Y用 // 漢字ROMを参照してフォントを表示する void test_iroha() { uint16_t buf[16]; for (int i=0; i <41; i++) { loadfontdata(buf, iroha[i]); setfontscl(buf, 25); } } // // 行の指定 // void selectRow(byte no) { uint16_t val = _BV(15-no); // ビット列データの出力 for( byte i = 0; i < 16; i++ ){ digitalWrite(DATAPIN, val & _BV(i) ? 1:0); digitalWrite(CLOCKPIN, HIGH); digitalWrite(CLOCKPIN, LOW); } } // // 行フォントパターンの送信 // void dataOut(uint16_t val ) { for( byte i = 0; i < 16; i++ ){ digitalWrite(DATAPIN, val & _BV(i) ? 1:0); digitalWrite(CLOCKPIN, HIGH); digitalWrite(CLOCKPIN, LOW); } } // // バッファ内データを表示する // void fontout() { // 点灯LEDが移動するパターン digitalWrite(ENABLEPIN,LOW); // OUTを有効にする for( byte i = 0; i < 16; i++ ) { digitalWrite(LATCHPIN, LOW); //送信開始 selectRow(i); dataOut(fbuf[i]); digitalWrite(LATCHPIN, HIGH); //送信開始 } digitalWrite(ENABLEPIN,HIGH); // OUTを有効にする } // // バッファにフォントパターンをセット // void setfont(uint16_t* fptr) { memcpy(fbuf, fptr, 32); } // // バッファ内の指定座標に点をセット // void setdot(uint8_t x, uint8_t y, byte dot) { // uint16_t v = ; fbuf[y] = dot ? fbuf[y]| (0x8000>>x): fbuf[y] & ~(0x8000>>x); } void testdotset() { for (byte y=0; y<16; y++) { for (byte x=0; x<16; x++) { setdot(x,y,1); delay(10); } } for (byte y=0; y<16; y++) { for (byte x=0; x<16; x++) { setdot(x,y,0); delay(10); } } } // // 指定座標にフォントパターンをセット // void setfontat(uint16_t* fptr, uint8_t x, uint8_t y) { uint16_t w; if (x>15 || y >15) return; for (byte j=y,i=0; j < 16; j++,i++) fbuf[j] = (fbuf[j]>>(16-x))<<(16-x) | fptr[i]>>x; } void test01() { for (byte i=0; i <11; i++) { for (byte x=15; x > 0; x--) { setfontat(fnt[i],0,x); delay(20); } } } // // ドット表示チェック(デバッグ用) // void dottest() { for (byte y=10; y < 11;y++) for (byte x=0;x <16;x++) { fbuf[y]= 0x8000>>x; delay(50); fbuf[y]= 0; } } // // バッファーデータのスクロール // h_mode : 0 なし,1 左 ,2 右 // v_mode : 0 なし,1 上, 2 下 // void scroll(uint8_t h_mode, uint8_t v_mode) { if (h_mode ==1) for (byte i = 0; i < 16; i++) fbuf[i] = fbuf[i]<<1; if (h_mode ==2) for (byte i = 0; i < 16; i++) fbuf[i] = fbuf[i]>>1; if (v_mode ==1) { for (byte i = 0; i < 15; i++) fbuf[i]= fbuf[i+1]; fbuf[15]=0; } if (v_mode == 2) { for (byte i = 15; i >0; i--) fbuf[i]= fbuf[i-1]; fbuf[0] = 0; } } // スクロールテスト void test02() { byte i; setfont(fnt[6]); for (i=0; i<16;i++) { scroll(1,0); delay(50); } delay(200); setfont(fnt[6]); for (i=0; i<16;i++) { scroll(2,0); delay(50); } delay(200); setfont(fnt[6]); for (i=0; i<16;i++) { scroll(0,1); delay(50); } delay(200); setfont(fnt[6]); for (i=0; i<16;i++) { scroll(0,2); delay(50); } delay(200); setfont(fnt[6]); for (i=0; i<16;i++) { scroll(1,1); delay(50); } delay(200); setfont(fnt[6]); for (i=0; i<16;i++) { scroll(2,2); delay(50); } delay(200); } // // スクロールしながらパターンを表示 // void setfontscl(uint16_t* fptr, uint16_t dly) { for (byte i=0; i<16; i++) { scroll(1, 0); setfontat(fptr, 15-i, 0) ; delay(dly); } } void setup() { pinMode(10,OUTPUT); SPI.begin(); //SPI.setClockDivider(SPI_CLOCK_DIV4); pinMode(ENABLEPIN,OUTPUT); pinMode(DATAPIN, OUTPUT); pinMode(LATCHPIN, OUTPUT); pinMode(CLOCKPIN, OUTPUT); digitalWrite(ENABLEPIN,HIGH); digitalWrite(CLOCKPIN, LOW); digitalWrite(LATCHPIN, HIGH); digitalWrite(ENABLEPIN,LOW); // OUTを有効にする setfont(fnt[9]); // フォントバッファに初期パターン設定 // 割り込み開始 MsTimer2::set(15, fontout); // 1/60秒程度で1文字を表示 MsTimer2::start(); } void loop(){ test_iroha(); // いろは歌表示(漢字ROM利用) delay(1000); test02(); // スクロールテスト testdotset(); // ドット単位アクセス表示 // 配列格納文字パターンを順番に表示する for (byte i =0; i < 11; i++) setfontscl(fnt[i],40); }
arduinoの文字列がUTF8を使っているのに対して、漢字フォントROMはJISコードなので、
プログラムで「はいろは歌」の文字列をJISコードにて保持して表示しています。
この点はちょっと面倒です。
この対応を模索しています。
「Arduinoで16x16 LEDドットマトリックスを利用する(7)」 に続きます。
関連記事
・Arduinoで16x16 LEDドットマトリックスを利用する(1)
・Arduinoで16x16 LEDドットマトリックスを利用する(2)
・Arduinoで16x16 LEDドットマトリックスを利用する(3)
・Arduinoで16x16 LEDドットマトリックスを利用する(4)
・Arduinoで16x16 LEDドットマトリックスを利用する(5)
・Arduinoで16x16 LEDドットマトリックスを利用する(6) (この記事です)
・Arduinoで16x16 LEDドットマトリックスを利用する(7)
・Arduinoで16x16 LEDドットマトリックスを利用する(8)
再チャレンジ版
・aitendo 16x16LEDマトリックスの制御 (1)
・aitendo 16x16LEDマトリックスの制御 (2)
・aitendo 16x16LEDマトリックスの制御 (3)
・aitendo 16x16LEDマトリックスの制御 (4)
・aitendo 16x16LEDマトリックスの制御 (5)
・ESP-WROOM-02を始めました(2)
« Arduinoで16x16 LEDドットマトリックスを利用する(5) | トップページ | OCN モバイル ONEが通信容量増量 »
「arduino」カテゴリの記事
- Arduino IDE+Arduino STM32環境で指定と異なるgccが使われてしまう(2025.01.23)
- Zorin OSでArduino Uno互換機(CH340)が認識しない(2025.01.19)
- Arduino IDE 2.3.4でArduino STM32を利用する(2025.01.12)
- Arduino用 SKK日本語変換ライブラリの開発 その1(2024.12.28)
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
「AVR」カテゴリの記事
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
- Arduino用SJIS漢字フォントライブラリ SDカード版を作成しました(2018.10.30)
- ATtiny13AでI2C接続キャラクタLCDを利用する(4)(2018.04.16)
- ATtiny13Aで赤外線リモコン受信センサーを使う(2)(2018.04.15)
- ATtiny13AでHC-SR04を使った距離計測(2018.04.14)
「表示器制御関連」カテゴリの記事
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
- Arduino用 美咲フォントライブラリを更新しました(2024.03.21)
- Raspberry Pi Pico(MicroPython)でLEDドットマトリックスを使ってみる(2024.03.14)
- Raspberry Pi Pico MicroPython用のマルチフォントライブラリ(2023.02.09)
- MicroPython(Raspberry Pi pico)で8x8ドットNeoPixcel文字表示(2023.02.08)
« Arduinoで16x16 LEDドットマトリックスを利用する(5) | トップページ | OCN モバイル ONEが通信容量増量 »
コメント