私の同僚が「MSP430」タグで記事を書いているように、このマイクロコントローラの私の知り合いは、テキサス・インスツルメンツに基づいたメモMSP430開発者キットから始まりました。 注文したキットは5日で届きました。 その後、LED「Hello、World」と...アイデアと時間の不足のためにロッカーに戻されました...
...しかし、倉庫内で未使用のチケットオフィス「Minika 1101F」が見つかった。 子供の頃から、よくある質問「中身は何ですか?」
内部では、マジックナンバー5.104.704のボードでIZhC13-8 / 7-01 LCDが検出されました。
これがこのボードの外観です
テーマ別フォーラムをスクロールすると、 回路基板の概念に出会いました。
ボードは両面で、2つのKR1820VG1マイクロ回路で構成されています(はい、2つのうちすべて正しいです-図には4つありますが、ボードにインストールされていない要素のリストが示されています)。 このチップは、Texas Instruments COP472-3チップの完全なアナログです。 データシートを持ってきます。 ソビエト(またはロシア語?)デザイナーがそれさえクローンしたことに再び驚きました !
各マイクロサーキットは、インジケーターの4つのデジタル桁を制御できます(このインジケーターは8桁です)。 したがって、マイクロ回路の1つが4つの上位ビットを担当し、もう1つが下位の4つのビットを担当します。
また、エンジニアは、悪名高いK561LN2で収集されたインバーターを介してすべての信号を「通過」させました(理由-私は理解できませんでした。
接続
LCDモジュールは、6ピンX7コネクタでキャッシュレジスタのメインボードに接続されました。 ここで、コネクタにあるコンタクトの順序を再確認する必要がありました。
導体がどこに向かっているかを見て、MSP430への接続図を描きました。
ポートMSP430G2553はトレースに関係します。 方法:
- P1.1- ジュニアクリスタルチョイス
- P1.2- シニアクリスタルセレクション
- P1.5-時計
- P1.7-データ
アルゴリズム
KR1820VG1超小型回路の動作アルゴリズムは、1990年の有名な記事で、 レオニードイバノビッチリディコカークロック温度計-電圧計によって説明されています。 また、インターネットで、ジャーナルELECTRONICSの有用なスキャンが見つかりました:Science、Technology、Business 5/2007 。
次の図は、カスケードモードでの2つのKR1820VG1超小型回路の動作を示しています。 これはまさに私たちが使用しているものです。
サービスビットセットの名前は、ここでは「ジュニア1/2」と「シニア」です。
カスケードのVG1のアルゴリズムについて説明します。 「ボード操作アルゴリズム」を書くことは可能ですが、そうではありません。 すべてのボード入力にインバータをはんだ付けしたことを忘れないでください。
作業は、1)初期化と2)実際には動作モードで構成されます。
トレースが初期化されます。 方法:
1)両方のチップで設定します^ CS1,2 = 0;
2)32ビットのデータをライン「D」に渡します。
3)4ビットの特別なセグメントを提供します(このインジケーターでは、これらは数字の上にダッシュがあります)。
4)4つの制御ビット0111を発行します(表を参照してください。「BEST1」)。
5)両方のチップで設定します^ CS1,2 = 1;
6)シニアチップを選択^ CS2 = 0、データを受信します。
7)32ビットのデータを「D」ラインに渡します。 4ビットの特別なセグメントを提供します。 4つの制御ビット1000を出力します(表の「SENIOR」を参照)。
8)^ CS = 0。
初期化コードは次のようになります
/* * LCD */ void initLCD(){ P1OUT |= CS1+CS2; // ~CS "0" // ( - , "1") // spi_IO(0); spi_IO(0); spi_IO(0); spi_IO(0); // 4 spi_IO(0x07); // 4 + 4 P1OUT &= ~(CS1 + CS2); // ~CS=1 ( ) P1OUT |= CS2; // ~CS=0 - spi_IO(0); spi_IO(0); spi_IO(0); spi_IO(0); // 4 spi_IO(0x08); // 4 + 4 P1OUT &= ~(CS2 + CS1); // ~CS=1 (!) }
便利な機能
/* "1" */ void bit1() { P1OUT &= ~D; P1OUT &= ~CLK; P1OUT |= CLK; } /* "0" */ void bit0() { P1OUT |= D; P1OUT &= ~CLK; P1OUT |= CLK; } /* */ void spi_IO( unsigned int data ) { unsigned int i; for( i = 0; i < 8; i++ ) { // if( data & 0x80 ) bit1(); else bit0(); data <<= 1; } }
チップは動作モードに入ります。
ここで、データを上位/下位4デジタル桁(つまり、上位/下位チップ)に書き込むには、目的のチップを選択してすぐに書き込むことができます。
作業モード:
1)必要なチップを選択(最年少^ CS1 = 0または最高^ CS2 = 0);
2)32ビットのデータを送信します。
3)4ビットの特別なセグメントを送信します。
4)4つの制御ビット(最年少の「BEST2」の場合は0110、上級の場合は1000)を送信します。
5)チップ(項目1で選択されたチップ= 1)を「選別しています」。
トレイルを厳密に判断しないでください。 コードの一部。 最適化および最適化できますが、記事の目的はそれではありません:)
文字列出力を表示する
/* * * data - * n - * dot - () */ void print_LCD( char data[], char n, char dot ) { unsigned char copy[8]; unsigned char i; if(n<1) return ; if(n>8) n=8; for( i = 0; i < 8; i++ ) if(i+1>n) copy[i] = ' ' ; else copy[i] = data[i]; // // 4 P1OUT |= CS1; for(i=0;i<4;i++){ if( dot & 0x80 ) spi_IO(char2byte(copy[i])+0x80); else spi_IO(char2byte(copy[i])); dot <<= 1; } // 4 , ( ) bit0(); bit0(); bit0(); bit0(); // bit0(); bit1(); bit1(); bit0(); P1OUT &= ~CS1; // 4 P1OUT |= CS2; for(i=4; i<8; i++){ if( dot & 0x80 ) spi_IO(char2byte(copy[i])+0x80); else spi_IO(char2byte(copy[i])); dot <<= 1; } // 4 , ( ) bit0(); bit0(); bit0(); bit0(); // bit1(); bit0(); bit0(); bit0(); P1OUT &= ~CS2; }
これで、個々のセグメントを強調表示できます。 しかし、これはまったく面白くないので、キャラクタージェネレーターが必要です!
サインジェネレーター
この図では、コードパッケージのビットの順序を確認しています(アルゴリズムの段落2を参照)。
そして、これは典型的なLCD配線図です(ただし、「K」は数字の上にあり、ここでは下にあります)。
文字ジェネレータのコードでは、すべてがケースを通り抜けています。私は謝ります:)
キャラクタージェネレーターコード
/* * */ int char2byte( char ch ){ switch(ch){ case '1' : return 0x06; case '2' : return 0x5B; case '3' : return 0x4F; case '4' : return 0x66; case '5' : return 0x6D; case '6' : return 0x7D; case '7' : return 0x07; case '8' : return 0x7F; case '9' : return 0x6F; case 'O' : case 'o' : case '0' : return 0x3F; case 'a' : case 'A' : return 0x77; case 'b' : case 'B' : return 0x7C; case 'c' : case 'C' : return 0x39; case 'd' : case 'D' : return 0x5E; case 'e' : case 'E' : return 0x79; case 'f' : case 'F' : return 0x71; case '-' : return 0x40; case ' ' : return 0x00; case 'p' : case 'P' : return 0x73; case 'g' : case 'G' : return 0x31; case 'l' : case 'L' : return 0x38; case 'h' : case 'H' : return 0x76; case 'y' : case 'Y' : return 0x38; case 'r' : case 'R' : return 0x50; case 'u' : return 0x1C; case 'U' : return 0x3E; case '|' : return 0x30; case '~' : return 0x01; // case '_' : return 0x08; // case '=' : return 0x09; // case 'j' : return 0x21; // ( - // jkmn ) case 'k' : return 0x03; // case 'm' : return 0x0C; // case 'n' : return 0x18; // default: return 0x00; } }
次に、いくつかのデモ関数が作成されました。これらは記事の最後のリンクで見ることができます。
あとがき
LCDボードは5Vで動作します。 MSP430ランチパッドでは、3.3Vのみが配線されます。 それらから、ボードも動作しますが、非常に退屈です。 おそらく、抵抗R3 *を選択することで必要な明るさを実現できますが、USB入力でピンをはんだ付けし、5Vを削除しても機能します:)
また、このボードでは、数字の上位4セグメントが右側にあり、若いセグメントが左側にあることに注意してください。
完全なファームウェアコードは、 ここからダウンロードできます。
見るために
かすかな心を覗かないでください。
#include <msp430g2553.h> #define CS1 BIT1 // #define CS2 BIT2 // #define CLK BIT5 // #define D BIT7 // char flag_next=0; // ( ) /* "1" */ void bit1() { P1OUT &= ~D; P1OUT &= ~CLK; P1OUT |= CLK; } /* "0" */ void bit0() { P1OUT |= D; P1OUT &= ~CLK; P1OUT |= CLK; } /* * ( ) */ void delay( unsigned int ms) { while (ms--) __delay_cycles(16000); } /* */ void spi_IO( unsigned int data ) { unsigned int i; for( i = 0; i < 8; i++ ) { // if( data & 0x80 ) bit1(); else bit0(); data <<= 1; } } /* * */ int char2byte( char ch ){ switch(ch){ case '1' : return 0x06; case '2' : return 0x5B; case '3' : return 0x4F; case '4' : return 0x66; case '5' : return 0x6D; case '6' : return 0x7D; case '7' : return 0x07; case '8' : return 0x7F; case '9' : return 0x6F; case 'O' : case 'o' : case '0' : return 0x3F; case 'a' : case 'A' : return 0x77; case 'b' : case 'B' : return 0x7C; case 'c' : case 'C' : return 0x39; case 'd' : case 'D' : return 0x5E; case 'e' : case 'E' : return 0x79; case 'f' : case 'F' : return 0x71; case '-' : return 0x40; case ' ' : return 0x00; case 'p' : case 'P' : return 0x73; case 'g' : case 'G' : return 0x31; case 'l' : case 'L' : return 0x38; case 'h' : case 'H' : return 0x76; case 'y' : case 'Y' : return 0x38; case 'r' : case 'R' : return 0x50; case 'u' : return 0x1C; case 'U' : return 0x3E; case '|' : return 0x30; case '~' : return 0x01; // case '_' : return 0x08; // case '=' : return 0x09; // case 'j' : return 0x21; // ( - // jkmn ) case 'k' : return 0x03; // case 'm' : return 0x0C; // case 'n' : return 0x18; // default: return 0x00; } } /* * * data - * n - * dot - () */ void print_LCD( char data[], char n, char dot ) { unsigned char copy[8]; unsigned char i; if(n<1) return ; if(n>8) n=8; for( i = 0; i < 8; i++ ) if(i+1>n) copy[i] = ' ' ; else copy[i] = data[i]; // // 4 P1OUT |= CS1; for(i=0;i<4;i++){ if( dot & 0x80 ) spi_IO(char2byte(copy[i])+0x80); else spi_IO(char2byte(copy[i])); dot <<= 1; } // 4 , ( ) bit0(); bit0(); bit0(); bit0(); // bit0(); bit1(); bit1(); bit0(); P1OUT &= ~CS1; // 4 P1OUT |= CS2; for(i=4; i<8; i++){ if( dot & 0x80 ) spi_IO(char2byte(copy[i])+0x80); else spi_IO(char2byte(copy[i])); dot <<= 1; } // 4 , ( ) bit0(); bit0(); bit0(); bit0(); // bit1(); bit0(); bit0(); bit0(); P1OUT &= ~CS2; } /* * LCD */ void initLCD(){ P1OUT |= CS1+CS2; // ~CS "0" // ( - , "1") // spi_IO(0); spi_IO(0); spi_IO(0); spi_IO(0); // 4 spi_IO(0x07); // 4 + 4 P1OUT &= ~(CS1 + CS2); // ~CS=1 ( ) P1OUT |= CS2; // ~CS=0 - spi_IO(0); spi_IO(0); spi_IO(0); spi_IO(0); // 4 spi_IO(0x08); // 4 + 4 P1OUT &= ~(CS2 + CS1); // ~CS=1 (!) } /* * */ void clear_LCD() { print_LCD( " " , 8, 0); // - } /* * */ void demo() { int demo_n = 1; while(1){ switch(demo_n){ case 0:{ int ms=50; while(1){ print_LCD("~~ " ,8,0); delay(ms); print_LCD(" ~~ " ,8,0); delay(ms); print_LCD(" ~~ " ,8,0); delay(ms); print_LCD(" ~~ " ,8,0); delay(ms); print_LCD(" ~~ " ,8,0); delay(ms); print_LCD(" ~~ " ,8,0); delay(ms); print_LCD(" ~~" ,8,0); delay(ms); print_LCD(" k" ,8,0); delay(ms); print_LCD(" 1" ,8,0); delay(ms); print_LCD(" m" ,8,0); delay(ms); print_LCD(" __" ,8,0); delay(ms); print_LCD(" __ " ,8,0); delay(ms); print_LCD(" __ " ,8,0); delay(ms); print_LCD(" __ " ,8,0); delay(ms); print_LCD(" __ " ,8,0); delay(ms); print_LCD(" __ " ,8,0); delay(ms); print_LCD("__ " ,8,0); delay(ms); print_LCD("n " ,8,0); delay(ms); print_LCD("| " ,8,0); delay(ms); print_LCD("j " ,8,0); delay(ms); if(flag_next==1) { demo_n=1; flag_next=0; break; } } } case 1:{ clear_LCD(); while(1){ print_LCD( " H" , 8, 0); delay(200); print_LCD( " HE" , 8, 0); delay(200); print_LCD( " HEL" , 8, 0); delay(200); print_LCD( " HELL", 8, 0); delay(200); print_LCD( " HELLO", 8, 0); delay(200); print_LCD( " HELLO ", 8, 0); delay(200); print_LCD( " HELLO ", 8, 0); delay(1000); print_LCD( "HELLO ", 8, 0); delay(200); print_LCD( "ELLO ", 8, 0); delay(200); print_LCD( "LLO " , 8, 0); delay(200); print_LCD( "LO " , 8, 0); delay(200); print_LCD( "O " , 8, 0); delay(200); print_LCD( " H" , 8, 0); delay(200); print_LCD( " HA" , 8, 0); delay(200); print_LCD( " HAB" , 8, 0); delay(200); print_LCD( " HABR", 8, 1); delay(200); print_LCD( " HABRR", 8, 2); delay(200); print_LCD( " HABRRu", 8, 4); delay(200); print_LCD( " HABRRu ", 8, 8); delay(1000); print_LCD( "HABRRu ", 8, 16); delay(200); print_LCD( "ABRRu ", 8, 32); delay(200); print_LCD( "BRRu ", 8, 64); delay(200); print_LCD( "RRu " , 8, 128); delay(200); print_LCD( "Ru " , 8, 0); delay(200); print_LCD( "u " , 8, 0); delay(200); if(flag_next==1) { demo_n=2; flag_next=0; break; } } //while } case 3:{ clear_LCD(); int ms=50; while(1){ print_LCD( "~~~~~~~~",8,0); delay(ms); print_LCD( "kkkkkkkk ",8,0); delay(ms); print_LCD( "11111111",8,0); delay(ms); print_LCD( "mmmmmmmm ",8,0); delay(ms); print_LCD( "nnnnnnnn ",8,0); delay(ms); print_LCD( "||||||||",8,0); delay(ms); print_LCD( "jjjjjjjj ",8,0); delay(ms); if(flag_next==1) { demo_n=0; flag_next=0; break; } } } } } } /* * main.c */ void main( void) { // WDTCTL = WDTPW + WDTHOLD; // - delay() BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; // These are the pins we need to drive. P1DIR |= CLK + D + CS1 + CS2; P1SEL &= ~BIT3; // 1.3 P1DIR &= ~BIT3; // Port 1 P1.3 (push button) as input, 0 is input P1REN |= BIT3; // P1IE |= BIT3; // P1IFG &= ~BIT3; // delay(500); // , initLCD(); // LCD __bis_SR_register(GIE); // demo(); // } #pragma vector=PORT1_VECTOR __interrupt void Port_1( void) { P1IFG &= ~BIT3; // flag_next=1; // }
さて、仕事の小さなビデオ
非常に興味深いヒント、コメント、コメント!
誰かがこの情報が役立つことを願っています。
ありがとう、また会いましょう。
PSそしてまたMinikのようなクールなサーマルプリンター...;)