//******************************************************************************** /*   <ADロガー(FAT32)V3> ■入力チャネル  ・11チャネル ■測定分解能  ・約4.9mV ■入力電圧範囲  ・0V~5V ■記録メディア  ・SDC(FAT32) ■測定周期  ・100msec、1sec、1min、10min ■平均測定回数  ・1回、10回、100回 */ //******************************************************************************** #define BYTE unsigned short #define WORD unsigned int #define DWORD unsigned long // #include "__Lib_FAT32.h" // sbit SW1 at RA7_bit; sbit SW2 at RA6_bit; sbit SW3 at RE3_bit; sbit LED at RA4_bit; // #define SW_START SW1 #define SW_STOP SW2 #define SW_MODE SW3 // #define SW_HOUR SW1 #define SW_MINUTE SW2 // #define SW_MONTH SW1 #define SW_DAY SW2 // #define SW_UP SW1 #define SW_DOWN SW2 //******************************************************************************** extern void main(); extern short get_mode(); extern void run_mode_0(); extern void run_mode_1(); extern void run_mode_2(); extern void run_mode_3(); extern void run_mode_4(); // extern void init_osc(); extern void init_port(); extern void init_comparator(); extern void init_adc(); extern void init_sdc_fat32(); extern void init_timer(); // extern void init_lcd(); extern void RegistCustomChar(); extern void BarDisp(char row, char column, short dat, short bar); // extern BYTE RTC_8564_Read(BYTE addr); extern void RTC_8564_Write(BYTE addr, BYTE dat); extern void get_date_time(char *dat); extern void set_date_time(char *dat); extern void disp_date_time(); extern void init_rtc(); extern void clock2timedate2(__TIME *tm); // extern DWORD get_clock(); extern void set_clock(DWORD clock); extern void clock2str(DWORD clock, char *str); extern void clock2timedate(DWORD clock, __TIME *tm); extern long wait_trigger(short mode); extern WORD ADC_Get_Sample_Average(BYTE channel); //******************************************************************************** char *tytle = "ad_logger_fat32 v3.1"; char buf[70]; char *file_name = "log_0000.txt"; WORD file_id = 0; __HANDLE fileHandle; __TIME TimeDate; BYTE td_hour, td_min, td_sec, td_month, td_day; short run_mode = 0; short cycle_mode = 1; short sampling_mode = 2; char *cycle_str[4] = { "100msec", "1sec ", "1min ", "10min " }; char *sampling_str[4] = { "1 ", "10 ", "100 ", "1000" }; short change_flg = 0; //******************************************************************************** //■メイン関数 void main() { short cnt; // init_osc(); init_comparator(); init_port(); init_adc(); init_lcd(); init_sdc_fat32(); init_rtc(); if (SW_MODE == 0) { Lcd_Out(1, 1, "date&time initialize"); Lcd_Out(3, 1, "-- 01/01 00:00:00 --"); while (SW_MODE == 0) { Delay_ms(100); } set_date_time("01/01 00:00:00"); Lcd_Cmd(_LCD_CLEAR); } init_timer(); // cycle_mode = EEPROM_Read(0); if ((cycle_mode < 0) || (cycle_mode > 3)) { cycle_mode = 1; } sampling_mode = EEPROM_Read(1); if ((sampling_mode < 0) || (sampling_mode > 3)) { sampling_mode = 1; } // for (cnt = 0; cnt < 3; cnt++) { LED = 1; Delay_ms(100); LED = 0; Delay_ms(100); } // while (1) { get_date_time(buf); Lcd_Out(1, 1, buf); // switch (get_mode()) { case 0://測定、表示、記録 run_mode_0(); break; case 1://時刻合わせ run_mode_1(); break; case 2://日付合わせ run_mode_2(); break; case 3://測定周期設定 run_mode_3(); break; case 4://平均化回数設定 run_mode_4(); break; } } } //******************************************************************************** void run_mode_0() { double ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10, ch11; long clock; // ch1 = ADC_Get_Sample_Average(0); ch2 = ADC_Get_Sample_Average(1); ch3 = ADC_Get_Sample_Average(2); ch4 = ADC_Get_Sample_Average(3); ch5 = ADC_Get_Sample_Average(4); ch6 = ADC_Get_Sample_Average(5); ch7 = ADC_Get_Sample_Average(6); ch8 = ADC_Get_Sample_Average(7); ch9 = ADC_Get_Sample_Average(8); ch10 = ADC_Get_Sample_Average(9); ch11 = ADC_Get_Sample_Average(10); // ch1 *= 4.8828125; ch2 *= 4.8828125; ch3 *= 4.8828125; ch4 *= 4.8828125; ch5 *= 4.8828125; ch6 *= 4.8828125; ch7 *= 4.8828125; ch8 *= 4.8828125; ch9 *= 4.8828125; ch10 *= 4.8828125; ch11 *= 4.8828125; // WordToStr(ch1, buf); WordToStr(ch2, &buf[5]); WordToStr(ch3, &buf[10]); WordToStr(ch4, &buf[15]); Lcd_Out(2, 1, buf); WordToStr(ch5, buf); WordToStr(ch6, &buf[5]); WordToStr(ch7, &buf[10]); WordToStr(ch8, &buf[15]); Lcd_Out(3, 1, buf); WordToStr(ch9, buf); WordToStr(ch10, &buf[5]); WordToStr(ch11, &buf[10]); Lcd_Out(4, 1, buf); // if (SW_START == 1) { return; } // Lcd_Chr(1, 20, 0xFF); LED = 1; // file_id++; WordToStr(file_id, buf); file_name[4] = (buf[1] == ' ') ? '0' : buf[1]; file_name[5] = (buf[2] == ' ') ? '0' : buf[2]; file_name[6] = (buf[3] == ' ') ? '0' : buf[3]; file_name[7] = (buf[4] == ' ') ? '0' : buf[4]; Lcd_Out(2, 1, " "); Lcd_Out(3, 1, " "); Lcd_Out(3, 1, file_name); Lcd_Out(4, 1, " "); Delay_ms(500); Lcd_Out(3, 1, " "); // clock2timedate2(&TimeDate); FAT32_SetTime(&TimeDate); Delay_ms(10); FAT32_Delete(file_name); Delay_ms(10); fileHandle = FAT32_Open(file_name, FILE_WRITE); FAT32_Write(fileHandle, "$START ", 7); get_date_time(buf); buf[14] = '\r'; buf[15] = '\n'; FAT32_Write(fileHandle, buf, 16); set_clock(0); while (SW_STOP != 0) { clock = wait_trigger(cycle_mode); if (clock == -1) { break; } // clock2str(clock, buf); // ch1 = ADC_Get_Sample_Average(0); ch2 = ADC_Get_Sample_Average(1); ch3 = ADC_Get_Sample_Average(2); ch4 = ADC_Get_Sample_Average(3); ch5 = ADC_Get_Sample_Average(4); ch6 = ADC_Get_Sample_Average(5); ch7 = ADC_Get_Sample_Average(6); ch8 = ADC_Get_Sample_Average(7); ch9 = ADC_Get_Sample_Average(8); ch10 = ADC_Get_Sample_Average(9); ch11 = ADC_Get_Sample_Average(10); // ch1 *= 4.8828125; ch2 *= 4.8828125; ch3 *= 4.8828125; ch4 *= 4.8828125; ch5 *= 4.8828125; ch6 *= 4.8828125; ch7 *= 4.8828125; ch8 *= 4.8828125; ch9 *= 4.8828125; ch10 *= 4.8828125; ch11 *= 4.8828125; // WordToStr(ch1, &buf[12]); WordToStr(ch2, &buf[17]); WordToStr(ch3, &buf[22]); WordToStr(ch4, &buf[27]); WordToStr(ch5, &buf[32]); WordToStr(ch6, &buf[37]); WordToStr(ch7, &buf[42]); WordToStr(ch8, &buf[47]); WordToStr(ch9, &buf[52]); WordToStr(ch10, &buf[57]); WordToStr(ch11, &buf[62]); buf[67] = '\r'; buf[68] = '\n'; FAT32_Write(fileHandle, buf, 69); } FAT32_Write(fileHandle, "$STOP ", 7); get_date_time(buf); buf[14] = '\r'; buf[15] = '\n'; FAT32_Write(fileHandle, buf, 16); FAT32_Close(fileHandle); LED = 0; Lcd_Chr(1, 20, ' '); } //******************************************************************************** void run_mode_1() { BYTE td; // Lcd_Out(2, 1, "clock adjust "); //“時”の設定 if (SW_HOUR == 0) { while (SW_HOUR == 0) { Delay_ms(100); } td_hour = RTC_8564_Read(4) & 0x3F; td = Bcd2Dec(td_hour); td++; if (td >= 24) { td = 0; } td_hour = Dec2Bcd(td); RTC_8564_Write(4, td_hour); } //“分”の設定 if (SW_MINUTE == 0) { while (SW_MINUTE == 0) { Delay_ms(100); } td_min = RTC_8564_Read(3) & 0x7F; td = Bcd2Dec(td_min); td++; if (td >= 60) { td = 0; } td_min = Dec2Bcd(td); RTC_8564_Write(3, td_min); RTC_8564_Write(2, 0); } } //******************************************************************************** void run_mode_2() { BYTE td; // Lcd_Out(2, 1, "date adjust "); //“月”の設定 if (SW_MONTH == 0) { while (SW_MONTH == 0) { Delay_ms(100); } td_month = RTC_8564_Read(7) & 0x1F; td = Bcd2Dec(td_month); td++; if (td >= 13) { td = 1; } td_month = Dec2Bcd(td); RTC_8564_Write(7, td_month); } //“日”の設定 if (SW_DAY == 0) { while (SW_DAY == 0) { Delay_ms(100); } td_day = RTC_8564_Read(5) & 0x3F; td = Bcd2Dec(td_day); td++; if (td >= 32) { td = 1; } td_day = Dec2Bcd(td); RTC_8564_Write(5, td_day); } } //******************************************************************************** void run_mode_3() { Lcd_Out(2, 1, "cycle mode "); // if (change_flg == 1) { change_flg = 0; Lcd_Out(3, 5, cycle_str[cycle_mode]); } // if (SW_UP == 0) { while (SW_UP == 0) { Delay_ms(100); } // cycle_mode++; if (cycle_mode == 4) { cycle_mode = 3; } Lcd_Out(3, 5, cycle_str[cycle_mode]); } // if (SW_DOWN == 0) { while (SW_DOWN == 0) { Delay_ms(100); } // cycle_mode--; if (cycle_mode == -1) { cycle_mode = 0; } Lcd_Out(3, 5, cycle_str[cycle_mode]); } // EEPROM_Write(0, cycle_mode); } //******************************************************************************** void run_mode_4() { Lcd_Out(2, 1, "sampling mode "); // if (change_flg == 1) { change_flg = 0; Lcd_Out(3, 5, sampling_str[sampling_mode]); } // if (SW_UP == 0) { while (SW_UP == 0) { Delay_ms(100); } // sampling_mode++; if (sampling_mode == 4) { sampling_mode = 3; } Lcd_Out(3, 5, sampling_str[sampling_mode]); } // if (SW_DOWN == 0) { while (SW_DOWN == 0) { Delay_ms(100); } // sampling_mode--; if (sampling_mode == -1) { sampling_mode = 0; } Lcd_Out(3, 5, sampling_str[sampling_mode]); } // EEPROM_Write(1, sampling_mode); } //******************************************************************************** short get_mode() { if (SW_MODE == 1) { return (run_mode); } while (SW_MODE == 0) { Delay_ms(100); } // Lcd_Cmd(_LCD_CLEAR); // change_flg = 1; run_mode++; if (run_mode == 5) { run_mode = 0; } return (run_mode); } //******************************************************************************** WORD ADC_Get_Sample_Average(BYTE channel) { int cnt, i; DWORD ad; // switch (sampling_mode) { case 0: i = 1; break; case 1: i = 10; break; case 2: i = 100; break; case 3: if (run_mode == 0) { i = 100; } else { i = 1000; } break; } ad = 0; for (cnt = 0; cnt < i; cnt++) { ad += ADC_Get_Sample(channel); } return (ad / i); } //******************************************************************************** long wait_trigger(short mode) { long clock; // switch (mode) { case 0: //100msec while (1) { clock = get_clock(); if ((clock % 10) == 0) { return(clock); } if (SW_STOP == 0) { return(-1); } } break; case 1: //1sec while (1) { clock = get_clock(); if ((clock % 100) == 0) { return(clock); } if (SW_STOP == 0) { return(-1); } } break; case 2: //1min while (1) { clock = get_clock(); if ((clock % 6000) == 0) { return(clock); } if (SW_STOP == 0) { return(-1); } } break; case 3: //10min while (1) { clock = get_clock(); if ((clock % 60000) == 0) { return(clock); } if (SW_STOP == 0) { return(-1); } } break; } return (-1); } //******************************************************************************** void clock2str(DWORD clock, char *str) //"00:00:00:000" { BYTE hh, mm, ss, ms; char tmp[4]; // hh = (clock % 8640000) / 360000; mm = (clock % 360000) / 6000; ss = (clock % 6000) / 100; ms = clock % 100; // ByteToStr(hh, tmp); str[0] = (tmp[1] == ' ') ? '0' : tmp[1]; str[1] = tmp[2]; str[2] = ':'; ByteToStr(mm, tmp); str[3] = (tmp[1] == ' ') ? '0' : tmp[1]; str[4] = tmp[2]; str[5] = ':'; ByteToStr(ss, tmp); str[6] = (tmp[1] == ' ') ? '0' : tmp[1]; str[7] = tmp[2]; str[8] = ':'; ByteToStr(ms, tmp); str[9] = (tmp[1] == ' ') ? '0' : tmp[1]; str[10] = tmp[2]; str[11] = '0'; str[12] = 0x00; } //******************************************************************************** void clock2timedate(DWORD clock, __TIME *tm) { tm->Year = 2012; tm->Month = 12; tm->Day = 27; tm->Hour = (clock % 8640000) / 360000; tm->Minute = (clock % 360000) / 6000; tm->Second = (clock % 6000) / 100; } //******************************************************************************** void clock2timedate2(__TIME *tm) { tm->Year = 2012; tm->Month = RTC_8564_Read(7) & 0x1F; tm->Day = RTC_8564_Read(5) & 0x3F; tm->Hour = RTC_8564_Read(4) & 0x3F; tm->Minute = RTC_8564_Read(3) & 0x7F; tm->Second = RTC_8564_Read(2) & 0x7F; } //******************************************************************************** DWORD clock = 0; DWORD clock_tmp = 0; short clock_flg = 0; // void interrupt() { if (PIR1.CCP1IF == 1) { PIR1.CCP1IF = 0; // clock++; switch (clock_flg) { case 1: clock_flg = 0; clock_tmp = clock; break; case 2: clock_flg = 0; clock = clock_tmp; break; } } } //******************************************************************************** DWORD get_clock() { clock_flg = 1; while (clock_flg == 1) { } return (clock_tmp); } //******************************************************************************** void set_clock(DWORD clock) { clock_tmp = clock; clock_flg = 2; while (clock_flg == 2) { } } //******************************************************************************** //■周期割り込み設定関数(10msec) void init_timer() { // CCPの設定 PIE1.CCP1IE = 1; PIR1.CCP1IF = 0; CCP1CON.CCP1M3 = 1; CCP1CON.CCP1M2 = 0; CCP1CON.CCP1M1 = 1; CCP1CON.CCP1M0 = 1; CCPR1L = 0x10; // 10msec...クロックが32Mhzの時 CCPR1H = 0x27; // 10msec...(1÷32000000)*4*8*10000(0x2710) // TIMER1の設定 PIE1.TMR1IE = 0; PIR1.TMR1IF = 0; TMR1L = 0; TMR1H = 0; T1CON.TMR1CS = 0; T1CON.T1CKPS0 = 1; T1CON.T1CKPS1 = 1; T1CON.TMR1ON = 1; // INTCON.PEIE = 1; INTCON.GIE = 1; } //******************************************************************************** //■SDCを初期化する関数です。 sfr sbit Mmc_Chip_Select at RC2_bit; sfr sbit Mmc_Chip_Select_Direction at TRISC2_bit; // void init_sdc_fat32() { SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); while (FAT32_Init() < 0) { Lcd_Out(2, 1, "SDC(FAT32) error!"); Delay_ms(500); Lcd_Out(2, 1, " "); Delay_ms(500); } SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH); // Lcd_Out(2, 1, "SDC(FAT32) complete!"); Delay_ms(500); Lcd_Cmd(_LCD_CLEAR); } //******************************************************************************** void init_osc() { OSCCON.IRCF2 = 1; OSCCON.IRCF1 = 1; OSCCON.IRCF0 = 1; OSCTUNE.PLLEN = 1; } //******************************************************************************** void init_adc() { ADCON1.PCFG3 = 0; ADCON1.PCFG2 = 0; ADCON1.PCFG1 = 0; ADCON1.PCFG0 = 0; ADCON1.VCFG1 = 0; ADCON1.VCFG0 = 0; // ADC_Init(); } //******************************************************************************** void init_port() { TRISA = 0b11101111; TRISB = 0b00010011; TRISC = 0b11111111; TRISD = 0b11111111; TRISE2_bit = 1; TRISE1_bit = 1; TRISE0_bit = 1; // LED = 0; } //******************************************************************************** void init_comparator() { CMCON.CM2 = 1; CMCON.CM1 = 1; CMCON.CM0 = 1; } //******************************************************************************** //■LCD初期関数 sbit LCD_D7 at RD7_bit; sbit LCD_D6 at RD6_bit; sbit LCD_D5 at RD5_bit; sbit LCD_D4 at RD4_bit; sbit LCD_EN at RC7_bit; sbit LCD_RS at RC6_bit; sbit LCD_D7_Direction at TRISD7_bit; sbit LCD_D6_Direction at TRISD6_bit; sbit LCD_D5_Direction at TRISD5_bit; sbit LCD_D4_Direction at TRISD4_bit; sbit LCD_EN_Direction at TRISC7_bit; sbit LCD_RS_Direction at TRISC6_bit; // void init_lcd() { short cnt; // Lcd_Init(); RegistCustomChar(); Lcd_Cmd(_LCD_CLEAR); Lcd_Cmd(_LCD_CURSOR_OFF); Lcd_Out(1, 1, tytle); for (cnt = 0; cnt <= 100; cnt++) { BarDisp(2, 1, cnt, 100); BarDisp(3, 1, cnt, 100); BarDisp(4, 1, cnt, 100); Delay_ms(10); } Lcd_Cmd(_LCD_CLEAR); } //******************************************************************************** //■■■キャラクタ登録関数■■■ const char character0[] = { 0, 0, 0, 0, 0, 0, 0, 0}; const char character1[] = { 0,16,16,16,16,16, 0, 0}; const char character2[] = { 0,24,24,24,24,24, 0, 0}; const char character3[] = { 0,28,28,28,28,28, 0, 0}; const char character4[] = { 0,30,30,30,30,30, 0, 0}; const char character5[] = { 0,31,31,31,31,31, 0, 0}; // void RegistCustomChar() { char i; // LCD_Cmd(64); for (i = 0; i<=7; i++) { LCD_Chr_Cp(character0[i]); } for (i = 0; i<=7; i++) { LCD_Chr_Cp(character1[i]); } for (i = 0; i<=7; i++) { LCD_Chr_Cp(character2[i]); } for (i = 0; i<=7; i++) { LCD_Chr_Cp(character3[i]); } for (i = 0; i<=7; i++) { LCD_Chr_Cp(character4[i]); } for (i = 0; i<=7; i++) { LCD_Chr_Cp(character5[i]); } LCD_Cmd(_LCD_RETURN_HOME); } //******************************************************************************** //■■■バー表示関数■■■ void BarDisp(char row, char column, short dat, short bar) { short j, k, cnt; // j = dat / 5; k = dat - (j * 5); // switch (row) { case 1: Lcd_Cmd(_LCD_FIRST_ROW); break; case 2: Lcd_Cmd(_LCD_SECOND_ROW); break; case 3: Lcd_Cmd(_LCD_THIRD_ROW); break; case 4: Lcd_Cmd(_LCD_FOURTH_ROW); break; } // for (cnt = 1; cnt < column; cnt++) { Lcd_Cmd(_LCD_MOVE_CURSOR_RIGHT); } // for (cnt = 0; cnt < j; cnt++) { Lcd_Chr_Cp(5); } Lcd_Chr_Cp(k); for (cnt++; cnt < (bar / 5); cnt++) { Lcd_Chr_Cp(' '); } } //******************************************************************************** #define ACK 1 #define NO_ACK 0 //■RTCからのデータ取得関数です。 BYTE RTC_8564_Read(BYTE addr) { BYTE dat; // Soft_I2C_Start(); Soft_I2C_Write(0xA2); Soft_I2C_Write(addr); Soft_I2C_Start(); Soft_I2C_Write(0xA3); dat = Soft_I2C_Read(NO_ACK); Soft_I2C_Stop(); // return (dat); } //******************************************************************************** //■RTCへのデータ書き込み関数です。 void RTC_8564_Write(BYTE addr, BYTE dat) { Soft_I2C_Start(); Soft_I2C_Write(0xA2); Soft_I2C_Write(addr); Soft_I2C_Write(dat); Soft_I2C_Stop(); } //******************************************************************************** //■RTCから日付時刻(月日時分秒)を取得する関数です。 //設定文字列のフォーマット→"12/27 12:34:56" void get_date_time(char * dat) { BYTE td_month, td_day, td_hour, td_min, td_sec; //日付時刻(月日時分秒)のRTCからの取得 td_month = RTC_8564_Read(7) & 0x1F; td_day = RTC_8564_Read(5) & 0x3F; td_hour = RTC_8564_Read(4) & 0x3F; td_min = RTC_8564_Read(3) & 0x7F; td_sec = RTC_8564_Read(2) & 0x7F; //日付時刻(月日時分秒)のSDCへの書き込み dat[0] = (td_month >> 4) + '0'; dat[1] = (td_month & 0x0F) + '0'; dat[2] = '/'; dat[3] = (td_day >> 4) + '0'; dat[4] = (td_day & 0x0F) + '0'; dat[5] = ' '; dat[6] = (td_hour >> 4) + '0'; dat[7] = (td_hour & 0x0F) + '0'; dat[8] = ':'; dat[9] = (td_min >> 4) + '0'; dat[10] = (td_min & 0x0F) + '0'; dat[11] = ':'; dat[12] = (td_sec >> 4) + '0'; dat[13] = (td_sec & 0x0F) + '0'; dat[14] = 0x00; } //******************************************************************************** //■RTC日付時刻(月日時分秒)設定関数 //設定文字列のフォーマット→"12/27 12:34:56" void set_date_time(char *dat) { //日付時刻(月日時分秒)のRTCへの書き込み td_month = ((dat[0] - '0') << 4) + (dat[1] - '0'); td_day = ((dat[3] - '0') << 4) + (dat[4] - '0'); td_hour = ((dat[6] - '0') << 4) + (dat[7] - '0'); td_min = ((dat[9] - '0') << 4) + (dat[10] - '0'); td_sec = ((dat[12] - '0') << 4) + (dat[13] - '0'); // RTC_8564_Write(7, td_month); //月の書き込み RTC_8564_Write(5, td_day); //日の書き込み RTC_8564_Write(4, td_hour); //時の書き込み RTC_8564_Write(3, td_min); //分の書き込み RTC_8564_Write(2, td_sec); //秒の書き込み } //******************************************************************************** //■RTCを初期化する関数です。 sbit Soft_I2C_Scl at RD3_bit; sbit Soft_I2C_Sda at RD2_bit; sbit Soft_I2C_Scl_Direction at TRISD3_bit; sbit Soft_I2C_Sda_Direction at TRISD2_bit; // void init_rtc() { BYTE td; // Soft_I2C_Init(); //書き込みと読み出しのテストをします。 td = Dec2Bcd(10); //2011 RTC_8564_Write(8, td); //年の書き込み td = RTC_8564_Read(8); //年の読み出し if (Bcd2Dec(td) != 10) { while (1) { Lcd_Out(2, 1, "RTC error!"); Delay_ms(500); Lcd_Out(2, 1, " "); Delay_ms(500); } } // Lcd_Out(2, 1, "RTC complete!"); Delay_ms(500); Lcd_Cmd(_LCD_CLEAR); } //********************************************************************************