Maruduinoで時計を作る。リアルタイムクロック(RTC MRX-8564)の利用。 [アプリケーション]
組み立て編はこちらです。
http://maruduino.blog.so-net.ne.jp/2010-08-07
組み立てが完了したので、簡単な?スケッチを記述してみました。ご参考になれば幸いです。
Wireライブラリを使って通信してみたのですが、あまり安定しない、読み出しがおかしい?などがあったので、ソフトウエアでI2C通信を実現しています。
Arduinoは勿論マスターモードとしています。
操作方法を書いておきます。
時刻設定モード:
SW1とSW3の同時押しで時刻設定モードに入ります。
LCDの上段には変更する日付または時刻が表示され、下段には変更位置を示すポインターが表示されています。
SW2で数字を増やし、SW3で数字を減らしますが、上限、下限まで達すると循環します。
数字が確定したらSW4で次の項目に移動します。最後の項目である秒の変更が完了してSW4を押すと、その時点で時刻設定が確定します。
※SW1を押すと入力を取りやめ、通常の時刻表示モードに戻ります。
日付や時刻の整合性はあまりチェックしていませんので、注意してください。
アラーム設定モード:
SW1とSW2の同時押しでアラーム設定モードに入ります。
時刻設定モードと同様上段には時刻、下段にはポインターが表示されます。
その他操作も時刻設定モードと同じです。
時刻の整合性はあまりチェックしていませんので、注意してください。
※アラームを鳴らしたくない時は24:00に設定してください。
アラーム鳴動解除:
アラーム鳴動中にSW1を押す事で鳴動を解除できます。
バッテリーバックアップがされているので、電源を落としても時刻の更新やアラーム時刻の保持は行われています。
こうやってプロトタイピングして、もっとコンパクトであったり、電池で駆動できるものを作って日々の生活に役立てるとか良いですよね。
実際、Arduinoではありませんが、別のOne Chipマイコンで作った自作の目覚まし時計に日々起こされていますヨ。
以下にスケッチを記述しておきます。
※関数time_adjust_mode、Alarm_set_modeにアトミックな処理を追加 2010/08/07 18:35
http://maruduino.blog.so-net.ne.jp/2010-08-07
組み立てが完了したので、簡単な?スケッチを記述してみました。ご参考になれば幸いです。
Wireライブラリを使って通信してみたのですが、あまり安定しない、読み出しがおかしい?などがあったので、ソフトウエアでI2C通信を実現しています。
Arduinoは勿論マスターモードとしています。
操作方法を書いておきます。
時刻設定モード:
SW1とSW3の同時押しで時刻設定モードに入ります。
LCDの上段には変更する日付または時刻が表示され、下段には変更位置を示すポインターが表示されています。
SW2で数字を増やし、SW3で数字を減らしますが、上限、下限まで達すると循環します。
数字が確定したらSW4で次の項目に移動します。最後の項目である秒の変更が完了してSW4を押すと、その時点で時刻設定が確定します。
※SW1を押すと入力を取りやめ、通常の時刻表示モードに戻ります。
日付や時刻の整合性はあまりチェックしていませんので、注意してください。
アラーム設定モード:
SW1とSW2の同時押しでアラーム設定モードに入ります。
時刻設定モードと同様上段には時刻、下段にはポインターが表示されます。
その他操作も時刻設定モードと同じです。
時刻の整合性はあまりチェックしていませんので、注意してください。
※アラームを鳴らしたくない時は24:00に設定してください。
アラーム鳴動解除:
アラーム鳴動中にSW1を押す事で鳴動を解除できます。
バッテリーバックアップがされているので、電源を落としても時刻の更新やアラーム時刻の保持は行われています。
こうやってプロトタイピングして、もっとコンパクトであったり、電池で駆動できるものを作って日々の生活に役立てるとか良いですよね。
実際、Arduinoではありませんが、別のOne Chipマイコンで作った自作の目覚まし時計に日々起こされていますヨ。
以下にスケッチを記述しておきます。
※関数time_adjust_mode、Alarm_set_modeにアトミックな処理を追加 2010/08/07 18:35
/***********************************************************************/ /* LCD clock */ /* I2C bus control RTC()RTC8564 use */ /* designed by hamayan */ /* Copyright(C) hamayan */ /***********************************************************************/ #define _SOFT_I2C_ #if defined( _SOFT_I2C_ ) #else #include <Wire.h> #endif #include <string.h> #include <LiquidCrystal.h> #include <avr/io.h> /*************************************************************************/ /* defines */ /*************************************************************************/ #define DI13 13 #define DI12 12 #define DI11 11 #define DI10 10 #define DI9 9 #define DI8 8 #define DI7 7 #define DI6 6 #define DI5 5 #define DI4 4 #define DI3 3 #define DI2 2 #define DI1 1 #define DI0 0 #define AN0 14 #define AN1 15 #define AN2 16 #define AN3 17 #define AN4 18 #define AN5 19 #define SW1 AN3 #define SW2 AN2 #define SW3 AN1 #define SW4 AN0 #define SCL_BIT 0b00100000 /*PC5=SCL*/ #define SDA_BIT 0b00010000 /*PC4=SDA*/ #define SCL_IS_HIGH PORTC |= SCL_BIT /*about 120ns swittching*/ #define SCL_IS_LOW PORTC &= ~SCL_BIT /*about 120ns swittching*/ #define SDA_IS_HIGH PORTC |= SDA_BIT /*about 120ns swittching*/ #define SDA_IS_LOW PORTC &= ~SDA_BIT /*about 120ns swittching*/ #define SDA_OUTPUT DDRC |= SDA_BIT #define SDA_INPUT DDRC &= ~SDA_BIT #define SCL_OUTPUT DDRC |= SCL_BIT #define ACK 0 /*ACK Bit*/ #define NACK 1 /*NACK Bit*/ #define RTC8564_CTRL1 0x00 #define RTC8564_CTRL2 0x01 #define RTC8564_SEC 0x02 #define RTC8564_MIN 0x03 #define RTC8564_HOUR 0x04 #define RTC8564_DAY 0x05 #define RTC8564_WEEK 0x06 #define RTC8564_MONTH 0x07 #define RTC8564_YEAR 0x08 #define RTC8564_MIN_ALM 0x09 #define RTC8564_HOUR_ALM 0x0A #define RTC8564_DAY_ALM 0x0B #define RTC8564_WEEK_ALM 0x0C #define RTC8564_CLK_FREQ 0x0D #define RTC8564_TIM_CTRL 0x0E #define RTC8564_TIMER 0x0F #if defined( _SOFT_I2C_ ) #define RTC_BASE_ADDR (0xa2) #else #define RTC_BASE_ADDR (0xa2 >> 1) #endif /*************************************************************************/ /* global parameter */ /*************************************************************************/ enum RTC8564Str {SECONDS,MINUTES,HOURS,DAYS,WEEKDAYS,MONTHS,YEARS}; /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ char date[ 20 ]; /**/ char alarm_set_time[] = "00:00"; unsigned long sectim; unsigned long lasttim; unsigned char switches[3]; boolean clock_disp = false; const char date_limit[][2] = /*offset = 2*/ { {'0','9'}, /*year 10*/ {'0','9'}, /*year 1*/ {'/','/'}, /**/ {'0','1'}, /*month 10*/ {'0','9'}, /*month 1*/ {'/','/'}, /**/ {'0','3'}, /*day 10*/ {'0','9'}, /*day 1*/ }; const char time_limit[][2] = /*offset = 0*/ { {'0','2'}, /*hour 10*/ {'0','9'}, /*hour 1*/ {':',':'}, /**/ {'0','5'}, /*monite 10*/ {'0','9'}, /*monite 1*/ {':',':'}, /**/ {'0','5'}, /*second 10*/ {'0','9'}, /*second 1*/ }; LiquidCrystal lcd(DI8, DI9, DI4, DI5, DI6, DI7); /*************************************************************************/ /* prototype */ /*************************************************************************/ static void clk100( void ); static void I2C_Terminate( void ); static void StartCondition( void ); static void StopCondition( void ); static int RcvAck( void ); static void ResAck( int ack ); static void BitWrite( int data ); static int BitRead( void ); static int ByteWrite( int data ); static int ByteRead( int ack ); static void date_print( const char *src, int x, int y ); static void time_print( const char *src, int x, int y ); static void ConvertFromRTC2DateTime( void ); void I2C_Init( void ); int I2C_Block_Write( int addr, const char *data, int size ); int I2C_Block_Read( int addr, char *data, int size ); int I2C_Write( int addr, unsigned char data ); int I2C_Read( int addr, unsigned char *data ); int InitRTC8564( int force ); unsigned char *DateStr2RTC8564Str( unsigned char *dest, const char *source ); char *RTC8564Str2DateStr( char *dest, const unsigned char source[] ); int I2CRTC8564_Write( unsigned char addr, char data ); int I2CRTC8564_Read( unsigned char addr, char *buff ); int I2CRTC8564_Blk_Read( unsigned char addr, char *buff, int size ); int I2CRTC8564_Blk_Write( unsigned char addr, const char *data, int size ); int RTC8564_CalenderSet( const char *date_time ); #define CalenderRead(buf) I2CRTC8564_Blk_Read(RTC8564_SEC, buf, 7) /*************************************************************************/ /* digital2 external int handler */ /*************************************************************************/ static void di2_int_hdr( void ) { sectim++; ConvertFromRTC2DateTime(); /*update clock*/ if( clock_disp == true ) { date_print(date,0,0); time_print(date,2,1); } } /*************************************************************************/ /* Switch down detection */ /*************************************************************************/ static unsigned char detect_sw_down( unsigned char *sw ) { unsigned char temp = PINC & 0x0f; sw[0] = sw[1]; sw[1] = sw[2]; sw[2] = temp ^ 0x0f; return sw[0] & sw[1] & temp; } /*************************************************************************/ /* RTC8564 data convert to date time strings. */ /*************************************************************************/ static void ConvertFromRTC2DateTime( void ) { char buf[10]; CalenderRead( buf ); RTC8564Str2DateStr( date, (const unsigned char *)buf ); /**/ } /*************************************************************************/ /* Date lcd print */ /*************************************************************************/ static void date_print( const char *src, int x, int y ) { char buf[16]; memcpy( buf, src, 10 ); buf[10] = '\0'; lcd.setCursor(x,y); lcd.print( buf ); } /*************************************************************************/ /* Time lcd print */ /*************************************************************************/ static void time_print( const char *src, int x, int y ) { char buf[16]; memcpy( buf, &src[11], 8 ); buf[8] = '\0'; lcd.setCursor(x,y); lcd.print( buf ); } /*************************************************************************/ /* Time adjust */ /*************************************************************************/ static void time_adjust_mode( void ) { int pos = 2; char copy_date[20]; boolean loop = true; memcpy( copy_date, date, sizeof(copy_date) ); lcd.clear(); date_print(copy_date,0,0); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 10 ) { loop = false; break; } if( pos == 4 || pos == 7 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --copy_date[pos] < date_limit[pos - 2][0] ) copy_date[pos] = date_limit[pos - 2][1]; lcd.setCursor(pos,0); lcd.print( copy_date[pos] ); break; case 0b00000100: /*up number*/ if( ++copy_date[pos] > date_limit[pos - 2][1] ) copy_date[pos] = date_limit[pos - 2][0]; lcd.setCursor(pos,0); lcd.print( copy_date[pos] ); break; case 0b00001000: /*abort*/ return; default: break; } } pos = 0; loop = true; lcd.clear(); time_print(copy_date,0,0); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 8 ) { loop = false; break; } if( pos == 2 || pos == 5 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --copy_date[pos + 11] < time_limit[pos][0] ) copy_date[pos + 11] = time_limit[pos][1]; lcd.setCursor(pos,0); lcd.print( copy_date[pos + 11] ); break; case 0b00000100: /*up number*/ if( ++copy_date[pos + 11] > time_limit[pos][1] ) copy_date[pos + 11] = time_limit[pos][0]; lcd.setCursor(pos,0); lcd.print( copy_date[pos + 11] ); break; case 0b00001000: /*abort*/ return; default: break; } } noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ memcpy( date, copy_date, sizeof(date) ); RTC8564_CalenderSet( date ); /*update calender.*/ EIMSK |= 0x01; /*int0 interrupt enable*/ } /*************************************************************************/ /* Alarm set */ /*************************************************************************/ static void Alarm_set_mode( void ) { int pos = 0; unsigned char temp; boolean loop = true; lcd.clear(); lcd.setCursor(0,0); lcd.print( alarm_set_time ); lcd.setCursor(pos,1); lcd.print( '^' ); while( loop ) { delay( 100 ); switch ( detect_sw_down( switches ) ) { case 0b00000001: /*confirm*/ lcd.setCursor(pos,1); lcd.print( ' ' ); if( ++pos == 5 ) { loop = false; break; } if( pos == 2 ) pos++; lcd.setCursor(pos,1); lcd.print( '^' ); break; case 0b00000010: /*down number*/ if( --alarm_set_time[pos] < time_limit[pos][0] ) alarm_set_time[pos] = time_limit[pos][1]; lcd.setCursor(pos,0); lcd.print( alarm_set_time[pos] ); break; case 0b00000100: /*up number*/ if( ++alarm_set_time[pos] > time_limit[pos][1] ) alarm_set_time[pos] = time_limit[pos][0]; lcd.setCursor(pos,0); lcd.print( alarm_set_time[pos] ); break; case 0b00001000: /*abort*/ return; default: break; } } temp = ((alarm_set_time[3] & 0x0f) << 4) + (alarm_set_time[4] & 0x0f); noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ I2CRTC8564_Write( RTC8564_MIN_ALM, temp ); EIMSK |= 0x01; /*int0 interrupt enable*/ temp = ((alarm_set_time[0] & 0x0f) << 4) + (alarm_set_time[1] & 0x0f); noInterrupts(); /*global interrupt disable*/ EIMSK &= ~0x01; /*int0 interrupt disable*/ interrupts(); /*global interrupt enable*/ I2CRTC8564_Write( RTC8564_HOUR_ALM, temp ); EIMSK |= 0x01; /*int0 interrupt enable*/ } /*************************************************************************/ /* setup */ /*************************************************************************/ void setup() { char buf[16]; unsigned char temp; // static const char date_time[] = "2010/08/07 02:04:00"; lcd.begin(16, 2); lcd.clear(); lcd.println( "designed by hamayan." ); #if defined( _SOFT_I2C_ ) I2C_Init(); #else /*_SOFT_I2C_*/ Wire.begin(); /*set i2c master device*/ TWSR &= 0xfc; /*baud rate control. prescaler=x1*/ TWBR = 72; /*baud rate control. 100khz*/ #endif /*_SOFT_I2C_*/ delay( 1000 ); if( InitRTC8564( 0 ) < 0 ) { lcd.clear(); lcd.println( "rtc init error." ); while(1) ; } I2CRTC8564_Read( RTC8564_MIN_ALM, (char *)&temp ); if( !(temp & 0x80) ) { alarm_set_time[3] = ((temp >> 4) & 0x07) + '0'; alarm_set_time[4] = (temp & 0x0f) + '0'; I2CRTC8564_Read( RTC8564_HOUR_ALM, (char *)&temp ); alarm_set_time[0] = ((temp >> 4) & 0x03) + '0'; alarm_set_time[1] = (temp & 0x0f) + '0'; } // RTC8564_CalenderSet( date_time ); /*force setting calender.*/ pinMode( SW1, INPUT ); /*set port at input mode*/ pinMode( SW2, INPUT ); /*set port at input mode*/ pinMode( SW3, INPUT ); /*set port at input mode*/ pinMode( SW4, INPUT ); /*set port at input mode*/ /*enable edge trigger interrupt*/ attachInterrupt(0, di2_int_hdr, FALLING); DDRD &= ~0b00000100; /*direction input*/ PORTD |= 0b00000100; /*enable pullup*/ /*display alarm set time*/ lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; lasttim = millis() + 100; } /*************************************************************************/ /* main loop */ /*************************************************************************/ void loop() { #define ALARM_PERIOD (60 * 5) unsigned char temp; static unsigned long oldsec; static int alarm_time; if( millis() > lasttim ) { lasttim = millis() + 100; /*next sample time update.*/ switch ( detect_sw_down( switches ) ) { case 0b00001010 : /*time adjust mode*/ clock_disp = false; time_adjust_mode(); lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; break; case 0b00001100 : /*alarm set mode*/ clock_disp = false; Alarm_set_mode(); lcd.clear(); lcd.setCursor(11,1); lcd.print( alarm_set_time ); clock_disp = true; break; case 0b00001000 : /*stop alarm*/ alarm_time = 0; break; default : break; } } if( oldsec != sectim ) { oldsec = sectim; if( date[18] == '0' && date[17] == '0' && alarm_set_time[4] == date[15] && alarm_set_time[3] == date[14] && alarm_set_time[1] == date[12] && alarm_set_time[0] == date[11] ) alarm_time = ALARM_PERIOD; /*? minutes*/ if( --alarm_time > 0 ) { if( alarm_time % 3 ) tone( DI13, 1000, 800 ); } else alarm_time = 0; } } /*************************************************************************/ /* wait functions */ /*************************************************************************/ #define wait1u() delayMicroseconds(1) #define wait5u() delayMicroseconds(5) /*************************************************************************/ /* 100 clocks function */ /*************************************************************************/ static void clk100( void ) { int i; /*i2c lock release*/ for( i = 0; i < 100; i++ ) { SCL_IS_LOW; wait1u(); SCL_IS_HIGH; wait1u(); } } /*************************************************************************/ /* initialize function */ /*************************************************************************/ void I2C_Init( void ) { int i; PORTC |= SDA_BIT | SCL_BIT; DDRC |= SDA_BIT | SCL_BIT; /*pc4=sda,pc5=scl*/ for( i = 0; i < 100; i++ ) { SCL_IS_LOW; wait1u(); SCL_IS_HIGH; wait1u(); } SDA_IS_LOW; StopCondition(); wait5u(); } /*************************************************************************/ /* I2C Terminate function */ /*************************************************************************/ static void I2C_Terminate( void ) { SCL_OUTPUT; SDA_OUTPUT; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_IS_HIGH; } /*************************************************************************/ /* start condition */ /*************************************************************************/ static void StartCondition( void ) { I2C_Terminate(); wait1u(); SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SCL_IS_LOW; } /*************************************************************************/ /* stop condition */ /*************************************************************************/ static void StopCondition( void ) { SCL_OUTPUT; SDA_OUTPUT; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_IS_HIGH; } /*************************************************************************/ /* ACK confirm function */ /*************************************************************************/ static int RcvAck( void ) { int ret; SCL_IS_LOW; /*about 120ns*/ SDA_INPUT; wait1u(); SCL_IS_HIGH; ret = (PINC & SDA_BIT) ? 1 : 0; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_OUTPUT; SCL_IS_LOW; return ret; } /*************************************************************************/ /* ACK responce function */ /*************************************************************************/ static void ResAck( int ack ) { SCL_IS_LOW; /*about 120ns*/ if(ack) SDA_IS_HIGH; else SDA_IS_LOW; wait1u(); SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_LOW; SDA_IS_LOW; } /*************************************************************************/ /* Bit Write function */ /*************************************************************************/ static void BitWrite( int data ) { SCL_IS_LOW; /*about 120ns*/ if(data) SDA_IS_HIGH; else SDA_IS_LOW; wait1u(); SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_LOW; SDA_IS_LOW; } /*************************************************************************/ /* Bit Read function */ /*************************************************************************/ static int BitRead( void ) { int ret; SCL_IS_LOW; /*about 120ns*/ wait1u(); SCL_IS_HIGH; ret = (PINC & SDA_BIT) ? 1 : 0; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_LOW; return ret; } /*************************************************************************/ /* Byte Write function */ /*************************************************************************/ static int ByteWrite( int data ) { BitWrite( data & 0x80 ); BitWrite( data & 0x40 ); BitWrite( data & 0x20 ); BitWrite( data & 0x10 ); BitWrite( data & 0x08 ); BitWrite( data & 0x04 ); BitWrite( data & 0x02 ); BitWrite( data & 0x01 ); // SDA_IS_LOW; return ( RcvAck() == 0 ) ? 0 : (-1); } /*************************************************************************/ /* Byte Read function */ /*************************************************************************/ static int ByteRead( int ack ) { int data = 0; SDA_INPUT; data |= ( BitRead() ) ? 0x80 : 0x00; data |= ( BitRead() ) ? 0x40 : 0x00; data |= ( BitRead() ) ? 0x20 : 0x00; data |= ( BitRead() ) ? 0x10 : 0x00; data |= ( BitRead() ) ? 0x08 : 0x00; data |= ( BitRead() ) ? 0x04 : 0x00; data |= ( BitRead() ) ? 0x02 : 0x00; data |= ( BitRead() ) ? 0x01 : 0x00; SDA_OUTPUT; ResAck( ack ); return data; } /*************************************************************************/ /* I2C Block Write function */ /*************************************************************************/ int I2C_Block_Write( int addr, const char *data, int size ) { StartCondition(); if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); return (-1); } for( ; size > 0; size-- ) { if( ByteWrite( *data++ ) == (-1) ) { I2C_Terminate(); return (-1); } } StopCondition(); return 0; } /*************************************************************************/ /* I2C Block Read function */ /*************************************************************************/ int I2C_Block_Read( int addr, char *data, int size ) { StartCondition(); if( ByteWrite( addr | 0x01 ) == (-1) ) { I2C_Terminate(); return (-1); } for( ; size > 0; size-- ) *data++ = ByteRead( (size == 1) ? 1 : 0 ); StopCondition(); return 0; } /*************************************************************************/ /* I2C Write function */ /*************************************************************************/ int I2C_Write( int addr, unsigned char data ) { #if defined( _SOFT_I2C_ ) StartCondition(); if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( data ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.beginTransmission( addr ); Wire.send( data ); return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2C Read function */ /*************************************************************************/ int I2C_Read( int addr, unsigned char *data ) { #if defined( _SOFT_I2C_ ) StartCondition(); if( ByteWrite( addr | 0x01 ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } *data = ByteRead( 1 ); StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.requestFrom( addr, 1 ); while( Wire.available() == 0 ) ; *data = Wire.receive(); return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2CRTC8564_Write */ /*************************************************************************/ int I2CRTC8564_Write( unsigned char addr, char data ) { #if defined( _SOFT_I2C_ ) StartCondition(); if( ByteWrite( RTC_BASE_ADDR ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( data ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.send( data ); return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2CRTC8564_Read */ /*************************************************************************/ int I2CRTC8564_Read( unsigned char addr, char *buff ) { #if defined( _SOFT_I2C_ ) StartCondition(); if( ByteWrite( RTC_BASE_ADDR ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } SDA_IS_HIGH; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ if( ByteWrite( RTC_BASE_ADDR | 0x01 ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } *buff = ByteRead( 1 ); StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.requestFrom( RTC_BASE_ADDR, 1 ); while( Wire.available() == 0 ) ; *buff = Wire.receive(); return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2CRTC8564_Blk_Read */ /*************************************************************************/ int I2CRTC8564_Blk_Read( unsigned char addr, char *buff, int size ) { #if defined( _SOFT_I2C_ ) char *ptr = buff; char *limit = &buff[ size - 1 ]; StartCondition(); if( ByteWrite( RTC_BASE_ADDR ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } SDA_IS_HIGH; SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SCL_IS_HIGH; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ SDA_IS_LOW; /*about 120ns*/ if( ByteWrite( RTC_BASE_ADDR | 0x01 ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } while( ptr < limit ) { *ptr++ = ByteRead( 0 ); } *ptr = ByteRead( 1 ); StopCondition(); return 0; #else /*_SOFT_I2C_*/ Wire.beginTransmission( RTC_BASE_ADDR ); Wire.send( addr ); Wire.requestFrom( RTC_BASE_ADDR, size ); while( Wire.available() < size ) ; for( ; size > 0; size-- ) { *buff++ = Wire.receive(); } return Wire.endTransmission(); #endif /*_SOFT_I2C_*/ } /*************************************************************************/ /* I2CRTC8564_Blk_Write */ /*************************************************************************/ int I2CRTC8564_Blk_Write( unsigned char addr, const char *data, int size ) { #if defined( _SOFT_I2C_ ) const char *ptr = data; const char *limit = &data[ size ]; StartCondition(); if( ByteWrite( RTC_BASE_ADDR ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } if( ByteWrite( addr ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } while( ptr < limit ) { if( ByteWrite( *ptr++ ) == (-1) ) { I2C_Terminate(); clk100(); return (-1); } } StopCondition(); return 0; #endif /*_SOFT_I2C_*/ return 0; } /*************************************************************************/ /* RTC-8564 initialize */ /*************************************************************************/ int InitRTC8564( int force ) { int i,ret; char temp,date_time[ 7 ],work[ 8 ]; unsigned char rtc_adr; static const unsigned char RTC8564_Init_Code[] = {0x20, 0x11, 0x00,0x10,0x18,0x07,0x04,0x05, 0x10,0x80, 0x80, 0x80, 0x80, 0x00,0x81,63 }; /*ctrl1,ctrl2,sec, min, hour,day, week,month,year,min_a,hour_a,day_a,week_a,freq,cont,timer*/ /*RTC8564 confirmed VLbit*/ if( I2CRTC8564_Read( RTC8564_SEC, &date_time[ SECONDS ] ) != 0 ) return (-1); if( date_time[ SECONDS ] & 0x80 || force ) /*VLbit was 1 then detected low voltage*/ { for( rtc_adr = 0; rtc_adr <= sizeof( RTC8564_Init_Code ); rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, RTC8564_Init_Code[ rtc_adr ] ) != 0 ) return (-1); } if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); /*timer start*/ for( i = 0; i < 100; i++ ) { if( I2CRTC8564_Read( RTC8564_YEAR, &date_time[ YEARS ] ) != 0 ) return (-1); /*RTC is not there.*/ if( date_time[ YEARS ] == RTC8564_Init_Code[ RTC8564_YEAR ] ) /**/ { break; } else { for( rtc_adr = 0; rtc_adr <= sizeof( RTC8564_Init_Code ); rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, RTC8564_Init_Code[ rtc_adr ] ) != 0 ) return (-1); } if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); } } if( i != 100 ) ret = 1; /**/ else ret = (-2); /*initialize error*/ } else ret = 0; if( ret > (-1) ) { if( I2CRTC8564_Blk_Read( RTC8564_SEC, work, 7 ) != 0 ) return (-1); RTC8564Str2DateStr( date, (const unsigned char *)work ); /**/ } return ret; } /*************************************************************************/ /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ /* DateStr2RTC8564Str( (unsigned char *)work, "2007/12/31 23:59:00" ); */ /* I2CRTC8564_Blk_Write( RTC8564_SEC, (const char *)work, 7 ); */ /*************************************************************************/ unsigned char *DateStr2RTC8564Str( unsigned char *dest, const char *source ) { dest[ 0 ] = ((source[ 17 ] & 0x07) << 4) | (source[ 18 ] & 0x0f); /*second*/ dest[ 1 ] = ((source[ 14 ] & 0x07) << 4) | (source[ 15 ] & 0x0f); /*minute*/ dest[ 2 ] = ((source[ 11 ] & 0x03) << 4) | (source[ 12 ] & 0x0f); /*hour*/ dest[ 3 ] = ((source[ 8 ] & 0x03) << 4) | (source[ 9 ] & 0x0f); /*day*/ dest[ 4 ] = 0; /*week*/ dest[ 5 ] = ((source[ 5 ] & 0x01) << 4) | (source[ 6 ] & 0x0f); /*month*/ dest[ 6 ] = ((source[ 2 ] & 0x0f) << 4) | (source[ 3 ] & 0x0f); /*year*/ return dest; } /*************************************************************************/ /* 0123456789012345678 */ /* 2007/11/21 15:12:00 */ /*************************************************************************/ char *RTC8564Str2DateStr( char *dest, const unsigned char source[] ) { dest[ 0 ] = '2'; dest[ 1 ] = '0'; dest[ 2 ] = (source[YEARS] >> 4) + '0'; dest[ 3 ] = (source[YEARS] & 0x0f) + '0'; dest[ 4 ] = '/'; dest[ 5 ] = ((source[MONTHS] >> 4) & 0x01) + '0'; dest[ 6 ] = (source[MONTHS] & 0x0f) + '0'; dest[ 7 ] = '/'; dest[ 8 ] = ((source[DAYS] >> 4) & 0x03) + '0'; dest[ 9 ] = (source[DAYS] & 0x0f) + '0'; dest[ 10 ] = ' '; dest[ 11 ] = ((source[HOURS] >> 4) & 0x03) + '0'; dest[ 12 ] = (source[HOURS] & 0x0f) + '0'; dest[ 13 ] = ':'; dest[ 14 ] = ((source[MINUTES] >> 4) & 0x07) + '0'; dest[ 15 ] = (source[MINUTES] & 0x0f) + '0'; dest[ 16 ] = ':'; dest[ 17 ] = ((source[SECONDS] >> 4) & 0x07) + '0'; dest[ 18 ] = (source[SECONDS] & 0x0f) + '0'; dest[ 19 ] = '\0'; return dest; } /*************************************************************************/ /* RTC-8564 Calender Set */ /*************************************************************************/ int RTC8564_CalenderSet( const char *date_time ) { int i; unsigned char rtc_adr,work[ 8 ]; DateStr2RTC8564Str( work, date_time ); /*timer stop*/ if( I2CRTC8564_Write( RTC8564_CTRL1, 0x20 ) != 0 ) return (-1); /*date and time write*/ for( rtc_adr = RTC8564_SEC, i = 0; rtc_adr <= RTC8564_YEAR; rtc_adr++ ) { if( I2CRTC8564_Write( rtc_adr, work[ i++ ] ) != 0 ) return (-1); } /*timer start*/ if( I2CRTC8564_Write( RTC8564_CTRL1, 0x00 ) != 0 ) return (-1); return 0; } /***********************************************************************/ /* designed by hamayan */ /* Copyright(C) hamayan */ /***********************************************************************/
ITRONプログラミング入門―H8マイコンとHOSで始める組み込み開発
- 作者: 濱原 和明
- 出版社/メーカー: オーム社
- 発売日: 2005/04/25
- メディア: 単行本
2010-08-07 14:44
nice!(0)
コメント(0)
トラックバック(0)
コメント 0