//**************************************************************** // I2C_RTC+ Temperature_Meter+ Logger // // Add Logger: Used UART -> Time & Temperature Transmit PC // Add EEPROM: AT24C256i32Kbytes) // Sample Vol: 256 or 4096 // // UART: 8 bit, non parity, 1 stop bit // U1ATX, U1ARX // // Used RTC8564 // // LCD unlook busy : not switch direction (write fixed) // // 7.37MHz Internal RC oscillator, 16x PLL enabled // Fcy=7.37MHzx16/4=29.48MHz, Tcy=33.92ns // // 2010/7/29: N.Ishii //**************************************************************** #include #include "delay.h" #include "i2c.h" #include #include // Divice configuration _FWDT(WDT_OFF); _FGS(CODE_PROT_OFF); _FOSC(CSW_FSCM_OFF & FRC_PLL16); //OSC, PLL Setting // _FOSC(CSW_FSCM_OFF & FRC_PLL4); //Used Debug OSC, PLL Setting: Slow Fcy // 7.37MHz Internal RC oscillator, 4x PLL enabled // Fcy=7.37MHzx4/4=7.37MHz, Tcy=136ns _FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN); // A/D control register unsigned int _ADCON1; unsigned int _ADCON2; unsigned int _ADCON3; unsigned int _ADCHS; unsigned int _ADPCFG; unsigned int _ADCSSL ; // UART control register unsigned int _U1BRG; unsigned int _U1MODE; unsigned int _U1STA; //#define Fcy 7370000*4 #define BaudRate 9600 #define CR 0x0d #define LF 0x0a #define EOF 0x1a /* #define S 0x53 #define P 0x50 #define M 0x4d #define H 0x48 */ //------------------------- unsigned char digit[3]; //unsigned char Eoc_flag; unsigned int Sec; //unsigned char stop_flag; // adc data unsigned int ResultData; unsigned int Temperature; unsigned char sw1_m0; unsigned char sw1_m1; unsigned char sw1_m2; unsigned char sw2_m0; unsigned char sw2_m1; unsigned char sw2_m2; unsigned char sw3_m0; unsigned char sw3_m1; unsigned char sw3_m2; unsigned char sw1_on_flag; unsigned char sw2_on_flag; unsigned char sw3_on_flag; unsigned char Logging_mode_flag; // message table for RTC char msg1[] = {"20\0"}; // Years 20** char msg2[] = {"SUN\0"}; // Weekdays char msg3[] = {"MON\0"}; char msg4[] = {"TUE\0"}; char msg5[] = {"WED\0"}; char msg6[] = {"THU\0"}; char msg7[] = {"FRI\0"}; char msg8[] = {"SAT\0"}; // message table for Logger char msg9[] = {"INTERVAL:\0"}; char msg10[] = {"SAMPLE :\0"}; char msg11[] = {"REC:0000/\0"}; char msg12[] = {"PLAY:0000/\0"}; // LCD Define: R/W_pin= GND (Fixed Write) #define LCD_DATA_WR_MODE PORTFbits.RF5 = 1 // RS_pin = 1 #define LCD_INST_WR_MODE PORTFbits.RF5 = 0 // RS_pin = 0 #define LCD_ENABLE_ON PORTFbits.RF4 = 1 #define LCD_ENABLE_OFF PORTFbits.RF4 = 0 #define RW_PIN PORTDbits.RD8 // PORT for RW #define LCD_DATA_BIT4 PORTBbits.RB4 #define LCD_DATA_BIT5 PORTBbits.RB5 #define LCD_DATA_BIT6 PORTBbits.RB6 #define LCD_DATA_BIT7 PORTBbits.RB7 //#define LCD_RS_BIT _RF5 //#define LCD_ENABLE_BIT _RF4 //--------------------------------------------------------------------------------------------- // LCD Instraction Code #define FOUR_BIT_FONT5x7dot 0x28 // + TWO_LINE(1/16Duty), SEG1_50_SEG51_100, COM1_COM16 #define DISP_ON_CURSOR_ON_BLINK_OFF 0x0e #define DISP_CLEAR_CURSOR_HOME 0x01 #define RAM_WR_AFTER_PLUS_1 0x06 // Entory mode set #define DDRAM_START_ADDRESS_SET 0x80 #define DISP_ON_CURSOR_OFF_BLINK_OFF 0x0c #define DISP_ON_CURSOR_OFF_BLINK_ON 0x08 // Blink ON add 0616 //--------------------------------------------------------------------------------------------- // I2C define #define RTC8564_SLVADRS_WR 0xa2 #define RTC8564_SLVADRS_RD 0xa3 #define EEPROM_SLVADRS_WR 0xa0 #define EEPROM_SLVADRS_RD 0xa1 //--------------------------------------------------------------------------------------------- /* Function prototypes */ void lcd_init(void) __attribute__ ((section (".libperi"))); void lcd_inst_wr(char) __attribute__ ((section (".libperi"))); void one_chr_wr(char) __attribute__ ((section (".libperi"))); void lcd_chr_wr(char *) __attribute__ ((section (".libperi"))); void lcd_cg_ram_user_set(void) __attribute__ ((section (".libperi"))); /* prototypes of three delay routines used in XLCD functions */ void DelayEPulseWidth() __attribute__ ((section (".libperi"))); void DelayPORXLCD() __attribute__ ((section (".libperi"))); void DelayXLCD() __attribute__ ((section (".libperi"))); void Delay200usXLCD() __attribute__((section (".libperi"))); //--------------------------------------------------------------------------------------------------- // 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 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 }; unsigned char rec_data[16]; // initialize I2C Parameter (PIC Side : I2CCON Reg) unsigned int I2Ccongig1 = I2C_ON & // I2C module enabled: 0xFFFF: I2CENbit15=1 I2C_IDLE_CON & // stop I2C module in Idle mode: 0xFFFF: I2CSIDLbit13=1 I2C_CLK_HLD & // hold clock: 0xEFFF: SCLRELbit12=0 I2C_IPMI_DIS & // IPMI mode not disabled: 0xF7FF: IPMIENbit11=0 I2C_7BIT_ADD & // I2CADD is 7-bit address: 0xFBFF: A10Mbit10=0 I2C_SLW_DIS & // Disable Slew Rate Control for 100KHz: 0xFFFF: DISSLEbit9=1 I2C_SM_DIS & // Disable SM bus specification: 0xFEFF: SMENbit8=0 I2C_GCALL_DIS & // Disable General call address: 0xFF7F: GCENbit7=0 I2C_STR_EN & // Enable clock stretching: 0xFFFF: STRENbit6=1 I2C_NACK & // Transmit 1 to send NACK as acknowledge: 0xFFFF: ACKDTbit5=1 I2C_ACK_DIS & // Acknowledge condition Idle: 0xFFEF: ACKENbit4=0 I2C_RCV_DIS & // Receive sequence not in progress: 0xFFF7: RCENbit3=0 I2C_STOP_DIS & // Stop condition Idle: 0xFFFB: PENbit2=0 I2C_RESTART_DIS;// Start condition Idle: 0xFFFD: RSENbit1=0 unsigned int I2Ccongig2 = 294; // I2CBRG = 294: Fcy=29.48MHz, Fscl=100kHz I2CBRG=(Fcy/Fscl)-1 1 // unsigned int I2Ccongig2 = 511; // Used Debug Fscl=14.4k(69.4ns)@Fcy=7.37MHz (Fscl=60k@Fcy=29.48MHz) //------------------------------------------------------------------------- unsigned char logger_write_data[16]; unsigned char logger_read_data[16]; unsigned int start_tmp; unsigned char interval_set; unsigned int sample_set; unsigned char sec_flag; unsigned char minute_flag; unsigned char hour_flag; //--------------------------------------------------------------------------- // For Logger Data Table unsigned char logger_write_data[] = { 0x00, // [0]:Hour 0x00, // [1]: 0x3a, // [2]:':' 0x00, // [3]:Minute 0x00, // [4]: 0x3a, // [5]:':' 0x00, // [6]:Seconds 0x00, // [7]: 0x2c, // [8]:',' 0x00, // [9]:Temperature 0x00, // [10]: 0x2e, // [11]:'.' 0x00, // [12]: 0x30, // [13]:'0'(const) CR, // [14]: LF // [15]: }; //unsigned char rx_uart_data[3]; //------------------------------------------------------------------------- // Delay Subrutin void DelayEPulseWidth(void) /* provides delay for 18Tcy */ { /* This is the width of the E signal */ /* required by the LCD controlller */ int i; for(i=0;i<18;i++) asm("clrwdt"); // #define ClrWdt() {__asm__ volatile ("clrwdt");} } void DelayPORXLCD(void) /* provides delay for atleast 15msec */ { /* Give a delay of atleast 15 msec after power up */ long i; for(i=0;i < 2000000;i++) asm("clrwdt"); } void DelayXLCD(void) /* provides delay for atleast 5msec */ { long i; for(i=0;i < 200000;i++) asm("clrwdt"); } void Delay200usXLCD(void) /* provides delay for 200uS */ { int i; for(i=0;i<8000;i++) asm("clrwdt"); } void Waitx1ms(int x) // Td = 1mS * x { int i,j; for(i = 0 ; i < x ; ++i) { for(j = 0 ; j < 5000 ; ++j) asm("clrwdt"); //Td=1mS } } void Waitx1us(int x) // Td = 1uS * x { int i,j; for(i = 0 ; i < x ; ++i) { for(j = 0 ; j < 5 ; ++j) asm("clrwdt"); //Td=1uS } } //-------------------------------------------------------------------- void one_chr_wr(char chr_code) { RW_PIN = 0; /* enable write */ LCD_DATA_WR_MODE; //RS_pin = 1: select data Reg /* // Configure the data pins as output (not need unlook busy switch direction) TRISBbits.TRISB4 =0; // RB4 is LCD DB4 OUTPUT TRISBbits.TRISB5 =0; // RB5 is LCD DB5 OUTPUT TRISBbits.TRISB6 =0; // RB6 is LCD DB6 OUTPUT TRISBbits.TRISB7 =0; // RB7 is LCD DB7 OUTPUT */ // A Higher 4bit data out LCD_DATA_BIT7 = (unsigned int)((chr_code & 0x80)>>7); LCD_DATA_BIT6 = (unsigned int)((chr_code & 0x40)>>6); LCD_DATA_BIT5 = (unsigned int)((chr_code & 0x20)>>5); LCD_DATA_BIT4 = (unsigned int)((chr_code & 0x10)>>4); LCD_ENABLE_ON; DelayEPulseWidth(); //need pulse width >= 220ns LCD_ENABLE_OFF; RW_PIN = 0; /* enable write */ LCD_DATA_WR_MODE; //RS_pin = 1: select data Reg // A Lower 4bit data out LCD_DATA_BIT7 = (unsigned int)((chr_code & 0x08)>>3); LCD_DATA_BIT6 = (unsigned int)((chr_code & 0x04)>>2); LCD_DATA_BIT5 = (unsigned int)((chr_code & 0x02)>>1); LCD_DATA_BIT4 = (unsigned int)(chr_code & 0x01); LCD_ENABLE_ON; DelayEPulseWidth(); LCD_ENABLE_OFF; /* // configure all pins to input mode (not need unlook busy switch direction) TRISBbits.TRISB7 = 1; TRISBbits.TRISB6 = 1; TRISBbits.TRISB5 = 1; TRISBbits.TRISB4 = 1; */ LCD_INST_WR_MODE; //RS_pin = 0: select Instruction Reg Delay200usXLCD(); // 40uS delay } void lcd_chr_wr(char *buffer) { while(*buffer != '\0') { one_chr_wr(*buffer); /* calling another function */ /* to write each char to the lcd module */ buffer++; } } void lcd_inst_wr(char inst_code) { RW_PIN = 0; /* enable write */ LCD_INST_WR_MODE; //RS_pin = 0: select Instruction Reg /* // Configure the data pins as output (not need unlook busy switch direction) TRISBbits.TRISB4 =0; // RB4 is LCD DB4 OUTPUT TRISBbits.TRISB5 =0; // RB5 is LCD DB5 OUTPUT TRISBbits.TRISB6 =0; // RB6 is LCD DB6 OUTPUT TRISBbits.TRISB7 =0; // RB7 is LCD DB7 OUTPUT */ // A Higher 4bit data out LCD_DATA_BIT7 = (unsigned int)((inst_code & 0x80)>>7); LCD_DATA_BIT6 = (unsigned int)((inst_code & 0x40)>>6); LCD_DATA_BIT5 = (unsigned int)((inst_code & 0x20)>>5); LCD_DATA_BIT4 = (unsigned int)((inst_code & 0x10)>>4); LCD_ENABLE_ON; DelayEPulseWidth(); //need pulse width >= 220ns LCD_ENABLE_OFF; RW_PIN = 0; /* enable write */ LCD_INST_WR_MODE; //RS_pin = 0 // A Lower 4bit data out LCD_DATA_BIT7 = (unsigned int)((inst_code & 0x08)>>3); LCD_DATA_BIT6 = (unsigned int)((inst_code & 0x04)>>2); LCD_DATA_BIT5 = (unsigned int)((inst_code & 0x02)>>1); LCD_DATA_BIT4 = (unsigned int)(inst_code & 0x01); LCD_ENABLE_ON; DelayEPulseWidth(); LCD_ENABLE_OFF; Delay200usXLCD(); // need >40uS delay (unlook busy) } void lcd_init(void) { // Allow a delay for POR.(minimum of 15ms) DelayPORXLCD(); //------ 1st step: port_output regster set -------------- // Initialize the data port/control pins to zero LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 0; LCD_DATA_BIT4 = 0; RW_PIN = 0; LCD_INST_WR_MODE; //RS_pin = 0 LCD_ENABLE_OFF; //E_pin = 0 //-------------------------------------------------------- //------- 2nd step: port_mode regster set --------------- // Configure the data pins as output TRISBbits.TRISB4 =0; // RB4 is LCD DB4 OUTPUT TRISBbits.TRISB5 =0; // RB5 is LCD DB5 OUTPUT TRISBbits.TRISB6 =0; // RB6 is LCD DB6 OUTPUT TRISBbits.TRISB7 =0; // RB7 is LCD DB7 OUTPUT // Make all control pins as outputs TRISDbits.TRISD8 =0; // RD8 is LCD RW OUTPUT TRISFbits.TRISF4 =0; // RF4 is LCD Enable OUTPUT TRISFbits.TRISF5 =0; // RF5 is LCD RS OUTPUT //------------------------------------------------------- // Initialize stage 1: Set stage 1 only 8-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; LCD_ENABLE_ON; DelayEPulseWidth(); //need pulse width >= 220ns LCD_ENABLE_OFF; DelayPORXLCD(); // 15ms // Initialize stage 2: Set stage 2 only 8-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; LCD_ENABLE_ON; DelayEPulseWidth(); //need pulse width >= 220ns LCD_ENABLE_OFF; DelayPORXLCD(); // 15ms // Initialize stage 3: Set stage 2 only 8-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 1; LCD_ENABLE_ON; DelayEPulseWidth(); //need pulse width >= 220ns LCD_ENABLE_OFF; DelayXLCD(); // 5ms // Initialize stage 4: 4-bit Interface LCD_DATA_BIT7 = 0; LCD_DATA_BIT6 = 0; LCD_DATA_BIT5 = 1; LCD_DATA_BIT4 = 0; LCD_ENABLE_ON; DelayEPulseWidth(); //need pulse width >= 220ns LCD_ENABLE_OFF; DelayXLCD(); // 5ms //----- Fixed LCD Setting------------ lcd_inst_wr(FOUR_BIT_FONT5x7dot); // Function Set lcd_inst_wr(DISP_ON_CURSOR_ON_BLINK_OFF); lcd_inst_wr(DISP_CLEAR_CURSOR_HOME); // Set DDRAM Address = 0 lcd_inst_wr(RAM_WR_AFTER_PLUS_1); // Entry mode Set } void const_lcd_disp(void) { // Initialize RTC Screen LCD Disp lcd_inst_wr(0x80); lcd_chr_wr(msg1); // '20' const disp1 lcd_inst_wr(0x84); one_chr_wr(0x2f); // '/' const disp2 lcd_inst_wr(0x87); one_chr_wr(0x2f); // '/' const disp3 lcd_inst_wr(0x87); one_chr_wr(0x2f); // '/' const disp3 lcd_inst_wr(0x8a); one_chr_wr(0x28); // '(' const disp4 lcd_inst_wr(0x8e); one_chr_wr(0x29); // ')' const disp5 lcd_inst_wr(0xc2); one_chr_wr(0x3a); // ':' const disp6 lcd_inst_wr(0xc5); one_chr_wr(0x3a); // ':' const disp6 } void const_lcd_disp_logger(void) { // Initialize Logger Set LCD Disp lcd_inst_wr(0x80); lcd_chr_wr(msg9); // 'INTERVAL:' const disp1 lcd_inst_wr(0xc0); lcd_chr_wr(msg10); // 'SAMPLE :' const disp2 } void line_clear(char clear_position , char clear_vol) { unsigned char i; lcd_inst_wr(clear_position); for (i = 0 ; i != clear_vol ; i++) {one_chr_wr(0x20);} // ' ' disp } //------------------------------------------------------------------------- void RTC_variable_disp(unsigned char Vol, unsigned char loc) { // Vol(BCD): 0x00-0x59( 00-59 Disp) unsigned char ascii[2]; // BCD_to_Ascii ascii[0] = (Vol & 0x0f) | 0x30; ascii[1] = ((Vol >> 4) & 0x0f) | 0x30; // LCD Disp lcd_inst_wr(loc); one_chr_wr(ascii[1]); one_chr_wr(ascii[0]); } void variable_lcd_disp(void) { if (Logging_mode_flag != 1) { // Not Logging Mode Then '20**/**/** (***)' Disp RTC_variable_disp(rec_data[8], 0x82); // Years: 10 RTC_variable_disp(rec_data[7] & 0x1f, 0x85); // Months: 1-12 (Noise mask: AND 1Fh Add 0613) RTC_variable_disp(rec_data[5] & 0x3f, 0x88); // Day: 1-31 lcd_inst_wr(0x8b); if ((rec_data[6] & 0x07) == 0) {lcd_chr_wr(msg2);} // 'SUN' if ((rec_data[6] & 0x07) == 1) {lcd_chr_wr(msg3);} // 'MON' if ((rec_data[6] & 0x07) == 2) {lcd_chr_wr(msg4);} // 'TUE' if ((rec_data[6] & 0x07) == 3) {lcd_chr_wr(msg5);} // 'WED' if ((rec_data[6] & 0x07) == 4) {lcd_chr_wr(msg6);} // 'THU' if ((rec_data[6] & 0x07) == 5) {lcd_chr_wr(msg7);} // 'FRI' if ((rec_data[6] & 0x07) == 6) {lcd_chr_wr(msg8);} // 'SAT' } RTC_variable_disp(rec_data[4] & 0x3f, 0xc0); // Hour: 0-24 RTC_variable_disp(rec_data[3] & 0x7f, 0xc3); // Minutes: 0-59 RTC_variable_disp(rec_data[2] & 0x7f, 0xc6); // Seconds: 0-59 } void time_set_disp(unsigned char Vol, unsigned char loc) { // Vol: 0x00-0xff( 000-255 Disp) unsigned char i; unsigned char digit[3]; unsigned char ascii[3]; // Bin_to_pacdec digit[0] = Vol%10; digit[1] = (Vol/10)%10; // digit[2] = (Vol/100)%10; /* digit[3] = (Vol/100)/10; */ // Decimal_to_ascii for (i = 0; i <= 1; ++i) {ascii[i] = digit[i] | 0x30;} // LCD Disp lcd_inst_wr(loc); one_chr_wr(ascii[1]); one_chr_wr(ascii[0]); } void logging_disp(unsigned int Vol, unsigned char loc) { // Vol: 0x0000-0x1fff( 000-4095 Disp) unsigned char i; unsigned char digit[4]; unsigned char ascii[4]; // Bin_to_pacdec digit[0] = Vol%10; digit[1] = (Vol/10)%10; digit[2] = (Vol/100)%10; digit[3] = (Vol/100)/10; // Decimal_to_ascii for (i = 0; i <= 3; ++i) {ascii[i] = digit[i] | 0x30;} // LCD Disp lcd_inst_wr(loc); one_chr_wr(ascii[3]); one_chr_wr(ascii[2]); one_chr_wr(ascii[1]); one_chr_wr(ascii[0]); } unsigned char bin_to_bcd(unsigned char Vol) { return(Vol + 6 * (Vol/10)); } //------------------------------------------------------------------------------ // I2C Sub routine void OpenI2C(unsigned int config1, unsigned int config2) { I2CBRG = config2; I2CCON = config1; } void IdleI2C(void) { // Wait until I2C Bus is Inactive while(I2CCONbits.SEN || I2CCONbits.PEN || I2CCONbits.RCEN || I2CCONbits.ACKEN || I2CSTATbits.TRSTAT); } void i2c_write(unsigned char data) { I2CTRN = data; } unsigned char i2c_read(void) { I2CCONbits.RCEN = 1; // Valid I2C Rec Mode while(I2CCONbits.RCEN); // 8th fall SCL Wait RCEN Reset I2CSTATbits.I2COV = 0; // 8th fall SCL I2CRSR->I2CRCV Then // Set I2COV(Rx Overflow) reason soft reset return(I2CRCV); // Return I2C_RX_Buffer } void receive_ack(void) { while(I2CSTATbits.TBF) {;} // Wait TBF'0':TxBuffer Enpty while(I2CSTATbits.ACKSTAT) {;} // Wait ACKSTAT'0':A Response ACK } void NotAckI2C(void) { I2CCONbits.ACKDT = 1; // Specify NACK Tx I2CCONbits.ACKEN = 1; // Master is Response Sq } void AckI2C(void) { I2CCONbits.ACKDT = 0; // Specify ACK Tx I2CCONbits.ACKEN = 1; // Master is Response Sq } //------------------------------------------------------------------------------------ void i2c_write_sr(unsigned char start_adrs, unsigned char end_adrs) { unsigned char i; // START Bus Event IdleI2C(); I2CCONbits.SEN = 1; // Set SENbit START Bus Event // Send Slave Address + Writebit while(I2CCONbits.SEN); // Wait SENbit Clear i2c_write(RTC8564_SLVADRS_WR); // Receive ACK From RTC8564 receive_ack(); // Send Write Top Address IdleI2C(); i2c_write(start_adrs); // Receive ACK From RTC8564 receive_ack(); // Send RTC_REG Write Data (Write Address Auto Incriment) for (i = start_adrs; i != end_adrs + 1; ++i) { IdleI2C(); i2c_write(rtc_write_data_tbl[i]); // Receive ACK From RTC8564 receive_ack(); } // Stop Bus Event IdleI2C(); I2CCONbits.PEN = 1; Delay200usXLCD(); // Delay for 200uS (needs > 1.3uS next start) } void i2c_read_sr(unsigned char start_adrs, unsigned char end_adrs) { unsigned char i; // START Bus Event IdleI2C(); I2CCONbits.SEN = 1; // Set SENbit START Bus Event // Send Slave Address + Writebit while(I2CCONbits.SEN); // Wait SENbit Clear i2c_write(RTC8564_SLVADRS_WR); // Receive ACK From RTC8564 receive_ack(); // Send Read Start Address IdleI2C(); i2c_write(start_adrs); // Receive ACK From RTC8564 receive_ack(); // RESTART Bus Event IdleI2C(); I2CCONbits.RSEN = 1; // Set RSENbit RESTART Bus Event // Send Slave Address + Readbit while(I2CCONbits.RSEN); // Wait RSENbit Clear i2c_write(RTC8564_SLVADRS_RD); // Receive ACK From RTC8564 receive_ack(); // Receive RTC_REG Read Data (Read Address Auto Incriment) for (i = start_adrs; i != end_adrs + 1; ++i) { IdleI2C(); rec_data[i] = i2c_read(); // Send ACK From PIC if (i != end_adrs) { // Add 0615 IdleI2C(); AckI2C(); } } // Send NACK From PIC: End of Rx IdleI2C(); NotAckI2C(); // Stop Bus Event IdleI2C(); I2CCONbits.PEN = 1; Delay200usXLCD(); // Delay for 200uS (needs > 1.3uS next start) } //--------------------------------------------------------------------------------------------- void i2c_eeprom_write_sr(unsigned int start_adrs, unsigned char len) { // start_adrs: 0x0000min - 0x7fffmax (EEPROM: 32768Bytes) unsigned char low_temp; unsigned char high_temp; low_temp = (char)(start_adrs & 0x00ff); high_temp = (char)((start_adrs >> 8) & 0x00ff); unsigned char i; // START Bus Event IdleI2C(); I2CCONbits.SEN = 1; // Set SENbit START Bus Event // Send Slave Address + Writebit while(I2CCONbits.SEN); // Wait SENbit Clear i2c_write(EEPROM_SLVADRS_WR); // Receive ACK From EEPROM receive_ack(); // Send Write Top High Address IdleI2C(); Waitx1us(40); i2c_write(high_temp); // Receive ACK From EEPROM receive_ack(); // Send Write Top Low Address IdleI2C(); Waitx1us(40); i2c_write(low_temp); // Receive ACK From EEPROM receive_ack(); // Send EEPROM Write Data (Write Address Auto Incriment) for (i = 0; i != len; ++i) { IdleI2C(); Waitx1us(40); // when Fcy=29.48M i2c_write(logger_write_data[i]); // Receive ACK From EEPROM receive_ack(); } // Stop Bus Event IdleI2C(); I2CCONbits.PEN = 1; // Waitx1ms(10); // Wait 10ms Waitx1ms(5); } void i2c_eeprom_read_sr(unsigned int start_adrs, unsigned char len) { unsigned char low_temp; unsigned char high_temp; low_temp = (char)(start_adrs & 0x00ff); high_temp = (char)((start_adrs >> 8) & 0x00ff); unsigned char i; // START Bus Event IdleI2C(); I2CCONbits.SEN = 1; // Set SENbit START Bus Event // Send Slave Address + Writebit while(I2CCONbits.SEN); // Wait SENbit Clear i2c_write(EEPROM_SLVADRS_WR); // Receive ACK From EEPROM receive_ack(); // Send Read Start High Address IdleI2C(); Waitx1us(40); i2c_write(high_temp); // Receive ACK From EEPROM receive_ack(); // Send Read Top Low Address IdleI2C(); Waitx1us(40); // when Fcy=29.48M i2c_write(low_temp); // Receive ACK From EEPROM receive_ack(); // RESTART Bus Event IdleI2C(); Waitx1us(40); I2CCONbits.RSEN = 1; // Set RSENbit RESTART Bus Event // Send Slave Address + Readbit while(I2CCONbits.RSEN); // Wait RSENbit Clear i2c_write(EEPROM_SLVADRS_RD); // Receive ACK From EEPROM receive_ack(); // Receive EEPROM Read Data (Read Address Auto Incriment) for (i = 0; i != len; ++i) { IdleI2C(); Waitx1us(40); logger_read_data[i] = i2c_read(); // Send ACK From PIC if (i != len - 1) { IdleI2C(); AckI2C(); } } // Send NACK From PIC: End of Rx IdleI2C(); NotAckI2C(); // Stop Bus Event IdleI2C(); I2CCONbits.PEN = 1; } void forward_rec_data(void) { // RTC Data logger_write_data[0] = (((rec_data[4] & 0x3f) >> 4) & 0x0f) | 0x30; // Hour logger_write_data[1] = ((rec_data[4] & 0x3f) & 0x0f) | 0x30; // logger_write_data[3] = (((rec_data[3] & 0x7f) >> 4) & 0x0f) | 0x30; // Minute logger_write_data[4] = ((rec_data[3] & 0x7f) & 0x0f) | 0x30; // logger_write_data[6] = (((rec_data[2] & 0x7f) >> 4) & 0x0f) | 0x30; // Seconds logger_write_data[7] = ((rec_data[2] & 0x7f) & 0x0f) | 0x30; // // Temperature_Data logger_write_data[9] = digit[2] | 0x30; // Temperature logger_write_data[10] = digit[1] | 0x30; // logger_write_data[12] = digit[0] | 0x30; // } void logging_rec_sr(void) { forward_rec_data(); i2c_eeprom_write_sr(start_tmp,16); // Page Write: 64Bytes(16*4)@1Page start_tmp = start_tmp+16; logging_disp(start_tmp,0x84); if ((start_tmp == sample_set) || (sw3_on_flag == 1)) { logger_write_data[0] = EOF; i2c_eeprom_write_sr(start_tmp,1); PORTBbits.RB9=1; // Red LED OFF start_tmp = 0; sw1_on_flag = 0; sw3_on_flag = 0; // sw1_m2 = 0; // sw3_m2 = 0; } } //--------------------------------------------------------------------------------------------- void time_adjust_mode(void) { unsigned char blink_location_tbl[] = { 0x83, // Year 0x86, // Months 0x89, // Days 0x8d, // Weekdays 0xc1, // Hour 0xc4, // Minute 0xc7 // Seconds }; // unsigned char i; unsigned char time_set_end; unsigned char sw1_count; unsigned char year_set,months_set,days_set,weekdays_set; unsigned char hour_set,minute_set,seconds_set; // i = 0; sw1_count = 0; year_set=months_set=days_set=weekdays_set=0; hour_set=minute_set=seconds_set=0; const_lcd_disp(); // '20xx/ / ...etc // initial time_set_mode all zero LCD Disp time_set_disp(year_set,0x82); time_set_disp(months_set,0x85); time_set_disp(days_set,0x88); time_set_disp(weekdays_set,0x8c); time_set_disp(hour_set,0xc0); time_set_disp(minute_set,0xc3); time_set_disp(seconds_set,0xc6); // Read SW Loop while(time_set_end != 1) { //Read SW sw1_m0 = PORTBbits.RB0; //New SW1 Data sw1_m2 = sw1_m1^(sw1_m0 & sw1_m1); //Neg_Edge Sence SW1 sw1_m1 = sw1_m0; //Chenge New Data to Old Data m1 sw2_m0 = PORTBbits.RB8; //New SW2 Data sw2_m2 = sw2_m1^(sw2_m0 & sw2_m1); //Neg_Edge Sence SW2 sw2_m1 = sw2_m0; //Chenge New Data to Old Data m1 sw3_m0 = PORTDbits.RD9; //New SW2 Data sw3_m2 = sw3_m1^(sw3_m0 | sw3_m1); //Pos_Edge Sence SW3 sw3_m1 = sw3_m0; //Chenge New Data to Old Data m1 if (sw1_m2 == 1){ // an Item Select SW ON ? // sw1_m2 = 0; ++sw1_count; if (sw1_count == 8) {sw1_count = 1;} if (sw1_count <= 7) { lcd_inst_wr(blink_location_tbl[sw1_count-1]); // Set CURSOR Location lcd_inst_wr(DISP_ON_CURSOR_ON_BLINK_OFF); // LCD CURSOR ON } } if (sw2_m2 == 1 && sw1_count >= 1){ // Time Set SW ON ? // sw2_m2 = 0; lcd_inst_wr(DISP_ON_CURSOR_OFF_BLINK_OFF); // LCD CURSOR OFF if (sw1_count == 1) { ++year_set; if (year_set >= 100) {year_set = 0;} time_set_disp(year_set,0x82); } if (sw1_count == 2) { ++months_set; if (months_set >= 13) {months_set = 1;} time_set_disp(months_set,0x85); } if (sw1_count == 3) { ++days_set; if (days_set >= 32) {days_set = 1;} time_set_disp(days_set,0x88); } if (sw1_count == 4) { ++weekdays_set; if (weekdays_set >= 7) {weekdays_set = 0;} time_set_disp(weekdays_set,0x8c); } if (sw1_count == 5) { ++hour_set; if (hour_set >= 25) {hour_set = 0;} time_set_disp(hour_set,0xc0); } if (sw1_count == 6) { ++minute_set; if (minute_set >= 60) {minute_set = 0;} time_set_disp(minute_set,0xc3); } if (sw1_count == 7) { ++seconds_set; if (seconds_set >= 60) {seconds_set = 0;} time_set_disp(seconds_set,0xc6); } } if (sw3_m2 == 1){ // Set Enter SW ON ? // sw3_m2 = 0; rtc_write_data_tbl[8] = bin_to_bcd(year_set); rtc_write_data_tbl[7] = bin_to_bcd(months_set); rtc_write_data_tbl[6] = bin_to_bcd(weekdays_set); rtc_write_data_tbl[5] = bin_to_bcd(days_set); rtc_write_data_tbl[4] = bin_to_bcd(hour_set); rtc_write_data_tbl[3] = bin_to_bcd(minute_set); rtc_write_data_tbl[2] = bin_to_bcd(seconds_set); // Initialize Slave RTC8564 i2c_write_sr(0,15); // Write RTC_Reg 16bytes: adrs = 0 to 15 -> Time Stop // CLKOUT = 1Hz time_set_end = 1; lcd_inst_wr(DISP_CLEAR_CURSOR_HOME); const_lcd_disp(); // '20xx/ / ...etc } Waitx1ms(1); // wait 1mS } } //--------------------------------------------------------------------------------------------- void logger_set_mode(void) { unsigned char blink_location_tbl[] = { 0x8a, // INTERVAL 0xca // SAMPLE }; // unsigned char i; unsigned char logger_set_end; unsigned char sw1_count; // i = 0; sw1_count = 0; // interval_set=sample_set=0; const_lcd_disp_logger(); // Logger set Vol Read From EEPROM i2c_eeprom_read_sr(32766,2); // rec_data[0]:Interval, [1]:sample interval_set = logger_read_data[0]; sample_set = logger_read_data[1]; // initial logger_set_mode LCD Disp time_set_disp(interval_set,0x89); // time_set_disp(sample_set,0xc9); // Read SW Loop while(logger_set_end != 1) { //Read SW sw1_m0 = PORTBbits.RB0; //New SW1 Data sw1_m2 = sw1_m1^(sw1_m0 & sw1_m1); //Neg_Edge Sence SW1 sw1_m1 = sw1_m0; //Chenge New Data to Old Data m1 sw2_m0 = PORTBbits.RB8; //New SW2 Data sw2_m2 = sw2_m1^(sw2_m0 & sw2_m1); //Neg_Edge Sence SW2 sw2_m1 = sw2_m0; //Chenge New Data to Old Data m1 sw3_m0 = PORTDbits.RD9; //New SW2 Data sw3_m2 = sw3_m1^(sw3_m0 | sw3_m1); //Pos_Edge Sence SW3 sw3_m1 = sw3_m0; //Chenge New Data to Old Data m1 if (sw1_m2 == 1){ // an Item Select SW ON ? // sw1_m2 = 0; ++sw1_count; if (sw1_count == 3) {sw1_count = 1;} if (sw1_count <= 2) { lcd_inst_wr(blink_location_tbl[sw1_count-1]); // Set CURSOR Location lcd_inst_wr(DISP_ON_CURSOR_ON_BLINK_OFF); // LCD CURSOR ON } } if (sw2_m2 == 1 && sw1_count >= 1){ // Logger Set SW ON ? // sw2_m2 = 0; lcd_inst_wr(DISP_ON_CURSOR_OFF_BLINK_OFF); // LCD CURSOR OFF if (sw1_count == 1) { ++interval_set; if (interval_set >= 3) {interval_set = 0;} time_set_disp(interval_set,0x89); } if (sw1_count == 2) { ++sample_set; if (sample_set >= 6) {sample_set = 0;} time_set_disp(sample_set,0xc9); } } if (sw3_m2 == 1){ // Set Enter SW ON ? // sw3_m2 = 0; // Save to EEPROM logger_write_data[0] = interval_set; logger_write_data[1] = sample_set; i2c_eeprom_write_sr(32766,2); if (sample_set == 0) sample_set = 256; if (sample_set == 1) sample_set = 512; if (sample_set == 2) sample_set = 1024; if (sample_set == 3) sample_set = 2048; if (sample_set == 4) sample_set = 4096; if (sample_set == 5) sample_set = 8192; logger_set_end = 1; lcd_inst_wr(DISP_CLEAR_CURSOR_HOME); const_lcd_disp(); // '20xx/ / ...etc } Waitx1ms(1); // wait 1mS } } // Temperature Subrutin void bin_to_pacdec(unsigned int Adc_Data) { digit[0] = Adc_Data%10; digit[1] = (Adc_Data/10)%10; digit[2] = (Adc_Data/100)%10; // digit[3] = (Adc_Data/100)/10;; } //------------------------------------------------------------- void lcd_temperature_disp(void) { // digit[2] disp lcd_inst_wr(0xca); one_chr_wr(digit[2] | 0x30); // digit[1] disp one_chr_wr(digit[1] | 0x30); // '.' decimal point disp one_chr_wr(0x2e); // '.' decimal point disp // digit[0] disp one_chr_wr(digit[0] | 0x30); // unit disp:'[Degrees C]' one_chr_wr(0xdf); one_chr_wr(0x43); } //----------------------------------------------------------------- // RS232C Subrutin void tx_uart_sr(void) { unsigned char i; /* Transmit UART_Data [0]-[15]LF */ for (i = 0; i != 16; ++i) { WriteUART1(logger_read_data[i]); while(BusyUART1()); } } /* void rx_uart_sr(void) { unsigned char i; // Recive UART_Data to LF i = 0; if (U1STAbits.URXDA == 1) { rx_uart_data[i] = ReadUART1(); while(rx_uart_data[i] != LF) { ++i; while(U1STAbits.URXDA==0); // Wait RX BUF Enpty // URXDA bit=1 Then Valid Data Possible Read rx_uart_data[i] = ReadUART1(); } } } */ // INT0 External Interrupt T=1Sec void __attribute__((__interrupt__, __shadow__, no_auto_psv)) _AltINT0Interrupt(void) { i2c_read_sr(2,8); // Read SecondsREG - YearsREG Add 0614 variable_lcd_disp(); // '2010/xx/xx/xx(xxx) xx:xx:xx // Temperature ADC Read while(!IFS0bits.ADIF); // End of convertion ? ResultData = ReadADC12(0); // Read 12bit ADC Data // Eoc_flag = 1; Temperature = (ResultData >> 3) & 0x1ff; // Down Resolution ability 12bit-> 9bit // 4096 -> 512 // LCD Temperature Disp : 00.0 - 51.1[Degrees Centigrade] // Ain: 0.01V@0.1[Degrees Centigrade] // Temperature: 1-> 00.1[Degrees Centigrade] // Temperature: 511-> 51.1[Degrees Centigrade] // Ain = (5.06 / 512) * Temperature; // 0.00988V * 1LSB -> 0.01V * 1LSB bin_to_pacdec(Temperature); lcd_temperature_disp(); // Loging Interval Count sec_flag = 1; ++Sec; if ((Sec >= 60) && (interval_set == 1)) { Sec = 0; minute_flag = 1; } if ((Sec >= 3600) && (interval_set == 2)) { Sec = 0; hour_flag = 1; } //Reset INT0 interrupt flag IFS0bits.INT0IF = 0; } //------------------------------i2c_rtc_add_adjust------------------------------------------------------------ // Main routine int main(void) { // unsigned char i; // TRISCbits.TRISC13 = 1; // RC13 is LED1,2 input(Hi-Z LED OFF) used debug TRISBbits.TRISB9 = 0; // RB9 is LED output PORTBbits.RB9 = 1; // Red LED OFF //Switch Port Set TRISBbits.TRISB0 =1; // RB0 is SW1 input TRISBbits.TRISB8 =1; // RB8 is SW2 input TRISDbits.TRISD9 =1; // RD9 is SW3 input // i = 0; sw1_m0=sw1_m1=sw1_m2=sw2_m0=sw2_m1=sw2_m2=sw3_m0=sw3_m1=sw3_m2 = 0; Sec = 0; sw1_on_flag = sw2_on_flag = sw3_on_flag = 0; start_tmp = 0; sec_flag = minute_flag = hour_flag = 0; Logging_mode_flag = 0; // for (i=0; i!=3;++i) rx_uart_data[i]=0; // Initialize LCD lcd_init(); lcd_inst_wr(DISP_ON_CURSOR_OFF_BLINK_OFF); // Initialize Master PIC I2C Port OpenI2C(I2Ccongig1, I2Ccongig2); // I2C_ON + I2C_7BIT_ADD + I2C_STR_EN Others Disable // Fscl = 100kHz // Confirmation UART1 Module OFF CloseUART1(); // Set INT UART1 (Desable Interrupt) ConfigIntUART1( UART_RX_INT_DIS & UART_TX_INT_DIS); // Initialize UART1 _U1BRG= 191; // BaudRate=Fcy/(16(U1BRG+1))= 9596bps(9600bps) // alternate I/O (U1ATX/U1ARX), N81 _U1MODE= UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_EN_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT; _U1STA= UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL & UART_TX_ENABLE & UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR; // Open UART1 OpenUART1(_U1MODE, _U1STA, _U1BRG); // Confirm to ADC Off ADCON1bits.ADON=0; // Initialize ADC _ADCHS= ADC_CH0_POS_SAMPLEA_AN2 & ADC_CH0_NEG_SAMPLEA_NVREF; // A-D channel-2 select SetChanADC12(_ADCHS); // ConfigIntADC12(ADC_INT_DISABLE); _ADCON1=ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & // ADC_CLK_AUTO & // ADC_CLK_TMR & // ADC Clock Syncronas Timer ADC_CLK_INT0 & // ADC Clock Syncronas INT0 ADC_AUTO_SAMPLING_ON & // Auto sampling on ADC_SAMP_OFF; _ADCON2=ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_1 & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF; // Tad={Tcy(ADCS+1)}/2>334ns, Then ADCS>18.7, Tad=10*Tcy _ADCON3=ADC_SAMPLE_TIME_1 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_10Tcy; _ADPCFG=ENABLE_AN2_ANA; // A-D channel-2 analog input _ADCSSL=SCAN_NONE; OpenADC12(_ADCON1, _ADCON2, _ADCON3, _ADPCFG, _ADCSSL); // Use Alternate Interrupt Vector Table INTCON2bits.ALTIVT=1; // INT0 pin to interupt on Rise Edge Trig INTCON2bits.INT0EP=0; Waitx1ms(1000); // Wait 1Sec // SW1+SW2 OFF and Power ON Then Normal Mode Batt Backup if (_RB0 == 1 && _RB8 == 1) { i2c_write_sr(0,1); // Cont1,2Reg write i2c_write_sr(9,15); // ALM,TIMInt,CLKOUTReg write const_lcd_disp(); // '20xx/ / ...etc // Logger set Vol Read From EEPROM i2c_eeprom_read_sr(32766,2); // rec_data[0]:Interval, [1]:sample interval_set = logger_read_data[0]; sample_set = logger_read_data[1]; if (sample_set == 0) sample_set = 256; if (sample_set == 1) sample_set = 512; if (sample_set == 2) sample_set = 1024; if (sample_set == 3) sample_set = 2048; if (sample_set == 4) sample_set = 4096; if (sample_set == 5) sample_set = 8192; } // SW1 ON and Power ON Then Logger Set Mode if (_RB0 == 0) {logger_set_mode();} // SW2 ON and Power ON Then Time Adjust Mode if (_RB8 == 0) {time_adjust_mode();} // RTC Time Start-> RTC_CLOCKOUT ON rtc_write_data_tbl[0] = 0x00; i2c_write_sr(0,0); // Enable Interrupt IEC0bits.INT0IE = 1; // Enable INT0 Interrupt Service Routine DISICNT = 0x0000; // Enable Interrupt while(1) { //Read SW sw1_m0 = PORTBbits.RB0; //New SW1 Data sw1_m2 = sw1_m1^(sw1_m0 & sw1_m1); //Neg_Edge Sence SW1 sw1_m1 = sw1_m0; //Chenge New Data to Old Data m1 sw2_m0 = PORTBbits.RB8; //New SW2 Data sw2_m2 = sw2_m1^(sw2_m0 & sw2_m1); //Neg_Edge Sence SW2 sw2_m1 = sw2_m0; //Chenge New Data to Old Data m1 sw3_m0 = PORTDbits.RD9; //New SW2 Data sw3_m2 = sw3_m1^(sw3_m0 | sw3_m1); //Pos_Edge Sence SW3 sw3_m1 = sw3_m0; //Chenge New Data to Old Data m1 if (sw1_m2 == 1) { // REC Mode /* if (interval_set != 0) { IEC0bits.INT0IE = 0; // Desable INT0 Interrupt Service Routine DISICNT = 0x0001; // Dsable Interrupt } */ IEC0bits.INT0IE = 0; // Desable INT0 Interrupt Service Routine DISICNT = 0x0001; // Dsable Interrupt PORTBbits.RB9 = 0; // Red LED ON start_tmp = 0; Logging_mode_flag = 1; line_clear(0x80,16); lcd_inst_wr(0x80); lcd_chr_wr(msg11); // 'REC:0000/' const disp logging_disp(sample_set,0x8a); if (interval_set == 1) {Sec = 60;} if (interval_set == 2) {Sec = 3600;} sw1_on_flag = 1; } // REC Mode if (interval_set == 0) { // Interval is 1Sec if (sw1_on_flag == 1) { IEC0bits.INT0IE = 1; // Enable INT0 Interrupt Service Routine DISICNT = 0x0000; // Enable Interrupt if (sec_flag == 1) { sec_flag = 0; logging_rec_sr(); } } } if (interval_set == 1) { // Interval is 1Minute if (sw1_on_flag == 1) { IEC0bits.INT0IE = 1; // Enable INT0 Interrupt Service Routine DISICNT = 0x0000; // Enable Interrupt if (minute_flag == 1) { minute_flag = 0; logging_rec_sr(); } } } if (interval_set == 2) { // Interval is 1Hour if (sw1_on_flag == 1) { IEC0bits.INT0IE = 1; // Enable INT0 Interrupt Service Routine DISICNT = 0x0000; // Enable Interrupt if (hour_flag == 1) { hour_flag = 0; logging_rec_sr(); } } } // PLAY Mode if (sw2_m2 == 1) { // Desable Interrupt IEC0bits.INT0IE = 0; // Desable INT0 Interrupt Service Routine DISICNT = 0x0001; // Dsable Interrupt start_tmp = 0; Logging_mode_flag = 1; line_clear(0x80,16); lcd_inst_wr(0x80); lcd_chr_wr(msg12); // 'PLAY:0000/' const disp logging_disp(sample_set,0x8a); i2c_eeprom_read_sr(start_tmp,16); while(logger_read_data[0] != EOF) { tx_uart_sr(); start_tmp = start_tmp+16; logging_disp(start_tmp,0x85); i2c_eeprom_read_sr(start_tmp,16); } // EOF start_tmp = 0; // Enable Interrupt IEC0bits.INT0IE = 1; // Enable INT0 Interrupt Service Routine DISICNT = 0x0000; // Enable Interrupt } if (sw3_m2 == 1) { // STOP Mode // PORTCbits.RC13 = 1; // Red LED ON sw3_on_flag = 1; } Waitx1ms(1); /* // Rx Team Command while(U1STAbits.URXDA==0); // Wait RX BUF Enpty // URXDA bit=1 Then Valid Data Possible Read rx_uart_data[0] = ReadUART1(); // READ 1byte */ } }