nobcha23の日記

PICマイコンやArduinoを使う電子回路遊びを紹介します

PIC12F1822、ST7032液晶とSHT-11を組み合わせる ソフト編

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

新規モニター登録

マクロミルへ登録