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進数で表示する表示器が作れました。












コメント