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

📄 pmp_rtc_driver.c

📁 嵌入式系统下的文件管理处理,和基本图片jpg格式处理原代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-------------------------------------------------*
* $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 + -