pic16f886 bme280 sensor v002 温湿度気圧センサー LCD

他力本願C言語シリーズ、そろそろ終わりです
今回も秋月電子販売の部品を使いました
温湿度気圧センサーAE-BME280 です I2C BUS で動きます
これですがC言語でも大変複雑なのでアセンブラでは一体
どのくらいの時間が掛かるか、あぁ想像したくない・・・。

bandicam 2019-02-06 11-20-25-583

今回もネット検索で見つかった製作記事のコピーです、こちらのブログ
趣味を楽しむ Enjoy your hobbyさんの記事からのコピーです
そっくりそのままでは無いです、CPUが違う、LCDが違う、などで
その部分は改造しています、初日は全く画面が出ないもののセンサーは
動いている、つまりアクセスして居る様子がオシロスコープで判った
のであとはLCD表示が出来れば良いわけです、初日に全く表示しなかった
理由は
・LCDが違う
・レジスタ・アドレスが違う
等から過去の製作プログラムを引っぱってきて追加しアドレス変更
したらアッサリと動いて仕舞いました、様々な計算、補正等が行われ
て居ますのでこれを理解するには相当な時間が掛かることでしょう
ただ、出来たものの精度は一切保証無しです、そこそこ出ていると
思えば宜しいでしょう。

回路図、センサー部分
3.3V電源なのでレベル・シフトのI2C bus buffer が必要です
これ、どっちが5Vかは決まってない様子ですググってみると
両方5Vのパターンがありました
bandicam 2019-02-06 12-19-59-813

回路図LCD部分
bandicam 2019-02-06 12-20-25-583

回路図CPU部分
bandicam 2019-02-06 12-22-16-009

ソースファイル
//============================================================================
// BME280気候センサーとLCD表示器を使用した温湿度気圧計測表示器
//============================================================================
//
// BME280データ処理部分は「SWITCHSCIENCE」さんのサイトから
// 使用させていただきました
//============================================================================
//  pic16f886 I2C bme280 sensor v002 2019/02/06(水) modified by maru
// データ処理の100%部分は「趣味を楽しむ Enjoy your hobby」さんのサイトから
// 使用させていただきました、LCDとPIC内部発振、キャラクタなど改造
//------------------------
// 初期設定
//------------------------
#include 
#include 
#include 
#include 
#pragma config FOSC = HS //高速オシレーター(4MHz以上)使用
#pragma config WDTE = OFF //ウォッチドッグタイマーOFF
#pragma config CP = OFF //コードプロテクションOFF
#pragma config PWRTE = ON //パワーアップタイマーON
#pragma config LVP = OFF//
//PICのクロック設定
#define _XTAL_FREQ 8000000 //PICのクロックをHzで設定(8MHz)
//モニター確認用LED
#define RED_led             RA0         //Red LED
#define YELLOW_led          RA1         //Yelloe LED
#define GREEN1_led          RA2         //Green LED1
#define GREEN2_led          RA3         //Green LED2
#define I2C_SCL             RC3         //I2c SCL (clock)
#define I2C_SDA             RC4         //I2c SDA (data)
#define RS232_TX            RC6         //RS232 TX
#define RS232_RX            RC7         //RS232 RX
//--------------------------------------------------------
// 関数定義エリア
// i2c 基本入出力関数
//--------------------------------------------------------
void i2c_CONF(void); //i2c初期設定
void i2c_START(void); //スタートコンディション発行
void i2c_ReSTART(void); //再スタートコンディション発行
void i2c_STOP(void); //ストップコンディション発行
void i2c_WRITE(unsigned char); //1バイト書き込み
unsigned char i2c_READ(void); //1バイト読み込み
unsigned char i2c_READC(void); //1バイト連続読み込み
//---------------------------------------------------------
// LCS表示制御コマンド
//---------------------------------------------------------
void LCD_init(void); //LCDの初期設定
void LCD_Init2(); //maru
void LCD_Clear(int); //LCDクリア(0=全面、1=1行目、2=2行目)
void LCD_puts(const char *p); //LCDへ連続文字表示
void LCD_Locate(unsigned char, unsigned char); //文字表示位置の設定
void LCD_CW(unsigned char); //LCDコマンド1バイト書き込み
void LCD_DW(unsigned char); //LCDデータ1バイト書き込み
//---------------------------------------------------------
// 気圧気温湿度センサーコマンド(PTHセンサー)
//---------------------------------------------------------
unsigned char pth_IDread(void); //センサーのソフトリセットとID読み取り
void pth_BREAD(unsigned char, unsigned char, unsigned char); //ブロック読み込み
void pth_readTrim(void); //センサー補正値の取得
void pth_setup(void); //センサー初期設定
void pth_readData(void); //センサー計測値読み取り
long int calibration_T(long int); //温度補正
unsigned long int calibration_P(signed long int); //気圧補正
unsigned long int calibration_H(signed long int); //湿度補正
//------------------------------
// その他関数
//------------------------------
void PIC_init(void); //PIC初期化
void Debug_RED(void); //デバッグ用赤色LED点滅
void Hex_Out(int); //整数を16進数で表示(ゼロサプレスしない)
void FloatDisp(float); //少数を少数以下1桁で表示
//---------------------------------------------------------
// 変数定義
//---------------------------------------------------------
int i, j; //ループカウンター
int disp; //文字変換する数値を代入
//unsigned char S_ADRS1 = 0xA0; // LCD Slave Address1
unsigned char S_ADRS1 = 0x7C; // LCD Slave Address1
unsigned char S_ADRS2 = 0xEC; // Senser Slave Address2
unsigned char RDDAT; //i2c受信関数データの一時保管
char str[5]; //16進文字変換結果代入
unsigned char para;
//----- センサー関連変数定義 --------
float temp_act = 0.0, press_act = 0.0, hum_act = 0.0;
long int temp_cal;
unsigned long int press_cal, hum_cal;
int buff[32]; //補正係数バッファ
unsigned long int hum_raw, temp_raw, pres_raw;
long int t_fine;
unsigned int dig_T1;
int dig_T2;
int dig_T3;
unsigned int dig_P1;
int dig_P2;
int dig_P3;
int dig_P4;
int dig_P5;
int dig_P6;
int dig_P7;
int dig_P8;
int dig_P9;
signed char dig_H1;
int dig_H2;
signed char dig_H3;
int dig_H4;
int dig_H5;
signed char dig_H6;
//========================================
//関数定義エリア
//========================================
//--------------------------------------------
// センサーセットアップ(補正係数読み込み含む)
//--------------------------------------------
void pth_setup(void) {
unsigned int osrs_t = 3; //Temperature oversampling x 4
unsigned int osrs_p = 3; //Pressure oversampling x 4
unsigned int osrs_h = 3; //Humidity oversampling x 4
unsigned int mode = 3; //Normal mode
unsigned int t_sb = 5; //Tstandby 1000ms
unsigned int filter = 0; //Filter off
unsigned int spi3w_en = 0; //3-wire SPI Disable
unsigned int ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode;
unsigned int config_reg = (t_sb << 5) | (filter << 2) | spi3w_en;
unsigned int ctrl_hum_reg = osrs_h;
//---------- センサーレジスターに初期設定を書き込み(各1バイト)---------
i2c_START();
i2c_WRITE(S_ADRS2);
i2c_WRITE(0xF2);
para = ctrl_hum_reg;
i2c_WRITE(para);
i2c_WRITE(0xF4);
para = ctrl_meas_reg;
i2c_WRITE(para);
i2c_WRITE(0xF5);
para = config_reg;
i2c_WRITE(para);
i2c_STOP();
}
//-------------------------------------
// センサー補正データの取得
//-------------------------------------
void pth_readTrim(void) {
//---------------------------------------------
// h88からA1までの25バイトを配列に読み込み表示
//---------------------------------------------
pth_BREAD(0x88, 24, 0); // レジスターアドレス 88-9F  24bytes
pth_BREAD(0xA1, 1, 24); // レジスターアドレス A1      1
pth_BREAD(0xE1, 7, 25); // レジスターアドレス E1-E7   7
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 以下はデータ確認用
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LCD_Clear(0); //LCD全クリア
LCD_puts("Data read OK");
__delay_ms(500);
LCD_Clear(0); //LCD全クリア
__delay_ms(500);
//-------------------------------------------
// 読み込んだデータを順次表示する(確認表示)
//-------------------------------------------
for (i = 0; i <= 31; i++) {
LCD_Clear(0);
disp = i + 0x88;
LCD_puts("Adrs = ");
Hex_Out(disp);
disp = buff[i];
LCD_Locate(0, 1);
LCD_puts("Data = ");
Hex_Out(disp);
__delay_ms(100);
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// ここまでデータ確認用
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 読み込んだ補正係数を変数に代入
//-----------------------------------------
dig_T1 = (buff[1] << 8) | buff[0];
dig_T2 = (buff[3] << 8) | buff[2];
dig_T3 = (buff[5] << 8) | buff[4];
dig_P1 = (buff[7] << 8) | buff[6];
dig_P2 = (buff[9] << 8) | buff[8];
dig_P3 = (buff[11] << 8) | buff[10];
dig_P4 = (buff[13] << 8) | buff[12];
dig_P5 = (buff[15] << 8) | buff[14];
dig_P6 = (buff[17] << 8) | buff[16];
dig_P7 = (buff[19] << 8) | buff[18];
dig_P8 = (buff[21] << 8) | buff[20];
dig_P9 = (buff[23] << 8) | buff[22];
dig_H1 = buff[24];
dig_H2 = (buff[26] << 8) | buff[25];
dig_H3 = buff[27];
dig_H4 = (buff[28] << 4) | (0x0F & buff[29]);
dig_H5 = (buff[30] << 4) | ((buff[29] >> 4) & 0x0F);
dig_H6 = buff[31];
}
//-------------------------------------------------------
// センサーから生の計測データを読みだす
//-------------------------------------------------------
void pth_readData(void) {
int i = 0;
unsigned long int data[8]; //レジスタアドレス F7 - FE を読み込む
i2c_START();
i2c_WRITE(S_ADRS2);
i2c_WRITE(0xF7);
i2c_ReSTART(); //再スタート
i2c_WRITE(S_ADRS2 + 0x01);
for (i = 0; i <= 7; i++) {
data[i] = i2c_READC(); //同じ変数の型であること。連続読み込みREADC
}
data[i + 1] = i2c_READ(); //同じ変数の型であること。最後の読み込みREADC
i2c_STOP();
pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
hum_raw = (data[6] << 8) | data[7];
}
//------------------------------------------------------
// 温度補正
//------------------------------------------------------
long int calibration_T(long int adc_T) {
long int var1, var2, T;
var1 = ((((adc_T >> 3) - ((long int) dig_T1 << 1))) * ((long int) dig_T2)) >> 11;
var2 = (((((adc_T >> 4) - ((long int) dig_T1)) * ((adc_T >> 4) - ((long int) dig_T1))) >> 12) * ((long int) dig_T3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}
//------------------------------------------------------
// 気圧補正
//------------------------------------------------------
unsigned long int calibration_P(long int adc_P) {
long int var1, var2;
unsigned long int P;
var1 = (((long int) t_fine) >> 1) - (long int) 64000;
var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * ((long int) dig_P6);
var2 = var2 + ((var1 * ((long int) dig_P5)) << 1);
var2 = (var2 >> 2)+(((long int) dig_P4) << 16);
var1 = (((dig_P3 * (((var1 >> 2)*(var1 >> 2)) >> 13)) >> 3)
+ ((((long int) dig_P2) * var1) >> 1)) >> 18;
var1 = ((((32768 + var1))*((long int) dig_P1)) >> 15);
if (var1 == 0) {
return 0;
}
P = (((unsigned long int) (((long int) 1048576) - adc_P)-(var2 >> 12)))*3125;
if (P < 0x80000000) {
P = (P << 1) / ((unsigned long int) var1);
} else {
P = (P / (unsigned long int) var1) * 2;
}
var1 = (((long int) dig_P9) * ((long int) (((P >> 3) * (P >> 3)) >> 13))) >> 12;
var2 = (((long int) (P >> 2)) * ((long int) dig_P8)) >> 13;
P = (unsigned long int) ((long int) P + ((var1 + var2 + dig_P7) >> 4));
return P;
}
//------------------------------------------------------
// 湿度補正
//------------------------------------------------------
unsigned long int calibration_H(long int adc_H) {
long int v_x1;
v_x1 = (t_fine - ((long int) 76800));
v_x1 = (((((adc_H << 14) -(((long int) dig_H4) << 20) - (((long int) dig_H5)
* v_x1)) + ((long int) 16384)) >> 15) * (((((((v_x1 * ((long int) dig_H6)) >> 10)
* (((v_x1 * ((long int) dig_H3)) >> 11) + ((long int) 32768))) >> 10)
+ ((long int) 2097152)) * ((long int) dig_H2) + 8192) >> 14));
v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((long int) dig_H1)) >> 4));
v_x1 = (v_x1 < 0 ? 0 : v_x1);
v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
return (unsigned long int) (v_x1 >> 12);
}
//----------------------------------
// PIC 初期設定
//----------------------------------
void PIC_init(void) {
//add maru
OSCCON = 0x70; //0x70=8MHz PIC16F886はINTOSC時最高8MHzまでしか出ない上の#define _XTAL_FREQ 8000000;と矛盾しては成らない
ANSEL = 0b00000000;
ANSELH = 0b00000000;
//
//PICのポート設定
ADCON0 = 0b10000000; //アナログ使用しない
ADCON1 = 0b00000110; //For degital I/O
TRISA = 0b00000000;
TRISB = 0b00000000;
TRISC = 0b10011000; // i2cポートは「入力モード」
//ポート初期化
PORTA = 0b11111111;
PORTB = 0b11111111;
PORTC = 0b11111111;
//割り込み不使用
INTCON = 0b00000000;
//TMRはフリーラン
OPTION_REG = 0b11000000;
TMR0 = 0;
//周辺機器割り込み不使用
PIE1 = 0;
//周辺機器割り込みフラグクリア
PIR1 = 0;
}
//------------------------------------
// i2C READ one : 受信 = RDDAT
//------------------------------------
unsigned char i2c_READ(void) {
ACKDT = 1;
RCEN = 1;
while (SSPIF == 0); //SSPIFが1になるまで待つ。0の間繰り返す
RDDAT = SSPBUF;
SSPIF = 0;
ACKEN = 1;
while (SSPIF == 0); //SSPIFが1になるまで待つ。0の間繰り返す
SSPIF = 0;
return RDDAT;
}
//------------------------------------
// i2C READ Continue : 受信 = read_data
//------------------------------------
unsigned char i2c_READC(void) {
ACKDT = 0;
RCEN = 1;
while (SSPIF == 0); //SSPIFが1になるまで待つ。0の間繰り返す
RDDAT = SSPBUF;
SSPIF = 0;
ACKEN = 1;
while (SSPIF == 0); //SSPIFが1になるまで待つ。0の間繰り返す
SSPIF = 0;
return RDDAT;
}
//-------------------------------------
// i2C WRITE (write_data)
//-------------------------------------
void i2c_WRITE(unsigned char w_data) {
//    unsigned char w_data;
while (BF == 1); //BFが0になるまで待つ。1の間繰り返す。
SSPBUF = w_data;
SSPIF = 0;
while (SSPIF == 0); //SSPIFが1になるまで待つ。0の間繰り返す
if (ACKSTAT == 1) {
SSPIF = 0;
} else {
SSPIF = 0;
}
}
//-----------------------------------
// i2C STOP Condition
//-----------------------------------
void i2c_STOP(void) {
PEN = 1;
while (SSPIF == 0);
SSPIF = 0;
}
//----------------------------------
// i2C START Condition
//----------------------------------
void i2c_START(void) {
SEN = 1;
while (SSPIF == 0); //SSPIFが1になるまで待つ。0の間繰り返す
SSPIF = 0;
}
//----------------------------------
// i2C Re-START Condition
//----------------------------------
void i2c_ReSTART(void) {
RSEN = 1;
while (SSPIF == 0); //SSPIFが1になるまで待つ。0の間繰り返す
SSPIF = 0;
}
//----------------------------------
// i2C 設定初期化
//----------------------------------
void i2c_CONF(void) {
SSPM3 = 1;
SSPM2 = 0;
SSPM1 = 0;
SSPM0 = 0;
SMP = 1;
CKE = 0;
SSPADD = 0x3F;
SSPEN = 1;
WCOL = 0;
SSPOV = 0;
}
//-------------------------------------------------------
//  pth センサーリセットとID読み取り
//-------------------------------------------------------
unsigned char pth_IDread(void) {
//--- Soft Reset ---
i2c_START();
i2c_WRITE(S_ADRS2);
i2c_WRITE(0xDE0); // soft resetaddress
i2c_WRITE(0xB6); // reset value B6
i2c_STOP();
//--- Sensor ID read out ---
i2c_START();
i2c_WRITE(S_ADRS2);
i2c_WRITE(0xD0); //Sensor ID resister address
i2c_ReSTART();
i2c_WRITE(S_ADRS2 + 1);
i2c_READ(); // 読み取り結果はRDDAT ID shouled be h60
i2c_STOP();
return RDDAT;
}
//------------------------------------------------------------------------
// pth Block Read ブロック読み込み
//   引数(Regis_Address, No# of bytes、配列書き込み位置)
//   結果は、buff[32]に格納。 転送バイト数は、 nod、配列書き込み位置ip
//------------------------------------------------------------------------
void pth_BREAD(unsigned char r_adrs, unsigned char nod, unsigned char ip) {
unsigned char ipp;
i2c_START();
i2c_WRITE(S_ADRS2);
i2c_WRITE(r_adrs);
i2c_ReSTART(); //再スタート
i2c_WRITE(S_ADRS2 + 0x01);
if (nod >= 2) {
for (ipp = ip; ipp <= ip + nod - 2; ipp++) {
buff[ipp] = i2c_READC(); //同じ変数の型であること。連続読み込みREADC
}
buff[ipp] = i2c_READ(); //同じ変数の型であること。最後の読み込みREADC(判断条件修正)
} else {
buff[ip] = i2c_READ(); //同じ変数の型であること。最後の読み込みREADC
}
i2c_STOP();
}
//---------------------------------------------------------
// Clear LCD Screen (ACM1602)
// 引数=0 全面
// 引数=1 1行目のみ
// 引数=2 2行目のみ
// 画面をクリア。カーソルはホームポジションに。
//---------------------------------------------------------
void LCD_Clear(int para) {
if (para == 0) {
LCD_CW(0x01); //LCDクリアリセット
return;
}
if (para == 1) {
LCD_Locate(0, (para - 1));
LCD_puts("                ");
return;
}
if (para == 2) {
LCD_Locate(0, (para - 1));
LCD_puts("                ");
return;
}
}
//-----------------------------------------------------------
//  Debug Red LED (OK)
//  赤色LEDを点滅させてプログラム停止 (PORT RB7接続のLED)
//------------------------------------------------------------
void Debug_RED() {
while (1) {
RED_led ^= 1;
__delay_ms(50);
}
}
//----------------------------------------------
// LCD Initialization
// 画面クリア後カーソルはホームへセット
// RAMメモリーポインター先頭
//-----------------------------------------------
void LCD_init() {
LCD_CW(0x01); // LCDリセット
LCD_CW(0x38);
LCD_CW(0x0F);
LCD_CW(0x06);
LCD_CW(0x80); // 表示RAM領域アドレスポインターを先頭に
}
//-----------------------------------------------
//  LCD文字表示(連続)
//  現在のカーソル位置から連続して文字を書き込む
//  1行目、2行目の終端を越えた文字は無視される
//------------------------------------------------
void LCD_puts(const char *p) {
while (*p != '\0') {
LCD_DW(*p);
p++;
}
}
//-----------------------------------------
//  LCD Cursor Control (x, y))
//-----------------------------------------
void LCD_Locate(unsigned char x, unsigned char y) {
unsigned char pos;
pos = 0x40 * y + x;
pos = pos + 0x80;
LCD_CW(pos);
}
//---------------------------------------------
// LCD コマンド1バイト書き込み
//---------------------------------------------
void LCD_CW(unsigned char lcd_cmd) {
i2c_START();
i2c_WRITE(S_ADRS1);
i2c_WRITE(0x00);
i2c_WRITE(lcd_cmd);
i2c_STOP();
__delay_ms(5);
}
//---------------------------------------------
// LCD データ1バイト書き込み
//---------------------------------------------
/*void LCD_DW(unsigned char lcd_dat) {
i2c_START();
i2c_WRITE(S_ADRS1);
i2c_WRITE(0x80);
i2c_WRITE(lcd_dat);
i2c_STOP();
__delay_ms(5);
}*/////old(org)
void LCD_DW(unsigned char lcd_dat) {
i2c_START();
i2c_WRITE(S_ADRS1);
i2c_WRITE(0x40);
i2c_WRITE(lcd_dat);
i2c_STOP();
__delay_ms(5);
}
//----------------------------------------------
// 整数を16進数x4に変換表示(ゼロサプレスしない)
//----------------------------------------------
void Hex_Out(int z_hex) {
if (z_hex <= 0x0FFF) LCD_puts("0"); //頭のゼロを表示
if (z_hex <= 0x00FF) LCD_puts("0"); //'0'ではだめ
if (z_hex <= 0x000F) LCD_puts("0");
itoa(str, z_hex, 16); // 16進表示
LCD_puts(str);
}
//---------------------------------------------------
// 浮動小数を小数点以下1位で文字表示(LCD)
//---------------------------------------------------
void FloatDisp(float suji) {
int seisu;
int syousu;
seisu = suji;
syousu = suji * 10 - (float) seisu * 10;
itoa(str, seisu, 10);
LCD_puts(str);
LCD_puts(".");
itoa(str, syousu, 10); //itoa() 関数は整数 n を文字ストリングに変換します。 このストリングは、渡されたバッファーに置かれます。
LCD_puts(str);
}
//////////////////// up to  End Of Program org ///////////////////////////
// undermentioned are add by maru 2019/02/05
#define LCD_ADD 0x7C            //LCDスレーブアドレス W
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_Stop() {
I2C_Master_Wait();
PEN = 1;
}
void I2C_Master_Write(unsigned d) {
I2C_Master_Wait();
SSPBUF = d;
}
void I2C_Master_Start() {
I2C_Master_Wait();
SEN = 1;
}
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 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 LCD_str(char *c) { //LCDに配列の文字を表示
unsigned char i, wk;
for (i = 0;; i++) {
wk = c[i];
if (wk == 0x00) {
break;
}
writeData(wk);
}
}
//------------------------------------------------
void trigger(){
RA0 = 1;
__delay_us(10);
RA0 = 0;
}
void LCD_Init2() { //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);
}
//-------------------------------------------------------
// メインプログラム
//-------------------------------------------------------
main() {
PIC_init(); // PICの入出力ポート、割り込み、AD変換など初期設定
i2c_CONF(); // PIC設定i2c用
//LCD_init(); // LCD初期化、クリアディスプレイ
LCD_Init2();
//LCD_CW(0x0C); // LCDカーソル非表示、ブリンクなし。
//-----------------------------
// PIC 起動確認用LED点滅 4回
//-----------------------------
RED_led = 0; // RED LED on
YELLOW_led = 0;
GREEN1_led = 0;
GREEN2_led = 0;
__delay_ms(500);
RED_led = 1; // RED LED off
__delay_ms(500);
RED_led = 0; // RED LED on
__delay_ms(500);
RED_led = 1; // RED LED off
YELLOW_led = 1;
GREEN1_led = 1;
GREEN2_led = 1;
__delay_ms(500);
//------------------------
// LCD 初期メッセージ表示
//------------------------
char moji1[] = "Copy_Right@";
char moji2[] = "     VividHobby";
char moji3[] = "Ready";
char moji4[] = "   C     %   hPa";
LCD_puts(" Copy_Right@");
__delay_ms(1000);
LCD_Locate(0, 1); // カーソルセット
LCD_puts("     VividHobby");
__delay_ms(1000);
LCD_Clear(0); //LCD全クリア
LCD_puts("modified by maru"); //1行目に表示
//------------------------------------------------------------------
//  センサー読み取り、計算、表示、処理開始
//------------------------------------------------------------------
//センサーIDを読み込む
disp = pth_IDread();
itoa(str, disp, 16); // 整数dispを16進文字変換
LCD_Locate(0, 1); //カーソル移動
LCD_puts("Sensor ID = ");
LCD_puts(str);
__delay_ms(1000);
//センサーの初期設定(補正係数読み込み含む)
pth_setup(); //補正係数読み込み pth_readTrim()は以下
pth_readTrim(); //補正データの読み取り(合計32バイト)
//-------------------------------------------------------------
//計測を連続して行う
//-------------------------------------------------------------
writeCommand(0x01); //画面をクリア
__delay_ms(20);
//writeCommand(0x80); //1列目へ移動
//LCD_str(moji4);
LCD_Clear(0); //LCD全クリア
LCD_puts("  'C     %   hPa");
while (1) {
//センサーから生の計測データを読み出す
trigger();
pth_readData();
temp_cal = calibration_T(temp_raw);
press_cal = calibration_P(pres_raw);
hum_cal = calibration_H(hum_raw);
temp_act = (double) temp_cal / 100.0;
press_act = (double) press_cal / 100.0;
hum_act = (double) hum_cal / 1024.0;
//-- 温度表示--
LCD_Locate(0, 1);
FloatDisp(temp_act);
//-- 湿度表示--
LCD_Locate(6, 1);
FloatDisp(hum_act);
LCD_puts(" ");
//-- 気圧表示--
disp = press_act;
itoa(str, disp, 10); // 整数dispを16進文字変換
LCD_Locate(12, 1);
LCD_puts(str);
LCD_puts("   ");
__delay_ms(3000);
}
//------------------------- ここまでを繰り返す----------------------------
}
//-------------------- End of Main program --------------------------------

HEXファイルが45KBほど在り、PIC KIT3での転送時間もやや長めだと
感じました。

ULPWU 超低電流SLEEPモードを使う PIC12F683

先日、友人との会話の中で、所有する車に警報機が実装されて居ない
という事で、購入しようと思えば星の数ほどピンからキリまで様々な
警報機が在るのですが「ダミーでも構わない」という事で製作する
ことに成りまして超単純なLチカを造ろうと、色々と考えて居たのです
至った結論として・・・・

・電池が矢鱈に長持ちする
・三回点滅にする
・警報機らしく見せかける

・・・・などを考慮して取り敢えずPIC12F683を使う事にしました
理由は・・・・

・8ピンと小さい
・ULPWU 超低電流SLEEPモードを持って居る

・・・・からです。

データシートに依れば下記の様に謳われています
Low-Power Features:
• Standby Current:
– 50 nA @ 2.0V, typical
• Operating Current:
– 11μA @ 32 kHz, 2.0V, typical
– 220μA @ 4 MHz, 2.0V, typical
• Watchdog Timer Current:
– 1μA @ 2.0V, typical

最低電流値が50nAとはなかなかの実力だと思います
電源電圧で変わる数値ですから額面通りに受け取れませんがそれでも
それ成りに極小電流値で動いて呉れることでしょう。

という訳で又々他力本願のC言語探しをしていたところ記事が見つか
りまして早速、コピペ致しました PIC マイコンを便利に使うページ
部分的なコピペですが難なくアッサリと動いて呉れました感謝です。

動画は未だブレッドボード試作ですが何か探してそれらしく見せかけ
る為に組み込む予定です。

LEDは三回点滅します
ON = 10ms
インターバル = 200ms
周期 = 3.28秒
ザックリ計算して92.3uA/h、エボルタUM-3 で1,000mA/hですから
1.23年ぐらい持つだろうという捕らぬ狸の皮算用中です
電池は三本、4.5Vで動かします。

写真は
黄色 LEDオン波形
青  ULPWU コンデンサ放電波形
ピンク CPUクロック出力波形、sleep したかの確認の為に出力して居ます

追記2019/01/30(水)
動画の周期は正確ではない事が発覚致しました
理由は何かですが、オシロスコープのプローブのインピーダンスですプローブ
を除去することで周期が9.2秒まで広がりました、現在ULPWU コンデンサは
積層セラミックコンデンサー104を二個パラレルに接続して居ますが一個に
減らしました、それでも周期は4.6秒ですからもっと少ない容量でも良いかも
知れません、要はお好み次第って事ですね。
DSCN0562

回路図です
bandicam 2019-01-29 21-55-26-894

ソースファイル、部分コピペにLEDの点滅を割り込ませただけです

/*
* File:   main.c
* Author: maru Jan,29,2019
*/
// インクルードファイル
#include 
#include 
#include 
// PIC12F683コンフィグレーションビット設定
// PIC12F683 Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits 自己発信、1/4周波数出力 3pin出力
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include 
// クロック周波数指定
// (__delay_ms()関数が必要としているため)
#define _XTAL_FREQ  1000000
/******************************
LowPowerSleep
*******************************/
void LowPowerSleep(void) {
#ifndef DEBUG
for (int i = 0; i < 3; i++) {
GP5 = 1;
__delay_ms(10);
GP5 = 0;
__delay_ms(200);
}
GP0 = 1;
TRISIO0 = 0; //charge start
__delay_us(650); //2*PI*C*R*10
GPIF = 0;
ULPWUE = 1; //enable ULPWU
IOC0 = 1;
#endif
GPIE = 1;
GIE = 1;
TRISIO0 = 1; //discharge start
#ifdef DEBUG
TMR0 = 0;
T0IF = 0;
while (!T0IF);
#else
SLEEP();
NOP();
#endif
}
/*
* main()関数
*/
int main(int argc, char** argv) {
// PICマイコン初期化
OSCCON = 0x40; //クロック周波数を1MHzに設定
ANSEL = 0x00; //すべてのピンをデジタルモードに設定
TRISIO = 0x00; //すべてのピンを出力に設定
// LEDのピンを0にして、LEDを消灯する
GP5 = 0;
// 点滅を永遠繰り返す
while (1) {
LowPowerSleep();
NOP();
}
// ここには到達しない
return (EXIT_SUCCESS);
}

“ULPWU 超低電流SLEEPモードを使う PIC12F683” の続きを読む

I2C Color Sensor S11059 02DT

他力本願C言語シリーズ、カラーセンサ
CPU = PIC16F886
LCD = AQM1602XA スレーブアドレス 0x7C(W)  READ不可
カラーセンサ = S-5851A  スレーブアドレス 0x90(W)  0x91(R)

以前の記事で製作したものはアセンブラでしたので今回はC言語での制御です
正直言うとアセンブラの方が楽で確実でした、なにせど素人プログラムなので
C言語で制御すると文字化けが止まりません、5桁書くと6桁表示されて最後の
数字が6桁目にコピーされる、や、ちょっと長い文字列を書くと全部文字化け
するなど悪戦苦闘しました、結果的に出来た物は R / G / B / IR の表示が出来ず
得られたデータの羅列と成っています。

勉強に成ったのは1バイトが二個のデータをどうやって1つの固まりにするのか
全く概念が掴めなかったのですが、何の事は無い、上位バイトを八回左シフト
して下位バイトとの論理和にすれば良いんですね、まぁその程度なんですよ
だからど素人なのです。

動画の数字ですが・・・・
RED     GREEN
BLUE   IR
・・・・という並びに成っています。

ソースファイルです、相変わらず他のデバイスの関数がありまして何でもアリ
のプログラムです、そういうゴミは消せば良いのですが何でLCDが文字化けを
起こすのか未だに原因不明です、うーーん、気持ちがスッキリしない・・・
/*
* File:   main.c
* Author: maru
* I2C_Color Sensor_S11059-02DT_v000
* Created on 2019/01/22(火)
*
*/
//******************************************************************************
//コンフィギュレーション
// CONFIG1 MPLAB XIDEの Production -> Set Configration bits で設定してもこのプログラムでの宣言が優先される
//#pragma config FOSC = INTRC_NOCLKOUT //RA6 = I/O          //デフォルトではRA6 = fosc/4 output
// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = ON      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)電源オン時、要リセット、しないとBootしない
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Reset Selection bits (BOR enabled)
#pragma config IESO = ON       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (RB3/PGM pin has PGM function, low voltage programming enabled)
// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
//******************************************************************************
//コンパイラ
#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 PCF8574AN_ADR_R 0x73      //Extentioned IO スレーブアドレス W
#define ToHome 0b00000010
#define shiftLeft 0b00011000
#define shiftRight 0b00011100
#define clear 0b00000001
//--------------------------
//******************************************************************************
static unsigned char I2C_rcv();
static void I2C_nacksnd();
static unsigned char I2C_ackchk();
char moji[] = " ";
char moji2[] = "Celsius ";
char moji3[] = "Thermal S-5851A SII"; //この文字列を長くするとカウントアップがバグる、原因不明
char moji4[] = "      "; //空白を書く、前の文字が残って邪魔をするから
char moji5[] = "."; //
char moji6[] = "C";
char moji10[] = "0000"; //温度計少数以下
char moji11[] = "0625"; //温度計少数以下
char moji12[] = "1250"; //温度計少数以下
char moji13[] = "1875"; //温度計少数以下
char moji14[] = "2500"; //温度計少数以下
char moji15[] = "3125"; //温度計少数以下
char moji16[] = "3750"; //温度計少数以下
char moji17[] = "4375"; //温度計少数以下
char moji18[] = "5000"; //温度計少数以下
char moji19[] = "5625"; //温度計少数以下
char moji20[] = "6250"; //温度計少数以下
char moji21[] = "6875"; //温度計少数以下
char moji22[] = "7500"; //温度計少数以下
char moji23[] = "8125"; //温度計少数以下
char moji24[] = "8750"; //温度計少数以下
char moji25[] = "9375"; //温度計少数以下
char moji30[] = "EEPROM bank="; //EEPROM
char moji31[] = "W="; //EEPROM
char moji32[] = "R="; //EEPROM
unsigned char k; // k = PCF8574ANから読み込んだデータ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k2; // k2 = MCP23017から読み込んだデータ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k3; // k3 = 温度センサーから読み込んだデータ、MSB  char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k4; // k4 = 温度センサーから読み込んだデータ、LSB  但し上位4bitのみ、下位4bitはゼロ、char型 保存できる値は-127?127  //unsigned char型 保存できる値は 0-255です
unsigned char k5;
unsigned char LED;
//---------------------------------
//for EEPROM
int HADR; //EEPROM High address
int LADR; //EEPROM Low address
int ROMDATA_W; //EEPROM write data
int ROMDATA_R; //EEPROM read data
//---------------------------------
//for cplor sensor S11059-02DT
int RGB_R_MSB; //RGB
int RGB_R_LSB; //RGB
int RGB_G_MSB; //RGB
int RGB_G_LSB; //RGB
int RGB_B_MSB; //RGB
int RGB_B_LSB; //RGB
int IR_MSB; //IR
int IR_LSB; //IR
int RGB_R; //RED
int RGB_G; //GREEN
int RGB_B; //BLUE
int IR; //Infra red
//******************************************************************************
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_Init() {
SSPCON = 0x28; //RC3/SCK/SCL  RC4/SDI/SDA として使用宣言
SMP = 1;
CKE = 0;
SSPADD = 0x13; //
}
//-------------------------------
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;
//    }
// ストップコンディション生成 ↑代替 maru
void I2C_Master_Stop() {
// SSP1CON2レジスタのPENビットを1に設定すると
// ストップコンディションが生成される
// 発行が完了するとSSP1IFが1になるのでwhile文で待つ
SSPIF = 0;
SSPCON2bits.PEN = 1;
while (SSPIF == 0) {
}
SSPIF = 0;
return;
}
//-------------------------------
//    void I2C_Master_Write(unsigned d)
//    {
//      I2C_Master_Wait();
//      SSPBUF = d;
//    }
//代替↑
void I2C_Master_Write(unsigned d)
// SSP1BUFに送信したいデータをセットすると、そのデータが送信される
// 発行が完了するとSSP1IFが1になるのでwhile文で待つ
// ACK 待ちは無い、https://tool-lab.com/make/pic-practice-40/
{
I2C_Master_Wait(); //これが無いと全く出鱈目に成る 
__delay_us(10); //add maru 20190125 18:15
SSPIF = 0;
SSPBUF = d;
while (SSPIF == 0) {
}
SSPIF = 0;
//   return;
}
//-------------------------------
// I2C ACK check
static unsigned char I2C_ackchk() {
unsigned char i2c_data;
if (ACKSTAT) {
i2c_data = 0xFF;
} else {
i2c_data = 0x00;
}
return (i2c_data);
}
//-------------------------------
// I2C Recive
//static unsigned char I2C_rcv() {
//	SSPIF = 0;
//	RCEN = 1;
//	while (RCEN) {}
//	return(SSPBUF);
//}
static unsigned char I2C_rcv() {
SSPIF = 0;
SSPCON2bits.RCEN = 1;
while (SSPIF == 0) {
}
SSPIF = 0;
return SSPBUF;
}
//-------------------------------
// I2C NACK send
//static void I2C_nacksnd() {
//	ACKDT = 1;
//	ACKEN = 1;
//	while (ACKEN) {}
//	return;
//}
//-------------------------------
static void I2C_nacksnd() {
// ACKDTにNACKをセット(負論理なので1を設定)
SSPCON2bits.ACKDT = 1;
// NACK信号生成
SSPCON2bits.ACKEN = 1;
while (SSPCON2bits.ACKEN) {
}
return;
}
//-------------------------------
static void I2C_acksnd() {
// ACKDTにACKをセット
SSPCON2bits.ACKDT = 0;
// NACK信号生成
SSPCON2bits.ACKEN = 1;
while (SSPCON2bits.ACKEN) {
}
return;
}
//-------------------------------
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_str2(char *c) { //LCDに配列の文字を表示
unsigned char i, wk;
for (i = 0; i < 5; i++) {
wk = c[i];
//__delay_us(30);
if (wk == 0x00) {
break;
}
writeData(wk);
}
}
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);
}
//******************************************************************************
//PCF8574AN Extentioned IO 部分
void PCF8574AN_W() { //PCF8574AN Extentioned IO WRITE
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) { //PCF8574AN Extentioned IO WRITE
I2C_Master_Init(100000);
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(PCF8574AN_ADR); //スレーブアドレス
I2C_Master_Write(LED); //データ送信
I2C_Master_Stop(); //ストップ・コンディション
__delay_ms(10);
}
void PCF8574AN_R() { //PCF8574AN Extentioned IO READ
//    I2C_Master_Init(100000);              //これだと遅い
I2C_Init(); //これだと速い
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(PCF8574AN_ADR_R); //スレーブアドレス read
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
k = I2C_rcv(); //スレーブアドレス側からのデータを受信する
//    I2C_rcv(k);                           //この文法では読めない
//    PORTA = (k);                          //ここに入れるのもOK
I2C_nacksnd(); //NACk送信
I2C_Master_Stop(); //ストップ・コンディション
__delay_ms(10);
}
//******************************************************************************
// MCP23017 16bit IO 部分
int GPA_LED;
int GPB_IN_DATA;
void MCP23017_GPA_INIT() {
//MCP23017_GPAイニシャライズ
I2C_Init(); //これだと速い
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x40); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x00); //レジスタ・ナンバー
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x00); //全入力設定 write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Stop(); //ストップ・コンディション
}
void MCP23017_GPB_INIT() {
//MCP23017_GPイニシャライズ
I2C_Init(); //これだと速い
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x40); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x01); //レジスタ・ナンバー
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0xFF); //全出力設定 write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Stop(); //ストップ・コンディション
}
void MCP23017_GPA_OUT(GPA_LED) {
//MCP23017_GPAにデータ出力させる、Lチカ
I2C_Init(); //これだと速い
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x40); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x14); //レジスタ・ナンバー
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(GPA_LED); //LED表示 write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Stop(); //ストップ・コンディション
}
void MCP23017_GPB_IN() {
//MCP23017_GPBのデータを読み込む、ディップスイッチ8bit
I2C_Init(); //これだと速い
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x40); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x13); //レジスタ・ナンバー
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_RepeatedStart(); //SR = RepeatedStart
I2C_Master_Write(0x41); //スレーブアドレス READ
I2C_Master_Wait();
I2C_ackchk();
k2 = I2C_rcv(); //スレーブアドレス側からのデータを受信する = k2
I2C_nacksnd(); //NACk送信
I2C_Master_Stop(); //ストップ・コンディション
__delay_ms(10);
}
//******************************************************************************
//I2C 温度センサー SII S-5851A 部分
void s5851a_init() //温度センサー初期化
{
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x90); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x01); //コンフィギュレーション・レジスタ
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x00); //常温設定
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Stop(); //ストップ・コンディション
}
void s5851a_me1() //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
{
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x90); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x00); //ダミー
I2C_Master_Wait();
I2C_ackchk();
I2C_Master_RepeatedStart(); //リスタート
I2C_Master_Write(0x91); //スレーブアドレス Read
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
k3 = I2C_rcv(); //スレーブアドレス側からのデータを受信するMSB
I2C_acksnd(); //ACK送信
k4 = I2C_rcv(); //スレーブアドレス側からのデータを受信するLSB 但し上位4bitのみ下位4bitはゼロ
I2C_nacksnd(); //NACK送信
I2C_Master_Stop(); //ストップ・コンディション
}
void s5851a_me2() //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
{
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x91); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
k3 = I2C_rcv(); //スレーブアドレス側からのデータを受信するMSB
I2C_acksnd(); //ACK送信
k4 = I2C_rcv(); //スレーブアドレス側からのデータを受信するLSB 但し上位4bitのみ下位4bitはゼロ
I2C_nacksnd(); //NACK送信
I2C_Master_Stop(); //ストップ・コンディション
}
void hairetsu() {
if (k4 == 0) {
LCD_str(moji10);
} else if (k4 == 1) {
LCD_str(moji11);
} else if (k4 == 2) {
LCD_str(moji12);
} else if (k4 == 3) {
LCD_str(moji13);
} else if (k4 == 4) {
LCD_str(moji14);
} else if (k4 == 5) {
LCD_str(moji15);
} else if (k4 == 6) {
LCD_str(moji16);
} else if (k4 == 7) {
LCD_str(moji17);
} else if (k4 == 8) {
LCD_str(moji18);
} else if (k4 == 9) {
LCD_str(moji19);
} else if (k4 == 0x0A) {
LCD_str(moji20);
} else if (k4 == 0x0B) {
LCD_str(moji21);
} else if (k4 == 0x0C) {
LCD_str(moji22);
} else if (k4 == 0x0D) {
LCD_str(moji23);
} else if (k4 == 0x0E) {
LCD_str(moji24);
} else if (k4 == 0x0F) {
LCD_str(moji25);
}
return;
}
//******************************************************************************
//I2C EEPROM 24LC64 部分
void EEPROM_W() //EEPROM 1 byte write routin 2019/01/22
{
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0xA0); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(HADR); //EEPROM High address
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(LADR); //EEPROM Low address
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(ROMDATA_W); //EEPROM Low address
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Stop(); //ストップ・コンディション
}
void EEPROM_R() //温度測定一回目のみ、二回目からはカレントリードと云う簡略化したプロトコルで良い
{
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0xA0); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(HADR); //EEPROM High address
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(LADR); //EEPROM Low address
I2C_Master_Wait();
I2C_ackchk();
I2C_Master_RepeatedStart(); //リスタート
I2C_Master_Write(0xA1); //スレーブアドレス Read
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
ROMDATA_R = I2C_rcv(); //スレーブアドレス側からのデータを受信するMSB
I2C_nacksnd(); //NACK送信
I2C_Master_Stop(); //ストップ・コンディション
}
//******************************************************************************
//I2C color srnsor S11059-02DT 部分
void COLOR_S() //I2C color srnsor S11059-02DT読み出し、イニシャライズは無い
{
//TRIGGER();
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x54); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x00); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x89); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_RepeatedStart(); //リスタート
I2C_Master_Write(0x54); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x00); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x09); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
__delay_ms(10);
//TRIGGER();
I2C_Master_Start(); //スタート・コンディション
I2C_Master_Write(0x54); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_Write(0x03); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
I2C_Master_RepeatedStart(); //リスタート
I2C_Master_Write(0x55); //スレーブアドレス write
I2C_Master_Wait();
I2C_ackchk(); //ACKチェック、無くても普通に動く、スレーブアドレス違ってもスルーする
RGB_R_MSB = I2C_rcv(); //スレーブアドレス側からのデータを受信する
I2C_acksnd(); //マスターから送信するack
RGB_R_LSB = I2C_rcv(); //スレーブアドレス側からのデータを受信する
I2C_acksnd(); //マスターから送信するack
RGB_G_MSB = I2C_rcv(); //スレーブアドレス側からのデータを受信する
I2C_acksnd(); //マスターから送信するack
RGB_G_LSB = I2C_rcv(); //スレーブアドレス側からのデータを受信する
I2C_acksnd(); //マスターから送信するack
RGB_B_MSB = I2C_rcv(); //スレーブアドレス側からのデータを受信する
I2C_acksnd(); //マスターから送信するack
RGB_B_LSB = I2C_rcv(); //スレーブアドレス側からのデータを受信する
I2C_acksnd(); //マスターから送信するack
IR_MSB = I2C_rcv(); //スレーブアドレス側からのデータを受信する
I2C_acksnd(); //マスターから送信するack
IR_LSB = I2C_rcv(); //スレーブアドレス側からのデータを受信する
I2C_nacksnd(); //NACK送信
I2C_Master_Stop(); //ストップ・コンディション
}
//******************************************************************************
int main(void) {
PICinit(); //PICを初期化
//-----------
I2C_Init(); //これだと速い
//-----------
LCD_Init(); //LCD初期化
__delay_ms(2);
//-----------
writeCommand(0x01); //画面をクリア
__delay_ms(10);
writeCommand(0x02); //ホームへカーソル移動
__delay_ms(2); // LCD側の処理待ち、LCDは全く読み込めないので見込み時間
//-------------------------------
/*
writeCommand(0x85); //2列目へ移動
LCD_str2(moji32);
writeCommand(0x8D); //2列目へ移動
LCD_str2(moji32);
writeCommand(0x85 + 0x40); //2列目へ移動
LCD_str2(moji32);
writeCommand(0x8D + 0x40); //2列目へ移動
LCD_str2(moji32);
__delay_ms(10);
*/
//-------------------------------
while (1) //Loop
{
COLOR_S(); //I2C color srnsor S11059-02DT読み出し
//-------------------------------
RGB_R_MSB = RGB_R_MSB << 8; //shift 8bit to left
RGB_R = RGB_R_MSB | RGB_R_LSB; // make 2 byte
RGB_G_MSB = RGB_G_MSB << 8; //shift 8bit to left
RGB_G = RGB_G_MSB | RGB_G_LSB; // make 2 byte
RGB_B_MSB = RGB_B_MSB << 8; //shift 8bit to left
RGB_B = RGB_B_MSB | RGB_B_LSB; // make 2 byte
IR_MSB = IR_MSB << 8; //shift 8bit to left
IR = IR_MSB | IR_LSB; // make 2 byte
writeCommand(0x80); //1列目へ移動
__delay_ms(10);
sprintf(moji, "%05d", RGB_R); //左寄せしない5桁
LCD_str2(moji);
__delay_ms(10);
writeCommand(0x88); //1列目へ移動
__delay_ms(10);
sprintf(moji, "%05d", RGB_G); //左寄せしない5桁
LCD_str2(moji);
__delay_ms(10);
writeCommand(0x80 + 0x40); //2列目へ移動
__delay_ms(10);
sprintf(moji, "%05d", RGB_B); //左寄せしない5桁
LCD_str2(moji);
__delay_ms(10);
writeCommand(0x88 + 0x40); //2列目へ移動
__delay_ms(10);
sprintf(moji, "%05d", IR); //左寄せしない5桁
TRIGGER();
LCD_str2(moji);
__delay_ms(3);
//-------------------------------
__delay_ms(333);
}
return 0; //Loop
//-------------------------------
}

“I2C Color Sensor S11059 02DT” の続きを読む