Padaukマイコンを使って、1と0で表現された2進数の値を、普通の数字の10進数で表示する表示器を作りました。
まずは7セグの制御プログラム
回路図
カソードコモンの7セグメントLED2つを使って、2桁の数字を表現できるようにします。
マイコンにはPadauk PFS123を使います。PadaukのマイコンはPA5だけがオープンドレイン出力になっていて、電流の吸い込みしかできません。そこで、PA5を7セグメントのカソードコモンに接続することにしました。
2桁ありますが、2桁同時に点灯させるのではなく、1桁目を点灯させたら一旦消して、次に2桁目だけを点灯させて一旦消して、また1桁目というように、2つの桁を交互にダイナミック点灯をさせます。こうすることで、セグメントaからセグメントgまでの配線を共通化し、配線の本数を減らします。
プログラム
#include <pdk/device.h> #include <stdint.h> #include "auto_sysclock.h" #include "delay.h" #define SEGA_BIT 0 #define SEGA_PORT PA #define SEGA_PORTCONT PAC #define SEGB_BIT 3 #define SEGB_PORT PA #define SEGB_PORTCONT PAC #define SEGC_BIT 4 #define SEGC_PORT PA #define SEGC_PORTCONT PAC #define SEGD_BIT 7 #define SEGD_PORT PA #define SEGD_PORTCONT PAC #define SEGE_BIT 5 #define SEGE_PORT PB #define SEGE_PORTCONT PBC #define SEGF_BIT 6 #define SEGF_PORT PB #define SEGF_PORTCONT PBC #define SEGG_BIT 7 #define SEGG_PORT PB #define SEGG_PORTCONT PBC #define DIGIT1_BIT 5 #define DIGIT1_PORT PA #define DIGIT1_PORTCONT PAC #define DIGIT2_BIT 6 #define DIGIT2_PORT PA #define DIGIT2_PORTCONT PAC #define SEGA_OFF() SEGA_PORT &= ~(1 << SEGA_BIT) #define SEGA_ON() SEGA_PORT |= (1 << SEGA_BIT) #define SEGB_OFF() SEGB_PORT &= ~(1 << SEGB_BIT) #define SEGB_ON() SEGB_PORT |= (1 << SEGB_BIT) #define SEGC_OFF() SEGC_PORT &= ~(1 << SEGC_BIT) #define SEGC_ON() SEGC_PORT |= (1 << SEGC_BIT) #define SEGD_OFF() SEGD_PORT &= ~(1 << SEGD_BIT) #define SEGD_ON() SEGD_PORT |= (1 << SEGD_BIT) #define SEGE_OFF() SEGE_PORT &= ~(1 << SEGE_BIT) #define SEGE_ON() SEGE_PORT |= (1 << SEGE_BIT) #define SEGF_OFF() SEGF_PORT &= ~(1 << SEGF_BIT) #define SEGF_ON() SEGF_PORT |= (1 << SEGF_BIT) #define SEGG_OFF() SEGG_PORT &= ~(1 << SEGG_BIT) #define SEGG_ON() SEGG_PORT |= (1 << SEGG_BIT) #define DIGIT1_OFF() DIGIT1_PORT |= (1 << DIGIT1_BIT) #define DIGIT1_ON() DIGIT1_PORT &= ~(1 << DIGIT1_BIT) #define DIGIT2_OFF() DIGIT2_PORT |= (1 << DIGIT2_BIT) #define DIGIT2_ON() DIGIT2_PORT &= ~(1 << DIGIT2_BIT) void setSeg( char num ) { switch (num) { case 0: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_ON(); SEGE_ON(); SEGF_ON(); SEGG_OFF(); break; case 1: SEGA_OFF(); SEGB_ON(); SEGC_ON(); SEGD_OFF(); SEGE_OFF(); SEGF_OFF(); SEGG_OFF(); break; case 2: SEGA_ON(); SEGB_ON(); SEGC_OFF(); SEGD_ON(); SEGE_ON(); SEGF_OFF(); SEGG_ON(); break; case 3: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_ON(); SEGE_OFF(); SEGF_OFF(); SEGG_ON(); break; case 4: SEGA_OFF(); SEGB_ON(); SEGC_ON(); SEGD_OFF(); SEGE_OFF(); SEGF_ON(); SEGG_ON(); break; case 5: SEGA_ON(); SEGB_OFF(); SEGC_ON(); SEGD_ON(); SEGE_OFF(); SEGF_ON(); SEGG_ON(); break; case 6: SEGA_ON(); SEGB_OFF(); SEGC_ON(); SEGD_ON(); SEGE_ON(); SEGF_ON(); SEGG_ON(); break; case 7: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_OFF(); SEGE_OFF(); SEGF_OFF(); SEGG_OFF(); break; case 8: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_ON(); SEGE_ON(); SEGF_ON(); SEGG_ON(); break; case 9: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_ON(); SEGE_OFF(); SEGF_ON(); SEGG_ON(); break; default: SEGA_OFF(); SEGB_OFF(); SEGC_OFF(); SEGD_OFF(); SEGE_OFF(); SEGF_OFF(); SEGG_OFF(); break; } } void main() { PDK_USE_FACTORY_IHRCR_16MHZ(); PDK_USE_FACTORY_BGTR(); AUTO_INIT_SYSCLOCK(); CLKMD &= ~CLKMD_ENABLE_WATCHDOG; // Disenable WDT SEGA_PORTCONT |= (1 << SEGA_BIT); // Set SEG pin as output SEGB_PORTCONT |= (1 << SEGB_BIT); // Set SEG pin as output SEGC_PORTCONT |= (1 << SEGC_BIT); // Set SEG pin as output SEGD_PORTCONT |= (1 << SEGD_BIT); // Set SEG pin as output SEGE_PORTCONT |= (1 << SEGE_BIT); // Set SEG pin as output SEGF_PORTCONT |= (1 << SEGF_BIT); // Set SEG pin as output SEGG_PORTCONT |= (1 << SEGG_BIT); // Set SEG pin as output DIGIT1_PORTCONT |= (1 << DIGIT1_BIT); // Set DIGIT pin as output DIGIT2_PORTCONT |= (1 << DIGIT2_BIT); // Set DIGIT pin as output SEGA_OFF(); SEGB_OFF(); SEGC_OFF(); SEGD_OFF(); SEGE_OFF(); SEGF_OFF(); SEGG_OFF(); DIGIT1_OFF(); DIGIT2_OFF(); while(1) { for(char i = 0 ; i<100 ; i++) { for(int j=0 ; j<20 ; j++) { char num = i%10; setSeg(num); DIGIT1_ON(); _delay_ms(2); DIGIT1_OFF(); num = i/10; setSeg(num); DIGIT2_ON(); _delay_ms(2); DIGIT2_OFF(); } } } }
6から33行目が各IOポートを定義、35から53がIOの操作の定義です。
setSeg関数で、指定された値を7セグメントLEDに表示します。
まずは、ダイナミック点灯の試験を兼ねて、00から99までカウントアップするプログラムにしました。
ブレッドボードに組み立て
先日作ったPadaukインサーキット書き込み機を経由して、マイコンの信号をブレッドボードへ取り出します。
インサーキット書き込み機を使うことで、プログラムを書き換える度にマイコンをブレッドボードから抜いて書き込み機に接続するという作業が不要になり、試行しやすくなります。
書き込み機にはこれを使っています。
実行
無事に2桁の数字を表示できました。
5ビット入力を追加
回路図
先ほどの回路に、5ビットの入力を追加しました。PadaukのIOはプルアップの設定ができるので、入力ピンをオープンにするとで1を入力し、グランドにショートすることで0を入力することにします。
プログラム
#include <pdk/device.h> #include <stdint.h> #include "auto_sysclock.h" #include "delay.h" #define SEGA_BIT 0 #define SEGA_PORT PA #define SEGA_PORTCONT PAC #define SEGB_BIT 3 #define SEGB_PORT PA #define SEGB_PORTCONT PAC #define SEGC_BIT 4 #define SEGC_PORT PA #define SEGC_PORTCONT PAC #define SEGD_BIT 7 #define SEGD_PORT PA #define SEGD_PORTCONT PAC #define SEGE_BIT 5 #define SEGE_PORT PB #define SEGE_PORTCONT PBC #define SEGF_BIT 6 #define SEGF_PORT PB #define SEGF_PORTCONT PBC #define SEGG_BIT 7 #define SEGG_PORT PB #define SEGG_PORTCONT PBC #define DIGIT1_BIT 5 #define DIGIT1_PORT PA #define DIGIT1_PORTCONT PAC #define DIGIT2_BIT 6 #define DIGIT2_PORT PA #define DIGIT2_PORTCONT PAC #define SEGA_OFF() SEGA_PORT &= ~(1 << SEGA_BIT) #define SEGA_ON() SEGA_PORT |= (1 << SEGA_BIT) #define SEGB_OFF() SEGB_PORT &= ~(1 << SEGB_BIT) #define SEGB_ON() SEGB_PORT |= (1 << SEGB_BIT) #define SEGC_OFF() SEGC_PORT &= ~(1 << SEGC_BIT) #define SEGC_ON() SEGC_PORT |= (1 << SEGC_BIT) #define SEGD_OFF() SEGD_PORT &= ~(1 << SEGD_BIT) #define SEGD_ON() SEGD_PORT |= (1 << SEGD_BIT) #define SEGE_OFF() SEGE_PORT &= ~(1 << SEGE_BIT) #define SEGE_ON() SEGE_PORT |= (1 << SEGE_BIT) #define SEGF_OFF() SEGF_PORT &= ~(1 << SEGF_BIT) #define SEGF_ON() SEGF_PORT |= (1 << SEGF_BIT) #define SEGG_OFF() SEGG_PORT &= ~(1 << SEGG_BIT) #define SEGG_ON() SEGG_PORT |= (1 << SEGG_BIT) #define DIGIT1_OFF() DIGIT1_PORT |= (1 << DIGIT1_BIT) #define DIGIT1_ON() DIGIT1_PORT &= ~(1 << DIGIT1_BIT) #define DIGIT2_OFF() DIGIT2_PORT |= (1 << DIGIT2_BIT) #define DIGIT2_ON() DIGIT2_PORT &= ~(1 << DIGIT2_BIT) void setSeg( char num ) { switch (num) { case 0: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_ON(); SEGE_ON(); SEGF_ON(); SEGG_OFF(); break; case 1: SEGA_OFF(); SEGB_ON(); SEGC_ON(); SEGD_OFF(); SEGE_OFF(); SEGF_OFF(); SEGG_OFF(); break; case 2: SEGA_ON(); SEGB_ON(); SEGC_OFF(); SEGD_ON(); SEGE_ON(); SEGF_OFF(); SEGG_ON(); break; case 3: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_ON(); SEGE_OFF(); SEGF_OFF(); SEGG_ON(); break; case 4: SEGA_OFF(); SEGB_ON(); SEGC_ON(); SEGD_OFF(); SEGE_OFF(); SEGF_ON(); SEGG_ON(); break; case 5: SEGA_ON(); SEGB_OFF(); SEGC_ON(); SEGD_ON(); SEGE_OFF(); SEGF_ON(); SEGG_ON(); break; case 6: SEGA_ON(); SEGB_OFF(); SEGC_ON(); SEGD_ON(); SEGE_ON(); SEGF_ON(); SEGG_ON(); break; case 7: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_OFF(); SEGE_OFF(); SEGF_OFF(); SEGG_OFF(); break; case 8: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_ON(); SEGE_ON(); SEGF_ON(); SEGG_ON(); break; case 9: SEGA_ON(); SEGB_ON(); SEGC_ON(); SEGD_ON(); SEGE_OFF(); SEGF_ON(); SEGG_ON(); break; default: SEGA_OFF(); SEGB_OFF(); SEGC_OFF(); SEGD_OFF(); SEGE_OFF(); SEGF_OFF(); SEGG_OFF(); break; } } void main() { PDK_USE_FACTORY_IHRCR_16MHZ(); PDK_USE_FACTORY_BGTR(); AUTO_INIT_SYSCLOCK(); CLKMD &= ~CLKMD_ENABLE_WATCHDOG; // Disenable WDT PBC = 0; //PortB All Input PBPH = 0x1F; //PullUp b0-b5 PBDIER = 0x1F; //Input b0-b5 SEGA_PORTCONT |= (1 << SEGA_BIT); // Set SEG pin as output SEGB_PORTCONT |= (1 << SEGB_BIT); // Set SEG pin as output SEGC_PORTCONT |= (1 << SEGC_BIT); // Set SEG pin as output SEGD_PORTCONT |= (1 << SEGD_BIT); // Set SEG pin as output SEGE_PORTCONT |= (1 << SEGE_BIT); // Set SEG pin as output SEGF_PORTCONT |= (1 << SEGF_BIT); // Set SEG pin as output SEGG_PORTCONT |= (1 << SEGG_BIT); // Set SEG pin as output DIGIT1_PORTCONT |= (1 << DIGIT1_BIT); // Set DIGIT pin as output DIGIT2_PORTCONT |= (1 << DIGIT2_BIT); // Set DIGIT pin as output SEGA_OFF(); SEGB_OFF(); SEGC_OFF(); SEGD_OFF(); SEGE_OFF(); SEGF_OFF(); SEGG_OFF(); DIGIT1_OFF(); DIGIT2_OFF(); while(1) { char bitInput = PB & 0x1F; char num = bitInput%10; setSeg(num); DIGIT1_ON(); _delay_ms(2); DIGIT1_OFF(); num = bitInput/10; setSeg(num); DIGIT2_ON(); _delay_ms(2); DIGIT2_OFF(); } }
168-710行でポートBの下位5ビットを入力に設定し、プルアップも設定しています。Padaukのポートを入力に設定するには、PBC(ポートBコントロールレジスタ)に0をセットし、PBDIER(ポートBデジタルインプットイネーブルレジスタ)に1をセットします。
1桁目の値は、196行のように10で割った余りを使用し、2桁目の値は202行目のように、10で割った値を使用します。
プログラム全体を、上に貼っておきます。
実行
スイッチを操作することで、0から31まで数字を表示することができました。
基板に実装
ブレッドボードで、正常に動作することがわかったので、基板上に回路を組み立てました。
Padaukマイコンを使うことで、シンプルにバイナリの値を10進数で表示する表示器が作れました。
コメント