---
---
12F1822 のMaster Synchronous Serial Port (MSSP) を使うと周辺機器と簡単にシリアル通信を行うことができます。MSSPは、SPIとI2Cという2種類の方式をサポートしていまが、ここでは、I2Cを利用したLCD表示器とのインターフェースだけを取り上げます。このため、I2C マスターモードが対象です。SCL(RA1) SDA(A2)の2ピンが対応しています。I2Cモードで使うときには、この2つのピンはオープンドレインの回路にする必要があるため、TRISレジスタで入力モードに設定する必要があります。I2Cに関連するレジスター一覧を下表に示します。
*注意*
SCL(RA1)ピンは、ICSP と共通使用しています。PICkitは内部でこの端子をプルダウンしているため、PICkit を接続したままでは、I2C機能が働きません。プログラムの動作確認をするときには、必ずPICkitを取り外します。
| I2C クロック | PIC クロック | ||
|---|---|---|---|
| 4M | 16M | 32M | |
| 400 kHz | - | 0x09 | 0x13 |
| 100 kHz | 0x09 | 0x27 | 0x4F |
| レジスタ | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
|---|---|---|---|---|---|---|---|---|
| INTCON | GIE | PEIE | TMR0IE | INTE | IOCIE | TMR0IF | INTF | IOCIF |
| PIE1 | TMR1GIE | ADIE | RCIE | TXIE | SSP1IE | CCP1IE | TMR2IE | TMR1IE |
| PIR1 | TMR1GIF | ADIF | RCIF | TXIF | SSP1IF | CCP1IF | TMR2IF | TMR1IF |
| SSP1CON1 | WCOL | SSPOV | SSPEN | CKP | SSPM<3:0> | |||
| SSP1CON2 | GCEN | ACKSTAT | ACKDT | ACKEN | RCEN | PEN | RSEN | SEN |
| SSP1STAT | SMP | CKE | D/nA | P | S | R/nW | UA | BF |
| SSP1ADD | baud レートクロック分周値 | |||||||
| SSP1BUF | 同期シリアルポート受信バッファ/ 送信レジス | |||||||
| レジスタ | BIT | 名 | 説明 | 1 | 0 |
|---|---|---|---|---|---|
| INTCON | 7 | GIE | 全インタラプトの使用許可 | 許可 | 否 |
| 6 | PEIE | 周辺機能インタラプトの使用許可 | 許可 | 否 | |
| PIE1 | 3 | SSP1IE | SSP1 インタラプトを使用許可 | 許可 | 否 |
| PIR1 | 3 | SSP1IF | SSP1 フラグ | 発生 | 未発生 |
| SSP1CON1 | 7 | WCOL | 書き込みコリジョン検出 | 発生 | 未発生 |
| 6 | SSPOV | 受信オーバーフロー | 発生 | 未発生 | |
| 5 | SSPEN | SSP イネーブルビット | 有効 | 無効 | |
| 4 | CKP | クロック ストレッチ制御 | Open | LOW | |
| 3 | SSPM3 | 1000 = I2C マスタモード、 クロック = FOSC / (4 * (SSP1ADD+1))(4) |
|||
| 2 | SSPM2 | ||||
| 1 | SSPM1 | ||||
| 0 | SSPM0 | ||||
| SSP1CON2 | 7 | GCEN | ジェネラルコール アドレス | 有効 | 無効 |
| 6 | ACKSTAT | 肯定応答(ACK)信号を受信 | YESS | NO | |
| 5 | ACKDT | マスタ受信モード肯定応答(ACK) シーケンス | 開始 | アイドル | |
| 4 | ACKEN | 受信イネーブルビット (I2C マスタモードのみ) | 有効 | 無効 | |
| 3 | PEN | ストップ条件 (I2C マスタモードのみ) | 開始 | アイドル | |
| 2 | RSEN | 反復スタート条件 (I2C マスタモードのみ) | 開始 | アイドル | |
| 0 | SEN | スタート条件 (I2C マスタモードのみ) | 開始 | アイドル | |
| SSP1STAT | 7 | SMP | スルーレート制御 (400 kHzは有効「0」にする) | 無効 | 有効 |
| 6 | CKE | SMBus 仕様 | 有効 | 無効 | |
| 0 | BF | SSP1BUFバッファフル ステータス | フル | 空 |
PI2Cを利用したLCD表示器(LCD-AQM0802A)「LCD Test / I2C com」と表示するプログラムを作成しました。通常 I2Cラインに取り付けるプルアップ抵抗は、PIC内の弱プルアップを利用しています。雑音の大きい環境で使用するときは、別途プルアップ抵抗を回路に取り付けてっください。
<回路図>
<プログラム>
/*********************************************************************
* データをLCDに表示する。
* 秋月(ACM1602NI)I2C LCD表示器を使用
* 4MHz (内部クロック)
*
* 1 VDD 8 VSS
* 2 RA5 7 RA0
* 3 RA4 6 RA1 SCL
* 4 MCLR 5 RA2 SDA
*
* PIC12F1822 MPLAB X IDE with XC8 Ver1.32
* Copyright (c) 2014 iwamoto All Rights Reserved
* *******************************************************************/
#define _XTAL_FREQ 4000000
//*********************************************************************
// 調整用定数
//*********************************************************************
#define CONTRAST 0x28 // for 3.3V
// #define CONTRAST 0x18 // for 5.0V
#include <xc.h>
//******************* コンフィグレーション ****************************
#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, 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 i2cByteWrite(char, char, char);
void i2cTxData(char);
void LCD_dat(char);
void LCD_cmd(char);
void LCD_clr(void);
void LCD_posyx(char,char);
void LCD_int(void);
void LCD_str(char *);
void LCD_ROMstr(const char *);
// ******************* main ******************************************
void main() {
char msgStart[] ="LCD Test";
OSCCON = 0b01101010; // 内部クロック4Mhz
PORTA = 0x00;
TRISA = 0xFF; // Port すべて入力
ANSELA = 0x00; // すべてデジタル
WPUA = 0xFF; // 弱プルアップ ON
nWPUEN = 0;
// SSP1設定 -----------------------------------------------
SSP1STAT = 0b10000000; // スルーレート制御はOff
SSP1ADD = 9; // クロック設定 100k@4MHz
SSP1CON1 = 0b00101000; // I2C Master modeにする
// --------------------------------------------------------
LCD_int(); // LCDを初期化
LCD_str(msgStart); // LCD上段に"LCD Disp Test"
LCD_posyx(1,1); // 下段にカーソル移動
LCD_ROMstr("I2C com"); // 下段に追記
while(1);
}
//********************************************************************
// I2C 関連
//********************************************************************
//-------- ByteI2C送信
void i2cByteWrite(char addr, char cont, char data){
SSP1CON2bits.SEN = 1; // Start condition 開始
while(SSP1CON2bits.SEN); // Start condition 確認
i2cTxData(addr); // アドレス送信
i2cTxData(cont); // 制御コード送信
i2cTxData(data); // データ送信
SSP1CON2bits.PEN = 1; // Stop condition 開始
while(SSP1CON2bits.PEN); // Stop condition 確認
}
//-------- Data送信
void i2cTxData(char data){
PIR1bits.SSP1IF = 0; // 終了フラグクリア
SSP1BUF = data; // データセット
while(!PIR1bits.SSP1IF); // 送信終了待ち
}
//********************************************************************
// LCD 関連
//********************************************************************
//-------- 1文字表示
void LCD_dat(char chr){
i2cByteWrite(0x7C, 0x40, chr);
__delay_us(50); // 50μsec
}
//-------- コマンド出力
void LCD_cmd(char cmd){
i2cByteWrite(0x7C, 0x00, cmd);
if(cmd & 0xFC) // 上位6ビットに1がある命令
__delay_us(50); // 50usec
else
__delay_ms(2); // 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;
}
LCD_cmd(pcode += xpos);
}
//-------- 初期化
void LCD_int(void){
__delay_ms(100);
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_ms(100);
__delay_ms(100);
LCD_cmd(0x38); // 表示命令モード
LCD_cmd(0x0C); // Display On
LCD_cmd(0x01); // Clear Display
}
//-------- 文字列出力
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
}
SSP1ADDに設定する
baudレート ジェネレータ(BRG)の
再読み込み値