📄 pmp_rtc_driver.c
字号:
/*-------------------------------------------------*
* $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
* 齐兰柱 准备一个新的代码分支
*
* Revision 1.2 2006/12/12 00:30:38 lanzhu
* 删除没有用的程序, 去除 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
* 加入了 系统 冷启动 热启动的判断
*
* Revision 1.4 2006/09/26 07:19:20 lanzhu
* 添加函数 UINT16 SPMP_RTC_Set32KOut( UINT16 Flag )
*
* Revision 1.3 2006/09/26 00:52:39 lanzhu
* 将 RTC 时间 和 FS 时间进行了协调使用
*
* Revision 1.2 2006/08/31 03:29:03 lanzhu
* 对各个API 进行测试
*
* Revision 1.1 2006/08/30 00:50:28 lanzhu
* add rtc driver
*
*
*--------------------------------------------------*/
// #define RTC_TEST
/*
1. 测试 日期的写入 和读出是否符合预期
BCD mode test OK!
HEX mode test OK!
2. 测试 Time 的写入 和读出是否符合预期
BCD mode test OK!
HEX mode test OK!
3. 对读数据进行测试
SCL 的速度进行测试, 加快速度, 减小一次的时间
|---------| |------
__| |______________|
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 内部寄存器的地址值
enum
{
RTC_ADDR_SECOND = 0x00, // 秒
RTC_ADDR_MINITE = 0x01, // 分钟
RTC_ADDR_HOUR = 0x02, // 小时
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, // 时间模块在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)
// 对于RTC 设备来说, 地址的最后 1 BIT 的意义
#define FLAG_WRITE_DATA (0)
#define FLAG_READ_DATA (1)
#define RTC_INTERNAL_ADDR_MAX (0x0f)
// 数据写入时的模式 0
#define RTC_WRITE_MODE_0 (0)
// 数据读出时的模式 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 的时间值
//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 );
// 设定 RTC 的时间值
static UINT16 SPMP_RTC_SetH_M_S( struct RTCtime_t *pTime_t );
// 设定 RTC 的日期值
static UINT16 SPMP_RTC_SetY_M_D_W( struct RTCdate_t *pDate_t );
// 设置数据的格式
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
// 进行测试, 在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;
// 设定日期时间
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中一次读取年月日时分秒星期信息
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];
// 判断输入参数是否合法
if ( (NULL == pDt) || (NULL == pWeek))
{
ERROR_REPORT;
return APP_DRV_ERR;
}
memset(buffer, '\0', sizeof(buffer));
// 从RTC 中读出 秒、分、时、星期、月、年 信息
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;
}
/************************************************************************/
/* 获得系统是否为冷启动
input:
pFlag [out] 存放标志的地址指针
output:
0 冷启动
非0值 热启动
func:
note:
*/
/************************************************************************/
UINT16 SPMP_RTC_GetColdStartFlag( void )
{
UINT8 buf[0x10];
memset(buf, '\0', sizeof(buf));
// 从 RTC 寄存器中读出数据
read_RTC_addr(RTC_ADDR_ALARM_B, 0x03, buf);
// 与特殊的字符串进行比较
if ( strcmp(buf, SPECIAL_STR))
{
return COLD_START_FLAG; // 冷启动
}
return HOT_START_FLAG; // 热启动
}
/************************************************************************/
/* 清除 冷启动标志
input: void
output: void
func:
将冷启动标志设置为无效
note:
*/
/************************************************************************/
void SPMP_RTC_ClrColdStartFlag( void )
{
UINT8 buf[0x10];
strcpy(buf, SPECIAL_STR);
// 从 RTC 寄存器中读出数据
write_RTC_addr(RTC_ADDR_ALARM_B, 0x03, buf);
memset(buf, '\0', sizeof(buf));
// 读出数据进行比较, 判断写入是否成功
read_RTC_addr(RTC_ADDR_ALARM_B, 0x03, buf);
if ( strcmp(buf, SPECIAL_STR) )
{
ERROR_REPORT;
}
return;
}
/************************************************************************/
/* 设置 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;
}
/************************************************************************/
/* 设定 年月日 时分秒 星期
input:
pTimeAttr [in] 年月日时分秒
WeekDay [in] 星期
output:
0 成功, 非0值失败
func:
设定日期时间星期
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;
// 如果输入的数据是 BCD 编码格式, 需要将数据转换为 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{
// 进行数据的复制
memcpy((UINT8 *)pTimeAttr, (UINT8 *)pTime, sizeof(Time_Attr_t));
}
// 首先进行FS 日期时间
err = fsFileTimeSet(pTimeAttr);
// 设定失败,报错退出
if ( err ) {
ERROR_REPORT;
return APP_DRV_ERR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -