⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds1302.c

📁 在PXA270上替换开发板的实时时钟RTC4513为DS1302的修改说明,自己写的,拿上来和大家共享,也希望大家提意见
💻 C
📖 第 1 页 / 共 2 页
字号:
   DS1302(RST_1302,HIGH);

   Cmd_Byte = WRITE_CMD;	/* set command to the 1302 for
   								burst write operation */
   shifter = 0x01;

   //写 写 命令
   for(i=0; i<8; i++)		/* shift out the command */
   {
      if (shifter & Cmd_Byte)
	 		DS1302(DAT_1302,HIGH);
		  else
	 		DS1302(DAT_1302,LOW);	/* set up the data port pin */

      DS1302(CLK_1302,HIGH);
      shifter = shifter << 1;
      DS1302(CLK_1302,LOW);		/* clock the chip */
   } //next i

	for(i=0; i<8; i++)		/* output all 8 bytes to DS1302 */
   	{
      shifter = 0x01;
      databyte = TimeBuffer[i];  /* get byte from buffer */
      for(j=0; j<8; j++)	/* shift out data */
      	{
      	if (shifter & databyte)
	 			DS1302(DAT_1302,HIGH);
			  else
	 			DS1302(DAT_1302,LOW);	/* set up the data port pin */

	      DS1302(CLK_1302,HIGH);
      	shifter = shifter << 1;
      	DS1302(CLK_1302,LOW);		/* clock the chip */
      	} //next j
   	} //next i

	Idle_1302();			/* set the port pins idle */
	return;
} /* end Write_1302_Data() */

/*******************************************************************
	Enable_1302

	Write enables the Dallas Semi 1302 clock chip.

********************************************************************/
void Enable_1302(void)
{
	unsigned char Cmd_Byte;				/*clock command*/
	unsigned char databyte;         	/*temp data byte*/
	unsigned char shifter;				/* bit selector */
	unsigned int i,j;

    DS1302(CLK_1302,LOW);
    DS1302(DAT_1302,LOW);
    DS1302(RST_1302,HIGH);

    Cmd_Byte = 0x8e;		/* set command to the 1302 for
                               write to write prot register */
    shifter = 0x01;
	//写0x8E表示写控制寄存器,后面必须跟着是0的一个字节
    for(i=0; i<8; i++)	/* shift out the command */
   	{
      if (shifter & Cmd_Byte)
	 		DS1302(DAT_1302,HIGH);
	  else
	 		DS1302(DAT_1302,LOW);

      DS1302(CLK_1302,HIGH);
      shifter = shifter << 1;
	  DS1302(CLK_1302,LOW);
   	} //next i


   shifter = 0x01;
   databyte =0; /* we want to write enable the DS1302 chip */
   //写8个零是DataSheet这样定的,WP位也写0表示去掉DS1302的写保护功能
   for(j=0; j<8; j++) /* shift out the data */
   {
      if (shifter & databyte)
	 		DS1302(DAT_1302,HIGH);
	  else
	 		DS1302(DAT_1302,LOW);

      DS1302(CLK_1302,HIGH);
      shifter = shifter << 1;
      DS1302(CLK_1302,LOW);		/* clock the chip */
    } //next j

	//秒寄存器的第7位表示时钟停止标记,为1表示时钟停止
    Idle_1302();			/* idle the port pins */
	return;
} /* end Enable_1302() */

/*******************************************************************
	Idle_1302

	This routine will set the port pins that drive the clock to
	their idle states.
********************************************************************/
void Idle_1302(void)
{
    //刚好和Enable相反
    DS1302(RST_1302,LOW);
    DS1302(DAT_1302,HIGH);
    DS1302(CLK_1302,HIGH);
	return;
} /* end Idle_1302() */

/*******************************************************************
	Lock_1302

	This routine will LOCK the clock and stop its oscillator to
	preserve Battery Life.
	Uses TimeBuffer[] as temporary storage.
********************************************************************/
void Lock_1302 (void)
   {
	unsigned char TimeBuffer[8];				//temp storage

   Read_1302_Data(&TimeBuffer[0]);        //get the time
	TimeBuffer[0] = TimeBuffer[0]|0x80;    //halt the clock
   Enable_1302();    							//write enable the clock
	Write_1302_Data(&TimeBuffer[0]);       //write back the halted time
	return;
   } /* end proc Lock_1203() */


/*******************************************************************
	Set_Time

	This routine SETs the clock and start its oscillator, write-
	protecting the clock registers.
	Obtains time from TimeBuffer[].
	//在WinCE架构中不用这个函数了
********************************************************************/
void Set_Time(unsigned char * TimeBuffer)
   {
   TimeBuffer[7] = '\x80';         //write protect the chip after write
   Enable_1302();                  //write enable the clock
   Write_1302_Data(TimeBuffer);              //write the clock and start it up
   } /* end proc Set_Time() */

/*******************************************************************
	Get_Time

	This routine GETs the time from the Dallas 1302 clock.
	The time is returned in TimeBuffer.
	This function returns 0 when the clock is operating properly.
	If the clock was locked (stopped) the default time is returned
	as 1/1/99, 12:00Noon and the function returns non-zero.
	//在WinCE架构中不用这个函数了
********************************************************************/
unsigned int Get_Time(unsigned char * TimeBuffer)
{
	unsigned int clock_locked;

	//get the time and put it in TimeBuffer[]
	clock_locked = Read_1302_Data(TimeBuffer);	
	//store the time in system variable time....
	//Note that since the values in the RTC and TimeBuffer are in
	//BCD, we need to convert back to normal numbers!
	return(clock_locked);
} /* end proc Get_Time() */


//本函数将替换RTC4513GetRealTime函数
void DS1302GetRealTime(LPSYSTEMTIME lpst)
{
	unsigned char TimeBuffer[8]; //temp storage
	unsigned char ucBCDLow, ucBCDHigh;

    OALMSG(1, (TEXT("+DS1302GetRealTime: Enter!\r\n")));

	Read_1302_Data(TimeBuffer);
	lpst->wMilliseconds = 0;

	ucBCDHigh = TimeBuffer[0] & 0x70;
	ucBCDLow = TimeBuffer[0] & 0x0F;
	ucBCDHigh >>= 4; //左移四位
	lpst->wSecond = (ucBCDLow + ucBCDHigh * 10);

	ucBCDHigh = TimeBuffer[1] & 0x70;
	ucBCDLow = TimeBuffer[1] & 0x0F;
	ucBCDHigh >>= 4; //左移四位
	lpst->wMinute = (ucBCDLow + ucBCDHigh * 10);

	ucBCDHigh = TimeBuffer[2] & 0x10; //暂时只支持24制??????
	ucBCDLow = TimeBuffer[2] & 0x0F;
	ucBCDHigh >>= 4; //左移四位
	lpst->wHour = (ucBCDLow + ucBCDHigh * 10);

	ucBCDHigh = TimeBuffer[3] & 0x30;
	ucBCDLow = TimeBuffer[3] & 0x0F;
	ucBCDHigh >>= 4; //左移四位
	lpst->wDay = (ucBCDLow + ucBCDHigh * 10);

	ucBCDHigh = TimeBuffer[4] & 0x10;
	ucBCDLow = TimeBuffer[4] & 0x0F;
	ucBCDHigh >>= 4; //左移四位
	lpst->wMonth = (ucBCDLow + ucBCDHigh * 10);

	lpst->wDayOfWeek = TimeBuffer[5]; //不会超过10的

	ucBCDHigh = TimeBuffer[6] & 0xF0;
	ucBCDLow = TimeBuffer[6] & 0x0F;
	ucBCDHigh >>= 4; //左移四位
	lpst->wYear = (ucBCDLow + ucBCDHigh * 10 + 2000);
	RETAILMSG(1,(TEXT("RTC4513GetRealTime: Year: %u, Month: %u, Day: %u, Hour: %u, Minute: %u, second: %u \r\n"),
		lpst->wYear, lpst->wMonth,lpst->wDay, lpst->wHour, lpst->wMinute,lpst->wSecond));

    OALMSG(1, (TEXT("-DS1302GetRealTime: Leave!\r\n")));
}

//本函数将替换RTC4513SetRealTime函数
void DS1302SetRealTime(LPSYSTEMTIME lpst)
{
	unsigned char TimeBuffer[8]; //temp storage
	unsigned char ucBCDLow, ucBCDHigh;

    OALMSG(1, (TEXT("+DS1302SetRealTime: Enter!\r\n")));
	lpst->wYear  = lpst->wYear % 100;
	//lpst->wDay  = lpst->wDay - 1; //用DS1302这里就不用减拉
	//lpst->wMonth  = lpst->wMonth - 1;

	ucBCDHigh = lpst->wSecond / 10;
	ucBCDLow = lpst->wSecond % 10;
	ucBCDHigh <<= 4; //右移四位
	TimeBuffer[0] = (ucBCDLow | ucBCDHigh);

	ucBCDHigh = lpst->wMinute  / 10;
	ucBCDLow = lpst->wMinute % 10;
	ucBCDHigh <<= 4; //右移四位
	TimeBuffer[1] = (ucBCDLow | ucBCDHigh);

	/*hours:   msb=1,12 hour/0,24 hour, BCD hour
				msb=0,	0-23 BCD
				msb=1,  {10}{0=am/1=pm}01-12 BCD // */
	ucBCDHigh = lpst->wHour / 10;
	ucBCDLow = lpst->wHour % 10;
	ucBCDHigh <<= 4; //右移四位,最高为铁定为0,这样就成24小时制了
	TimeBuffer[2] = (ucBCDLow | ucBCDHigh);

	ucBCDHigh = lpst->wDay / 10;
	ucBCDLow = lpst->wDay % 10;
	ucBCDHigh <<= 4; //右移四位
	TimeBuffer[3] = (ucBCDLow | ucBCDHigh);

	ucBCDHigh = lpst->wMonth / 10;
	ucBCDLow = lpst->wMonth % 10;
	ucBCDHigh <<= 4; //右移四位
	TimeBuffer[4] = (ucBCDLow | ucBCDHigh);

	TimeBuffer[5] = (BYTE)lpst->wDayOfWeek; //不会超过10的

	ucBCDHigh = lpst->wYear / 10;
	ucBCDLow = lpst->wYear % 10;
	ucBCDHigh <<= 4; //右移四位
	TimeBuffer[6] = (ucBCDLow | ucBCDHigh);

	TimeBuffer[7] = '\x80'; //write protect the chip after write

	Enable_1302(); //write enable the clock
	Write_1302_Data(TimeBuffer); //write the clock and start it up
	RETAILMSG(1,(TEXT("RTC4513SetRealTime: Year: %u, Month: %u, Day: %u, Hour: %u, Minute: %u, second: %u \r\n"),
		lpst->wYear, lpst->wMonth,lpst->wDay, lpst->wHour, lpst->wMinute,lpst->wSecond));

    OALMSG(1, (TEXT("-DS1302SetRealTime: Leave!\r\n")));
}

//本函数应该在OEMInit中被调用
//本函数将替换RTC4513_Init函数
void DS1302_Init(void)
{
	PHYSICAL_ADDRESS PhysicAddr;
	XLLP_UINT32_T uiArrPin[2] = {1, 0};
	OALMSG(1, (TEXT("DS1302_Init Enter!\r\n")));

	//这里要初始化三个GPIO为双向的,方便以后使用,同时获取其地址
//	PhysicAddr.LowPart = ;
//	PhysicAddr.HighPart = 0;
	g_pBaseAddressGPIORegs = (BULVERDE_GPIO_REG *) OALPAtoVA(BULVERDE_BASE_REG_PA_GPIO, FALSE);
	if(NULL == g_pBaseAddressGPIORegs)
	{
		return ;
	}

	//设置几个管脚为GPIO用的
	uiArrPin[1] = VAL_GPIO_INDEX_CLK;
	XllpGpioClearAlternateFn(g_pBaseAddressGPIORegs, uiArrPin);
	XllpGpioSetFallingEdgeDetectDisable(g_pBaseAddressGPIORegs, uiArrPin);
	XllpGpioSetRisingDetectDisable(g_pBaseAddressGPIORegs, uiArrPin);
	uiArrPin[1] = VAL_GPIO_INDEX_DATA;
	XllpGpioClearAlternateFn(g_pBaseAddressGPIORegs, uiArrPin);
	XllpGpioSetFallingEdgeDetectDisable(g_pBaseAddressGPIORegs, uiArrPin);
	XllpGpioSetRisingDetectDisable(g_pBaseAddressGPIORegs, uiArrPin);
	uiArrPin[1] = VAL_GPIO_INDEX_RST;
	XllpGpioClearAlternateFn(g_pBaseAddressGPIORegs, uiArrPin);
	XllpGpioSetFallingEdgeDetectDisable(g_pBaseAddressGPIORegs, uiArrPin);
	XllpGpioSetRisingDetectDisable(g_pBaseAddressGPIORegs, uiArrPin);

	SetPinDirection(RST_1302, FALSE); //设为输出方向
	SetPinDirection(DAT_1302, FALSE); //设为输出方向
	SetPinDirection(CLK_1302, FALSE); //设为输出方向
	OALMSG(1, (TEXT("DS1302_Init Leave!\r\n")));
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -