PR 記事には広告が含まれています
スポンサーリンク
Translate

Padaukマイコンで5ビットバイナリを10進数表示する表示器を作りました

スポンサーリンク

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インサーキット書き込み機を経由して、マイコンの信号をブレッドボードへ取り出します。

インサーキット書き込み機を使うことで、プログラムを書き換える度にマイコンをブレッドボードから抜いて書き込み機に接続するという作業が不要になり、試行しやすくなります。

書き込み機にはこれを使っています。

Padaukマイコンライターキット | kohacraftのshop
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進数で表示する表示器が作れました。

Padaukマイコンライターキット | kohacraftのshop
Padaukマイコンにドラッグ&ドロップで書き込めるライターキットです