I2C PIC16F886 LCD AQM1602XA EX_IO_PCF8574AN_c

他力本願のC言語入門で下記の制御です
・CPU  PIC16F886
・LCD AQM1602XA
・I/O PCF8574AN
アセンブラでも記事がありますのでご参考まで

動作は下記の様に成って居ます
・LCD AQM1602XA
 0 -> 1 -> 2…32768 -> -32768 -> -32767…-3 -> -2 -> -1 -> 0 の繰り返し
・I/O PCF8574AN
 0 -> 1 -> 2・・・255 -> 0 -> 1・・・の繰り返し
データは出しっ放しでスレーブアドレス側からのデータ読み込みは有りません

参考にしたと申しますか殆どパクッたプログラムです
出典元はWak-techさんです、とても丁寧で判りやすいブログです
この場を借りて御礼申し上げます。

ソースです、なにぶんど素人なのでへたくそです笑って下さい
/*
* File:   main.c
* Author: maru
* PCF8574AN_pic16f886_v001
* Created on 2019/01/09, 8:57
* 0 -> 1 -> 2...32768 -> -32768 -> -32767...-3 -> -2 -> -1 -> 0 の繰り返し
*/
// CONFIG1 MPLAB XIDEの Production -> Set Configration bits で設定してもこのプログラムでの宣言が優先される
//#pragma config FOSC = INTRC_NOCLKOUT //RA6 = I/O          //デフォルトではRA6 = fosc/4 output
#pragma config FOSC = INTRC_CLKOUT //RA6 = fosc/4 output
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = OFF
//#pragma config CLKOUTEN = OFF
//#pragma config IESO = OFF
#pragma config FCMEN = OFF
// CONFIG2
#pragma config WRT = OFF
//#pragma config VCAPEN = OFF
//#pragma config PLLEN = ON
//#pragma config STVREN = ON
#pragma config BOR4V = BOR40V
#pragma config LVP = ON
#include 
#include 
#include 
#include 
#define _XTAL_FREQ 8000000      //PIC16F886はINTOSC時最高8MHzまでしか出ない下のOSCCON = 0x70;と矛盾しては成らない
#define LCD_ADD 0x7C            //LCDスレーブアドレス W
#define S5851A_ADR 0x90         //温度センサースレーブアドレス W
#define PCF8574AN_ADR 0x70      //Extentioned IO スレーブアドレス W
#define ToHome 0b00000010
#define shiftLeft 0b00011000
#define shiftRight 0b00011100
#define clear 0b00000001
char moji[] = " ";
char moji2[] = "counter= ";
char moji3[] = "v001";      //この文字列を長くするとカウントアップがバグる、原因不明
void TRIGGER(){
PORTAbits.RA0 = 1;    //for debug オシロスコープ・トリガ用 PORTA-RA0
__delay_us(10);
PORTAbits.RA0 = 0;
}
void I2C_Master_Init(const unsigned long c)
{
SSPCON  = 0b00101000;     //RC3/SCK/SCL  RC4/SDI/SDA として使用宣言
SSPCON2 = 0;
SSPADD = (_XTAL_FREQ/(4*c))-1;
SSPSTAT = 0b00000000 ;    // 標準速度モードに設定する(100kHz)
}
void I2C_Master_Wait()
{
while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
}
void I2C_Master_Start()
{
I2C_Master_Wait();
SEN = 1;
}
void I2C_Master_RepeatedStart()
{
I2C_Master_Wait();
RSEN = 1;
}
void I2C_Master_Stop()
{
I2C_Master_Wait();
PEN = 1;
}
void I2C_Master_Write(unsigned d)
{
I2C_Master_Wait();
SSPBUF = d;
}
void writeData(char t_data){
I2C_Master_Start();             //スタート・コンディション
I2C_Master_Write(LCD_ADD);      //0x7C スレーブアドレス
I2C_Master_Write(0x40);         //0x40  キャラクタを書くよって宣言
I2C_Master_Write(t_data);       //キャラクタの送信
I2C_Master_Stop();              //ストップ・コンディション
__delay_ms(10);
}
void writeCommand(char t_command){
I2C_Master_Start();
I2C_Master_Write(LCD_ADD);
I2C_Master_Write(0x00);
I2C_Master_Write(t_command);
I2C_Master_Stop();
__delay_ms(10);
}
void PICinit(){
OSCCON = 0x70;          //0x70=8MHz PIC16F886はINTOSC時最高8MHzまでしか出ない上の#define _XTAL_FREQ 8000000;と矛盾しては成らない
ANSEL  = 0b00000000;
ANSELH = 0b00000000;
TRISA  = 0b00000000;
TRISB  = 0b00000000;
TRISC  = 0b00011000;
PORTA  = 0b00000000;    //2進数で書いた場合
PORTB  = 0x00;          //16進数で書いた場合
}
void LCD_Init(){            //LCDの初期化、秋月のマニュアル通り
//TRIGGER();                //for debug オシロスコープ・トリガ用 PORTA-RA0
I2C_Master_Init(100000);
__delay_ms(400);
//TRIGGER();                //for debug オシロスコープ・トリガ用 PORTA-RA0
writeCommand(0x38);       //このプロトコルは S 0x7C 0x00 0x38 A P と成っているから下のプロトコルも全部一個ずつ送信している
__delay_ms(20);
writeCommand(0x39);
__delay_ms(20);
writeCommand(0x14);
__delay_ms(20);
writeCommand(0x73);
__delay_ms(20);
writeCommand(0x52);
__delay_ms(20);
writeCommand(0x6C);
__delay_ms(250);
writeCommand(0x38);
__delay_ms(20);
writeCommand(0x01);
__delay_ms(20);
writeCommand(0x0C);
__delay_ms(20);
}
void LCD_str(char *c) {     //LCDに配列の文字を表示
unsigned char i,wk;
for (i=0 ; ; i++) {
wk = c[i];
if  (wk == 0x00) {break;}
writeData(wk);
}
}
//S5851A_ADR 温度センサー部分=========================================================================================
void S5851A_W(char t_data){
I2C_Master_Init(100000);
I2C_Master_Start();             //スタート・コンディション
I2C_Master_Write(S5851A_ADR);      //スレーブアドレス
I2C_Master_Write(0x01);         //
I2C_Master_Write(t_data);       //キャラクタの送信
I2C_Master_Stop();              //ストップ・コンディション
__delay_ms(10);
}
//S5851A_ADR 温度センサー部分=========================================================================================
//PCF8574AN Extentioned IO 部分=========================================================================================
void PCF8574AN_W(){
I2C_Master_Init(100000);
I2C_Master_Start();             //スタート・コンディション
I2C_Master_Write(PCF8574AN_ADR);      //スレーブアドレス
I2C_Master_Write(0xAA);         //データ送信
I2C_Master_Stop();              //ストップ・コンディション
__delay_ms(10);
}
void PCF8574AN_W2(char LED){
I2C_Master_Init(100000);
I2C_Master_Start();             //スタート・コンディション
I2C_Master_Write(PCF8574AN_ADR);      //スレーブアドレス
I2C_Master_Write(LED);         //データ送信
I2C_Master_Stop();              //ストップ・コンディション
__delay_ms(10);
}
//PCF8574AN Extentioned IO 部分=========================================================================================
int main(void){
PICinit();      //PICを初期化
//  TRIGGER();
PCF8574AN_W();
// S5851A_W(0x00);       //温度センサー、コンフィギュレーションレジスタ書き込みプロトコル
LCD_Init();
writeCommand(0x01); //画面をクリア
__delay_ms(20);
writeCommand(0x02); //ホームへカーソル移動
__delay_ms(2); // LCD側の処理待ち
int count = 0;      //カウント初期値
int count2 = 0;      //カウント初期値
__delay_ms(1000);
writeCommand(0x80); //1列目へ移動
LCD_str(moji3);           //
__delay_ms(100);
writeCommand(0x80+0x40); //2列目へ移動
LCD_str(moji2);           //毎回「counter」と書き込むのは無駄なのでループ外へ出した
__delay_ms(100);
//------------------------------------------------------
while(1){
//writeCommand(ToHome);     //画面左上へカーソルを移動
writeCommand(0x88+0x40); //カーソル移動
count++;                  //カウントアップ
//-----------------------
sprintf(moji,"%d",count);     //mojiにcounter:countを代入
LCD_str(moji);                //mojiを表示
//-----------------------
TRIGGER();
count2++;
PCF8574AN_W2(count2);         //インクリメントした数値をPCF8574AN Extentioned IO に I2C送信
//-----------------------
__delay_ms(1);               //1ms遅延
}
return 0;
//------------------------------------------------------
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です