CH552でシリアル入力 [Arduino]
先日のスケッチをいじって、CH552のシリアル入力を使ってみました。
シリアル出力は、ちょっと癖があるらしいのですが、入力はそれほどむつかしいことはありませんでした。
ふつうのArduinoとCh55xduinoでちょっと違うところ。
・配列の宣言に __xdata
・関数の宣言と定義が必要 (CとC++の違いらしい)
・PROGMEMのデータの読み取りは "pgm_read_~"なし
・shiftOutがなかった (MSBFIRST、16ビット専用のコードを作ってみた)
・USBSerialは通信速度とか関係なし? (300bpsでも2000000bpsでも送信できた)
以下、拙いソース
今のところCh55xduinoは、とりあえずArduino用にスケッチ作ってそれを移植するという感じです。
シリアル出力は、ちょっと癖があるらしいのですが、入力はそれほどむつかしいことはありませんでした。
ふつうのArduinoとCh55xduinoでちょっと違うところ。
・配列の宣言に __xdata
・関数の宣言と定義が必要 (CとC++の違いらしい)
・PROGMEMのデータの読み取りは "pgm_read_~"なし
・shiftOutがなかった (MSBFIRST、16ビット専用のコードを作ってみた)
・USBSerialは通信速度とか関係なし? (300bpsでも2000000bpsでも送信できた)
以下、拙いソース
// Flowing text string from serial input <<CH552 version>>
// Quadruple Matrix LED Driven by MAX7219
uint8_t CLK = 15; // to MAX7219 CLOCK
uint8_t CS = 16; // to MAX7219 LOAD(~CS)
uint8_t DAT = 17; // to MAX7219 DIN
uint8_t BUF[32] = {0}; // matrix LED image [ring buffer]
uint8_t pBUF = 0; // display start position in BUF
uint8_t pTEXT = 0; // start position in TEXT string
uint8_t pCHAR = 4; // start position in character (left:3or4, right:0)
uint8_t fPROP = 1; // blanks on the left side of characters (0:no, 1:yes) (for proportional font)
__xdata char TEXT[256] = "Hello world!";
static const uint32_t FONT4x8[] PROGMEM = {
0x00000000, 0x000000BF, 0x00030003, 0xF42FF42F, 0x44EA4B32, 0x2313C8C4, 0xE6996690, 0x00000403, // !"#$%&'
0x003C4281, 0x0081423C, 0x00140814, 0x00103810, 0x00008060, 0x00101010, 0x00000080, 0xC0300C03, // ()*+,-./
0x7E91897E, 0x0082FF80, 0xE291918E, 0x42898976, 0x3826FF20, 0x4F898971, 0x7E898972, 0x01E11907, // 01234567
0x76898976, 0x4E91917E, 0x00006666, 0x0080E666, 0x18244281, 0x28282828, 0x81422418, 0x0201B10E, // 89:;<=>?
0x7E81995E, 0xFE1111FE, 0xFF898976, 0x7E818166, 0xFF81817E, 0xFF898989, 0xFF090901, 0x7E8191F2, // @ABCDEFG
0xFF0808FF, 0x0081FF81, 0x80817F01, 0xFF0814E3, 0xFF808080, 0x061806ff, 0xFF0618FF, 0x7E81817E, // HIJKLMNO
0xFF11110E, 0x3E4171BE, 0xFF11718E, 0x46899162, 0x01FF0101, 0x7F80807F, 0x3FC0601F, 0xe018e01f, // PQRSTUVW
0xF70808F7, 0x07F80807, 0xC1B18D83, 0x00FF8181, 0x030C30C0, 0x008181FF, 0x00060106, 0x80808080, // XYZ[\]^_
0x00010204, 0x609494F8, 0xFE909060, 0x78848448, 0x609090FE, 0x78949458, 0x08FC0A0A, 0x18A4A47E, // `abcdefg
0xFE0808F0, 0x000000FA, 0x0080807A, 0xFE205088, 0x00007E80, 0x04f804f8, 0xFc0404F8, 0x78848478, // hijklmno
0xFC242418, 0x182424FC, 0xFC100808, 0x4894A448, 0x087E8888, 0x7C80807C, 0x7C80403C, 0xc020c03c, // pqrstuvw
0xEC1010EC, 0x0C90907C, 0xC4A4948C, 0x00187E81, 0x000000FF, 0x00817E18, 0x10081008 }; // xyz{|}~
void ledOut( uint16_t, uint16_t, uint16_t, uint16_t );
void refreshLED();
void setup() {
pinMode( CLK, OUTPUT );
pinMode( CS , OUTPUT );
pinMode( DAT, OUTPUT );
ledOut( 0x0F00, 0x0F00, 0x0F00, 0x0F00 ); // Display Test(0xXF): Normal Operation (0)
ledOut( 0x0B07, 0x0B07, 0x0B07, 0x0B07 ); // Scan Limit (0xXB): Display all digits (7)
ledOut( 0x0A01, 0x0A01, 0x0A01, 0x0A01 ); // Intensity (0xXA): Luminance (0-F)
ledOut( 0x0900, 0x0900, 0x0900, 0x0900 ); // Decode Mode (0xX9): No decode (00)
ledOut( 0x0C01, 0x0C01, 0x0C01, 0x0C01 ); // Shutdown (0xXC): Normal Operation (0)
}
void loop() {
/*** Get string from serial ***/
char rx, pRx = 0; // Receive data length
while( USBSerial_available() ) {
rx = USBSerial_read();
if( rx == '\n' || rx == '\r' ) break; // Exit if end of string
TEXT[pRx++] = rx; // Add character
if( pRx == sizeof(TEXT) - 1 ) break; // Exit if buffer is full
}
if( pRx ) { // if the data is not empty..
TEXT[pRx] = '\0'; // terminate a string
pCHAR = (pTEXT) ? 36 : pCHAR; // insert spaces to the next string
pTEXT = 0; // reset display start position
while( USBSerial_available() ) USBSerial_read(); // discard the rest of the data
}
/*** Scroll the text ***/
char c = TEXT[ pTEXT ]; // character to display
refreshLED();
delay(200);
if( pCHAR > 4 ) BUF[pBUF] = 0; // display blank
if( pCHAR == 4 ) switch( c ) { // for blank or 5-dot width
case ' ': fPROP = 0; pCHAR = 1; break;
case 'M': fPROP = 0; BUF[pBUF] = 0xFF; break;
case 'm': fPROP = 0; BUF[pBUF] = 0xFC; break;
case 'W': fPROP = 0; BUF[pBUF] = 0x1F; break;
case 'w': fPROP = 0; BUF[pBUF] = 0x3c; break;
default : pCHAR--; // Move character display start position
}
if( pCHAR < 4 ) {
BUF[pBUF] = FONT4x8[ c-' ' ] >> ( pCHAR * 8 );
while( !BUF[pBUF] && fPROP ) BUF[pBUF] = FONT4x8[ c-' ' ] >> ( --pCHAR * 8 ); // remove blanks
fPROP = 0;
}
if( !pCHAR-- ) { // When finished displaying a character
fPROP = 1; // revert flag
if( TEXT[++pTEXT] ) pCHAR = 5; // If there is a following character
else { pTEXT = 0; pCHAR = 36; } // Reset display start position
}
pBUF = ++pBUF %32; // Move display start position of ring buffer
}
void ledOut( uint16_t d0, uint16_t d1, uint16_t d2, uint16_t d3 ) {
uint16_t d[]={ d0, d1, d2, d3 };
digitalWrite( CS, LOW );
for(uint8_t n=0; n<4; n++) {
for (uint8_t i=15; i<16; i--) { // shiftOut MSBFIRST 16bit
digitalWrite( DAT, ( d[n]>>i ) & 1 );
digitalWrite( CLK, HIGH );
digitalWrite( CLK, LOW );
}
}
digitalWrite( CS, HIGH );
}
void refreshLED() {
uint8_t d[4];
for(uint8_t m=0; m<8; m++) { // matrix LED data line
for(uint8_t b=0; b<8; b++) { // bit
for(uint8_t n=0; n<4; n++) { // Number of LEDs
d[n] = d[n]<<1 | ((BUF[(b+n*8+pBUF)%32]>>m) & 1);
}
}
ledOut(((m+1)<<8)+d[0], ((m+1)<<8)+d[1], ((m+1)<<8)+d[2], ((m+1)<<8)+d[3] );
}
}
今のところCh55xduinoは、とりあえずArduino用にスケッチ作ってそれを移植するという感じです。
4連マトリックスLEDで文字列を流す [Arduino]
4連マトリックスLEDで文字列を流してみたいと思います。
とりあえず半角英数・記号のみ。
漢字を扱うことの問題は、フォントの著作権と文字コードです。
ということで英数・記号フォントを自作しました。
・基本4×8ドットをいっぱいに使う
・見栄えとスペースの節約のためにプロポーショナルフォント
・4ドット幅だと表現が厳しい"M","W","m","w"は1ドット追加
としました。
とりあえず半角英数・記号のみ。
漢字を扱うことの問題は、フォントの著作権と文字コードです。
ということで英数・記号フォントを自作しました。
・基本4×8ドットをいっぱいに使う
・見栄えとスペースの節約のためにプロポーショナルフォント
・4ドット幅だと表現が厳しい"M","W","m","w"は1ドット追加
としました。
// Quadruple Matrix LED Driven by MAX7219
// *** flowing text string ***
uint8_t CLK = 13; // to MAX7219 CLOCK
uint8_t CS = 10; // to MAX7219 LOAD(~CS)
uint8_t DAT = 11; // to MAX7219 DIN
uint8_t BUF[32] = {0}; // matrix LED image [ring buffer]
uint8_t pBUF = 0; // display start position in BUF
uint8_t pTEXT = 0; // start position in TEXT string
uint8_t pCHAR = 4; // start position in character (left:3or4, right:0)
uint8_t fPROP = 1; // blanks on the left side of characters (0:no, 1:yes) (for proportional font)
char TEXT[128] = "Hello world !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
static const uint32_t FONT4x8[] PROGMEM = {
0x00000000, 0x000000BF, 0x00030003, 0xF42FF42F, 0x44EA4B32, 0x2313C8C4, 0xE6996690, 0x00000403, // !"#$%&'
0x003C4281, 0x0081423C, 0x00140814, 0x00103810, 0x00008060, 0x00101010, 0x00000080, 0xC0300C03, // ()*+,-./
0x7E91897E, 0x0082FF80, 0xE291918E, 0x42898976, 0x3826FF20, 0x4F898971, 0x7E898972, 0x01E11907, // 01234567
0x76898976, 0x4E91917E, 0x00006666, 0x0080E666, 0x18244281, 0x28282828, 0x81422418, 0x0201B10E, // 89:;<=>?
0x7E81995E, 0xFE1111FE, 0xFF898976, 0x7E818166, 0xFF81817E, 0xFF898989, 0xFF090901, 0x7E8191F2, // @ABCDEFG
0xFF0808FF, 0x0081FF81, 0x80817F01, 0xFF0814E3, 0xFF808080, 0x061806ff, 0xFF0618FF, 0x7E81817E, // HIJKLMNO
0xFF11110E, 0x3E4171BE, 0xFF11718E, 0x46899162, 0x01FF0101, 0x7F80807F, 0x3FC0601F, 0xe018e01f, // PQRSTUVW
0xF70808F7, 0x07F80807, 0xC1B18D83, 0x00FF8181, 0x030C30C0, 0x008181FF, 0x00060106, 0x80808080, // XYZ[\]^_
0x00010204, 0x609494F8, 0xFE909060, 0x78848448, 0x609090FE, 0x78949458, 0x08FC0A0A, 0x18A4A47E, // `abcdefg
0xFE0808F0, 0x000000FA, 0x0080807A, 0xFE205088, 0x00007E80, 0x04f804f8, 0xFc0404F8, 0x78848478, // hijklmno
0xFC242418, 0x182424FC, 0xFC100808, 0x4894A448, 0x087E8888, 0x7C80807C, 0x7C80403C, 0xc020c03c, // pqrstuvw
0xEC1010EC, 0x0C90907C, 0xC4A4948C, 0x00187E81, 0x000000FF, 0x00817E18, 0x10081008 }; // xyz{|}~
void setup() {
pinMode( CLK, OUTPUT );
pinMode( CS , OUTPUT );
pinMode( DAT, OUTPUT );
ledOut( 0x0F00, 0x0F00, 0x0F00, 0x0F00 ); // Display Test(0xXF): Normal Operation (0)
ledOut( 0x0B07, 0x0B07, 0x0B07, 0x0B07 ); // Scan Limit (0xXB): Display all digits (7)
ledOut( 0x0A01, 0x0A01, 0x0A01, 0x0A01 ); // Intensity (0xXA): Luminance (0-F)
ledOut( 0x0900, 0x0900, 0x0900, 0x0900 ); // Decode Mode (0xX9): No decode (00)
ledOut( 0x0C01, 0x0C01, 0x0C01, 0x0C01 ); // Shutdown (0xXC): Normal Operation (0)
}
void loop() {
char c = TEXT[ pTEXT ]; // character to display
refreshLED();
delay(200);
if( pCHAR > 4 ) BUF[pBUF] = 0; // display blank
if( pCHAR == 4 ) switch( c ) { // for blank or 5-dot width
case ' ': fPROP = 0; pCHAR = 1; break;
case 'M': fPROP = 0; BUF[pBUF] = 0xFF; break;
case 'm': fPROP = 0; BUF[pBUF] = 0xFC; break;
case 'W': fPROP = 0; BUF[pBUF] = 0x1F; break;
case 'w': fPROP = 0; BUF[pBUF] = 0x3c; break;
default: pCHAR--; // Move character display start position
}
if( pCHAR < 4 ) {
BUF[pBUF] = pgm_read_dword(FONT4x8 + c-' ') >> ( pCHAR * 8 ); // if you don't use PROGMEM -> FONT4x8[ c-' ' ]
while( !BUF[pBUF] && fPROP ) BUF[pBUF] = pgm_read_dword(FONT4x8 + c-' ') >> ( --pCHAR * 8 ); // remove blanks
fPROP = 0;
}
if( !pCHAR-- ) { // When finished displaying a character
fPROP = 1; // revert flag
if( TEXT[++pTEXT] ) pCHAR = 5; // If there is a following character
else { pTEXT = 0; pCHAR = 36; } // Reset display start position
}
++pBUF %= 32; // Move display start position of ring buffer
}
void ledOut( uint16_t d0, uint16_t d1, uint16_t d2, uint16_t d3 ) {
uint16_t d[]={ d0, d1, d2, d3 };
digitalWrite( CS, LOW );
for(uint8_t n=0; n<4; n++) {
shiftOut( DAT, CLK, MSBFIRST, d[n]>>8 );
shiftOut( DAT, CLK, MSBFIRST, d[n] );
}
digitalWrite( CS, HIGH );
}
void refreshLED() {
uint8_t d[4];
for(uint8_t m=0; m<8; m++) { // matrix LED data line
for(uint8_t b=0; b<8; b++) { // bit
for(uint8_t n=0; n<4; n++) { // Number of LEDs
d[n] = d[n]<<1 | ((BUF[(b+n*8+pBUF)%32]>>m) & 1);
}
}
ledOut(((m+1)<<8)+d[0], ((m+1)<<8)+d[1], ((m+1)<<8)+d[2], ((m+1)<<8)+d[3] );
}
}
タグ:Matrix LED
CH552Eduinoをつくってみた。 [Arduino]
ちいさいものが好きなので、CH552EのテストボードをKiCadで設計してみました。
・メインのCH552Eは裏面に
・リセットボタン・ブートローダボタンはほぼ使う機会がなかったので省略
・USBとの接続ピン(UDP, UDM)(UDPはブートローダにも)はブレットボードには使わない位置へ
・USBとの接続ピン以外はICピン配列順にしたかったけど、リセットピンだけ引き回せず別位置へ
・リセッタブルヒューズなど安全性の配慮はなし
・外部電源非対応(USB type-C only)
・そのかわりに、ちゃんとCC1, CC2に5.1kΩの抵抗はつける
2バージョン作成。
3Dイメージ
これらの基板を発注してしばらく待ちます。
先日、基板が届いたので、チップ抵抗、チップキャパシタ、USB-Cレセプタクルを載せてみました。
できあがりサイズは、USB type-C DIP変換基板とか、USB-TTL変換基板くらいのサイズです。
チップ部品のはんだ付けは、まだまだ難儀しています。
先日の演奏スケッチで動作確認できました。
・メインのCH552Eは裏面に
・リセットボタン・ブートローダボタンはほぼ使う機会がなかったので省略
・USBとの接続ピン(UDP, UDM)(UDPはブートローダにも)はブレットボードには使わない位置へ
・USBとの接続ピン以外はICピン配列順にしたかったけど、リセットピンだけ引き回せず別位置へ
・リセッタブルヒューズなど安全性の配慮はなし
・外部電源非対応(USB type-C only)
・そのかわりに、ちゃんとCC1, CC2に5.1kΩの抵抗はつける
2バージョン作成。
3Dイメージ
これらの基板を発注してしばらく待ちます。
先日、基板が届いたので、チップ抵抗、チップキャパシタ、USB-Cレセプタクルを載せてみました。
できあがりサイズは、USB type-C DIP変換基板とか、USB-TTL変換基板くらいのサイズです。
チップ部品のはんだ付けは、まだまだ難儀しています。
先日の演奏スケッチで動作確認できました。