PIC12F1822の基本動作から応用プログラムまでを学びます。

ホーム
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
    
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
シリアル信号LCD表示器

12F1822のUARTとI2C通信機能を使用し、非同期のシリアル信号入力を持つLCD表示器を作成します。マイコンからの情報を少ない配線数で表示でき、マイコン側のソフトウエアも単純なプログラムで処理できる表示ユニットです。ASCII文字以外は、画面表示に最低限必要と思われる制御コードを受け付けます。非同期受信は、パリティーなし、9600bpsのロジックレベル信号の入力とします。文字を表示するLCDは、  秋月の8文字x2行のI2CLCD表示器を使いましたが、aitendo のI2CLCD表示器やストロベリリナックスのI2CLCD表示器は、同じ制御コードを持っているため、同一のプログラムで使用可能です。

制御コード 動作
0x00 何もしない
0x01 クリア 全表示をクリアし、カーソルを上段先頭にする
0x02 カーソルを上段先頭にする
0x03 カーソルを下段先頭にする
0x8X カーソルを上段 X番目(0-F)にする
0x9X カーソルを下段 X番目(0-F)にする
0x20-0x7F ASCII文字(英数字)を表示
0xA0-0xFF ASCII文字(カタカナ、特殊文字)を表示

<回路図>

<プログラム> main.c

/*********************************************************************
 *  UART で受信したデータをLCDに表示する。
 *    秋月(ACM1602NI)I2C LCD表示器を使用
 *          4MHz (内部クロック)
 *
 *     1 VDD         8 VSS
 *  Rx 2 RA5         7 RA0
 *     3 RA4         6 RA1 SCL
 *     4 MCLR        5 RA2 SDA
 *
 * PIC12F1822  MPLAB X IDE with XC8 Ver1.32
 * Copyright (c) 2012 iwamoto All Rights Reserved
 * *******************************************************************/
#define CR_EN1  RCSTAbits.CREN
#define O_ERR1  RCSTAbits.OERR

#include <xc.h>
#include "L_i2cLCD.h"    //I2C接続LCD関数

//******************* コンフィグレーション ****************************
#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = ON, CP = OFF
#pragma config CPD = OFF, BOREN = ON, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF
#pragma config WRT = OFF, PLLEN = OFF, STVREN = ON, BORV = LO, LVP = OFF
//
void i2cintl(void);

// ******************* main ******************************************
void main() {
    char i;

    OSCCON = 0b01101010;              // 内部クロック4Mhz
    TRISA = 0xFF;                     // Port すべて入力
    ANSELA = 0x00;                    // すべてデジタル
    PORTA = 0x00;
    WPUA   = 0b00001110;              // RA1,2 弱プルアップ ON
    nWPUEN = 0;
    APFCONbits.RXDTSEL = 1;           // RX/DT機能をRA5 に割当
//------------ Initialize UART -------------------
    RCSTA   = 0b10010000;
    TXSTA   = 0b00000100;
    BAUDCON = 0b00001000;
    SPBRGH  = 0;
    SPBRG   = 103;

    i2cintl();
    LCD_int();                               // LCDを初期化
    LCD_ROMstr("LCD Test");                  // LCD上段に""LCD Test"
    LCD_posyx(1,1);                          // 下段にカーソル移動
    LCD_ROMstr(" I2C");                      // LCD下段に" I2C"

    while(1){
        while (!PIR1bits.RCIF);              // 受信するまで待つ
        if(RCSTAbits.OERR){                  // Overrunエラーなら
            RCSTAbits.CREN=0;                // エラーをクリア
            RCSTAbits.CREN=1;                // 再起動
            i = RCREG;
            continue;
        }
        i = RCREG;                          // 受信データを取り込む
        if(i == 1)LCD_cmd(0x01);            // Clearコマンド出力
        else if(i == 2)LCD_posyx(0,0);      // 1行目先頭に移動
        else if(i == 3)LCD_posyx(1,0);      // 2行目先頭に移動
        else if((i>=0x80)&&(i<=0x9F))       // 80-9Fはカーソル移動
            LCD_posyx((i&0x10)>>4,i&0x0F);
        else if(i>=0x20)LCD_dat(i);         // 0x20以上は文字の表示
    }
}
//********************************************************************
// SSP1を I2C Master mode、SCL 100kHz @ 4MHz に設定
//********************************************************************
void i2cintl(void){
    SSP1CON1 = 0b00001000;                  // I2C Master modeにする
    SSP1CON2 = 0x00;                        // PowerOn初期値にする
    SSP1STAT = 0b10000000;                  // スルーレート制御はOff
    SSP1ADD  = 9;                           // クロックの設定 100k@4MHz
    SSP1CON1bits.SSPEN = 1;                 // SSP 有効にする bit5
}

<プログラム> L_i2cLCD.h

//*************************************************************
// I2C LCD ライブラリ  20141112
// 以下の機能を提供する
//
//    LCD_int()     ----- 初期化(I2C初期化を含む)
//    LCD_cmd(cmd)  ----- コマンド出力
//    LCD_dat(chr)  ----- 1文字表示
//    LCD_str(*str) ----- 文字列表示
//    LCD_ROMstr(*str) -- ROM文字列表示
//    LCD_hex(char);
//    LCD_posyx(y,x) ---- カーソル位置指定、行 y、横位置 x
//    LCD_clr()     ----- 全消去
//    LCD_icon_on(icn); -- 指定アイコン ON
//    LCD_icon_off(icn);-- 指定アイコン OFF
//    LCD_icon_clr();----- 全アイコン OFF
//
//液晶表示器とPICはI2Cにより接続される
//         内部クロック 4MHz
//
// Copyright (c) 2012-2014 iwamoto All Rights Reserved
//************* Delay *******************************************
// 必要とするディレイ時間をクロック周波数から計算し、
// 指定するために、クロック周波数を指定する。
//***************************************************************
#define _XTAL_FREQ 4000000

//
//*************** Delay Define for 4MHz Clock*********
#define  Delay_50uS   __delay_us(50)
#define  Delay_2mS    __delay_ms(2)
#define  Delay_100mS  __delay_ms(100)
//********************************
//  調整用定数
//*********************************
#define CONTRAST  0x28          // for 3.3V
//#define CONTRAST  0x2D                // for 3.3V
// #define CONTRAST  0x18               // for 5.0V


//********************************
//  アイコン定数
//*********************************
#define i_Ant  0x4010           // アンテナ
#define i_Tel  0x4210           // 電話
#define i_Aud  0x4410           // 音声
#define i_Pulg  0x4610          // 接続
#define i_Up  0x4710            // Up
#define i_Dn  0x4708            // Down
#define i_UpDn  0x4718          // Down
#define i_Lock  0x4910          // 鍵
#define i_XFlag  0x4B10         // X旗
#define i_BatEMP  0x4D02        // バッテリー空
#define i_BatLOW  0x4D12        // バッテリー小
#define i_BatMID  0x4D1A        // バッテリー中
#define i_BatFUL  0x4D1E        // バッテリー満
#define i_Circle  0x4F10        // 三重丸

//******************* 提供機能 *******************************
void LCD_dat(char chr);
void LCD_cmd(char cmd);
void LCD_clr(void);
void LCD_int(void);
void LCD_str(char *str);
void LCD_posyx(char ypos,char xpos);
void LCD_icon_on(int icn);
void LCD_icon_off(int icn);
void LCD_icon_clr(void);
void LCD_ROMstr(const char *);
void LCD_hex(char);


<プログラム> L_i2cLCD.c

////////////////////////////////////////////////////////////
// I2C LCD ライブラリ 20141112
//  秋月(ACM1602NI)I2C 液晶表示 および
//  ストロベリーリナックス液晶表示 ライブラリ
//  以下の機能を提供
//    LCD_int()     ----- 初期化
//    LCD_cmd(cmd)  ----- コマンド出力
//    LCD_dat(chr)  ----- 1文字表示
//    LCD_str(*str) ---- 文字列表示
//    LCD_ROMstr(*str) -- ROM文字列表示
//    LCD_hex(char);
//    LCD_posyx(y,x) ---- カーソル位置指定、行 y、横位置 x
//    LCD_clr()      ----- 全消去
//    LCD_icon_on(icn);--- 指定アイコンON
//    LCD_icon_off(icn);-- 指定アイコンOFF
//    LCD_icon_clrf();---- 全アイコンOFF
//液晶表示器とPICはI2Cにより接続される
//         内部クロック 4MHz
//
// Copyright (c) 2012-2014 iwamoto All Rights Reserved
////////////////////////////////////////////////////////////

#include <xc.h>
#include "L_i2cLCD.h"

void _EEByteWrite(char, char, char);
void _i2cTx(char);

void _EEByteWrite(char addr, char cont, char data){
    SSP1CON2bits.SEN = 1;     // Start condition 開始
    while(SSP1CON2bits.SEN);  // Start condition 確認
    _i2cTx(addr);             // アドレス送信
    _i2cTx(cont);             // 制御コード送信
    _i2cTx(data);             // データ送信
    SSP1CON2bits.PEN = 1;     // Stop condition 開始
    while(SSP1CON2bits.PEN);  // Stop condition 確認
}

void _i2cTx(char data){
    PIR1bits.SSP1IF = 0;      // 終了フラグクリア
    SSP1BUF = data;           // データセット
    while(!PIR1bits.SSP1IF);  // 送信終了待ち
}
//-------- 1文字表示
void LCD_dat(char chr){
    _EEByteWrite(0x7C, 0x40, chr);
    Delay_50uS;              // 50μsec
}
//-------- コマンド出力
void LCD_cmd(char cmd){
    _EEByteWrite(0x7C, 0x00, cmd);
    if(cmd & 0xFC)           // 上位6ビットに1がある命令
        Delay_50uS;          // 50usec
    else
        Delay_2mS;           // 2msec ClearおよびHomeコマンド
}
//-------- 全消去
void LCD_clr(void){
    LCD_cmd(0x01);           //Clearコマンド出力
}
//-------- カーソル位置指定
void LCD_posyx(char ypos, char xpos){
    unsigned char pcode;
    switch(ypos & 0x03){
        case 0:    pcode=0x80;break;
        case 1:    pcode=0xC0;break;
        case 2:    pcode=0x94;break;
        case 3:    pcode=0xD4;break;
    }
    LCD_cmd(pcode += xpos);
}
//-------- 文字列出力
void LCD_str(char *str){
    while(*str)              //文字列の終わり(00)まで継続
        LCD_dat(*str++);     //文字出力しポインタ+1
}
//-------- Rom 文字列出力
void LCD_ROMstr(const char *str){
    while(*str)              //文字列の終わり(00)まで継続
        LCD_dat(*str++);     //文字出力しポインタ+1
}
//-------- 16進文字変換表示
void LCD_hex(char c){
    const char hexch[] ="0123456789ABCDEF";
    LCD_dat(hexch[c >> 4]);
    LCD_dat(hexch[c & 0xF]);
}

//-------- 初期化
void LCD_int(void){
//    SSP1CON1 = 0x28;          //I2Cマスターモード指定
//    SSP1STAT = 0x00;
//    SSP1ADD = BaudConst;      //Board Rate

    Delay_100mS;
    LCD_cmd(0x38);           // 8bit 2行 表示命令モード
    LCD_cmd(0x39);           // 8bit 2行 拡張命令モード
    LCD_cmd(0x14);           // OSC  BIAS 設定1/5
                             // コントラスト設定
    LCD_cmd(0x70 + (CONTRAST & 0x0F));
    LCD_cmd(0x5C + (CONTRAST >> 4));
    LCD_cmd(0x6B);           // Ffollwer
    Delay_100mS;
    Delay_100mS;
    LCD_cmd(0x38);           // 表示命令モード
    LCD_cmd(0x0C);           // Display On
    LCD_cmd(0x01);           // Clear Display
}
//-- 指定アイコン ON
void LCD_icon_on(int icn){
    LCD_cmd(0x39);            // 拡張命令モード
    LCD_cmd(icn >> 8);        // Icon アドレス
    LCD_dat(icn & 0xFF);      // Icon ビット <ON>
    LCD_cmd(0x38);            // 表示命令モード
}
//-- 指定アイコン OFF
void LCD_icon_off(int icn){
    LCD_cmd(0x39);            // 拡張命令モード
    LCD_cmd(icn >> 8);        // Icon アドレス
    LCD_dat(0x00);            // Icon ビット <OFF>
    LCD_cmd(0x38);            // 表示命令モード
}
//-- 全アイコン OFF
void LCD_icon_clr(void){
    unsigned char icn = 0x40;
    LCD_cmd(0x39);            // 拡張命令モード
    while(icn <= 0x4F){
        LCD_cmd(icn++);       // Icon アドレス
        LCD_dat(0x00);        // Icon ビット <OFF>
    }
    LCD_cmd(0x38);            // 表示命令モード
}