2018-10-31に更新

8ピンPIC用のデバッグモニタ作成

読了目安:10分

キャラクタLCDを購入していたのだがずっと触らずに放置していた。
色々調べてみるときむ茶さんのところに
デバッグモニターの作成
という記事があったのだが、面倒くさそうだし
LCDの操作自体はシンプルそうなので必要な時に
ピン数の多いICで直接操作すればいいかな、くらいの感じで考えていた。

別でmTouchというタッチセンサっぽいものが気になったので
PIC12F1822を購入していたのだがずっと手を付けずにいた。
ようやくやってみようという気になって色々調べてみたところ、
どうも離している時と触っている時の充電、放電の回数をカウントする必要があるらしく、
ちゃんと大きな数値をデバッグできないと作成が出来ないっぽいことがわかった。

なるほど、だからデバッグモニタを作成する必要があったのか…と理解。
この方法なら1ピンでモニタを操作できることになる。

さて、やってみようと思いきや記事に書かれている
モニタを直接操作するためのICがない。
手元にある8ビットの安いICはPIC18F14K50くらい。
20ピンもあるのでなんとなくもったいない気がしたが
とりあえずブレッドボードで仮に作成してみることにした。

でよくよく記事を見ると、どうもソフトウェアでシリアル通信をしているらしい。
でもちょっとまてよ、PIC18F14K50は普通にシリアル通信に対応してたはず。
もしかするとこのシリアル通信とソフトウェアシリアルで通信できるんだろうか?
そう思いPIC18F14K50は普通にシリアル通信の機能を使ってやってみることにした。

下記がPIC18F14K50側のプログラム。

|c|

include <xc.h>

include <stdlib.h>

include "skUARTlib.h"

if defined _18F14K50

pragma config FOSC = IRC, PLLEN = ON, FCMEN = OFF

pragma config IESO = OFF, USBDIV = OFF, CPUDIV = NOCLKDIV

pragma config PWRTEN = ON, BOREN = ON, WDTEN = OFF

pragma config HFOFST = OFF, MCLRE = OFF

pragma config STVREN = ON, BBSIZ = OFF, LVP = OFF

pragma config XINST = OFF

pragma config CP0 = OFF, CP1 = OFF, CPB = OFF

pragma config WRT0 = OFF, WRT1 = OFF, WRTB = OFF, WRTC = OFF

pragma config EBTR0 = OFF, EBTR1 = OFF, EBTRB = OFF

define _XTAL_FREQ 8000000 // CLK 12MHz (use from __delay_ms)

define LCD_RS PORTCbits.RC0

define LCD_EN PORTCbits.RC1

define LCD_D4 PORTCbits.RC3

define LCD_D5 PORTCbits.RC4

define LCD_D6 PORTCbits.RC5

define LCD_D7 PORTCbits.RC6

endif

define LCD_STROBE() ((LCD_EN=1),(LCD_EN=0))

void Wait(unsigned int num)
{
int i ;

 // numで指定した回数だけ繰り返す
 for (i=0 ; i&lt;num ; i++) {
      __delay_ms(10) ;     // 10msプログラムの一時停止
 }

}

void lcd_write(unsigned char c)
{
// 送信データのバイト列上位4ビットを処理
LCD_D4 = ( ( c >> 4 ) & 0x01 ) ;
LCD_D5 = ( ( c >> 5 ) & 0x01 ) ;
LCD_D6 = ( ( c >> 6 ) & 0x01 ) ;
LCD_D7 = ( ( c >> 7 ) & 0x01 ) ;
LCD_STROBE() ;
// 送信データのバイト列下位4ビットを処理
LCD_D4 = ( ( c ) & 0x01 ) ;
LCD_D5 = ( ( c >> 1 ) & 0x01 ) ;
LCD_D6 = ( ( c >> 2 ) & 0x01 ) ;
LCD_D7 = ( ( c >> 3 ) & 0x01 ) ;
LCD_STROBE() ;
}

void command(unsigned char c)
{
LCD_RS = 0 ;
LCD_D4 = ( ( c ) & 0x01 ) ;
LCD_D5 = ( ( c >> 1 ) & 0x01 ) ;
LCD_D6 = ( ( c >> 2 ) & 0x01 ) ;
LCD_D7 = ( ( c >> 3 ) & 0x01 ) ;
LCD_STROBE() ;
}

/*******************************************************************************
* lcd_clear - LCDモジュールの画面を消す処理 *
*******************************************************************************/
void lcd_clear(void)
{
LCD_RS = 0 ;
lcd_write(0x01) ; // Clear Display : 画面全体に20Hのスペースで表示、カーソルはcol=0,row=0に移動
__delay_ms(2) ; // LCDが処理(1.53ms)するのを待ちます
}
/*******************************************************************************
* lcd_setCursor - LCDモジュール画面内のカーソル位置を移動する処理 *
* col : 横(列)方向のカーソル位置(0-15) *
* row : 縦(行)方向のカーソル位置(0-1) *
********************************************************************************/
void lcd_setCursor(int col, int row)
{
int row_offsets[] = { 0x00, 0x40 } ;

 LCD_RS = 0 ;
 lcd_write(0x80 | (col + row_offsets[row])) ; // Set DDRAM Adddress : 00H-0FH,40H-4FH

}
/*******************************************************************************
* lcd_putc - LCDにデータを1バイト出力する処理 *
* c : 出力する文字データ *
*******************************************************************************/
void lcd_putc(char c)
{
LCD_RS = 1 ; // RSの制御信号線をセットします
lcd_write( c ) ; // LCDにデータの送信
}
/*******************************************************************************
* lcd_puts - LCDに文字列データを出力する処理(文字列をNULL(0x00)まで繰返し出力)*
* s : 出力する文字列のデータ *
*******************************************************************************/
void lcd_puts(const char * s)
{
LCD_RS = 1 ; // RSの制御信号線をセットします
while(s) lcd_write(s++) ;
}
/*******************************************************************************
* lcd_init - LCDの初期化処理 *
*******************************************************************************/
void lcd_init()
{
LCD_RS = 0 ;
LCD_EN = 0 ;

 __delay_ms(15) ;    // 電源ON後15msまで待ってから初期化

 // LCDの立上げ時のチェックデータ(イニシャライズ処理用)を設定
 command(0x03) ;
 __delay_ms(5) ;
 command(0x02) ;
 // LCDにコマンドを発行します
 lcd_write(0x28) ;   // function set   : データ線は4本・表示は2行・フォントは5x8ドット
 lcd_write(0x0c) ;   // display control: 画面表示はON・カーソル表示はOFF・カーソル点滅はOFF
 lcd_clear() ;       // Clear Display  : 画面をクリアし、カーソル位置はcol=0,row=0
 lcd_write(0x06) ;   // entry mode set : 文字を表示した次にカーソルを移動するを指示

}

void interrupt inter(void) {
InterUART();
}

void main(void)
{
int i = 0;
char s[17];
// char debug[2] = "a";

OSCCON = 0b01100010;
TRISC  = 0b00000000;
ANSEL  = 0b00000000;
ANSELH = 0b00000000;
PORTC = 0;
InitUART(12, 10, 51);

lcd_init();
lcd_setCursor(0, 0);
lcd_puts(" Monitor  Start ");

while(1) {
    if (UART_Available() != 0) {
        char c = UART_Read();
        if (c == '\n' || c == '\r') {
            c = 0;
        }

// debug[0] = c;
// UART_Send(debug, 2);
if (i < 16 || c == 0) {
s[i++] = c;
if (c == 0) {
lcd_setCursor(0, 1);
lcd_puts(" ");
lcd_setCursor(0, 1);
lcd_puts(s);
i = 0;
}
}
}
}

return;

}
||

skUARTlib.hはこれまたきむ茶さんのところで手に入れたUARTプログラム。
FT232RLとつないでteratermから文字を送ってみたら
とくにつまづくことなくモニタに文字を表示することが出来た。感動。
(ヌル文字の送り方が分からなかったので改行もヌル文字として扱っている)

引き続きPIC12F1822側の送信プログラムを試してみた。
…が、動かない。
どうも厳密なソフトウェアシリアルではなく、
ソフトウェアシリアル同士でのみ通信できるシリアル通信もどきのようだ。

困った…、どう調整すればいいのかも分からない…。

PIC12F1822 シリアル通信
で検索してみたところ、またもやきむ茶さんのサイトに辿り着いた。
ぼーっと眺めていると、なんかUARTが使えるとか書いてある。
え…?

データシートを見てみたら確かにRX, TXのピンがある。
何だそりゃと思いつつskUARTlib.hを使ったプログラムに書き換えてみたら
普通に動いた。
こっちのほうが簡単じゃないか。

|c|
// 12F1822によるLCDモニターのサンプルプログラム

include <xc.h>

include <string.h>

include <stdlib.h>

include "skUARTlib.h"

define _XTAL_FREQ 8000000

// コンフィギュレーション1の設定
// CLKOUTピンをRA4ピンで使用する(CLKOUTEN_OFF):内部クロック使用する(FOSC_INTOSC)
// 外部クロック監視しない(FCMEN_OFF):外部・内部クロックの切替えでの起動はなし(IESO_OFF)
// 電源電圧降下常時監視機能ON(BOREN_ON):電源ONから64ms後にプログラムを開始する(PWRTEN_ON)
// ウオッチドッグタイマー無し(WDTE_OFF):
// 外部リセット信号は使用せずにデジタル入力(RA3)ピンとする(MCLRE_OFF)
// プログラムメモリーを保護しない(CP_OFF):データメモリーを保護しない(CPD_OFF)
__CONFIG(CLKOUTEN_OFF & FOSC_INTOSC & FCMEN_OFF & IESO_OFF & BOREN_ON &
PWRTE_ON & WDTE_OFF & MCLRE_OFF & CP_OFF & CPD_OFF) ;
// コンフィギュレーション2の設定
// 動作クロックを32MHzでは動作させない(PLLEN_OFF)
// スタックがオーバフローやアンダーフローしたらリセットをする(STVREN_ON)
// 低電圧プログラミング機能使用しない(LVP_OFF)
// Flashメモリーを保護しない(WRT_OFF):電源電圧降下常時監視電圧(2.5V)設定(BORV_25)
__CONFIG(PLLEN_OFF & STVREN_ON & WRT_OFF & BORV_HI & LVP_OFF);

/*******************************************************************************
* メインの処理 *
*******************************************************************************/
void main()
{
int i ;
char s[17] ;

 OSCCON  = 0b01110010 ;   // 内部クロックは8MHzとする
 ANSELA  = 0b00000000 ;   // アナログは使用しない(すべてデジタルI/Oに割当てる)
 TRISA   = 0b00000000 ;   // ピンはRA1(SCL)/RA2(SDA)のみ入力(RA3は入力専用)
 PORTA   = 0b00000000 ;   // 出力ピンの初期化(全てLOWにする)

 // LCDモニターを使用する為の初期化処理
 InitUART(2, 3, 51);

 i = 0 ;
 while(1) {
      itoa(s,i,10) ;
      UART_Send(s, strlen(s) + 1);
      i++ ;
      __delay_ms(1000) ;  // 1秒後に繰り返す
 }

}
||

画像をつけようと思ったが
輝度調整を省いたのでLCDが明るすぎてLCDしか映らなかったので省略。

さてこれでmTouchが試せそうだ。

ツイッターでシェア
みんなに共有、忘れないようにメモ

だら@Crieit開発者

Crieitの開発者です。 Webエンジニアです(在宅)。大体10年ちょい。 記事でわかりにくいところがあればDMで質問していただくか、案件発注してください。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, Laravel, React, Flutter, Vue.js, Node, RoR 趣味:Elixir, Phoenix, Nuxt, Express, GCP, AWS等色々 PHPフレームワークちいたんの作者

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント