2つの温度 (車内温度・車外温度) と1つの湿度を計測します。
コンパイラはCCS Cを使用しています。
#include <16f876.h> #include "FsID.h" #fuses HS, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP #device ADC=10, *=16 // A/D変換 10ビットモード, 16bitポインタ指定 #use delay( Clock = 20000000 ) // クロック周波数指定 #use i2c( slave, SDA=PIN_C4, SCL=PIN_C3, ADDRESS=ADD_ENVIRON, FAST, FORCE_HW ) #use fast_io( A ) #use fast_io( B ) #use fast_io( C ) // マクロ定義 ************************************************************** #define CH_TEMPOUT 0 // 外気温 入力チャンネル #define CH_TEMPIN 1 // 内気温 〃 #define CH_HUM 4 // 湿度 入力チャンネル // プロトタイプ宣言 ******************************************************** signed long Thermometer( int ); long Hygrometer(); void DisplayLCD(); long MinusSign( signed long Data ); // グローバル変数宣言 ****************************************************** signed long AirTemp; // 外気温[x10℃] signed long RoomTemp; // 内気温[x10℃] long Humidity; // 湿度[x10%] // ------------------------------------------------- #include "lcd_lib.h" // 液晶表示ライブラリ #include "i2c.h" // I2C送受信処理 #include "ad.h" // A/D // ===================================================================== // SSP割り込み処理 #int_ssp void ssp_interupt() { if( i2c_poll() ) { // 受信 int Receive; Receive = i2c_read(); } else { // 送信 I2cSlaveSend16( ( long )AirTemp ); I2cSlaveSend16( ( long )RoomTemp ); I2cSlaveSend16( Humidity ); } } // ===================================================================== // メイン関数 void main() { /* ------------------------------------------------------ A0,A1:温度測定(AN_in) A5:湿度測定(AN_in) C3:I2C_SCL(in) C4:I2C_SDA(in) -------------------------------------------------------*/ set_tris_a( 0b00100011 ); set_tris_b( 0b00000000 ); set_tris_c( 0b00011000 ); output_a( 0x00 ); output_b( 0x00 ); output_c( 0x00 ); setup_adc_ports( A_ANALOG ); // Setup A/D Converter setup_adc( adc_clock_div_32 ); // Fosc/32 最高速度 // ------------------------------------------------------ enable_interrupts( GLOBAL ); // グローバル割り込み許可 lcd_init(); printf( lcd_data, "Fs - environment" ); // 入力信号が安定するまで待つ ----- delay_ms( 1000 ); // -------------------------------- AirTemp = RoomTemp = Humidity = 0; enable_interrupts( INT_SSP ); // SSP割り込み許可。外部との通信を開始する while( 1 ) { // 外気温 測定 AirTemp = Thermometer( CH_TEMPOUT ); // 内気温 測定 RoomTemp = Thermometer( CH_TEMPIN ); // 湿度 測定 Humidity = Hygrometer(); DisplayLCD(); delay_ms( 90 ); } } // ===================================================================== // 温度 測定 signed long Thermometer( int Channel ) { const signed long minTemp = -15; // 測定最低温度 const long TempData[ 81 ] = // 温度データ表(-15~64℃) { 0x064F, 0x068F, 0x06D1, 0x0714, 0x0759, 0x07A0, 0x07E9, 0x0834, 0x0880, 0x08CE, 0x091D, 0x096D, 0x09BF, 0x0A11, 0x0A65, 0x0ABB, 0x0B12, 0x0B6B, 0x0BC5, 0x0C1F, 0x0C7B, 0x0CD7, 0x0D34, 0x0D92, 0x0DF0, 0x0E4E, 0x0EAF, 0x0F0F, 0x0F72, 0x0FD3, 0x1033, 0x1095, 0x10F7, 0x1159, 0x11BB, 0x121C, 0x127E, 0x12DE, 0x1340, 0x13A1, 0x1400, 0x1460, 0x14BF, 0x151D, 0x157B, 0x15D8, 0x1634, 0x1690, 0x16EB, 0x1744, 0x179D, 0x17F4, 0x184A, 0x189F, 0x18F3, 0x1946, 0x1998, 0x19E9, 0x1A39, 0x1A86, 0x1AD3, 0x1B1F, 0x1B69, 0x1BB2, 0x1BF9, 0x1C40, 0x1C85, 0x1CC9, 0x1D0C, 0x1D4D, 0x1D8D, 0x1DCC, 0x1E09, 0x1E45, 0x1E7F, 0x1EB9, 0x1EF1, 0x1F28, 0x1F5F, 0x1F93, 0xFFFF, // 最後は番兵 }; int Count; long Data; Data = ADConv10( Channel ) * 10; // アナログ入力 x10 for( Count = 0; Data >= TempData[ count + 1 ]; Count++ ) { // 温度データ表と比較 } // 測定範囲オーバー if( Data < TempData[ 0 ] || Count >= 80 ) { // エラー(コード:0x7FFF) return 0x7FFF; } // 小数点以下計算 Data -= TempData[ Count ]; Data /= ( TempData[ Count + 1 ] - TempData[ Count ] ) / 10; // 温度[x10℃] = ((最低温度 + データ位置) * 10) + 少数点以下の値 return ( minTemp + Count ) * 10 + Data; } // ===================================================================== // 湿度 測定 long Hygrometer() { int i; long Data; long Result = 0; // 32回の平均値を測定値とする for( i = 0; i < 32; i++ ) { Data = ADConv10( CH_HUM ); // 湿度100%以上は 測定エラー if( Data >= 1000 ) { // エラー(コード:0xFFFF) return 0xFFFF; } Result += Data; } // 湿度[x10%] = (A/D平均値 - 仮想GND電圧) * 10 / 5 return ( Result / 32 - 0x0200 ) * 2; } // ===================================================================== // LCD表示処理 void DisplayLCD() { long Work; lcd_cmd( 0xC0 ); // 内気温 printf( lcd_data, "In:" ); Work = MinusSign( RoomTemp ); printf( lcd_data, "%2lu.%1luC\xDF ", Work / 10, Work % 10 ); // 湿度 if( Humidity == 0xFFFF ) { printf( lcd_data, "error" ); // エラー表示 } else { printf( lcd_data, "%2lu.%1lu%%", Humidity / 10, Humidity % 10 ); } } // マイナス記号処理 long MinusSign( signed long Data ) { if( Data >= 0x0000 ) { // 表示位置を合わせるため符号表示を手動で行う printf( lcd_data, " " ); return Data; } else { printf( lcd_data, "-" ); // 2の補数により絶対値をとる return ~Data + 1; } }