他力本願の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; //------------------------------------------------------ }