JH7UBCブログ

アマチュア無線 電子工作 家庭菜園など趣味のブログです

PIC16F1827 MAX7219 8×7セグメントLED表示テスト その2

2023-05-24 11:24:22 | PIC16F1827
 前の記事の続きです。
 PIC16F1827でMAX7219使用の8×7セグメントLEDに数値を表示するテストをします。

 一般に良く利用されるLCD表示器LCD1602などの場合、キャラクタコードを送るだけでよいのですが、MAX7219の場合は、Digit番号と数値を送る必要があります。そこで、PIC内の数値(バイナリ)を10進数に変換しなければなりません。

 以前、ArduinoでMAX7219のテストをしたときには、数値を文字列に変換し、LEDに表示するために、アスキーコードを数値に変換しました。その記事はこちら

  今回は、簡単なアルゴリズムで数値(バイナリ)から表示用のデータを取り出すことにしました。10のn乗で割って、商と剰余を計算し、その都度、商を表示する方法です。
 例えば数値 n=12345678とした場合、表示器の桁数が8桁ですので、除数josu=10000000で割ります。商は sho=12345678 / 10000000 = 1 です。このshoの値をDigit8にセットすればいいわけです。この時、余り(剰余)は、joyo=12345678 % 10000000 = 2345678となります。
 このjoyoをnとして、次は除数を1/10にして、josu=1000000として、同じ計算をして、Digit7にセットします。以下この繰り返しになります。
 このままだと小さい数値の場合に上位に「0」が表示されてしまいますので、ゼロ消しをします。最初にゼロフラッグzflagを立てておいて、最初の数値がゼロでなくなったときにゼロフラッグを下ろします。ゼロフラッグが立っている時には「0」ではなく、「空白」を表示するようにします。

 これをプログラムにすると次のようになります。
-------------------------------------------------------
//数値を表示する
void Num_Display(uint32_t n){
     uint32_t josu = 10000000;
     uint8_t sho;
     uint32_t joyo;
     uint8_t i=8;
     uint8_t zflag = 1;
     while(i){
         sho = n / josu;
         joyo = n % josu;
         if(zflag==1 && sho==0){
             sho = 0x0f; //空白
         }
         else{
             zflag = 0;
         }
          maxTransfer(i,sho);
         n = joyo;
         josu = josu / 10;
         i--;
    }
}
-------------------------------------------------------

 mainルーチンに
uint32_t k = 0;
     while(1){
         Num_Display(k);
         k++;
         __delay_ms(100);
    }
を書き込んで、0.1秒ごとに数値をカウントアップさせてみました。
その時の様子です。ゼロ消しがされた数値が表示され、カウントアップされました。


 もっとうまい方法があると思うのですが、とりあえず表示されました。

PIC16F1827 MAX7219 8×7セグメントLED表示テスト その1

2023-05-23 14:12:59 | PIC16F1827
 昨年の秋、MPLAB X + XC8 + MCC環境下で、PIC16F1827を使って、MAX7219使用8桁7セグメントLEDの表示テストをしました。しかし、うまくいきませんでした。

 MCCを使うとCONFIGの設定や各設定が格段に楽になるのですが、その分ブラックボックス化され、いざ不具合を見つけようとすると難しくなります。

 そこで、今回はMCCを使わないで、XC8だけでテストをしてみます。MAX7219使用8桁7セグメントLEDの表示テストについては、Arduinoで既に行っており(当ブログでの記事はこちら)、今回はそのスケッチをMPLAB Xに移植する形で行いました。

 テストした回路図です。PIC16F1827のクロックは、今後周波数カウンタへの発展を考えて、外部クロック(クリスタルオシレータ20MHz)を使っています。

 MAX7219のコントロールは、SPIで行います。その時のタイミングチャートです。(MAX7219の説明書より)
 CSを1から0にしてデータ転送を開始します。CLKの立ち上がりでDINの値が読み込まれます。8bitデータを送ったらCSを1に戻します。

 PIC16G1827でSPIのタイミングを決めるのは、SSPXCON1レジスタとSSPXSTATレジスタです。今回はSSP1を使いますのでX=1とします。
 まず、SSP1CON1レジスタの設定です。(必要な部分だけ設定します)



 SSP1を有効にするため、SSP1EN=1とします。
 クロックの極性は常時Lowでアクティブ時にHighですので、CKP=0とします。
 次に、SSP1STATレジスタの設定をします。


 クロックエッジCKEは、CKP=0のとき立ち上がりを指定のCKE=1とします。サンプル位置は中央でSMP=0とします。
 以上の条件で、PIC16F1827のSPI出力をpico scopeで確認してみました。
 SSP1BUF=0x55(0b01010101)として出力しました。
 
 MAX7219のタイミングに合っています。OKです。
 テストしたプログラムです。
--------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

// CONFIG1
#pragma config FOSC = ECH       //外部クロック
#pragma config WDTE = OFF       //ウオッチドックタイマーを使わない
#pragma config PWRTE = ON       //パワーアップタイマーON
#pragma config MCLRE = OFF      //外部リセット信号は使用しない、
#pragma config CP = OFF         //プログラムメモリーを保護しない
#pragma config CPD = OFF        //データメモリーを保護しない
#pragma config BOREN = ON       //ブラウンアウト リセット 有効
#pragma config CLKOUTEN = OFF   //Clock Out OFF
#pragma config IESO = OFF       //外部・内部クロックの切替えでの起動はなし
#pragma config FCMEN = OFF      //外部クロック監視しない

// CONFIG2
#pragma config WRT = OFF        //Flashメモリーを保護しない
#pragma config PLLEN = OFF      //PLLを使わない
#pragma config STVREN = ON      //スタックがオーバフローやアンダーフローしたらリセットをする
#pragma config BORV = HI        //電源電圧降下常時監視電圧(2.5V)設定(HI)
#pragma config LVP = OFF        //低電圧プログラミング機能使用しない

#define _XTAL_FREQ 20000000 //クロック20MHz
#define CS LATBbits.LATB3

// MAX7219 Register Address
#define MAX7219_DECODE_MODE 0x09
#define MAX7219_INTENSITY 0x0a
#define MAX7219_SCAN_LIMIT 0x0b
#define MAX7219_SHUTDOWN 0x0C
#define MAX7219_DISPLAY_TEST 0x0f

void SPI_init(){
     SSP1CON1 = 0b00100000; //SSP1EN=1:SSP1 Enable,CKP=0:Idle Low,Clock=FOSC/4
     SSP1STAT = 0b01000000; //SMP=0:middle,CKE=1:Active to Idle
}

void maxTransfer(uint8_t address,uint8_t data){
     CS = 0;
     uint8_t dammy;
     //send address
     dammy = SSP1BUF;
     SSP1BUF = address;
     while(!SSP1STATbits.BF);
     //send data
     dammy = SSP1BUF;
     SSP1BUF = data;
     while(!SSP1STATbits.BF);
     CS =1;
}

void MAX7219_init(){
     maxTransfer(MAX7219_DECODE_MODE, 0xff);// Code B decode for digits 7-0
     maxTransfer(MAX7219_INTENSITY, 0x03); // Intensity
     maxTransfer(MAX7219_SCAN_LIMIT, 0x07);// Display digits 01234567
     maxTransfer(MAX7219_SHUTDOWN, 0x01);// Normal Operation
     maxTransfer(MAX7219_DISPLAY_TEST, 0x00);// Normal Operation
}

void Clear_Display(){
     for(uint8_t i=1;i<=8;i++){
         maxTransfer(i,0x0f);
    }
}

void main(){
     ANSELA = 0b00000000 ; // AN0-AN4は使用しない
     ANSELB = 0b00000000 ; // AN5-AN11は使用しない
     TRISA = 0b00000000 ; // PORTAは全て出力(RA5は入力)
     TRISB = 0b00000000 ; // PORTBは全て出力
     PORTA = 0b00000000 ; // PORTA初期化
     PORTB = 0b00000000 ; // PORTB初期化
     CS = 1; //CS初期値
     SPI_init();      //SPI初期化
     MAX7219_init();  //MAX7219初期化
     Clear_Display(); //ディスプレイクリア

for(uint8_t i=1;i<=8;i++){    
     maxTransfer(i,i);
     __delay_ms(1000);
}

     while(1){
         maxTransfer(MAX7219_DISPLAY_TEST, 0x01);// 全点灯
         __delay_ms(500);
         maxTransfer(MAX7219_DISPLAY_TEST, 0x00);// normal mode
         __delay_ms(500);        
    }
}
--------------------------------------------------------------------
 ディスプレイをクリアした後、Digit0からDigit7に1から8を表示し、その後、全点灯とノーマル表示を0.5秒ごとに表示します。

 ノーマル表示の様子です。数10mA程度の電流が流れます。

 全点灯の様子です。200mA程度電流が流れます。


今日は種まき

2023-05-20 14:43:31 | 家庭菜園と花
 昨日は雨が降り、肌寒かったのですが、今日は薄曇りから午後になって日差しも出てきました。

 ということで、今日は野菜の種を蒔きました。


 手前のネットがコマツナとチンゲンサイ。奥のネットがハツカダイコンです。無農薬農法ですので、虫に食べられないようにネットを張って大事に育てます。

 どりらも6月中旬には収穫できると思います。

 タワーの北側に名付けて「落ちこぼれ花壇」があります。自分で種まきはせず、あちこちからこぼれてきり、貰い物だったりする花を咲かせる花壇です。


 カーネーションの一種とオルレア(白い花)が咲いています。
 それから、その辺に咲いていたものを移植したビオラが咲いています。

ナス苗の定植

2023-05-16 15:01:20 | 家庭菜園と花
 今日は朝から五月晴れの気持ちの良い日です。

 先週9日(火)にコメリからナスやトマトなどの苗を購入しました。


 その後、寒いくらいの日が続いたので、1週間待って今日、ナス苗を植えつけました。



 ナスの種類は、このところ毎年植えている「超やわらかナス」、去年から植え始めた「長ナス」、それから「米ナス」と「白ナス」を植えてみました。

 普通、ナスは60cm間隔で植えますが、私は広めの1m間隔で植えつけました。ほとんど剪定しないで株を大きく育てるためです。さて、今年はどんな出来になるでしょうか。

 この後、トマト、ピーマン、シシトウ、ズッキーニの苗を植えつけます。

5月17日追記

 今日も朝から快晴。午前中に残った苗を植えつけました。

 まず、ピーマン2本とシシトウ、パプリカ。

 続いて、トマト6本とズッキーニ2本を植えつけました。

 トマトは今年も横向きに寝かせて植えつけました。
 茎が立ち上がってきたら支柱を立てます。