---
---
16F1459のMaster Synchronous Serial Port (MSSP) を使うと周辺機器と簡単にシリアル通信を行うことができます。MSSPは、SPIとI2Cという2種類の方式をサポートしていまが、ここでは、I2Cを利用したLCD表示器のインターフェースだけを取り上げます。このため、I2C マスターモードが対象です。 SCL SDAの2ピンが対応しています。I2Cモードで使うときには、この2つのピンはオープンドレインの回路にする必要があるため、TRISレジスタで入力モードに設定しておく必要があります。 I2Cに関連するレジスター一覧を下表に示します。
レジスタ | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
---|---|---|---|---|---|---|---|---|
INTCON | GIE | PEIE | TMR0IE | INTE | IOCIE | TMR0IF | INTF | IOCIF |
PIE1 | TMR1GIE | ADIE | RCIE | TXIE | SSP1IE | - | TMR2IE | TMR1IE |
PIR1 | TMR1GIF | ADIF | RCIF | TXIF | SSP1IF | - | TMR2IF | TMR1IF |
PIE2 | OSFIE | C2IE | C1IE | - | BCL1IE | USBIE | ACTIE | - |
PIR2 | OSFIF | C2IF | C1IF | - | BCL1IF | USBIF | ACTIF | - |
SSPCON1 | WCOL | SSPOV | SSPEN | CKP | SSPM<3:0> | |||
SSPCON2 | GCEN | ACKSTAT | ACKDT | ACKEN | RCEN | PEN | RSEN | SEN |
SSPCON3 | ACKTIM | PCIE | SCIE | BOEN | SDAHT | SBCDE | AHEN | DHEN |
SSPSTAT | SMP | CKE | D/A | P | S | WnR | UA | BF |
SSPADD | ADD<7:0> | |||||||
SSPBUF | MSSP Receive Buffer/Transmit Register | |||||||
TRISB | TRISB7 | TRISB6 | TRISB5 | TRISB4 |
レジスタ | BIT | 名 | 説明 | 1 | 0 |
---|---|---|---|---|---|
INTCON | 7 | GIE | 全インタラプトの使用許可 | 許可 | 否 |
6 | PEIE | 周辺機能インタラプトの使用許可 | 許可 | 否 | |
PIE1 | 3 | SSP1IE | SSP インタラプトを使用許可 | 許可 | 否 |
PIR1 | 3 | SSP1IF | SSP インタラプト フラグ | 発生 | 未発生 |
PIE2 | 3 | BCL1IE | バス衝突 インタラプトを使用許可 | 許可 | 否 |
PIR2 | 3 | BCL1IF | バス衝突 インタラプト フラグ | 発生 | 未発生 |
SSPCON1 | 7 | WCOL | 送信時Bus衝突 | 発生 | なし |
6 | SSPOV | 受信時SSPBUFオーバーラン | 発生 | なし | |
5 | SSPEN | MSSPの動作 | ON | OFF | |
<3:0> | SSPM | I2C Master modeは、0b1000 に設定 | |||
SSPCON2 | 6 | ACKSTAT | ACK受信状況 | 未 | 受信済 |
5 | ACKDT | マスタ受信時のNACK/ACK指示 | NACK | ACK | |
4 | ACKEN | マスタ受信時のACKシーケンス開始 (自動リセット) | 開始 | 待ち | |
3 | RCEN | 受信機能を許可 | 許可 | 禁止 | |
2 | PEN | Stop 状況開始 (完了で自動リセット) | 開始 | 待ち | |
1 | RSEN | Repeat Start 状況開始 (完了で自動リセット) | 開始 | 待ち | |
0 | SEN | Start 状況開始 (完了で自動リセット) | 開始 | 待ち | |
SSPCON3 | 7 | ACKTIM | ACKタイミング状況 | ACK内 | ACK外 |
6 | PCIE | Stop 状況割込み | 許可 | 禁止 | |
5 | SCIE | Start 状況割込み | 許可 | 禁止 | |
3 | SDAHT | SCL立下り後のSDA Hold Time | 300 nS | 100 nS | |
SSPSTAT | 7 | SMP | Slew rate 制御の無効(100k用)/有効(400k用) | 100Hzk | 400kHz |
6 | CKE | スレッシュホールド電圧の異なるbusを使用 | SMbus | 標準 | |
5 | D/A | (Read only) 直前Byteの内容 | data | address | |
4 | P | (Read only) 直前にStop bit | なし | 検出 | |
3 | S | (Read only) 直前にStart bit | なし | 検出 | |
2 | R/W | (Read only) 送信状況 | 送信中 | 待機 | |
1 | UA | (Read only) 10-bit I2C mode only | |||
0 | BF | (Read only) SSPBUF状況 | フル | 空 |
I2C クロック周波数 | Fosc | ||
---|---|---|---|
48MHz | 16MHz | 4MHz | |
400 KHz | 0x1D | 0x18 | --- |
100 KHz | 0x77 | 0x63 | 0x09 |
I2Cクロック周波数と、SSPADDへの設定値
秋月(ACM1602NI)I2C LCD表示器へ文字を表示するプログラムです。 i2cは双方向性バスで受信(スレーブ)側の応答を確認したり、送受信信号が衝突した場合などのエラーを検出する機能を持っています。しかし、このプログラムでは、これら機能をすべて省略し、表示データや制御コードを一方的にLCD表示器に送信しています
<プログラム>
/// データをLCDに表示する。 // 秋月(AQM0802A)I2C 8x2 LCD表示器への書き込み // 「LCD Test」と液晶表示する。 // 1)Define I/O PORT // SDA : PORTB(4) pin13 // SCL : PORTB(6) pin11 // 2)OSC // 4MHz (内部クロック) // // Language: MPLABX XC8 // Target: PIC16F1459 // Copyright (c) 2015 iwamoto All Rights Reserved //********************************************************* #include <xc.h> #include <stdio.h> #define _XTAL_FREQ 4000000 //********************************************************************* // 調整用定数 //********************************************************************* #define CONTRAST 0x28 // for 3.3V // #define CONTRAST 0x18 // for 5.0V //************* Config *********************************** #pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF #pragma config BOREN = ON, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF #pragma config WRT = OFF, CPUDIV = NOCLKDIV, USBLSCLK = 48MHz, PLLMULT = 3x #pragma config PLLEN = DISABLED, STVREN = ON, BORV = LO, LPBOR = OFF, LVP = OFF //******************************************************** void i2cByteWrite(char, char, char); // i2c byte送信 void i2cTxData(char); // i2c SSPBUF セット void LCD_dat(char); // 1文字表示 void LCD_cmd(char); // コマンド出力 void LCD_clr(void); // 全消去 void LCD_int(void); // 初期化 void LCD_posyx(char,char); // カーソル位置指定 // **************** printf Routen ***************************** // LCD で printf関数が使用できるようにするため putch を設定する void putch(char data) { LCD_dat(data); // LCD への一文字表示関数 } //////////// Main ////////////////////////////////// void main(void){ char msgStart[] ="LCD Test"; unsigned char num = 0; OSCCON = 0b00110110; // 内部クロック4Mhz ANSELA = 0; // PortAをデジタルI/Oにする TRISA4 = 1; // PortA4をデジタルInputにする ANSELB = 0; // PortBをデジタルI/Oにする TRISB = 0b11111111; // PortBを入力I/Oにする nWPUEN = 0; // 弱プルアップをONにする SSPCON1 = 0x28; // I2Cマスターモード指定 SSPSTAT = 0x00; SSPADD = 0x09; // I2Cクロック周波数100KHz for 4MHz LCD_int(); // LCD初期化 num=0; printf("LCD Test"); // 上行に表示 while(1){ LCD_posyx(1,3); // 下行4文字目から printf("%02X",num++); // 16進で2文字表示 __delay_ms(1000); // 1000msec } } //-------- i2cで1byteデータを送信する ----------------------- // 以下の引数が必要 // addr : Slaveのアドレス // cont : Slaveへ制御コード // data : 送信するデータ // NACKやBus衝突などの対応は行っていない // ----------------------------------------------------------- void i2cByteWrite(char addr, char cont, char data){ SEN = 1; // Start condition 開始 while(SEN); // Start condition 確認 i2cTxData(addr); // アドレス送信 i2cTxData(cont); // 制御コード送信 i2cTxData(data); // データ送信 SSP1IF = 0; // 終了フラグクリア PEN = 1; // Stop condition 開始 while(PEN); // Stop condition 確認 } //-------- SSPBUFに1文字保存し送信終了を待つ ----------------- void i2cTxData(char data){ SSP1IF = 0; // 終了フラグクリア SSPBUF = data; // データセット while(!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; // 1行目 case 1: pcode=0xC0;break; // 2行目 } 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 }
*注意*
SCL SDAの2ピンはオープンドレインの回路にする必要があるため、TRISレジスタで入力モードに設定しておく必要があります。
SCL SDAの2ピンの配置は、PIC16F1455とPIC16F1459で異なります。注意が必要です。
pin10
pin9
pin11
pin13