/**************************************************************************** * メイン・プログラム:QVGA表示気圧・温湿度計テスト4 * * PIC24Fトレーニング基板使用 * 2.4インチQVGA液晶モジュール(aitendo): UL024TF * 温湿度センサ:HDC1000 * 大気圧センサ:LPS25H * I2C-RTCモジュール:RTC8564NB(今回は電池BUP有りの時刻合わせ付き) * * 原典参考先: * @ トラ技2006年3月号 山本さんの記事 * A 「太田さんのホームページ」の記事 * B 「きむ茶工房ガレージハウス」の記事 * * Condition: * 8MHz Internal RC oscillator, 4x PLL (8MHzx4= 32MHz) * Fcy=32MHz/2=16MHz, Tcy=62.5ns * * CPU: PIC24FJ64GA002 * * 2017.3.5 初期作成 N.Ishii *****************************************************************************/ #include "p24FJ64GA002.h" #include "stdio.h" #include "colorlcd_libdsPICVH.h" #include "skI2C_PIC24F_lib.h" // I2C通信用ライブラリ #include "skHDC_PIC24F.h" // HDC1000用関数ライブラリ #include "skLPS25H_PIC24F.h" // LPS25H用関数ライブラリ #define HDC1000_ADRS 0x40 // HDC1000のI2Cアドレス #define LPS25H_ADRS 0x5D // LPS25HのI2Cアドレス(SDO/SAO is HIGH) #define RTC8564_ADRS 0x51 // RTC8564NBのI2Cアドレス /// コンフィギュレーション ビットの設定 _CONFIG1( JTAGEN_OFF // JTAGの使用:無効 & GCP_OFF // コードプロテクト:しない & GWRP_OFF // 書き込みプロテクト:しない & BKBUG_OFF // バックグラウンドデバッグ:無効 & COE_OFF // クリップオンエミュレーション:無効 & ICS_PGx1 // EMUC/EMUDをPCG1/PGD1と共用 & FWDTEN_OFF // WDT:無効 ) /// Fosc = FRC (Fosc=32MHz) _CONFIG2( IESO_OFF // 2速度スタートアップ:無効 & FNOSC_FRCPLL // 8MHz Internal RC oscillator, 4x PLL-> 8MHzx4=32MHz & FCKSM_CSDCMD // クロック切り替え・クロックモニタ:供に無効 & OSCIOFNC_ON // OSCOピン機能:RA3ポートとする 161118 & IOL1WAY_OFF // RPレジスタプロテクト:プロテクトしない & I2C1SEL_PRI // I2C1のピン選択:主ピンを使用する & POSCMOD_NONE // 主発振器:使用しない ) //---------------------------------------------------------------------------------------------------------------------- // initialize RTC8564 Side Reg Write Data unsigned char rtc_write_data_tbl[] = { 0x20, // [0]:Control1REG: Time Stop 0x00, // [1]:Control2REG: ALM INT.TIMMER INT Desable 0x00, // [2]:SecondsREG: Set 0 Set 0x00, // [3]:MinutesREG: Set 0 Min 0x00, // [4]:HourREG: Set 0 Hour 0x15, // [5]:DayREG 0x02, // [6]:WeekdaysREG: TUE 0x06, // [7]:MonthsREG 0x10, // [8]:YearsREG 0x80, // [9]:Minute_AlamREG: Not Used ALM Interrupt 0x80, // [10]:Hour_AlamREG 0x80, // [11]:Day_AlamREG 0x80, // [12]:Weekday_AlamREG 0x83, // [13]:CLKOUT_frequencyREG: Set 1Hz Output ON 0x00, // [14]:Timer_contorolREG: Not Used Timer Interrupt 0x01 // [15]:Timer_downcount Set Vule }; //----------------------------------------------------------------------------------- /// メッセージデータ定義 char MsgDate[] = "xx/xx/xx"; char MsgTime[] = "xx:xx:xx"; //---------------------------------------------------------------------------------- /// RTC受信データバッファ unsigned char rec_data[16]; unsigned char year, month, day, week, hour, min, sec; //------------------------------------------------------------------------- #define HIST_MAX 151 // 履歴ポイント:151max 170121 #define GET_NONEXT (-1) #define GET_EMPTY (-2) /// SWのポート宣言定義 #define PLOT_INTERVAL_SW PORTBbits.RB0 // SW1:電源ON時のみ読込み→ プロット間隔設定用でレベルセンス #define HOLD_SW PORTBbits.RB1 // SW2:更新待機期間のみ読込み→ ホールドON/OFF用でエッジセンス割込み // SW1,2は、以下の機能を兼用している #define SW1 PORTBbits.RB0 // 桁送り(項目選択) #define SW2 PORTBbits.RB1 // 数値設定 /// LEDのポート宣言定義 #define LED LATAbits.LATA3 //// リングバッファ用 /// 温度 char temp_hist[HIST_MAX]; // temp_hist[151]:温度値データ履歴バッファ int temp_hist_head = 0; int temp_hist_full = 1; /// 湿度 char humi_hist[HIST_MAX]; // humi_hist[151]:湿度値データ履歴バッファ int humi_hist_head = 0; int humi_hist_full = 1; /// 気圧 int pres_hist[HIST_MAX]; // pres_hist[151]:気圧値データ履歴バッファ int pres_hist_head = 0; int pres_hist_full = 1; int graph_count; int GraphLoopMax; // 浮動小数変数 double Humi ; // 湿度の値を保存する変数 double Temp ; // 温度の値を保存する変数 double Press ; // 大気圧の値を保存する変数 char HOLD_ON_flag = 0; char hold_status = 0; char EndFlag = 0; // 関数のプロトタイプ宣言 void PressureRead() ; void HDC_Read() ; void print_axis(void); void print_graph(unsigned short, unsigned short, unsigned short); void add_temp(char); int get_temp(int, char *); void add_humi(char); int get_humi(int, char *); void add_pres(int); int get_pres(int, int *); //------------------------------------------------------------------------- void WriteRTC(char, char); void ReadRTC(char, char); char getNum(char num,char top,char y,char x); char getDigit(char num,char top,char y,char x); //------------------------------------------------------------------------- void main(void) { int ans1,ans2 ; //// I/O設定 AD1PCFG = 0xFFFF; // A/D Digi 選択:全デジタルI/Oに設定 CLKDIV = 0x0000; // System Clock devider 1:1 /// Setup PORT In/Out TRISB = 0x001F; // RB0,1:プロット間隔設定・ホールド(時刻合わせ時の項目選択・数値セット兼用)SW入力、他(QVGAポート)は出力 // RB2 is SDA2 (Hi), RB3 is SCL2 (Hi), RB4 INT1入力として使用 RPINR0bits.INT1R = 4; // INT1をRP4(RB4 pin)に割り当てる INTCON2bits.INT1EP=0; // 立上りエッジ割込み TRISA = 0x0007; // RA4(LCD_RST/),RA3(LED) is Out, Other is Input(未使用) /// Inittalize LED OFF LED = 1; /// Set Pull Up CNPU1 = 0x0030; // Pull Up Port is RB0(SW2), RB1(SW1) // Set Switch Change Notification Interrupts CNEN1 = 0x0020; // Valid SW2:CN5/RB1 IPC4bits.CNIP = 5; /// Initialize I2C2 I2C2BRG = 0x9E; // 100kHz I2C2CON = 0x8000; // Enable I2C2 /// 液晶表示器の初期化と開始メッセージ表示 lcd_Init(); lcd_Clear(BLACK); lcd_Str(0, 0, "Start Test_4", CYAN, BLACK); delay_ms(1000); // RTC8564内部水晶振動子が、発振するまで待つ lcd_Clear(BLACK); /// RTC8564初期化 /// <時計合わせについて> /// バックアップ電池交換時、HOLD SWを押しながら、電源ONすると、時計合わせモードになるので /// そこで、合わせた年月日、週、時分秒の値(BCD)を、RTCライトデータテーブルの該当位置に上書きし /// それを、制御レジスタ、アラームレジスタ等の初期値と共に、RTC8564レジスタに書込む。 /// 一旦電源を切って、普通に電源をONすると、ノーマルモードになる。 /// 尚、電池を抜いたまま、電源を入れた場合は、初期値は書込まれず、時計動作だけスタートする形になる。 if(!SW2){ // HOLD SWが押されている場合は、時計合わせモードに移行する。 /// 時計初期値 BCDで設定する。(時刻合わせ画面用) year = 0x17; // 2017年 month = 0x02; // 2月 day = 0x05; // 5日 week = 0x00; // 表示には使わない hour = 0x23; // 23時 min = 0x59; // 59分 sec = 0x00; // 0秒 /// 年月日・曜日/時分設定画面表示 lcd_Str(0, 0, "Time Ajust Mode", CYAN, BLACK); lcd_Str(0, 2, "17/02/05", CYAN, BLACK); lcd_Str(0, 4, "23:59:oo", CYAN, BLACK); /// PushSWでの初期値設定(年月日・曜日) year = getNum( year,99,2,0); // 年の設定 month = getNum(month,19,2,3); // 月の設定 day = getNum( day,39,2,6); // 日の設定 /// PushSWでの初期値設定(時分) hour = getNum(hour,29,4,0); // 時の設定 min = getNum( min,59,4,3); // 分の設定 //// ここまでの設定(SW1で最後の項目の分まで送って、SW2で合わせ(或いはそのままで))、SW1で送ると //// 年月日曜日・時刻レジスタの設定を行い、00秒から時計が動き始める。 lcd_Clear(BLACK); // 設定終了直後の表示をクリア /// 年月日曜日・時刻レジスタの設定 rtc_write_data_tbl[2] = sec; // SecondsREG rtc_write_data_tbl[3] = min; // MinutesREG rtc_write_data_tbl[4] = hour; // HourREG rtc_write_data_tbl[5] = day; // DayREG rtc_write_data_tbl[6] = week; // WeekdaysREG rtc_write_data_tbl[7] = month; // MonthsREG rtc_write_data_tbl[8] = year; // YearsREG WriteRTC(0,15); // Write RTC_Reg 16bytes: adrs = 0 to 15 -> Time Stop } //// 固定値表示 /// 単位 lcd_Str(3, 7, "゚C", WHITE, BLACK); lcd_Str(4, 11, "%", WHITE, BLACK); lcd_Str(4, 1, "hPa", WHITE, BLACK); //// 目盛値表示 /// 湿度 lcd_Str(21, 16, "0", WHITE, BLACK); lcd_Str(21, 13, "50", WHITE, BLACK); lcd_Str(21, 10, "100", WHITE, BLACK); /// 温度 lcd_Str(21, 9, "0", WHITE, BLACK); lcd_Str(21, 8, "20", WHITE, BLACK); lcd_Str(21, 6, "50", WHITE, BLACK); /// 気圧 lcd_Str(21, 5, "960", WHITE, BLACK); lcd_Str(21, 2, "1000", WHITE, BLACK); lcd_Str(21, 0, "1040", WHITE, BLACK); //// プロット間隔設定SW読込みと、時間軸レンジ表示 if(PLOT_INTERVAL_SW) { graph_count= 60; GraphLoopMax= 60; lcd_Str(0, 16, "30min/D", WHITE, BLACK); } else { graph_count=600; GraphLoopMax= 600; lcd_Str(0, 16, "5h/D ", WHITE, BLACK); } /// 両センサの初期化を行う ans1 = HDC_Init(HDC1000_ID,HDC1000_ADRS) ; // 湿度センサーの初期化を行う ans2 = PressureInit(LPS25H,LPS25H_ADRS) ; // 大気圧センサーの初期化を行う if ((ans1 == 0) && (ans2 == 0)) { /// RTC8564始動 rtc_write_data_tbl[0] = 0x00; // コントロールレジスタ1の、bit5:STOPビット=0にして、時計動作をスタート WriteRTC(0,0); IEC1bits.INT1IE = 1; // INT1割込み許可 } else { lcd_Str(0, 0, "Init NG", CYAN, BLACK); while(1) ; // プログラム終了 } while(1) { if(EndFlag) { // 割込み処理終了 EndFlag= 0; IEC1bits.CNIE = 1; // SW割込み許可 この期間のみ割込み許可 print_axis(); // グラフの座標軸を表示 print_graph(MAGENTA, CYAN, YELLOW); // 温度値履歴グラフを表示 /// Cheack HOLD SW Status while (HOLD_ON_flag) { hold_status = 1; // 1秒更新待ち期間に、HOLD SWが押されたら、再度押されるまでホールド維持 IEC1bits.INT1IE = 0; // INT1割込み禁止 } hold_status = 0; // 再度押されたらホールド解除 IEC1bits.CNIE = 0; // SW割込み禁止 IEC1bits.INT1IE = 1; // INT1割込み許可 } } } /************************************ * INT1外部割込み処理関数:1秒周期 *************************************/ void __attribute__((__interrupt__, no_auto_psv)) _INT1Interrupt(void) { char buf[7]; //Reset INT1 interrupt flag IFS1bits.INT1IF = 0; // LED = !LED; ReadRTC(2,8); // Read SecondsREG - YearsREG /// Set to LCD Buffer MsgDate[0] = ((rec_data[8] >> 4) & 0x0F) + 0x30; // 年 MsgDate[1] = (rec_data[8] & 0x0F) + 0x30; MsgDate[3] = ((rec_data[7] & 0x1F) >> 4) + 0x30; // 月:01〜12 ※ 読出し時、b7は、Cビット、b6-5は不定なので、0x1Fでマスクが必要 MsgDate[4] = (rec_data[7] & 0x0F) + 0x30; MsgDate[6] = ((rec_data[5] & 0x3F) >> 4) +0x30; // 日:01〜31 ※ 読出し時、b7-6は不定なので、0x3Fでマスクが必要 MsgDate[7] = (rec_data[5] & 0x0F) + 0x30; MsgTime[0] = ((rec_data[4] & 0x3F) >> 4) + 0x30; // 時:00〜23 ※ 読出し時、b7-6は不定なので、0x3Fでマスクが必要 MsgTime[1] = (rec_data[4] & 0x0F) + 0x30; MsgTime[3] = ((rec_data[3] & 0x7F) >> 4) + 0x30; // 分:00〜59 ※ 読出し時、b7は不定なので、0x7Fでマスクが必要 MsgTime[4] = (rec_data[3] & 0x0F) + 0x30; MsgTime[6] = ((rec_data[2] & 0x7F) >> 4) + 0x30; // 秒:00〜59 ※ 読出し時、b7は、VLビットなので、0x7Fでマスクが必要 MsgTime[7] = (rec_data[2] & 0x0F) + 0x30; /// カレンダ時刻表示 lcd_Str(0, 13, MsgDate, GREEN, BLACK); // 年月日表示 lcd_Str(0, 14, MsgTime, GREEN, BLACK); // 時分秒表示 /// 温湿度センサーから湿度・温度値を読出し、液晶表示する HDC_Read() ; sprintf((char *)buf,"%.2f",Temp); lcd_Str(0, 6, " ", WHITE, BLACK); // 更新前の数値表示(最大6文字分)をクリアしてから、更新表示 lcd_Str(0, 6, buf, WHITE, BLACK); // 温度(℃)の表示 sprintf((char *)buf,"%.2f",Humi); lcd_Str(0, 10, " ", WHITE, BLACK); // 更新前の数値表示(最大6文字分)をクリアしてから、更新表示 lcd_Str(0, 10, buf, WHITE, BLACK); // 温度(%)の表示 /// 気圧センサーから、気圧値を読出し、液晶表示する。 PressureRead() ; // 結果は、Press(フロート型)に格納されている sprintf((char *)buf,"%.2f",Press); lcd_Str(0, 0, " ", WHITE, BLACK); // 更新前の数値表示(最大7文字分)をクリアしてから、更新表示 lcd_Str(0, 0,buf, WHITE, BLACK); // 気圧(hPa)の表示 print_graph(BLACK, BLACK, BLACK); // 過去の履歴ラインを消す //// 1分又は、10分ごとの温度を保存する(リングバッファによる温度履歴の管理処理) ++graph_count; if (graph_count >= GraphLoopMax) { graph_count = 0; /// 温度データをリングバッファに格納 add_temp((char)Temp); /// 湿度データをリングバッファに格納 add_humi((char)Humi); /// 気圧データをリングバッファに格納 add_pres((int)Press); } EndFlag= 1; } /*********************************************** * Switch Change Notification Interrupts ************************************************/ void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) { delay_ms(10); if (!hold_status) { // hold_status -> 0: RUN if (!HOLD_SW) HOLD_ON_flag = 1; } else { // hold_status -> 1: HOLD_ON Loop if (!HOLD_SW) HOLD_ON_flag = 0; } IFS1bits.CNIF = 0; // Clear CN Interrupt Flag } //------------------------------------------------------------------------------------------------------------ /******************************************************************************* * ans = HDC_Read() * * 湿度・温度を読込む処理 * * 読み込まれた湿度(%)はHumi変数に、温度値(℃)はTemp変数に其々格納されます。 * * この処理は約15ms程時間が掛かります。 * * ans : 0=正常 1=異常(相手からACKが返ってこない) * * ============================================================================ * * * * PIC24F用に改修 * * 2017/1/2 N.Ishii * *******************************************************************************/ void HDC_Read() { union { unsigned int i ; unsigned char c[2] ; } data ; // 湿度データを受信する HDC_Receive(HUMI_ADRS,(unsigned char *)data.c) ; Humi = (double)data.i / 65536.0 ; Humi = Humi * 100.0 ; // 温度データを受信する HDC_Receive(TEMP_ADRS,(unsigned char *)data.c) ; Temp = (double)data.i / 65536.0 ; Temp = (Temp * 165.0) - 40.0 ; } /******************************************************************************* * ans = PressureRead() * * 圧力・温度を読込み気圧値を計算する処理 * * 計算された気圧値(hPa)はPress変数に、温度値(℃)はTemp変数に其々格納されます。* * ans : 0=正常 1=異常(相手からACKが返ってこない) * * ============================================================================ * * * * PIC24F用に改修 * * 2017/1/2 N.Ishii * *******************************************************************************/ void PressureRead() { unsigned char data[6] ; // 圧力と温度データを受信する(このデータはデバイス内部で移動平均化されています) PressureReceive(PRESS_OUT_ADRS,&data[0],3) ; // 圧力値 PressureReceive(TEMP_OUT_ADRS,&data[3],2) ; // 温度値 // 大気圧の計算を行う Press = ((unsigned long)data[2]<<16) + ((unsigned long)data[1]<<8) + data[0] ; Press = Press / 4096.0 ; // hPa /* // 温度の計算を行う→ 温度は、HDC1000の方で行うので、コメントアウト Temp = (int)(1 + ~((unsigned int)data[4]<<8 | data[3])) * -1 ; Temp = 42.5 + (Temp / 480.0) ;// ℃ */ } //---------------------------------------------------------------------------------------------------------- /********************************************************************* * RTC I2C書込み関数 * * <使い方> * @ 連続した、レジスタアドレスに、データを書込みたい時は、 *   その範囲の、レジスタにデータをセットした後に、その *   開始アドレスから終了アドレスまでを指定して、この関数を *   実行する。 *   但し、全16個のレジスタに初期値(テーブル)を書込む時は、 *   WriteRTC(0,15); *   を実行するだけでよい。 *   その配列名は、rtc_write_data_tblとする。([0]〜[15]) * * A 任意のレジスタに、1バイトのデータを書込みたい時には、 *   前もって、希望のレジスタ番地(配列の要素)に、データをセット *   してから、開始と終了アドレスを同じアドレスにして、この関数 *   を実行する。 ***********************************************************************/ void WriteRTC(char start_adrs, char end_adrs) { unsigned char i; I2C_Start(RTC8564_ADRS,RW_0); // スタートコンディションを発行〜 I2Cアドレス + Wビットを送信〜 ACK応答が、'0' になるまで待つ I2C_Send(start_adrs); // 書込み開始番地送信〜 ACK応答が、'0' になるまで待つ /// 当該RTCレジスタへデータを書き込む。 (アドレスは自動インクリメント) for (i = start_adrs; i != end_adrs + 1; ++i) { I2C_Send(rtc_write_data_tbl[i]); } I2C_Stop() ; // ストップコンディションを発行する delay_us(200); // Delay for 200uS (次のスタートまで、1.3uS以上必要) } /*********************************************************************************** * RTC I2C読込み関数 * * <使い方> * 書込み関数と、同様です。(書込みのところを、読込みに置換えて説明文をみてください) ************************************************************************************/ void ReadRTC(char start_adrs,char end_adrs) { unsigned char i; I2C_Start(RTC8564_ADRS,RW_0); // スタートコンディションを発行〜I2Cアドレス + Wビットを送信〜ACK応答が、'0' になるまで待つ I2C_Send(start_adrs); // 読出し開始番地送信〜 ACK応答が、'0' になるまで待つ I2C_rStart(RTC8564_ADRS,RW_1) ; // リピート・スタートコンディションを発行する〜I2Cアドレス + Rビットを送信〜ACK応答が、'0' になるまで待つ //// 当該RTCレジスタのデータを読出す。 (アドレスは自動インクリメント) for (i = start_adrs; i != end_adrs; ++i) { rec_data[i] = I2C_Receive(ACK); // 最終アドレスの前までは、読出し後、マスタへ、ACK送信 } /// i= 最終アドレスになって抜けて来る rec_data[i] = I2C_Receive(NOACK); // 最終アドレスの読出し後、マスタへ、NACK送信 I2C_Stop() ; // ストップコンディションを発行する delay_us(200); // Delay for 200uS (次のスタートまで、1.3uS以上必要) } //------------------------------------------------------------------------------------------------------------ /****** 2桁の初期値を入力する関数 ****************************** * num 入力される初期数 top 値の最大値 * y 十の位のLCD縦位置 x 十の位のLCD横位置 ****************************************************************/ char getNum(char num,char top,char y,char x){ char tens, ones; lcd_Char(x, y+1, 0x5E, CYAN, BLACK); // 10の位の下に、カーソル"^"表示 top = top/10; tens = num >> 4; ones = num & 0xF; tens=getDigit(tens,top,y,x); // 10位設定 lcd_Char(x, y+1, 0x20, CYAN, BLACK); // 現在のカーソルクリアし lcd_Char(x+1, y+1, 0x5E, CYAN, BLACK); // 1位桁に、カーソル移動 ones=getDigit(ones,9,y,x+1); // 1位設定 lcd_Char(x+1, y+1, 0x20, CYAN, BLACK); // 現在のカーソルクリア return ((tens << 4) + ones) ; // 値計算 } /****** 1桁の初期値を入力する関数 ******************************** * num 入力される初期数 top 値の最大値 * y 十の位のLCD縦位置 x 十の位のLCD横位置 *******************************************************************/ char getDigit(char num,char top,char y,char x){ char OnSW; top++; while(1){ OnSW = 5; // SWがOnでないことを確認する do{ if(SW1 & SW2)OnSW--; else OnSW = 5; // 1mSecおきに5回確認 // →1mS周期でのセンスはチャッタと見なす delay_ms(1); // 1mSec遅延 }while(OnSW); while(SW1 & SW2); // SWのPushを待つ // → 押されてない状態を確認してから初めてSW ON待ちを行っている if(!SW1)return num; // SW1で終了 if(!SW2){ // SW2で数値を+1 num++; num %= top; lcd_Char(x, y, num+0x30, CYAN, BLACK); } } } //------------------------------------------------------------------------------------------------------------------ /************************** * グラフの座標軸表示 ***************************/ void print_axis(void) { int i; //// X、Y座標軸表示 /// 湿度座標:0〜100% 10%刻み/ 時間軸は、30分刻みで、開始点0分〜 150分後まで for(i=99; i<= 249; i+=30) lcd_Line(i, 0, i, 100, BROWN); // X axis(時間軸:x座標が変化) for(i=0; i<= 100; i+=10) lcd_Line(99, i, 249, i, BROWN); // Y axis(横線:y座標が変化) /// 温度座標:0〜50℃ 10℃刻み for(i=99; i<= 249; i+=30) lcd_Line(i, 102, i, 152, BROWN); // X axis(時間軸:x座標が変化) for(i=102; i<= 152; i+=10) lcd_Line(99, i, 249, i, BROWN); // Y axis(横線:y座標が変化) /// 気圧座標:960〜1040hPa 10hPa刻み for(i=99; i<= 249; i+=30) lcd_Line(i, 154, i, 234, BROWN); // X axis(時間軸:x座標が変化) for(i=154; i<= 234; i+=10) lcd_Line(99, i, 249, i, BROWN); // Y axis(横線:y座標が変化) } /****************************************** * 温湿度値履歴グラフを表示 *******************************************/ void print_graph(unsigned short T_Color, unsigned short H_Color, unsigned short P_Color) { char temp_hist_val; char humi_hist_val; int pres_hist_val; int temp, humi, pres, p, col; p = -1; col = 0; /// 温度値履歴グラフを表示 while ((p = get_temp(p, &temp_hist_val)) != GET_EMPTY) { temp = (int)temp_hist_val; if((temp >= 0) && (temp <= 50)) { // 通常処理 lcd_Pixel(249 - col, 137-temp ,T_Color); // x=249の位置(右端Y座標軸上)から、プロット:170121 } else { if(temp > 50) { // 50℃を超えたら、リミット処理 lcd_Pixel(249 - col, 87 ,T_Color); } else if(temp < 0) { // 0℃を下回ったら、リミット処理 lcd_Pixel(249 - col, 137 ,T_Color); } } if (p < 0) break; ++col; } p = -1; col = 0; /// 湿度値履歴グラフを表示 while ((p = get_humi(p, &humi_hist_val)) != GET_EMPTY) { humi = (int)humi_hist_val; if(humi <= 100) { // 通常処理 lcd_Pixel(249 - col, 239-humi ,H_Color); // x=248の位置から、プロット } else { // 100%を超えたら、リミット処理 lcd_Pixel(249 - col, 139 ,H_Color); } if (p < 0) break; ++col; } p = -1; col = 0; /// 気圧値履歴グラフを表示 while ((p = get_pres(p, &pres_hist_val)) != GET_EMPTY) { pres = pres_hist_val; if((pres >= 960) && (pres <= 1045)) { // 通常処理 lcd_Pixel(249 - col, 85-(pres-960) ,P_Color); // x=248の位置から、プロット } else { if(pres > 1040) { // 1040hPaを超えたら、リミット処理 lcd_Pixel(249 - col, 5 ,P_Color); } else if(pres < 960) { // 960hPaを下回ったら、リミット処理 lcd_Pixel(249 - col, 85 ,P_Color); } } if (p < 0) break; ++col; } } //// 以下は、リングバッファ用関数------------------------------------------------------------------------- /**************************************************** * 温度データをリングバッファに格納 *****************************************************/ void add_temp(char t) { temp_hist[temp_hist_head] = t; // 温度データ履歴バッファ(temp_hist[0]から順)に、温度値を格納 ++temp_hist_head; // バッファアドレスをインクリメント if (temp_hist_head >= HIST_MAX) { // temp_hist[149]まで(つまり、HIST_MAX=150)格納したら temp_hist_full = 1; // fullフラグをセットし、 temp_hist_head = 0; // headフラグをリセット } } /**************************************************** * 湿度データをリングバッファに格納 *****************************************************/ void add_humi(char h) { humi_hist[humi_hist_head] = h; // 温度データ履歴バッファ(humi_hist[0]から順)に、温度値を格納 ++humi_hist_head; // バッファアドレスをインクリメント if (humi_hist_head >= HIST_MAX) { // humi_hist[149]まで(つまり、TEMP_HIST_MAX=150)格納したら humi_hist_full = 1; // fullフラグをセットし、 humi_hist_head = 0; // headフラグをリセット } } /**************************************************** * 気圧データをリングバッファに格納 *****************************************************/ void add_pres(int pr) { pres_hist[pres_hist_head] = pr; // 気圧データ履歴バッファ(pres_hist[0]から順)に、気圧値を格納 ++pres_hist_head; // バッファアドレスをインクリメント if (pres_hist_head >= HIST_MAX) { // pres_hist[149]まで(つまり、PRES_HIST_MAX=150)格納したら pres_hist_full = 1; // fullフラグをセットし、 pres_hist_head = 0; // headフラグをリセット } } /**************************************************** * リングバッファから温度データを取得 *****************************************************/ int get_temp(int p, char *t) { int i; if (!temp_hist_full && (temp_hist_head == 0)) { *t = 0; return GET_EMPTY; } if (p < 0) { i = temp_hist_head; } else { i = p; } --i; if (i < 0) { i = HIST_MAX - 1; } *t = temp_hist[i]; if (temp_hist_full) { if (i == temp_hist_head) return GET_NONEXT; else return i; } else { if (i == 0) return GET_NONEXT; else return i; } } /**************************************************** * リングバッファから湿度データを取得 *****************************************************/ int get_humi(int p, char *h) { int i; if (!humi_hist_full && (humi_hist_head == 0)) { *h = 0; return GET_EMPTY; } if (p < 0) { i = humi_hist_head; } else { i = p; } --i; if (i < 0) { i = HIST_MAX - 1; } *h = humi_hist[i]; if (humi_hist_full) { if (i == humi_hist_head) return GET_NONEXT; else return i; } else { if (i == 0) return GET_NONEXT; else return i; } } /**************************************************** * リングバッファから気圧データを取得 *****************************************************/ int get_pres(int p, int *pr) { int i; if (!pres_hist_full && (pres_hist_head == 0)) { *pr = 0; return GET_EMPTY; } if (p < 0) { i = pres_hist_head; } else { i = p; } --i; if (i < 0) { i = HIST_MAX - 1; } *pr = pres_hist[i]; if (pres_hist_full) { if (i == pres_hist_head) return GET_NONEXT; else return i; } else { if (i == 0) return GET_NONEXT; else return i; } }