2013年9月28日土曜日

I2C RTC をつかってみました

ストロベリーリナックスさんで販売中のリアルタイムクロック(RTC)モジュールを
試食しました~。

モジュールにはSTMicroelectronics社の M41T62 が載っています。

とっても小さなICで、半田付けは厳しいですねー。
モジュールになっていてうれしいです(笑


でのI2Cのバスにそのままつないでみました。





【用意するもの】
M41T62 リアルタイムクロック(RTC)モジュール

※以下前回と同じです。
I2C接続小型LCDモジュールピッチ変換キット
PSoC 5LP テストボード[QFN68][Rev.B]
MiniProg3

PSoC Creator 3.3 CP3
PSoC Programmer



【調理のしかた】
1.前回の「I2CLCDをつかってみた」と同様にI2C,I2C_LCDを配置します。
  LCDに表示できていることを確認してください。

2.[main.c] を書き換えます。
#include 
#define CENTURY			0x00u	//0x00:2000年 0x40:2100年 0x80:2200年 0xC0:2300年
#define	SET_SEC			0x00u	
#define	SET_MIN			0x15u
#define SET_HOUR		0x16u
#define	SET_DAY			0x07u	
#define	SET_DATE		0x12u
#define	SET_MONTH	   (0x08u | CENTURY)
#define	SET_YEAR		0x16u

#define RTC_Address  0x68u  // 0b1101000
//--  RegisterAddrressMAP -- //
#define RTC_10_100_SEC 0x00u 
#define RTC_SEC   0x01u 
#define RTC_MIN   0x02u 
#define RTC_HOUR  0x03u 
#define RTC_DAY   0x04u 
#define RTC_DATE  0x05u 
#define RTC_MONTH  0x06u 
#define RTC_YEAR  0x07u 
#define RTC_CAL   0x08u 
#define WR_BufferSize     20u

uint8 WR_BUFFER[WR_BufferSize];
uint8 Buffer[16u];

void I2C_LCD_Position(uint8 row, uint8 column)
{
 if(row == 0){
  I2C_LCD_1_SetDDRAM(0x80u + column);
 }else{
  I2C_LCD_1_SetDDRAM(0xC0u + column);
 }
}

void I2C_LCD_Init(void) 
{
 CyDelay(40u);     //40mS 待機
 I2C_LCD_1_FunctionSetNormal();
 I2C_LCD_1_ReturnHome();
 I2C_LCD_1_FunctionSetExtended();
 I2C_LCD_1_InternalOscFrequency();
 I2C_LCD_1_ContrastSet();
 I2C_LCD_1_PwrIconContrast();
 I2C_LCD_1_FollowerCtrl();
 CyDelay(200u);     //200mS 待機
 I2C_LCD_1_FunctionSetNormal();
 I2C_LCD_1_DisplayOn();
 I2C_LCD_1_Clear();
 I2C_LCD_1_EntryModeSet();
 //I2C_LCD_1_WriteControl(0x0Fu); //Disp:On Cursor:On Position:On
}

void I2C_RTC_Read(void)
{
    uint8 temp;
	WR_BUFFER[0] = 0x00;
	temp = I2C_1_MasterSendStart(RTC_Address,I2C_1_WRITE_XFER_MODE);
    temp = I2C_1_MasterWriteByte(WR_BUFFER[0]);
	
	temp = I2C_1_MasterReadBuf(RTC_Address, (uint8 *)Buffer,
								8, I2C_1_MODE_REPEAT_START);
	while (temp != I2C_1_MSTR_NO_ERROR);
	while(I2C_1_MasterStatus() & I2C_1_MSTAT_XFER_INP);
	temp = I2C_1_MasterClearStatus();
}
void I2C_RTC_Write(void)
{
    uint8 temp,count;
	WR_BUFFER[0] = 0x00;
	for(count=0;count<10;count++){
		WR_BUFFER[count+1] = Buffer[count];
	}
	temp = I2C_1_MasterWriteBuf(RTC_Address, (uint8 *)WR_BUFFER,
					   10u, I2C_1_MODE_COMPLETE_XFER);
	while (temp != I2C_1_MSTR_NO_ERROR);
	while(I2C_1_MasterStatus() & I2C_1_MSTAT_XFER_INP);
	temp = I2C_1_MasterClearStatus();
}
void I2C_RTC_Init(void)
{										// RTC初期化
	I2C_RTC_Read();						
	if(Buffer[0x04u]&0xF0u){			// 今回はモジュールのSQWをみて判断します。
		Buffer[0x04u] 	 &= 0x0Fu;		// SQW出力off
		Buffer[RTC_SEC]   = SET_SEC;
		Buffer[RTC_MIN]   = SET_MIN;
		Buffer[RTC_HOUR]  = SET_HOUR;
		Buffer[RTC_DAY]   = SET_DAY;
		Buffer[RTC_DATE]  = SET_DATE;
		Buffer[RTC_MONTH] = SET_MONTH;
		Buffer[RTC_YEAR]  = SET_YEAR;
		I2C_RTC_Write();
	}
}


int main()
{
	CyGlobalIntEnable;
	I2C_1_Start();
	I2C_LCD_Init();
	I2C_LCD_Position(0,0);
	I2C_LCD_1_PrintString("Hello");
	I2C_LCD_Position(1,0);
	I2C_LCD_1_PrintString("PSoC5LP!");	
	CyDelay(2000u);
	I2C_LCD_1_Clear();
	I2C_RTC_Init();
	
	while(1){

		I2C_RTC_Read();
		I2C_LCD_Position(0,0);
		I2C_LCD_1_PrintInt8(Buffer[RTC_YEAR]);I2C_LCD_1_PutChar('/');
		I2C_LCD_1_PrintInt8(Buffer[RTC_MONTH]&0x1Fu);I2C_LCD_1_PutChar('/');
		I2C_LCD_1_PrintInt8(Buffer[RTC_DATE]);
		I2C_LCD_Position(1,0);
		I2C_LCD_1_PrintInt8(Buffer[RTC_HOUR]);I2C_LCD_1_PutChar(':');
		I2C_LCD_1_PrintInt8(Buffer[RTC_MIN]&0x7Fu);I2C_LCD_1_PutChar(':');
		I2C_LCD_1_PrintInt8(Buffer[RTC_SEC]&0x7Fu);
		CyDelay(100u);	
    }
}

/* [] END OF FILE */

3.PSoC 5LP テストボードとRTCモジュールを接続します。
  P12[0] --- SCL(8)
  P12[1] --- SDA(1)
   +3.3V  --- EXT(4)
    GND --- GND(3)
4.MiniProg3 を接続して、書き込みます。
プロジェクトファイル一式

2 件のコメント:

  1. 拝見させて頂きました。
    同じM41T62のモジュールと、Renesas RX113の組み合わせで日付と時刻を表示させてみたのですが、なぜか‘年’の情報が‘FF’となって返ってきます。
    初期化か何かに問題があるのでしょうか。

    返信削除
  2. Takashi Yumitaさん
    コメントありがとうございます。
     
    >なぜか‘年’の情報が‘FF’となって返ってきます。
    オシロやプロトコルアナライザ等で信号線を確認してみては、どうでしょう?
    ほかの項目(月、日、時間)は正常な値が取得できれば、"年" のスペルミスなどがないか確認してみてください。

    返信削除