/******************************************************************** * Scope_PIC32MX_V2.c * <特徴> * @ オシロ画面イメージをSDカードに保存可能 * A RTC8564による時計を装備し、SDカードにタイムスタンプを保存 * B トリガレベル調整を、ロータリエンコーダで行う * * * Graphic LCD(Monochrome): SG12864A * * Condition: * 8MHz External X'tal Oscillator, 20x PLL (8MHzx20= 160MHz) * Fcy=160MHz/2=80MHz, Tcy=12.5ns * * CPU: PIC32MX340F256H * * N.Ishii 2014.12.4 *********************************************************************/ #include /* PIC32 peripheral library */ #include "glcd_lib32k.h" #include // コンフィギュレーション設定 // CPU=80MHz Peri=80MHz,HS+PLL,Divider=1/2,PLL=x20,WDT=Off #pragma config FNOSC=PRIPLL, POSCMOD=HS, FPLLIDIV=DIV_2 #pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_1 #pragma config FWDTEN=OFF, ICESEL=ICS_PGx2 /// ファイルシステム用変数 FSFILE *fptr; size_t result; /////------- <オシロ表示イメージの、SDカードへの保存関連> ------------------------------------------ /// データバッファ unsigned char Disp_BUF[1024]; // 元になる、表示用のデータバッファ unsigned char Buffer[1024]; // BMPデータバッファ ////// 128x64ドット白黒BMPヘッダ情報部の、固定データ62バイトセット const unsigned char monochroBmpHeader[62]= { /// ファイルヘッダ部:14バイト 'B', 'M', // ファイルタイプ 2バイト 0x3E, 0x04, 0x00, 0x00, // ファイルサイズ 4バイト:0x0000043E(1086バイト=62+1024) 0x00, 0x00, // 予約領域1 2バイト:0x0000 (常に固定) 0x00, 0x00, // 予約領域2 2バイト:0x0000 (常に固定) 0x3E, 0x00, 0x00, 0x00, // ファイル先頭から画像データまでのオフセット 4バイト:0x0000003E(62バイト) /// 情報ヘッダ部:40バイト 0x28, 0x00, 0x00, 0x00, // 情報ヘッダサイズ 4バイト:0x00000028(40バイト) 0x80, 0x00, 0x00, 0x00, // 画像の幅 [ピクセル] 4バイト:0x00000080(128ピクセル) 0x40, 0x00, 0x00, 0x00, // 画像の高さ [ピクセル] 4バイト:0x00000040(64ピクセル) 0x01, 0x00, // 色ビット数 [bit]:1画素当たりのデータサイズ 2バイト:0x0001(白黒は、"1":2色ビットマップ) 0x01, 0x00, // 1画素当りのデータサイズ 2バイト:0x0001 0x00, 0x00, 0x00, 0x00, // 圧縮形式 4バイト:0x00000000(白黒は無圧縮なので、"0") 0x00, 0x04, 0x00, 0x00, // 画像データサイズ 4バイト:0x00000400(1024バイト) 0xC4, 0x0E, 0x00, 0x00, // 水平解像度 [dot/m] 4バイト:0x00000EC4(3480) 0xC4, 0x0E, 0x00, 0x00, // 垂直解像度 [dot/m] 4バイト:0x00000EC4(3480) 0x00, 0x00, 0x00, 0x00, // 格納パレット数[使用色数] 4バイト:0x00000000('0'の場合もある→確認済) 0x00, 0x00, 0x00, 0x00, // 重要色数 4バイト:0x00000000('0'の場合もある→確認済) /// バレットデータ部:8バイト(※ 白黒の場合、パレットデータ:4バイトブロックが、2個存在する) 0x00, // 青 1バイト:0x00(白黒の場合は、0x00か、0xFFのいずれかの値が入るようである) 0x00, // 緑 1バイト:0x00(白黒の場合は、0x00か、0xFFのいずれかの値が入るようである) 0x00, // 赤 1バイト:0x00(白黒の場合は、0x00か、0xFFのいずれかの値が入るようである) 0x00, // 予約領域 1バイト:0x00(常に、0x00) 0xFF, // 青 1バイト:0xFF(白黒の場合は、0x00か、0xFFのいずれかの値が入るようである) 0xFF, // 緑 1バイト:0xFF(白黒の場合は、0x00か、0xFFのいずれかの値が入るようである)緑 0xFF, // 赤 1バイト:0xFF(白黒の場合は、0x00か、0xFFのいずれかの値が入るようである) 0x00 // 予約領域 1バイト:0x00(常に、0x00) }; /// A Variable (Global) short FileNo = 0; char FileName[] = "Wavexxx.bmp"; ////------------------------------------------------------------------------------------------------------------ /////------- <RTC8564関連>------------------------------------------ // 液晶表示器メッセージ定数 char MsgClock[] = "'xx/mm/dd hh:mm"; // For I2C // 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 0x30, // [3]:MinutesREG: Set 0 Min 0x14, // [4]:HourREG: Set 0 Hour 0x29, // [5]:DayREG 0x03, // [6]:WeekdaysREG: TUE 0x10, // [7]:MonthsREG 0x14, // [8]:YearsREG 0x80, // [9]:Minute_AlamREG: Not Used ALM Interrupt 0x80, // [10]:Hour_AlamREG 0x80, // [11]:Day_AlamREG 0x80, // [12]:Weekday_AlamREG 0x80, // [13]:Not Used CLKOUT 0x00, // [14]:Timer_contorolREG: Not Used Timer Interrupt 0x01 // [15]:Timer_downcount Set Vule }; unsigned char rec_data[16]; ////----------------------------------------------------------------------------------- // I2C define #define RTC8564_SLVADRS_WR 0xA2 #define RTC8564_SLVADRS_RD 0xA3 ////----------------------------------------------------------------------------------- /// A Variable (Global) char YearSet= 0; char MonthsSet= 0; char DaysSet= 0; char WeekdaysSet= 0; char MinuteSet= 0; char SecondsSet= 0; char HourSet= 0; char TimeSetEnd = 0; /// 時計合わせSW状態テンポラリ char TmSel_m0; // New Temp char TmSel_m1; // Old Temp char TmSel_m2; // Edge Temp char TmAdj_m0; char TmAdj_m1; char TmAdj_m2; char TmEnt_m0; char TmEnt_m1; char TmEnt_m2; char SelCount= 0; ////------------------------------------------------------------------------------------------------------------ /////------- <オシロ関連>------------------------------------------ // トリガレベル・メッセージテーブル(デバッグ用) char MsgTrig[] = "Trg:xxxx"; /// Rotary ecoder #define RE_A PORTBbits.RB12 #define RE_B PORTBbits.RB13 #define AC_DC_SW PORTDbits.RD1 #define TRIG_MODE_SW PORTDbits.RD0 #define HOLD_SW PORTBbits.RB2 // TM_SEL兼用 #define SLOPE_SW PORTBbits.RB1 // TM_ADJ兼用 #define READY_SW PORTFbits.RF4 // TM_ENT兼用 #define WRITE_SW PORTFbits.RF5 ////----------------------------------------------------------------------------------- /// A Variable (Global) unsigned short Buffer1[192]; unsigned short Index,TSW,VSW; short POT,Ypos; unsigned short Dummy; short i; char re_b_m0; // ROTARY ENCODER OLD Temp char re_b_m1; // ROTARY ENCODER NEW Temp char re_b_m2; // ROTARY ENCODER EDGE Temp char EndFlag; char HOLD_ON_flag = 0; char hold_status = 0; char Write_flag = 0; char READY_flag = 0; char ready_status = 0; char POS_flag = 1; // Defult Trigger Slope is positive char RtcDispFlag= 1; // デフォルトでは、イメージ保存時、時計表示を行う。 ////------------------------------------------------------------------------------------------------------------ /// Function Prottypes void Oscillo(void); void AxisDraw(void); void Single_trigger_mode(void); void Oscillo_single_trigger(void); void RotaryEncoderRead(void); void dotyline(unsigned short x0); void dotxline(unsigned short y0); void lcd_ImageRead(void); void Conv_DispBufTable_to_BmpTable(void); void BmpDataWrite(void); void WriteRTC(unsigned char start_adrs, unsigned char end_adrs); void ReadRTC(unsigned char start_adrs, unsigned char end_adrs); void time_adjust_mode(void); void RtcDisp(void); void itostring(char digit, unsigned int data, char *buffer); /************************************************ * Function Main ************************************************/ int main(void) { //システム最適設定 SYSTEMConfigPerformance(80000000); mJTAGPortEnable(DEBUG_JTAGPORT_OFF); // JTAGを無効化 //I/O設定 AD1PCFG = 0xFFFE; // GLCD制御信号レベルの初期化 LCD_E = 0; LCD_CS1 = 1; LCD_CS2 = 1; LCD_RW = 1; LCD_DI = 1; LCD_TRIS = 0x0000; // LCDデータバス(DB0-DB7)オール出力(TRISE= 0) TRISB = 0xFFDF; // RB3-5:SD_CD,WE入力、CS出力、RB2,1:HOLD_SW、SLOPE_SW入力、RB0:オシロ入力 // RB12,13:RE-A,B入力、RB8-11:TSW-1,2,4,8入力     (TM_SEL兼)(TM_ADJ兼) TRISD = 0xFF03; // RD8-10:ATT-A,B.C入力、RD5-7:LCD_CS1,CS2,DI出力、RD2-4:HOLD,TRIG,READY_LED出力、RD0,1:SING/NOR_SW,AC/DC_SW入力 TRISF = 0xFFFC; // RF4,5:READY(TM_ENT兼),WRITE_SW入力、R0,1:LCD_R/W,E出力 TRISG = 0xFEBF; // RG6-8:SD_SCK出力,SDI入力,SDO出力、RG2,3:I2C_SCL1,SDA1入力 LATDbits.LATD2 = 1; // HOLD_LED消灯 LATDbits.LATD3 = 1; // TRIG_LED消灯 LATDbits.LATD4 = 1; // READY_LED消灯 // 液晶表示器の初期化 lcd_Init(); lcd_Clear(0); lcd_Str(0, 0, "Scope PIC32MX V2"); delay_ms(1000); /// ADC初期設定 AD1CON1 = 0x0044; // サンプルモード等設定 // b15:ON:0:ADCモジュールOFF // b14:FRZ:0:デバッグ中動作継続 // b13:ADSIDL:0:アイドルモードでも動作継続 // b12:x:0 //------------------------------------------------------------------------------------------ // b11:x:0 // b10:FORM<2>:0:データフォーマット= 整数16ビット // b_9:FORM<1>:0 // b_8:FORM<0>:0 //------------------------------------------------------------------------------------------ // b_7:SSRC<2>:0:サンプルクロックソース= T3一致でサンプリング終了し変換開始(ADC1の場合) // b_6:SSRC<1>:1 // b_5:SSRC<0>:0 // b_4:CLRASAM:0:割込みで変換継続 //------------------------------------------------------------------------------------------ // b_3:x:0 // b_2:ASAM:1:サンプリングは最後の変換終了直後に開始する。SAMPビットは自動セットされる // b_1:SAMP:0:S/Hはホールド中 // b_0:DONE:0:ADCステータスビット //------------------------------------------------------------------------------------------ AD1CON2 = 0x003C; // スキャンモード等設定 // b15:VCFG<2>:0:VREF=AVDD-AVSS // b14:VCFG<1>:0: // b13:VCFG<0>:0: // b12:OFFCAL:0:較正モード無効 //------------------------------------------------------------------------------------------ // b11:x:0 // b10:CSCNA:0:※ 入力スキャンしない // b_9:x:0 // b_8:x:0 //------------------------------------------------------------------------------------------ // b_7:BUFS:0(R-Only):※ バッファフルステータス  // b_6:x:0          BUF_0〜7に書込み中、BUF8〜15内のデータにアクセスせよ // b_5:SMPI<3>:1:※ 16回のサンプル/変換動作完了毎に割込み発生 // b_4:SMPI<2>:1 //------------------------------------------------------------------------------------------ // b_3:SMPI<1>:1 // b_2:SMPI<0>:1 // b_1:BUFM:0:※ 16ワード単一結果バッファを使用 // b_0:ALTS:0:※ 常にMUXA入力選択を使用 //------------------------------------------------------------------------------------------ AD1CON3 = 0x0202; // ADCクロック等設定 // b15:ADRC:0:ADCクロックソース= システムクロックから取出したクロック // b14:x:0 // b13:x:0 // b12:SAMC<4>:0:自動サンプル時間(Acquisition Time)Tsmp= 2Tad= 2*75nS= 150nS(規格:≧132nSmin):80MIPS //------------------------------------------------------------------------------------------ // b11:SAMC<3>:0 // b10:SAMC<2>:0 // b_9:SAMC<1>:1 // b_8:SAMC<0>:0 //------------------------------------------------------------------------------------------ // b_7:ADCS<7>:0:ADCクロック周期(Tad)= 2*Tcy*(ADCS+1)= 2*12.5nS*(2+1)= 75nS(規格:≧65nSmin):80MIPS // b_6:ADCS<6>:0 // b_5:ADCS<5>:0 // b_4:ADCS<4>:0 //------------------------------------------------------------------------------------------ // b_3:ADCS<3>:0 // b_2:ADCS<2>:0 // b_1:ADCS<1>:1 // b_0:ADCS<0>:0 //------------------------------------------------------------------------------------------ //////////////////////////////////////////////////////////////////////////////////////////////// /// <総変換時間算出> ///  @ 80MIPSの場合 /// Tconv= 12Tad= 12*0.075uS= 0.9uS /// 総変換時間= Tsmp + Tconv= 0.15uS+ 0.9uS= 1.05uS /////////////////////////////////////////////////////////////////////////////////////////////// AD1CHS = 0x00000000; // MUX設定 // b31:CH0NB:0:B側のS/Hは未使用(負側入力をAVCCに接続) // b30:x:0 // b29:x:0 // b28:x:0 //------------------------------------------------------------------------------------------ // b27:CH0SB<3>:0 // b26:CH0SB<2>:0 // b25:CH0SB<1>:0 // b24:CH0SB<0>:0 //------------------------------------------------------------------------------------------ // b23:CH0NA:0:S/H(CH0)負側入力は、AVSSに接続 // b22:x:0 // b21:x:0 // b20:x:0 //------------------------------------------------------------------------------------------ // b19:CH0SA<3>:0:※ AN0 for CH0 +IN // b18:CH0SA<2>:0 // b17:CH0SA<1>:0 // b16:CH0SA<0>:0 //------------------------------------------------------------------------------------------ AD1CSSL = 0x0000; // 入力スキャンCH設定 // b15:CSS15:0:入力スキャンに、AN15を選択しない // b14:CSS14:0:入力スキャンに、AN14を選択しない // b13:CSS13:0:入力スキャンに、AN13を選択しない // b12:CSS12:0:入力スキャンに、AN12を選択しない //------------------------------------------------------------------------------------------ // b11:CSS11:0:入力スキャンに、AN11を選択しない // b10:CSS10:0:入力スキャンに、AN10を選択しない // b_9:CSS9:0:入力スキャンに、AN9を選択しない // b_8:CSS8:0:入力スキャンに、AN8を選択しない //------------------------------------------------------------------------------------------ // b_7:CSS7:0:入力スキャンに、AN7を選択しない // b_6:CSS6:0:入力スキャンに、AN6を選択しない // b_5:CSS5:0:入力スキャンに、AN5を選択しない // b_4:CSS4:0:入力スキャンに、AN4を選択しない //------------------------------------------------------------------------------------------ // b_3:CSS3:0:入力スキャンに、AN3を選択しない // b_2:CSS2:0:入力スキャンに、AN2を選択しない // b_1:CSS1:0:入力スキャンに、AN1を選択しない // b_0:CSS0:0:入力スキャンに、AN0を選択しない //----------------------------------------------------------------------------------------- AD1PCFG = 0xFFFE; // アナログ/デジタルピン設定 // b15:PCFG15:1 // b14:PCFG14:1 // b13:PCFG13:1 // b12:PCFG12:1 //------------------------------------------------------------------------------------------ // b11:PCFG11:1 // b10:PCFG10:1 // b_9:PCFG9:1 // b_8:PCFG8:1 //------------------------------------------------------------------------------------------ // b_7:PCFG7:1 // b_6:PCFG6:1 // b_5:PCFG5:1 // b_4:PCFG4:1 //------------------------------------------------------------------------------------------ // b_3:PCFG3:1 // b_2:PCFG2:1 // b_1:PCFG1:1 // b_0:PCFG0:AN0を、アナログ入力ピンに設定(他は全てデジタル入力ピンに設定) //------------------------------------------------------------------------------------------ AD1CON1bits.ADON = 1; // ADC Start mAD1ClearIntFlag(); // Clead AD1 IF Flag mAD1SetIntPriority(7); // AD1割込み優先レベル初期設定 mAD1SetIntSubPriority(3); // AD1割込みサブ優先レベル初期設定 mAD1IntEnable(1); // Enable ADC INT /// Timer3:T3初期設定= Tcy*PS*n= 0.0125uS*2*400 = 10uS(1mS/D) PR3 = 399; // n = 400 (PR3=n-1 T3CON = 0x0010; // T3_OFF, T3_GATE_OFF, T3_PS_1_2, T3_SOURCE_INT /// スイッチ状態変化割込みと、内部プルアップ設定 mCNOpen(CN_ON, CN3_ENABLE | CN4_ENABLE | CN17_ENABLE | CN18_ENABLE, CN3_PULLUP_ENABLE | CN4_PULLUP_ENABLE | CN5_PULLUP_ENABLE | CN6_PULLUP_ENABLE | CN17_PULLUP_ENABLE | CN18_PULLUP_ENABLE); // CN機能使用SW:HOLD_SW, SLOPE_SW, READY_SW, WRITE SW // 内部プルアップ使用SW:上記以外では、SD_WE,CD(これらは、CN割込み未使用) // ダミー入力で、PIC内外の状態を一致させ、割込み要因をリセットする Dummy= PORTB; Dummy= PORTF; /// I2Cの初期設定 100kbps 7bit address OpenI2C1(I2C_ON | I2C_7BIT_ADD, 398); delay_ms(1000); // RTC8564内部水晶振動子が、発振するまで待つ /// RTC8564初期化 /// <時計合わせについて> /// バックアップ電池交換時、HOLD SWを押しながら、電源ONすると、時計合わせモードになるので /// そこで、合わせた年月日、週、時分秒の値(BCD)を、RTCライトデータテーブルの該当位置に上書きし /// それを、制御レジスタ、アラームレジスタ等の初期値と共に、RTC8564レジスタに書込む。 /// 一旦電源を切って、普通に電源をONすると、ノーマルモードになる。 /// 尚、電池を抜いたまま、電源を入れた場合は、初期値は書込まれず、時計動作だけスタートする形になる。 if(!HOLD_SW){ // HOLD SWが押されている場合は、時計合わせモードに移行する。 time_adjust_mode(); } // RTC Time Start rtc_write_data_tbl[0] = 0x00; // コントロールレジスタ1の、bit5:STOPビット=0にして、時計動作をスタート WriteRTC(0,0); /// WRITE SWを押しながら、電源ONすると、イメージ保存時、時計表示を行わない。 if(!WRITE_SW) RtcDispFlag= 0; /// POT変数の初期化(トリガレベルを、REによりデジタル値で直に与える) POT = 512; // センターレベル設定 Ypos = 32; // トリガレベルライン表示の、Yポジション初期化 mCNClearIntFlag(); //CN割り込みフラグクリア ConfigIntCN(CHANGE_INT_ON | CHANGE_INT_PRI_2); // CN割り込み有効化 // マルチベクタ割り込み設定、割り込み許可 INTEnableSystemMultiVectoredInt(); /// メイン・ループ while(1){ /// Draw a Graph of Input Wave Data Index = 0; EndFlag = 0; // Clear End of Convertion Flag if (TRIG_MODE_SW) { // Trigger is AUTO Mode /* Switching Sampling Period */ TSW = (~PORTB & 0x0F00) >> 8; // Read Decimal Dip SW if (TSW == 9) T3CONbits.TCKPS = 4; // PS3 = 1/16 else T3CONbits.TCKPS = 1; // PS3 = 1/2 switch(TSW){ case 0: PR3 = 79; // 2usec(0.1ms/div) break; case 1: PR3 = 159; // 4usec(0.2ms/div) break; case 2: PR3 = 399; // 10usec(0.5ms/div) break; case 3: PR3 = 799; // 20usec(1.0ms/div) break; case 4: PR3 = 1599; // 50usec(2.0ms/div) break; case 5: PR3 = 3999; // 100usec(5.0ms/div) break; case 6: PR3 = 7999; // 200usec(10ms/div) break; case 7: PR3 = 15999; // 500usec(20ms/div) break; case 8: PR3 = 39999; // 1000usec(50ms/div) break; case 9: PR3 = 49999; // 5000usec(500ms/div) break; default:PR3 = 399; // 10usec(0.5ms/div) break; } LATDbits.LATD4 = 1; // Red LED OFF READY_flag = 0; ready_status = 0; T3CONbits.TON = 1; // T3ON-> ADC Start while(!EndFlag); Oscillo(); // Disp. Oscillo EndFlag = 0; Index = 0; /// Cheack HOLD_RUN_SW Status while (HOLD_ON_flag){ /// RTCCレジスタ読込と時計表示 RtcDisp(); hold_status = 1; /// オシロ画面ホールド中に、書込みSWが押されたら /// 画面イメージを読込み、そのデータを正規のBMPデータに変換して /// SDカードに書込む。 if(Write_flag){ lcd_ImageRead(); Conv_DispBufTable_to_BmpTable(); for(i= 0; i< 1024; i++) Buffer[i]= ~Buffer[i]; // データ論理反転して入れ替え BmpDataWrite(); Write_flag= 0; } } hold_status = 0; /// ロータリエンコーダ読込み(波形描画更新インターバル:約0.3秒も兼ねている) for(i= 0; i < 300; ++i){ delay_ms(1); RotaryEncoderRead(); // ロータリエンコーダ読込み } } else Single_trigger_mode(); } } /************************************************ * ADC Interrupt: 2Channel, 4Times (Duble Buffer) * ADC Interrupt Period = T3_Period*2*4 *************************************************/ void __ISR(27, ipl7) AD1Interrupt(void) { //LATDbits.LATD3 = ~LATDbits.LATD3; mAD1ClearIntFlag(); // Clead IF Flag Buffer1[Index++] = ADC1BUF0; // 1Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF1; // 2Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF2; // 3Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF3; // 4Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF4; // 5Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF5; // 6Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF6; // 7Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF7; // 8Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF8; // 9Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUF9; // 10Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUFA; // 11Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUFB; // 12Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUFC; // 13Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUFD; // 14Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUFE; // 15Times: Buffer <- AN0 Input Data Buffer1[Index++] = ADC1BUFF; // 16Times: Buffer <- AN0 Input Data if(Index >= 192){ // Buffer Full ? T3CONbits.TON = 0; // Buffer Full Then T3 OFF and EOC Flag ON EndFlag = 1; } } /********************************************* * スイッチ状態変化割り込み処理 * HOLD, SLOPE, READY, WRITE SW **********************************************/ void __ISR(26, ipl2) CNHandler(void){ delay_ms(20); // スイッチ安定待ち if(!hold_status){ // hold_status -> 0: RUN if(!HOLD_SW){ LATDbits.LATD2 = 0; // HOLD LED ON HOLD_ON_flag = 1; } } else{ // hold_status -> 1: HOLD_ON Loop if(!HOLD_SW){ LATDbits.LATD2 = 1; // HOLD LED OFF HOLD_ON_flag = 0; } } if(ready_status){ if (!READY_SW) READY_flag = 1; } if(!SLOPE_SW) { if(POS_flag) POS_flag = 0; else POS_flag = 1; } if((hold_status) || (ready_status)){ if(!WRITE_SW) Write_flag = 1; } delay_ms(10); // スイッチON->OFF時の、チャッタ回避 Dummy= PORTB; // 状態合わせ Dummy= PORTF; mCNClearIntFlag(); //割り込みフラグクリア } /****************************************** * Drawing Coordinate Axis *******************************************/ void AxisDraw(void){ lcd_Clear(0); lcd_Line(0, 0, 0, 63); // Y axis_1: 左端の、Yライン描画 dotyline(51); // Y axis_2: 中央付近最初の、時間軸Yライン描画 dotyline(101); // Y axis_3: 右端付近2番目の、時間軸Yライン描画 lcd_Line(0, 32, 127, 32); // X axis dotxline(49); dotxline(17); /// Disp.SLOPE if (POS_flag == 1) lcd_Char1(7, 10, 0x9E); else lcd_Char1(7, 10, 0x9F); /// Disp. AC/DC if (AC_DC_SW == 0) lcd_Char1(7, 1, 0x9D); // CH1:DCキャラクタ表示 else lcd_Char1(7, 1, 0x9C); // CH1:ACキャラクタ表示 /// Disp. Unit Time Axis (msec/div) switch(TSW){ case 0: lcd_Str(7,11,"0.1mS/D "); break; case 1: lcd_Str(7,11,"0.2mS/D "); break; case 2: lcd_Str(7,11,"0.5mS/D "); break; case 3: lcd_Str(7,11,"1.0mS/D "); break; case 4: lcd_Str(7,11,"2.0mS/D "); break; case 5: lcd_Str(7,11,"5.0mS/D "); break; case 6: lcd_Str(7,11,"10mS/D "); break; case 7: lcd_Str(7,11,"20mS/D "); break; case 8: lcd_Str(7,11,"50mS/D "); break; case 9: lcd_Str(7,11,"500mS/D"); break; default:lcd_Str(7,11,"0.5mS/D "); break; } /// Disp. Unit Volt Axis (V/D or mV/D) VSW = (PORTD & 0x0700) >> 8; // Read VSW switch(VSW){ case 0: lcd_Str(7,2,"50mV/D"); break; case 1: lcd_Str(7,2,"0.1V/D"); break; case 2: lcd_Str(7,2,"0.25V/D"); break; case 3: lcd_Str(7,2,"0.5V/D"); break; case 4: lcd_Str(7,2,"1.0V/D"); break; case 5: lcd_Str(7,2,"2.5V/D"); break; case 6: lcd_Str(7,2,"5.0V/D"); break; case 7: lcd_Str(7,2,"10V/D"); break; default:lcd_Str(7,2,"2.5V/D"); break; } /// トリガレベルライン描画 lcd_Line(125, Ypos, 128, Ypos); /* /// トリガレベル値表示(デバッグ用) itostring(4, POT, MsgTrig + 4); // POTデータを文字列に変換 lcd_Str(0, 10, MsgTrig); // トリガレベル値表示 */ } /******************************************************* * Disp. Oscillo (Disp. Save Buffer Data) * Detect Trigger-> Disp. 128Data from this Position * Not Detect Trigger-> Disp. 128Data from Top Position *******************************************************/ void Oscillo(void){ unsigned short i,x; AxisDraw(); // Drawing Coordinate Axis x = 0; // First Data /* Check Trigger */ while((x < 128) && !((Buffer1[x]=POT))){ x++; } /* Detect Trigger-> Disp. 128Data from this Position */ if(x<64){ LATDbits.LATD3 = 0; // Green LED ON for(i=0; i<127; i++){ lcd_Line(i, Buffer1[i+x]/16, i+1, Buffer1[i+x+1]/16); } } /* Not Detect Trigger-> Disp. 128Data from Top Position */ else { LATDbits.LATD3 = 1; // Green LED OFF for(i=0; i<127; i++){ lcd_Line(i, Buffer1[i]/16, i+1, Buffer1[i+1]/16); } } } /****************************************************** * Disp. Oscillo and Cheack trigger for Single mode *******************************************************/ void Oscillo_single_trigger(void){ unsigned short i,x; x = 0; // First Data /* Check Trigger */ if (POS_flag) { while((x < 128) && !((Buffer1[x]=POT))){ x++; } } else { // Trigger Slope is negative while((x < 128) && !((Buffer1[x+1]=POT))){ x++; } } /// Detect Trigger-> Disp. 128Data from this Position if(x<64){ LATDbits.LATD3 = 0; // Green LED ON LATDbits.LATD4 = 1; // Red LED OFF AxisDraw(); for(i=0; i<127; i++){ lcd_Line(i, Buffer1[i+x]/16, i+1, Buffer1[i+x+1]/16); } READY_flag = 0; } /// Not Detect Trigger-> Retry sample else { LATDbits.LATD3 = 1; // Green LED OFF } } /********************************************* * Single_trigger_mode **********************************************/ void Single_trigger_mode(void) { hold_status = 1; while ((!READY_flag) && (!TRIG_MODE_SW)) { /// RTCCレジスタ読込みと時計表示 RtcDisp(); ready_status = 1; /// READY SW ON待ちの途中で、書込みSWが押されたら /// 画面イメージを読込み、そのデータを正規のBMPデータに変換して /// SDカードに書込む。 if(Write_flag){ lcd_ImageRead(); Conv_DispBufTable_to_BmpTable(); for(i= 0; i< 1024; i++) Buffer[i]= ~Buffer[i]; // データ論理反転して入れ替え BmpDataWrite(); Write_flag= 0; } } if (!TRIG_MODE_SW) { ready_status = 0; LATDbits.LATD4 = 0; // Red LED ON T3CONbits.TON = 1; // T3ON-> ADC Start while(!EndFlag); Oscillo_single_trigger(); } } /******************************************* * Assist Line X Coordinate Axis (Dot Line) ********************************************/ void dotxline(unsigned short y0){ unsigned short i; for(i=0; i<128; i+=3) lcd_Pixel(i, y0-1, 1); } /******************************************* * Assist Line Y Coordinate Axis (Dot Line) ********************************************/ void dotyline(unsigned short x0){ unsigned short i; for(i=0; i<64; i+=3) lcd_Pixel(x0-1, i, 1); } /*********************************************** * ロータリエンコーダ読込み処理 * RE-B相の立下りエッジを基準に、メインループで読込む ************************************************/ void RotaryEncoderRead(void) { //Read ROTARY ENCODER B_Clock re_b_m0 = RE_B; re_b_m2 = re_b_m1^(re_b_m0 & re_b_m1); //Neg_Edge Sence CLOCK re_b_m1 = re_b_m0; //Chenge New Data to Old Data m1 if (re_b_m2 == 1) { //Neg_Edge Sence B_Clock ? if(RE_A == 0){ // 右回転の場合、トリガレベルアップ:+16ステップで最大レベル1008の31ポイント ++Ypos; POT+= 16; if(POT > 1008){ Ypos= 63; POT= 1008; } } else{ // 左回転の場合、トリガレベルダウン:-16ステップで最小レベル0の32ポイント --Ypos; POT-= 16; if(POT < 0){ Ypos= 0; POT= 0; } } } } ///------------------------------------------------------------------------------------------------------------------------- /********************************************************************* * 液晶イメージデータ(全画面分)を読出し、表示バッファに格納する関数 * 最下段のデータ(page7相当)から格納 * 座標は(0,0)-(127,63) の範囲内 **********************************************************************/ void lcd_ImageRead(void){ char cs; short page, colum; short Xpos; unsigned char dummy; for(page=7; page>=0; page--){ for(colum=0; colum<128; colum++){ if(colum > 63){ Xpos=colum-64; cs = 1; } else{ Xpos = colum; cs = 2; } //// ページをセットする lcd_Write(cs, 0xB8+page, 1); //// 液晶の仕様により、本番のリードの前に、ダミーリードを行う lcd_Write(cs, 0x40+Xpos, 1); // set colum dummy = lcd_Read(cs); // get current data(1回目はダミーリード) //// 本番のリード lcd_Write(cs, 0x40+Xpos, 1); // set colum /// 表示バッファ:Disp_BUF[*]の、ポインタを、仮にiとすると /// iと、pageと、columの関係は、次のようになる。 /// page7で、colum= 0〜127の時、i= colum+0 (0〜127) /// page6で、colum= 0〜127の時、i= colum+128(128〜255) /// page5で、colum= 0〜127の時、i= colum+256(256〜383) /// page4で、colum= 0〜127の時、i= colum+384(384〜511) /// page3で、colum= 0〜127の時、i= colum+512(512〜689) /// page2で、colum= 0〜127の時、i= colum+640(640〜767) /// page1で、colum= 0〜127の時、i= colum+768(768〜895) /// page0で、colum= 0〜127の時、i= colum+896(896〜1023) /// 上の関係を、iについての式にすると、下のように書ける。 /// i= colum+ (7-page)*128 Disp_BUF[colum+ (7-page)*128] = lcd_Read(cs); // get current data(2回目のリードが本番) } } } /********************************************************************** * 液晶イメージを読込み格納した表示バッファの配列を、 * 標準の、BMPイメージデータの配列に変換 ***********************************************************************/ void Conv_DispBufTable_to_BmpTable(void) { short i; // 元表示用データバッファ:Disp_BUF[*]の、ポインタ short j; // BMPデータバッファ:Buffer[*]の、ポインタ /// 各バッファのポインタを、最初の開始位置に初期化 i= 0; j= 0; do{ /// 8 x 8ビットブロックの配列変換(縦8ビット配列を、横8ビット配列に変換)------ Buffer[j+0]= (Disp_BUF[i+0] & 0x80) | (Disp_BUF[i+1] & 0x80)>> 1 | (Disp_BUF[i+2] & 0x80)>> 2 | (Disp_BUF[i+3] & 0x80)>> 3 | (Disp_BUF[i+4] & 0x80)>> 4 | (Disp_BUF[i+5] & 0x80)>> 5 | (Disp_BUF[i+6] & 0x80)>> 6 | (Disp_BUF[i+7] & 0x80)>> 7; Buffer[j+16]= (Disp_BUF[i+0] & 0x40)<< 1 | (Disp_BUF[i+1] & 0x40) | (Disp_BUF[i+2] & 0x40)>> 1 | (Disp_BUF[i+3] & 0x40)>> 2 | (Disp_BUF[i+4] & 0x40)>> 3 | (Disp_BUF[i+5] & 0x40)>> 4 | (Disp_BUF[i+6] & 0x40)>> 5 | (Disp_BUF[i+7] & 0x40)>> 6; Buffer[j+32]= (Disp_BUF[i+0] & 0x20)<< 2 | (Disp_BUF[i+1] & 0x20)<< 1 | (Disp_BUF[i+2] & 0x20) | (Disp_BUF[i+3] & 0x20)>> 1 | (Disp_BUF[i+4] & 0x20)>> 2 | (Disp_BUF[i+5] & 0x20)>> 3 | (Disp_BUF[i+6] & 0x20)>> 4 | (Disp_BUF[i+7] & 0x20)>> 5; Buffer[j+48]= (Disp_BUF[i+0] & 0x10)<< 3 | (Disp_BUF[i+1] & 0x10)<< 2 | (Disp_BUF[i+2] & 0x10)<< 1 | (Disp_BUF[i+3] & 0x10) | (Disp_BUF[i+4] & 0x10)>> 1 | (Disp_BUF[i+5] & 0x10)>> 2 | (Disp_BUF[i+6] & 0x10)>> 3 | (Disp_BUF[i+7] & 0x10)>> 4; Buffer[j+64]= (Disp_BUF[i+0] & 0x08)<< 4 | (Disp_BUF[i+1] & 0x08)<< 3 | (Disp_BUF[i+2] & 0x08)<< 2 | (Disp_BUF[i+3] & 0x08)<< 1 | (Disp_BUF[i+4] & 0x08) | (Disp_BUF[i+5] & 0x08)>> 1 | (Disp_BUF[i+6] & 0x08)>> 2 | (Disp_BUF[i+7] & 0x08)>> 3; Buffer[j+80]= (Disp_BUF[i+0] & 0x04)<< 5 | (Disp_BUF[i+1] & 0x04)<< 4 | (Disp_BUF[i+2] & 0x04)<< 3 | (Disp_BUF[i+3] & 0x04)<< 2 | (Disp_BUF[i+4] & 0x04)<< 1 | (Disp_BUF[i+5] & 0x04) | (Disp_BUF[i+6] & 0x04)>> 1 | (Disp_BUF[i+7] & 0x04)>> 2; Buffer[j+96]= (Disp_BUF[i+0] & 0x02)<< 6 | (Disp_BUF[i+1] & 0x02)<< 5 | (Disp_BUF[i+2] & 0x02)<< 4 | (Disp_BUF[i+3] & 0x02)<< 3 | (Disp_BUF[i+4] & 0x02)<< 2 | (Disp_BUF[i+5] & 0x02)<< 1 | (Disp_BUF[i+6] & 0x02) | (Disp_BUF[i+7] & 0x02)>> 1; Buffer[j+112]= (Disp_BUF[i+0] & 0x01)<< 7 | (Disp_BUF[i+1] & 0x01)<< 6 | (Disp_BUF[i+2] & 0x01)<< 5 | (Disp_BUF[i+3] & 0x01)<< 4 | (Disp_BUF[i+4] & 0x01)<< 3 | (Disp_BUF[i+5] & 0x01)<< 2 | (Disp_BUF[i+6] & 0x01)<< 1 | (Disp_BUF[i+7] & 0x01); ///----------------------------------------------------------------------------- i+= 8; // 次の、8 x 8ビットブロックの、Disp_BUF[*]の、開始位置に移動 j++; // 次の、8 x 8ビットブロックの、Buffer[*]の、開始位置に移動 if(j == 16) j= 128; // 最下段(page7相当)の、16ブロック分の変換が終了したら、次の上段(page6相当)の、開始位置に移動 if(j == 144) j= 256; // page6相当の、16ブロック分の変換が終了したら、次の上段(page5相当)の、開始位置に移動 if(j == 272) j= 384; // page5相当の、16ブロック分の変換が終了したら、次の上段(page4相当)の、開始位置に移動 if(j == 400) j= 512; // page4相当の、16ブロック分の変換が終了したら、次の上段(page3相当)の、開始位置に移動 if(j == 528) j= 640; // page3相当の、16ブロック分の変換が終了したら、次の上段(page2相当)の、開始位置に移動 if(j == 656) j= 768; // page2相当の、16ブロック分の変換が終了したら、次の上段(page1相当)の、開始位置に移動 if(j == 784) j= 896; // page1相当の、16ブロック分の変換が終了したら、次の上段(page0相当)の、開始位置に移動 }while(i< 1017); // 最後のブロックの、Disp_BUF[*]の、開始位置は、1016になるので、 // i= 1017で全エリア(全128ブロック:64ビット x 128=8192ビット=1024バイト) // の変換が終了することになる } /*********************************************************************************** * BMPデータ(ヘッダ情報含む)を、SDカードに書込んだ後、 * その時のタイムスタンプを書込む。。 * * <備考> * RTCC(時計)が無いと、イメージをSDに保存した時に、時刻関連の情報が * でたらめになるため。ホールド中に、書込みSWが押されたら、その時のタイムスタンプを * SDに保存する必要がある。 * これは、FAT32 FSconfig.hで、USERDEFINEDCLOCKを有効(#define USERDEFINEDCLOCK) * にして、SetClockVars関数を使うにとによって可能となる。 * ちなみに、FAT32 FSconfig.hで、USEREALTIMECLOCKを有効(#define USEREALTIMECLOCK) * にして、自動設定にしてみたが、上手く行かなかった。 ************************************************************************************/ void BmpDataWrite(void){ /// カード挿入まで待つ lcd_Clear(0); // 画面消去 while(!MDD_MediaDetect()){ // カード挿入中か? lcd_Str(3, 0, "Wait Card Insert!"); // 挿入待ちメッセージ delay_ms(500); } delay_ms(100); /// 挿入されたら、ファイルシステムを初期化する lcd_Str(3, 0, "Find Card OK! "); FSInit(); // FS初期化 delay_ms(200); lcd_Str(3, 0, "Bmp Write Start!"); itostring(3, FileNo, FileName+4); // ファイル名更新 fptr = FSfopen(FileName, "w"); // File Open (Write Mode) if(fptr != NULL){ // ファイルオープンに成功(書込みなので、ファイル生成に成功)の場合、以下を実行 /// まずは、ヘッダ情報部:62バイト(BMPフォーマットを、白黒の、128x64ドットに限定しているので、全て固定値で、OK if(FSfwrite(monochroBmpHeader, 62, 1, fptr) != 1){ lcd_Str(3, 0, "File Write error"); // 書き込み失敗 while(1); // エラー停止 } /// 次に、データ部:1024バイト if(FSfwrite(Buffer, 1024, 1, fptr) != 1){ lcd_Str(3, 0, "File Write error"); // 書き込み失敗 while(1); // エラー停止 } /// 最後に、タイムスタンプを書込む /// RTCCレジスタ値は、BCDなので、バイナリに変換してから値を渡している。 /// また、年レジスタは、下2桁分しかないので、2000を足している。 SetClockVars(2000+((rec_data[8] >> 4)*10+(rec_data[8] & 0x0F)), // 年 ((rec_data[7] & 0x1F) >> 4)*10+(rec_data[7] & 0x0F), // 月 ((rec_data[5] & 0x3F) >> 4)*10+(rec_data[5] & 0x0F), // 日 ((rec_data[4] & 0x3F) >> 4)*10+(rec_data[4] & 0x0F), // 時 ((rec_data[3] & 0x7F) >> 4)*10+(rec_data[3] & 0x0F), // 分 ((rec_data[2] & 0x7F) >> 4)*10+(rec_data[2] & 0x0F)); // 秒 /// ファイルをクローズ if(FSfclose(fptr)){ lcd_Str(3, 0, "File Close error"); // エラーメッセージ while(1); // クローズエラー停止 } /// ファイル名番号更新 FileNo++; // ファイル番号更新 if(FileNo > 999){ // ファイル番号上限か? FileNo = 0; } delay_ms(100); lcd_Str(3, 0, "Bmp Write End! "); delay_ms(200); HOLD_ON_flag= 0; // SDカードへの書込みが終了したら、ホールドモードを抜ける LATDbits.LATD2 = 1; // HOLD LED OFF } else{ // ファイルオープン失敗の場合 lcd_Str(3, 0, "File Open error!"); // 失敗メッセージ while(1); // エラー停止 } } /***************************************************************** * ホールドモード中または、READY SW ON待ち中に、レジスタリードし、 * 液晶に、年/月/日、時:分を表示させる。 ******************************************************************/ void RtcDisp(void) { ReadRTC(2,8); // rec_data[*] <-- Read SecondsREG 〜 YearsREG /// RTCレジスタ値は、BCDなので、これをアスキーに変換してから、 /// それぞれの、メッセージバッファ位置に、格納後、液晶表示する。 MsgClock[1] = (rec_data[8] >> 4) + 0x30; // 年:01〜99 MsgClock[2] = (rec_data[8] & 0x0F) + 0x30; MsgClock[4] = ((rec_data[7] & 0x1F) >> 4) + 0x30; // 月:01〜12 ※ 読出し時、b7は、Cビット、b6-5は不定なので、0x1Fでマスクが必要 MsgClock[5] = (rec_data[7] & 0x0F) + 0x30; MsgClock[7] = ((rec_data[5] & 0x3F) >> 4) +0x30; // 日:01〜31 ※ 読出し時、b7-6は不定なので、0x3Fでマスクが必要 MsgClock[8] = (rec_data[5] & 0x0F) + 0x30; MsgClock[10] = ((rec_data[4] & 0x3F) >> 4) + 0x30; // 時:00〜23 ※ 読出し時、b7-6は不定なので、0x3Fでマスクが必要 MsgClock[11] = (rec_data[4] & 0x0F) + 0x30; MsgClock[13] = ((rec_data[3] & 0x7F) >> 4) + 0x30; // 分:00〜59 ※ 読出し時、b7は不定なので、0x7Fでマスクが必要 MsgClock[14] = (rec_data[3] & 0x0F) + 0x30; if(RtcDispFlag) lcd_Str(0, 3, MsgClock); // 時計表示 } ///-------------------------------------------------------------------------------------------------------------- /********************************************************************* * RTC I2C書込み関数 * * <使い方> * @ 連続した、レジスタアドレスに、データを書込みたい時は、 *   その範囲の、レジスタにデータをセットした後に、その *   開始アドレスから終了アドレスまでを指定して、この関数を *   実行する。 *   但し、全16個のレジスタに初期値(テーブル)を書込む時は、 *   WriteRTC(0,15); *   を実行するだけでよい。 *   その配列名は、rtc_write_data_tblとする。([0]〜[15]) * * A 任意のレジスタに、1バイトのデータを書込みたい時には、 *   前もって、希望のレジスタ番地(配列の要素)に、データをセット *   してから、開始と終了アドレスを同じアドレスにして、この関数 *   を実行する。 ***********************************************************************/ void WriteRTC(unsigned char start_adrs, unsigned char end_adrs) { char i; /// START Bus Event StartI2C1(); // Startシーケンス /// Send Slave Address + Writebit IdleI2C1(); // wait MasterWriteI2C1(RTC8564_SLVADRS_WR); // RTCスレーブアドレス書き込み送信 // スレーブアドレスは、b7〜b1(7ビット)+b0:W/=0 /// Receive ACK From RTC8564 IdleI2C1(); // wait while(I2C1STATbits.ACKSTAT); // ACK応答が、'0' になるまで待つ(エラー処理は省略した) /// Send Write Start Address IdleI2C1(); MasterWriteI2C1(start_adrs); /// Receive ACK From RTC8564 IdleI2C1(); // wait while(I2C1STATbits.ACKSTAT); // ACK応答が、'0' になるまで待つ(エラー処理は省略した) /// Send RTC_REG Write Data (Write Address Auto Incriment) for (i = start_adrs; i != end_adrs + 1; ++i) { IdleI2C1(); MasterWriteI2C1(rtc_write_data_tbl[i]); // Receive ACK From RTC8564 IdleI2C1(); // wait while(I2C1STATbits.ACKSTAT); // ACK応答が、'0' になるまで待つ(エラー処理は省略した) } /// Stop Bus Event StopI2C1(); // Stopシーケンス delay_us(200); // Delay for 200uS (needs > 1.3uS next start) } /************************************************************** * RTC I2C読込み関数 * * <使い方> * 書込み関数と、同様です。(書込みのところを、読込みに置換えて説明文をみてください) ***************************************************************/ void ReadRTC(unsigned char start_adrs, unsigned char end_adrs) { char i; // START Bus Event StartI2C1(); // Startシーケンス /// Send Slave Address + Writebit IdleI2C1(); // wait MasterWriteI2C1(RTC8564_SLVADRS_WR); // RTCスレーブアドレス書き込み送信 // スレーブアドレスは、b7〜b1(7ビット)+b0:W/=0 /// Receive ACK From RTC8564 IdleI2C1(); // wait while(I2C1STATbits.ACKSTAT); // ACK応答が、'0' になるまで待つ(エラー処理は省略した // Send Read Start Address IdleI2C1(); MasterWriteI2C1(start_adrs); /// Receive ACK From RTC8564 IdleI2C1(); // wait while(I2C1STATbits.ACKSTAT); // ACK応答が、'0' になるまで待つ(エラー処理は省略した) // RESTART Bus Event RestartI2C1(); // RESTARTシーケンス // Send Slave Address + Readbit IdleI2C1(); // wait MasterWriteI2C1(RTC8564_SLVADRS_RD); /// Receive ACK From RTC8564 IdleI2C1(); // wait while(I2C1STATbits.ACKSTAT); // ACK応答が、'0' になるまで待つ(エラー処理は省略した) // Receive RTC_REG Read Data (Read Address Auto Incriment) for (i = start_adrs; i != end_adrs + 1; ++i) { IdleI2C1(); rec_data[i] = MasterReadI2C1(); // Send ACK From PIC if (i != end_adrs) { IdleI2C1(); I2C1CONbits.ACKDT = 0; // Specify ACK Tx I2C1CONbits.ACKEN = 1; // Master is Response Sq } } // Send NACK From PIC: End of Rx IdleI2C1(); I2C1CONbits.ACKDT = 1; // Specify NACK Tx I2C1CONbits.ACKEN = 1; // Master is Response Sq /// Stop Bus Event StopI2C1(); // Stopシーケンス delay_us(200); // Delay for 200uS (needs > 1.3uS next start) } /****************************************** * 時計合わせモード *******************************************/ void time_adjust_mode(void) { /// トップメッセージ表示 lcd_Clear(0); lcd_Str(0, 0, "TIME ADJUST MODE"); /// 時計合わせの、初期画面(ALL '0'固定)表示 lcd_Str(2, 3, "'00/00/00(0)"); // 時計表示_1:上段 lcd_Str(4, 4, "00:00:00"); // 時計表示_2:下段 // Read SW Loop while(TimeSetEnd != 1) { /// 3つのSWの、立下りエッジセンスを行う // HOLD_SW(TM_SEL兼用) TmSel_m0 = HOLD_SW; //New SW Data TmSel_m2 = TmSel_m1^(TmSel_m0 & TmSel_m1); //Neg_Edge Sence SW TmSel_m1 = TmSel_m0; //Chenge New Data to Old Data m1 // SLOPE_SW(TM_ADJ兼用) TmAdj_m0 = SLOPE_SW; TmAdj_m2 = TmAdj_m1^(TmAdj_m0 & TmAdj_m1); TmAdj_m1 = TmAdj_m0; // READY_SW(TM_ENT兼用) TmEnt_m0 = READY_SW; TmEnt_m2 = TmEnt_m1^(TmEnt_m0 & TmEnt_m1); TmEnt_m1 = TmEnt_m0; /// TM_SEL SWが押された場合の処理 if(TmSel_m2){ ++SelCount; if(SelCount == 8) SelCount= 1; /// TM_SEL_SWを押す度に、カーソルを設定項目の下に移動する。 switch(SelCount){ case 1: lcd_Str(5, 11, " "); // 1つ前に表示されているカーソル表示を消す lcd_Str(3, 5, "^"); // 年項目の下にカーソル表示(階乗記号を流用) break; case 2: lcd_Str(3, 5, " "); // 1つ前に表示されていたカーソル表示を消す lcd_Str(3, 8, "^"); // 月項目の下にカーソル表示(階乗記号を流用) break; case 3: lcd_Str(3, 8, " "); // 1つ前に表示されていたカーソル表示を消す lcd_Str(3, 11, "^"); // 日項目の下にカーソル表示(階乗記号を流用) break; case 4: lcd_Str(3, 11, " "); // 1つ前に表示されていたカーソル表示を消す lcd_Str(3, 13, "^"); // 週項目の下にカーソル表示(階乗記号を流用) break; case 5: lcd_Str(3, 13, " "); // 1つ前に表示されていたカーソル表示を消す lcd_Str(5, 5, "^"); // 時目の下にカーソル表示(階乗記号を流用) break; case 6: lcd_Str(5, 5, " "); // 1つ前に表示されていたカーソル表示を消す lcd_Str(5, 8, "^"); // 分項目の下にカーソル表示(階乗記号を流用) break; case 7: lcd_Str(5, 8, " "); // 1つ前に表示されていたカーソル表示を消す lcd_Str(5, 11, "^"); // 秒項目の下にカーソル表示(階乗記号を流用) break; default: ; break; } } /// TM_ADJ SWが押された場合の処理 if(TmAdj_m2){ /// 各設定項目によって、それぞれのアジャスト処理に分岐する switch(SelCount){ case 1: ++YearSet; if (YearSet == 100) YearSet = 0; /// バイナリ→パックドデシマル→アスキー変換してから、液晶に設定値を表示する。(以下同様) lcd_Char1(2, 4, (YearSet/10)%10 + 0x30); // 上位桁 lcd_Char1(2, 5, YearSet%10 + 0x30); // 下位桁 break; case 2: ++MonthsSet; if(MonthsSet == 13) MonthsSet = 1; lcd_Char1(2, 7, (MonthsSet/10)%10 + 0x30); // 上位桁 lcd_Char1(2, 8, MonthsSet%10 + 0x30); // 下位桁 break; case 3: ++DaysSet; if(DaysSet == 32) DaysSet = 1; lcd_Char1(2, 10, (DaysSet/10)%10 + 0x30); // 上位桁 lcd_Char1(2, 11, DaysSet%10 + 0x30); // 下位桁 break; case 4: ++WeekdaysSet; if(WeekdaysSet == 7) WeekdaysSet = 0; lcd_Char1(2, 13, WeekdaysSet%10 + 0x30); // 週は1桁表示 break; case 5: ++HourSet; if(HourSet == 24) HourSet = 0; lcd_Char1(4, 4, (HourSet/10)%10 + 0x30); // 上位桁 lcd_Char1(4, 5, HourSet%10 + 0x30); // 下位桁 break; case 6: ++MinuteSet; if(MinuteSet == 60) MinuteSet = 0; lcd_Char1(4, 7, (MinuteSet/10)%10 + 0x30); // 上位桁 lcd_Char1(4, 8, MinuteSet%10 + 0x30); // 下位桁 break; case 7: ++SecondsSet; if(SecondsSet == 60) SecondsSet = 0; lcd_Char1(4, 10, (SecondsSet/10)%10 + 0x30); // 上位桁 lcd_Char1(4, 11, SecondsSet%10 + 0x30); // 下位桁 break; default: ; break; } } /// TM_ENT SWが押された場合の処理 if(TmEnt_m2){ /// バイナリ→BCD変換してから、該当RTCデータデーブル位置に上書きする。 rtc_write_data_tbl[8] = YearSet+6 * (YearSet/10); rtc_write_data_tbl[7] = MonthsSet+6 * (MonthsSet/10); rtc_write_data_tbl[6] = WeekdaysSet+6 * (WeekdaysSet/10); rtc_write_data_tbl[5] = DaysSet+6 * (DaysSet/10); rtc_write_data_tbl[4] = HourSet+6 * (HourSet/10); rtc_write_data_tbl[3] = MinuteSet+6 * (MinuteSet/10); rtc_write_data_tbl[2] = SecondsSet+6 * (SecondsSet/10); // 時計合わせしたデータを、RTC8564に書込む。 WriteRTC(0,15); // Write RTC_Reg 16bytes: adrs = 0 to 15 -> Time Stop TimeSetEnd= 1; } delay_ms(5); // チャッター回避 } } ///---------------------------------------------------------------------------------------------------- /***************************************** * 数値から文字列に変換 *****************************************/ void itostring(char digit, unsigned int data, char *buffer) { char i; buffer += digit; // 文字列の最後 for(i=digit; i>0; i--) { // 最下位桁から上位へ buffer--; // ポインター1 *buffer = (data % 10) + '0'; // その桁数値を文字にして格納 data = data / 10; // 桁-1 } }