/******************************************************************** * PIC32MX_RTC8564_Test_1.c * PIC32MX内蔵の、RTCCを使わず、I2C_RTCの、RTC8564を外付して * 時計動作を確認する。 * Test_1では、タイムアジャストとバックアップは省略した。 * * 実験ハードは、PIC32MXトレーニング基板を使用 * * Graphic LCD(Monochrome): SG12864A * ファイルシステム:MMD File System→ FAT16(FAT32互換) * * Condition: * 8MHz External X'tal Oscillator, 20x PLL (8MHzx20= 160MHz) * Fcy=160MHz/2=80MHz, Tcy=12.5ns * * CPU: PIC32MX340F256H * * N.Ishii 2014.10.29 *********************************************************************/ #include /* PIC32 peripheral library */ #include "glcd_lib32k.h" // コンフィギュレーション設定 // 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 // 液晶表示器メッセージ定数 char MsgClock_1[] = "'xx/mm/dd"; char MsgClock_2[] = "hh:mm:ss"; //--------------------------------------------------------------------------------------------------- // 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) short i; /// Function Prottypes void RtcDisp(void); void WriteRTC(unsigned char start_adrs, unsigned char end_adrs); void ReadRTC(unsigned char start_adrs, unsigned char end_adrs); /*************************************************************** * Function Main * トレーニング基板の、単chオシロハードを、そのまま流用したので * 初期設定は、アナログ部を含め、そのままにした。 ****************************************************************/ int main(void) { //システム最適設定 SYSTEMConfigPerformance(80000000); mJTAGPortEnable(DEBUG_JTAGPORT_OFF); // JTAGを無効化 //I/O設定 AD1PCFG = 0xFFF8; // // GLCD制御信号レベルの初期化 LCD_E = 0; LCD_CS1 = 1; LCD_CS2 = 1; LCD_RW = 1; LCD_DI = 1; LCD_TRIS = 0x0000; // LCDデータバス(DB0-DB7)オール出力(TRISE= 0) TRISD = 0xFF17; // LCD_CS1,CS2,DI:全て出力・デバッグLED:出力・SW2-5:入力、他未使用ピンは入力設定 TRISF = 0xFFFC; // LCD_E,RW:全て出力、他未使用ピンは入力設定 TRISG = 0x028C; // SD_SDO,SCK:出力、SDI:入力・他未使用ピンは入力設定 TRISB = 0xFFDF; // RB5:SD_CS出力、RB4:SD_WE入力、RB3:SD_CD入力、RB2:AN2(トリガ入力)、RB1:AN1未使用、RB0:オシロ入力 CNPUE = 0x0060; // SD_CD(CN5),WE(CN6)のみ内部プルアップ LATDbits.LATD3 = 1; // デバッグLED消灯 /// 液晶表示器の初期化 lcd_Init(); lcd_Clear(0); lcd_Str(0, 0, "Start RTC Test"); /// I2Cの初期設定 100kbps 7bit address OpenI2C1(I2C_ON | I2C_7BIT_ADD, 398); /// RTC8564初期化 delay_ms(1000); // RTC8564内部水晶振動子が、発振するまで待つ WriteRTC(0,15); // Write RTC_Reg 16bytes: adrs = 0 to 15 -> Time Stop // RTC Time Start rtc_write_data_tbl[0] = 0x00; // コントロールレジスタ1の、bit5:STOPビット=0にして、時計動作をスタート WriteRTC(0,0); lcd_Clear(0); while(1){ RtcDisp(); } } ///----------------------------------------------------------------------------------------------------------------- /***************************************************************** * RTCレジスタを読出し、液晶に、年/月/日、時:分 * を表示する。 ******************************************************************/ void RtcDisp(void) { ReadRTC(2,8); // rec_data[*] <-- Read SecondsREG 〜 YearsREG /// RTCレジスタ値は、BCDなので、これをアスキーに変換してから、 /// それぞれの、メッセージバッファ位置に、格納後、液晶表示する。 MsgClock_1[1] = (rec_data[8] >> 4) + 0x30; // 年:01〜99 MsgClock_1[2] = (rec_data[8] & 0x0F) + 0x30; MsgClock_1[4] = ((rec_data[7] & 0x1F) >> 4) + 0x30; // 月:01〜12 ※ 読出し時、b7は、Cビット、b6-5は不定なので、0x1Fでマスクが必要 MsgClock_1[5] = (rec_data[7] & 0x0F) + 0x30; MsgClock_1[7] = ((rec_data[5] & 0x3F) >> 4) +0x30; // 日:01〜31 ※ 読出し時、b7-6は不定なので、0x3Fでマスクが必要 MsgClock_1[8] = (rec_data[5] & 0x0F) + 0x30; lcd_Str(2, 3, MsgClock_1); // 時計表示_1:上段 /// 週は、メッセージバッファを介さず、週レジスタの値に対応する、週文字を /// そのまま、液晶に出力する。 /// ※ 週レジスタ:0〜7→ 読出し時、b3-7は不定なので、0x07でマスクが必要 if((rec_data[6] & 0x07) == 0) lcd_Str(2, 12, "(SUN)"); if((rec_data[6] & 0x07) == 1) lcd_Str(2, 12, "(MON)"); if((rec_data[6] & 0x07) == 2) lcd_Str(2, 12, "(TUE)"); if((rec_data[6] & 0x07) == 3) lcd_Str(2, 12, "(WED)"); if((rec_data[6] & 0x07) == 4) lcd_Str(2, 12, "(THU)"); if((rec_data[6] & 0x07) == 5) lcd_Str(2, 12, "(FRI)"); if((rec_data[6] & 0x07) == 6) lcd_Str(2, 12, "(SAT)"); MsgClock_2[0] = ((rec_data[4] & 0x3F) >> 4) + 0x30; // 時:00〜23 ※ 読出し時、b7-6は不定なので、0x3Fでマスクが必要 MsgClock_2[1] = (rec_data[4] & 0x0F) + 0x30; MsgClock_2[3] = ((rec_data[3] & 0x7F) >> 4) + 0x30; // 分:00〜59 ※ 読出し時、b7は不定なので、0x7Fでマスクが必要 MsgClock_2[4] = (rec_data[3] & 0x0F) + 0x30; MsgClock_2[6] = ((rec_data[2] & 0x7F) >> 4) + 0x30; // 秒:00〜59 ※ 読出し時、b7は、VLビットなので、0x7Fでマスクが必要 MsgClock_2[7] = (rec_data[2] & 0x0F) + 0x30; lcd_Str(4, 4, MsgClock_2); // 時計表示_2:下段 } /********************************************************************* * 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) { unsigned 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) }