i2cまがいシリアル接続はPORTのビット制御で行います。TRISとPORTのビット単位上げ下げでビットプリミティブを作ります。i2cはMSSPを使います。
MSSPを使うi2cマスター用関数はいつものものを流用。i2c接続LCDも流用です。
SHT-11制御部もライブラリー関数にしようとしましたが、訳わからんエラー出て断念しました。
ところでメモリー消費ですが、なな、なんと96%です。
RTCもつなぎたいですが、RTCだけでも2kワードには収まりませんから、8ピンでは時計付き温度湿度計は無理なようです。
とりあえず、MAINのソースです。
/************************************************* SHT-11 THERMOMETER of PIC12F1822 By nobcha all right reserved Ver 1. 10/08/2013 for SHT-11 & ST7032 PIC12F1822 PIN Assign #7 RA0:monitor LED #6 RA1:SCL #5 RA2:SDA #4 RA3:MCLR #3 RA4:SCK for SHT-11 #2 RA5:DATA for SHT-11 OSC INT 8MHz Development Circumstance MPLAB IDE V8.92 HiTECH C V9.83 ************************************************* */ #define _LEGACY_HEADERS #define _XTAL_FREQ 8000000 #include <htc.h> #include <stdio.h> #include "lcd_i2c_mssp.h" #include "sht11.h" __CONFIG( FOSC_INTOSC & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF ); __CONFIG( WRT_OFF & PLLEN_OFF & STVREN_ON & LVP_OFF ); // bit position #define bitSCK 4 // SCKポートのビット番号 (RA4) #define bitDATA 5 // DATAポートのビット番号(RA5) // port group #define SHT_PORT PORTA // SCK、DATAが所属するポート・グループ #define SHT_TRIS TRISA // ポートのI/O切り替えTRISアドレス // DATA port mode set #define DATA_H() SHT_TRIS|=(1<<bitDATA) // 入力に設定(Hi-Z="H") #define DATA_L() SHT_TRIS&=~(1<<bitDATA) // 出力に設定("L") // マクロ:温度値 Temperature = −40 + 0.01×(AD値) #define CalcTMP10() (ADValTmp- 4000+5)/10; // 温度変換マクロ(10倍値) // Prototyping functions // Function prototyping void mssp_init(void); void reg_init(void); void Init_port(void); void SCK_H(void); // SCK H化関数 void SCK_L(void); // SCK L化 void SHTInit(void); // SHT初期化 void SHTTSSeq(void); // SHTのTSシーケンス unsigned char SHTWrite(unsigned char); // SHTバイト書き込み unsigned char SHTRead(unsigned char); // SHTから読み込み int CalcHR10(void); // 湿度換算(10倍値) // Grobal variables unsigned char PBuf = 0; // 出力ポートのバッファ int ADValHR, ADValTmp; // Humidity & Temperature AD value void main(void) { int wdat,ValHR10; unsigned char bdat_H, bdat_L, bdat_CRC; char Str[9]; // 文字列バッファ char Msg[] = "SHT-11 "; reg_init(); mssp_init(); // MSSP initialize LATA0 = 1; lcd_init(); // LCD initialize __delay_ms(200); lcd_goto(0x0); lcd_str(Msg); // LCDへ表示 __delay_ms(400); SHTInit(); while(1) { __delay_ms(200); // Humidity reading SHTTSSeq(); // TSシーケンス発行 SHTWrite(0x05); // measure humidity コマンド送信 // 変換完了待ち while((SHT_PORT & (1<<bitDATA))) {} // A-D変換完了を待つ bdat_H = SHTRead(0); // read high byte(ACK) bdat_L = SHTRead(0); // read low byte(ACK) bdat_CRC = SHTRead(1); // read CRC(NOACK) ADValHR = ((int)bdat_H << 8) | bdat_L; // 16ビットに合成 ValHR10 = CalcHR10(); // 工学数値へ変換 sprintf(Str, "RH=%d.%d%%", ValHR10 / 10, ValHR10 % 10); // 文字列を作成 lcd_goto(0x40); lcd_str(Str); // LCDへ表示 // Temperature reading SHTTSSeq(); // TSシーケンス発行 SHTWrite(0x03); // measure Temperature コマンド送信 // 変換完了待ち while((SHT_PORT & (1<<bitDATA))) {} // A-D変換完了を待つ bdat_H = SHTRead(0); // read high byte(ACK) bdat_L = SHTRead(0); // read low byte(ACK) bdat_CRC = SHTRead(1); // read CRC(NOACK) ADValTmp = ((int)bdat_H << 8) | bdat_L; // 16ビットに合成 wdat = CalcTMP10() ; sprintf(Str, "RT=%d.%d゚C", wdat / 10, wdat % 10); // 文字列を作成 lcd_goto(0x0); lcd_str(Str); // LCDへ表示 } } /*************************************** * Register initialize ****************************************/ void reg_init(void){ /* INITIALIZE REGISTERs */ OSCCON = 0b01110000; // Set 8MHz PORTA = 0b00000000; // Clear TRISA = 0b00100110; // RA1,RA2 INPUT ANSELA = 0b00000000; // All digital CM1CON0 = 0b00000111; // No using compalator OPTION_REG = 0b00100100; // PORTB pullup,INTEDG 0,TOCS T0CKI 1,ToSE0,PSA TIMER0,1/32 INTCON=0; // INT off T1CON = 0; // Timer1 off PIR1 = 0b00000000; // ADIF 0,RCIF 0,TXIF 0,SSPIF 0,CCP1IF 0,TMR2IF 0,TMR1IF 0 } /*************************************** * MSSP initialize ****************************************/ void mssp_init(void){ /* SSP1CON1 REGISTERS */ SSPEN = 1; //Enables Serial Port Mode SSPM3 = 1; ///////// SSPM2 = 0; //I2C Master Mode SSPM1 = 0; // clock= Fosc/(4*(SSP1ADD+1)) SSPM0 = 0; //////// /* SSPCON2 REGISTERS */ SSP1CON2 = 0x00; /* SSPCON3 REGISTERS */ SSP1CON3 = 0x00; /* SSP1STAT REGISTERS */ SMP = 1; //SPI MASTER MODE CKE = 1; //SMBus Specific Inputs Enabled //SSP1ADD = 0x19; //~75kHz //SSP1ADD = 0x13; //~100kHz //SSP1ADD = 0x07; //~400kHz SSP1ADD = 0x50; } //--------------------------------------------------- /* エレキジャック マイコンの応用「2線式 温・湿度センサSHT11」を参考。作者の中尾さんに感謝します。 http://www.eleki-jack.com/mycom2/pic/cat94/2_sht11/ */ // SCKを"H"レベルに設定する関数 void SCK_H(void) { PBuf |= (1<<bitSCK); // SCK="H" SHT_PORT = PBuf; } // SCKを"L"レベルに設定する関数 void SCK_L(void) { PBuf &= ~(1<<bitSCK); // SCK="L" SHT_PORT = PBuf; } //---------------------------------------------------- /* 初期化 SHTInit() SHTを使うにあたり、I/Oポートの初期化。 SCK、DATA両ポートの入出力方向を設定し、 両ポートの状態をアイドルにする。 "PBuf"はグローバル変数、出力ポート用バッファ。 設定値を全ビット同時に更新するため一時変数で 出力値を設定し レジスタへ書き込む。 */ // // SHTポート初期化 // void SHTInit(void) { unsigned char buf; SHT_TRIS = (1<<bitDATA)| SHT_TRIS; // DATA input(Hiz-H) PBuf |= ~(1<<bitDATA); // DATA = "L" PBuf &= ~(1<<bitSCK); // SCK = "L" SHT_PORT = PBuf; // 初期値を出力 buf = SHT_TRIS; buf &= ~(1<<bitSCK); // SCK output ("L") buf |= (1<<bitDATA); // DATA input (HiZ-"H") SHT_TRIS = buf; // I/Oを設定 } //--------------------------------------------------------------- /* TS(トランスミッション・スタート)シーケンス発行 SHTTSSeq() TSシーケンスを発行する関数です。 コマンドを送信する前に必ずTSシーケンスを発行する必要があります。 */ // // SHT TSシーケンス // void SHTTSSeq(void) { DATA_H(); SCK_H(); DATA_L(); SCK_L(); SCK_H(); DATA_H(); SCK_L(); } //---------------------------------------------------------- /* バイト・データ送信 SHTWrite() バイト・データそマスタ送信(書き込み)する関数。 データ送信した後にSHT11がスレーブの送信したACKデータを受信。 マスタ送信するデータは引数の"dat"で渡します。 マスタ送信したあとにSHTがスレーブ送信した"ACK"/"NOACK"は、 関数の戻り値で得られます。戻り値が"0"のときが"ACK"です。 送信するデータは最上位から1ビットずつ取り出して、 その値をDATAポートに設定しながら、 SCKポートからクロック・パルスを出力します。 SCKパルスの立ち下がりエッジで出力データを更新する。 */ unsigned char SHTWrite(unsigned char dat) { unsigned char i, rdat; // DATAビットの出力 for(i = 0; i < 8; i++) { SCK_L(); if(dat & 0x80) { // MSB // "1" DATA_H(); } else { // "0" DATA_L(); } SCK_H(); dat <<= 1; // 次のビット } SCK_L(); // ACKビットの入力 DATA_H(); // 入力に切り替え SCK_H(); // ↑edge if(SHT_PORT & (1<<bitDATA)) { // read DATA // 1 rdat = 1; // NOACK } else { // 0 rdat = 0; // ACK } SCK_L(); return rdat; } //------------------------------------------------------- /* バイト・データ受信 SHTRead() バイト・データをSHT11からマスタ受信(読み出し)関数。 データを受信した後に"ACK"/"NOACK"をマスタ送信。 引数の"ack"を0にすると"ACK"、"1"にすると"NOACK"で応答。 受信したデータは関数の戻り値。 SCKポートからクロック・パルスを出力しながら、 DATAポートで受信したビットを順番に変数へ格納して、 それを8回繰り返すことにより1バイトのデータを得る。 受信データはSCKパルスの立ち上がりエッジで取り込み。 */ unsigned char SHTRead(unsigned char ack) { unsigned char i, dat; dat = 0; DATA_H(); // 入力に切り替え // DATAビットの入力 for(i = 0; i < 8; i++) { dat <<= 1; // 次のビット SCK_H(); // ↑edge if(SHT_PORT & (1<<bitDATA)) { // read DATA // "1" dat |= 1; } SCK_L(); } // ACKビットの出力 if(!ack) { DATA_L(); } else { DATA_H(); } SCK_H(); SCK_L(); // ↓edge DATA_H(); // 入力に切り替え return dat; } /* 湿度値 RHlinear = −4 + 0.0405×(AD値) − 2.8×10-6×(AD値)2 */ int CalcHR10(void) { int ad, x1, x2, x3, x4, cd10, b10; // 桁ごとの数値を取り出す ad = ADValHR; x1 = ad / 1000; ad = ad - 1000 * x1; x2 = ad / 100; ad = ad - 100 * x2; x3 = ad / 10; x4 = ad - 10 * x3; // 桁ごとにA-D値を掛け算する x1 = ADValHR * x1; x2 = (ADValHR * x2 + 5) / 10; // 小数点以下四捨五入 x3 = (ADValHR * x3 + 50) / 100; // 小数点以下四捨五入 x4 = (ADValHR * x4 + 500) / 1000; // 小数点以下四捨五入 x1 = x1 + x2 + x3 + x4; // 計算結果を合成 x2 = (x1 + 5) / 10; // 1/10する. 小数点以下四捨五入 cd10 = (28 * x2 + 50) / 100; x1 = (ADValHR * 4 + 5) / 10; x2 = (ADValHR * 5 + 500) / 1000; b10 = x1 + x2; return -40 + b10 - cd10; // 湿度値を10倍した整数値 }
ホームページではまとめて記載
http://chitose6thplant.web.fc2.com/n_4digit/1822_sht.html