?? pmp_rtc_driver.c
字號(hào):
/*-------------------------------------------------*
* $RCSfile: pmp_rtc_driver.c,v $
* $Date: 2007/01/17 12:28:43 $
* $Author: lanzhu $
* $Log: pmp_rtc_driver.c,v $
* Revision 1.1.1.1 2007/01/17 12:28:43 lanzhu
* 齊蘭柱 準(zhǔn)備一個(gè)新的代碼分支
*
* Revision 1.2 2006/12/12 00:30:38 lanzhu
* 刪除沒(méi)有用的程序, 去除 WARNING
*
* Revision 1.1.1.1 2006/12/05 03:01:16 lanzhu
* no message
*
* Revision 1.1.1.1 2006/12/01 09:49:35 lanzhu
* no message
*
* Revision 1.5 2006/09/27 05:53:04 lanzhu
* 加入了 系統(tǒng) 冷啟動(dòng) 熱啟動(dòng)的判斷
*
* Revision 1.4 2006/09/26 07:19:20 lanzhu
* 添加函數(shù) UINT16 SPMP_RTC_Set32KOut( UINT16 Flag )
*
* Revision 1.3 2006/09/26 00:52:39 lanzhu
* 將 RTC 時(shí)間 和 FS 時(shí)間進(jìn)行了協(xié)調(diào)使用
*
* Revision 1.2 2006/08/31 03:29:03 lanzhu
* 對(duì)各個(gè)API 進(jìn)行測(cè)試
*
* Revision 1.1 2006/08/30 00:50:28 lanzhu
* add rtc driver
*
*
*--------------------------------------------------*/
// #define RTC_TEST
/*
1. 測(cè)試 日期的寫(xiě)入 和讀出是否符合預(yù)期
BCD mode test OK!
HEX mode test OK!
2. 測(cè)試 Time 的寫(xiě)入 和讀出是否符合預(yù)期
BCD mode test OK!
HEX mode test OK!
3. 對(duì)讀數(shù)據(jù)進(jìn)行測(cè)試
SCL 的速度進(jìn)行測(cè)試, 加快速度, 減小一次的時(shí)間
|---------| |------
__| |______________|
6.8 us 12.4 us
clock 的頻率約為: 51.5K Hz
*/
#include "SPMP_define.h"
#include <string.h>
#include "spca_general.h"
#include "sig_api.h"
#include "os_api.h"
#include "hw_disp.h"
#include "system_api.h"
#include "fs_api.h"
#include "appdriver.h"
// Host GPIO register map table
enum
{
REG_HOST_INTERFACE_ENABLE = 0x1000b320, // r/w
REG_HGPIO_DRIVING_SET = 0x10000184, // R/W
REG_HGPIO_PULL_SELECT = 0x100001a8, // R/W
REG_HGPIO_PULL_ENABLE = 0x100001cc, // R/W
REG_HGPIO_INPUT_ENABLE = 0x100001f0, // R/W
REG_HGPIO_OUTPUT_ENABLE = 0x1000b064, // R/W
REG_HGPIO_OUTPUT_VALUE = 0x1000b068, // R/W
REG_HGPIO_INPUT_VALUE = 0x1000b06c, // R
REG_HGPIO_SELECT = 0x1000b0e2,
};
// RTC 內(nèi)部寄存器的地址值
enum
{
RTC_ADDR_SECOND = 0x00, // 秒
RTC_ADDR_MINITE = 0x01, // 分鐘
RTC_ADDR_HOUR = 0x02, // 小時(shí)
RTC_ADDR_WEEK = 0x03, // 星期
RTC_ADDR_DAY = 0x04, // 日
RTC_ADDR_MONTH = 0x05, // 月
RTC_ADDR_YEAR = 0x06, // 年
RTC_ADDR_ALARM_A = 0x08, // alarm A 的秒寄存器
RTC_ADDR_ALARM_B = 0x0b, // alarm B 的秒寄存器
RTC_ADDR_CTL1 = 0x0e, // 控制寄存器1
RTC_ADDR_CTL2 = 0x0f, // 控制寄存器2
I2C_RTC_ADDR = 0x32, // 時(shí)間模塊在I2C 總線上被分配的地址
};
/**************************************************************************
* G E N E R A L C O N S T A N T S *
**************************************************************************/
#define BASE_YEAR_HEX (2000)
#define BASE_YEAR_BCD (0x2000)
#define SPECIAL_STR ("P9D")
#define CLK_ENABLE_BIT (1<<3)
#define HOUR_12_24_BIT (1<<5)
#define I2C_RTC_ADDR (0x32)
#define I2C_NORMAL_DELAY (32)
#define TEST_BIT (4)
#define I2C_SCL_BIT (2)
#define I2C_SDA_BIT (3)
#define LOW_LEVEL (0x00)
#define HIGH_LEVEL (0x01)
// 對(duì)于RTC 設(shè)備來(lái)說(shuō), 地址的最后 1 BIT 的意義
#define FLAG_WRITE_DATA (0)
#define FLAG_READ_DATA (1)
#define RTC_INTERNAL_ADDR_MAX (0x0f)
// 數(shù)據(jù)寫(xiě)入時(shí)的模式 0
#define RTC_WRITE_MODE_0 (0)
// 數(shù)據(jù)讀出時(shí)的模式 4
#define RTC_READ_MODE_4 (4)
/**************************************************************************
* M A C R O S *
**************************************************************************/
/**************************************************************************
* D A T A T Y P E S *
**************************************************************************/
struct RTCtime_t
{
UINT16 Second;
UINT16 Minute;
UINT16 Hour;
};
struct RTCdate_t {
UINT16 Week;
UINT16 Day;
UINT16 Month;
UINT16 Year;
};
/**************************************************************************
* G L O B A L D A T A *
**************************************************************************/
static UINT16 rtc_data_format;
/************************************************************************/
/* */
/************************************************************************/
static UINT16 ValueHEX_2_BCD( UINT16 hex );
static UINT16 ValueBCD_2_HEX( UINT16 bcd );
// 獲得 RTC 的時(shí)間值
//static UINT16 SPMP_RTC_GetNowH_M_S( struct RTCtime_t * pTime_t );
// 獲得 RTC 的日期值
static UINT16 SPMP_RTC_GetNowY_M_D_W( struct RTCdate_t *pDate_t );
// 設(shè)定 RTC 的時(shí)間值
static UINT16 SPMP_RTC_SetH_M_S( struct RTCtime_t *pTime_t );
// 設(shè)定 RTC 的日期值
static UINT16 SPMP_RTC_SetY_M_D_W( struct RTCdate_t *pDate_t );
// 設(shè)置數(shù)據(jù)的格式
static UINT16 SPMP_RTC_SetDataFormat( UINT16 DataFormat );
static UINT16 read_RTC_addr(UINT8 rtc_internal_add, UINT8 len, UINT8 *pbuf);
static UINT16 write_RTC_addr(UINT8 rtc_internal_add, UINT8 len, UINT8 *pbuf);
static void host_interface_disable( void );
static void send_rtc_addr(UINT8 Addr, UINT8 Flag);
static void set_register(UINT32 RegAddr, UINT8 BitOffset, UINT8 Flag);
static void i2c_start( void );
static void i2c_stop( void );
static void i2c_delay( UINT8 delay );
static void scl_output_bit( UINT8 data );
static void sda_output_bit( UINT8 data );
static UINT8 sda_input_bit( void );
static void i2c_read_ack(UINT8 data);
static void i2c_byte_send( UINT8 data);
static void i2c_byte_receive(UINT8 * pdata);
static UINT16 get_data_format( void );
static UINT16 bcd_2_hex(UINT8 *pBCD, UINT8 *pHex, UINT8 len);
static UINT16 hex_2_bcd(UINT8 *pHex, UINT8 *pBCD, UINT8 len);
#ifdef RTC_TEST
// 進(jìn)行測(cè)試, 在HOST GPIO4 上輸出方波
void qlz_test( void )
{
UINT16 i;
UINT8 data;
UINT32 reg_add;
struct RTCdate_t Date_t;
struct RTCtime_t Time_t;
Time_Attr_t tmp_DT;
DEBUG_OUTPUT(("rtc initial\r\n"));
// initial SPMP3XXX HOST interface
SPMP_RTC_InterfaceInitial();
/*
read_RTC_addr(UINT8 rtc_internal_add, UINT8 len, UINT8 *pbuf);
write_RTC_addr(UINT8 rtc_internal_add, UINT8 len, UINT8 *pbuf);
*/
UINT8 buf[0x04];
i = 0X7D6;
DEBUG_OUTPUT(("111 i = 0x%x\r\n", i));
i = ValueHEX_2_BCD(i);
DEBUG_OUTPUT(("222 i = 0x%x\r\n", i));
while (1);
while (1);
// set Data format
SPMP_RTC_SetDataFormat( DATA_FORMAT_HEX );
/*
UINT32 tm_sec;
UINT32 tm_min;
UINT32 tm_hour;
UINT32 tm_mday;
UINT32 tm_mon;
UINT32 tm_year;
*/
tmp_DT.tm_year = 0x2006;
tmp_DT.tm_mon = 9;
tmp_DT.tm_mday = 0x25;
tmp_DT.tm_hour = 0x23;
tmp_DT.tm_min = 0x49;
tmp_DT.tm_sec = 0;
// 設(shè)定日期時(shí)間
SPMP_RTC_SetDateTime( &tmp_DT, 0x01, DATA_FORMAT_BCD);
DEBUG_OUTPUT((" debug stop!\r\n"));
while (1)
{
SPMP_RTC_GetH_M_S( &tmp_DT, DATA_FORMAT_HEX );
DEBUG_OUTPUT(("Time: ------- %x %x %x\r\n",
tmp_DT.tm_hour,
tmp_DT.tm_min,
tmp_DT.tm_sec ));
SPMP_RTC_GetY_M_D_W( &tmp_DT, &i, DATA_FORMAT_HEX );
DEBUG_OUTPUT(("Date: ------- %x %x %x %x\r\n",
tmp_DT.tm_year,
tmp_DT.tm_mon,
tmp_DT.tm_mday,
i));
osTimeDly(100);
}
}
#endif
/************************************************************************/
/* 從RTC中一次讀取年月日時(shí)分秒星期信息
input:
pDt [out] Time_Attr_t *
pWeek [out] UINT16 *
output:
0 成功, 非0值失敗
func:
note:
*/
/************************************************************************/
UINT16 SPMP_RTC_GetDateTime( Time_Attr_t *pDt, UINT16 *pWeek)
{
UINT8 buffer[0x10];
// 判斷輸入?yún)?shù)是否合法
if ( (NULL == pDt) || (NULL == pWeek))
{
ERROR_REPORT;
return APP_DRV_ERR;
}
memset(buffer, '\0', sizeof(buffer));
// 從RTC 中讀出 秒、分、時(shí)、星期、月、年 信息
read_RTC_addr(RTC_ADDR_SECOND, 0x07, buffer);
pDt->tm_sec = ValueBCD_2_HEX( buffer[0] );
pDt->tm_min = ValueBCD_2_HEX( buffer[1] );
pDt->tm_hour = ValueBCD_2_HEX( buffer[2] );
pDt->tm_mday = ValueBCD_2_HEX( buffer[3] );
*pWeek = buffer[4];
pDt->tm_mon = ValueBCD_2_HEX( buffer[5] );
pDt->tm_year = ValueBCD_2_HEX( buffer[6] )+ BASE_YEAR_HEX;
return APP_DRV_OK;
}
/************************************************************************/
/* 獲得系統(tǒng)是否為冷啟動(dòng)
input:
pFlag [out] 存放標(biāo)志的地址指針
output:
0 冷啟動(dòng)
非0值 熱啟動(dòng)
func:
note:
*/
/************************************************************************/
UINT16 SPMP_RTC_GetColdStartFlag( void )
{
UINT8 buf[0x10];
memset(buf, '\0', sizeof(buf));
// 從 RTC 寄存器中讀出數(shù)據(jù)
read_RTC_addr(RTC_ADDR_ALARM_B, 0x03, buf);
// 與特殊的字符串進(jìn)行比較
if ( strcmp(buf, SPECIAL_STR))
{
return COLD_START_FLAG; // 冷啟動(dòng)
}
return HOT_START_FLAG; // 熱啟動(dòng)
}
/************************************************************************/
/* 清除 冷啟動(dòng)標(biāo)志
input: void
output: void
func:
將冷啟動(dòng)標(biāo)志設(shè)置為無(wú)效
note:
*/
/************************************************************************/
void SPMP_RTC_ClrColdStartFlag( void )
{
UINT8 buf[0x10];
strcpy(buf, SPECIAL_STR);
// 從 RTC 寄存器中讀出數(shù)據(jù)
write_RTC_addr(RTC_ADDR_ALARM_B, 0x03, buf);
memset(buf, '\0', sizeof(buf));
// 讀出數(shù)據(jù)進(jìn)行比較, 判斷寫(xiě)入是否成功
read_RTC_addr(RTC_ADDR_ALARM_B, 0x03, buf);
if ( strcmp(buf, SPECIAL_STR) )
{
ERROR_REPORT;
}
return;
}
/************************************************************************/
/* 設(shè)置 RTC 32K 脈沖的輸出
input:
Flag [in]
0 disable 32K output
非0值 enable 32K output
output:
0 成功, 非0值失敗
func:
note:
*/
/************************************************************************/
UINT16 SPMP_RTC_Set32KOut( UINT16 Flag )
{
UINT8 data;
// read control register value
read_RTC_addr( RTC_ADDR_CTL2, 0x01, &data );
if ( !Flag ) {
data |= CLK_ENABLE_BIT;
}
else{
data &= ~CLK_ENABLE_BIT;
}
write_RTC_addr(RTC_ADDR_CTL2, 0x01, &data);
if (Flag){
DEBUG_OUTPUT(("Enable CLK: "));
}
else{
DEBUG_OUTPUT(("Disable CLK: "));
}
return APP_DRV_OK;
}
/************************************************************************/
/* 設(shè)定 年月日 時(shí)分秒 星期
input:
pTimeAttr [in] 年月日時(shí)分秒
WeekDay [in] 星期
output:
0 成功, 非0值失敗
func:
設(shè)定日期時(shí)間星期
note:
*/
/************************************************************************/
UINT16 SPMP_RTC_SetDateTime(Time_Attr_t *pTime,
UINT16 WeekDay,
UINT16 DataFormat)
{
UINT16 err;
struct RTCtime_t tmp_time;
struct RTCdate_t tmp_date;
Time_Attr_t tmp_DT;
Time_Attr_t *pTimeAttr;
pTimeAttr = &tmp_DT;
// 如果輸入的數(shù)據(jù)是 BCD 編碼格式, 需要將數(shù)據(jù)轉(zhuǎn)換為 HEX
if (DATA_FORMAT_BCD == DataFormat)
{
pTimeAttr ->tm_year = ValueBCD_2_HEX( pTime ->tm_year );
pTimeAttr ->tm_mon = ValueBCD_2_HEX( pTime ->tm_mon );
pTimeAttr ->tm_mday = ValueBCD_2_HEX( pTime ->tm_mday );
pTimeAttr ->tm_hour = ValueBCD_2_HEX( pTime ->tm_hour );
pTimeAttr ->tm_min = ValueBCD_2_HEX( pTime ->tm_min );
pTimeAttr ->tm_sec = ValueBCD_2_HEX( pTime ->tm_sec );
}
else{
// 進(jìn)行數(shù)據(jù)的復(fù)制
memcpy((UINT8 *)pTimeAttr, (UINT8 *)pTime, sizeof(Time_Attr_t));
}
// 首先進(jìn)行FS 日期時(shí)間
err = fsFileTimeSet(pTimeAttr);
// 設(shè)定失敗,報(bào)錯(cuò)退出
if ( err ) {
ERROR_REPORT;
return APP_DRV_ERR;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -