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

ホーム
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
    
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
MSSP I2C
2017-12-1

PIC16F1619には、Master Synchronous Serial Port (MSSP) があり、MSSP を使うと周辺機器と簡単にシリアル通信を行うことができます。MSSPは、SPIとI2Cという2種類の方式をサポートしていまが、ここでは、I2Cを利用したLCD表示器とのインターフェースだけを取り上げます。このため、I2C マスターモードが対象です。

MSSPのプログラム例

<回路図>

PI2Cを利用したLCD表示器(LCD-AQM0802A)「LCD Test / I2C com」と表示するプログラムを作成しました。通常 I2Cラインに取り付けるプルアップ抵抗は、PIC内の弱プルアップを利用しています。雑音の大きい環境で使用するときは、別途プルアップ抵抗を回路に取り付けてください。

<プログラム>

/*********************************************************************
 *  データをLCDに表示する。
 *    秋月(ACM1602NI)I2C LCD表示器を使用
 *          1MHz (内部クロック)
 * RB6 SCL
 * RB4 SDA
 *
 * PIC16F1619  MPLAB X IDE with XC8
 * Copyright (c) 2017 iwamoto All Rights Reserved
 * *******************************************************************/
#include <xc.h>

#define _XTAL_FREQ 1000000

//*********************************************************************
//  調整用定数
//*********************************************************************
#define CONTRAST  0x28          // for 3.3V
// #define CONTRAST  0x18       // for 5.0V

#define slaveDeviceAddress 0x7C

// CONFIG1
#pragma config FOSC = INTOSC
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
#pragma config IESO = ON
#pragma config FCMEN = ON
// CONFIG2
#pragma config WRT = OFF
#pragma config PPS1WAY = ON
#pragma config ZCD = OFF
#pragma config PLLEN = OFF
#pragma config STVREN = ON
#pragma config BORV = LO
#pragma config LPBOR = OFF
#pragma config LVP = ON
// CONFIG3
#pragma config WDTCPS = WDTCPS1F
#pragma config WDTE = OFF
#pragma config WDTCWS = WDTCWSSW
#pragma config WDTCCS = SWC

//******************* プロトタイプ *******************************
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_put(char);

void LCD_str(char *);
void LCD_ROMstr(const char *);

/*********************************************************
                         Main application
 *********************************************************/
void main(void)
{
    OSCCON = 0x58;	// FOSC; PLL disabled; 1MHz_HF;

    LATA = 0x00;	// 全てクリア
    LATB = 0x00;
    LATC = 0x00;
    TRISA = 0xFF;	// 全て入力
    TRISB = 0xFF;
    TRISC = 0xFF;
    ANSELC = 0x00;	// 全てデジタル
    ANSELB = 0x00;
    ANSELA = 0x00;
    WPUB = 0xFF;	// 全て弱プルアップ
    WPUA = 0xFF;
    WPUC = 0xFF;
    OPTION_REGbits.nWPUEN = 0;

    ODCONB = 0b01010000;    // RB6,RB4をオープンドレイン
    SSPCLKPPS = 0b00001110; // RB6をCLK入力に指定
    RB6PPS    = 0b00010000; // RB6をCLK出力に指定
    SSPDATPPS = 0b00001100; // RB4をDATに入力指定
    RB4PPS    = 0b00010001; // RB4をDAT出力に指定

    // SSP1設定 -----------------------------------------------
    SSP1STAT = 0b10000000;     // スルーレート制御はOff
    SSP1ADD  = 3;              // クロック設定 65k@1MHz
    SSP1CON1 = 0b00101000;     // I2C Master modeにする
    // --------------------------------------------------------
    char msgStart[] ="LCD Test";
    LCD_int();                 // LCDを初期化
    LCD_str(msgStart);         // LCD上段に"LCD Disp Test"
    LCD_posyx(1,1);            // 下段にカーソル移動
    LCD_ROMstr("I2C com");     // 下段に追記

    while (1)
    {
        // Add your application code
    }
}

//********************************************************************
// 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
}