|
发表于 2008-2-1 09:17:54
|
显示全部楼层
我前两天刚做的, 用M16IO真接驱动DS12C887, 下面给出读写函数, 晶振是11.059MHz, 数据口接PORTD:
#define _REG_A 0x0A
#define _REG_B 0x0B
#define _REG_C 0x0C
#define _REG_D 0x0D
#define _REG_SEC 0x00
#define _REG_SEC_ALM 0x01
#define _REG_MIN 0x02
#define _REG_MIN_ALM 0x03
#define _REG_HOUR 0x04
#define _REG_HOUR_ALM 0x05
#define _REG_WKD 0x06
#define _REG_DATE 0x07
#define _REG_MONTH 0x08
#define _REG_YEAR 0x09
#define _REG_CENTURY 0x32 //DS12887这个字节是普通数据, 只有DS12C887才是世纪寄存器
//A寄存器
// -----------------------------------------------------------------
// | UIP | DV2 | DV1 | DV0 | RS3 | RS2 | RS1 | RS0 |
// -----------------------------------------------------------------
//UIP:是否正在更新时间
//DV2,DV1,DV0:用于打开/关闭振荡器, 复位计数链
//RS3,RS2,RS1,RS0:与方波频率有关的设置
//B寄存器
// -----------------------------------------------------------------
// | SET | PIE | AIE | UIE | SQWE | DM | 24/12 | DSE |
// -----------------------------------------------------------------
//SET:是否进入设置状态
//PIE, AIE, UIE, SQWE, DSE: 周期中断允许, 闹铃中断允许,
//更新结束中断允许, 方波输出允许, 夏时制允许(四月份的第一个周日)
//DM:指定时间数据的格式, 1为二进制格式, 0为BCD格式
//24/12:小时的格式
//C寄存器
// -----------------------------------------------------------------
// | IRQF | PF | AF | UF | 0 | 0 | 0 | 0 |
// -----------------------------------------------------------------
//IRQF:中断标志位
//PF:周期中断标志
//AF:闹铃中断标志
//UF:更新结束中断标志
//D寄存器
// -----------------------------------------------------------------
// | VRT | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
// -----------------------------------------------------------------
//VRT:只读, 正常为1, 为0则表时数据和时钟中的数据失效, 锂电池没电了
void DS12x887_Init(void)
{
//全部配置为输出引脚
_DS12x887_DATA_OUT;
_SET_BIT(_DDR(_TO_DS12x887_RW), _DS12x887_RW_PIN);
_SET_BIT(_DDR(_TO_DS12x887_CS), _DS12x887_CS_PIN);
_SET_BIT(_DDR(_TO_DS12x887_AS), _DS12x887_AS_PIN);
_SET_BIT(_DDR(_TO_DS12x887_DS), _DS12x887_DS_PIN);
_DS12x887_AS_LO;
_DS12x887_DS_LO;
_DS12x887_RW_LO;
_DS12x887_CS_HI;
}
void DS12x887_Write(unsigned char Add, unsigned char Data)
{
//
_DS12x887_CS_LO;
NOP();
NOP();
_DS12x887_DS_HI;
_DS12x887_RW_HI; //给出读信号
NOP();
NOP();
NOP();
NOP();
_DS12x887_AS_HI; //锁存信号高电平
NOP();
NOP();
_DS12x887_DATA_OUT; //数据口设置为输出
NOP();
NOP();
_DS12x887_OUT_DATA = Add; //给出地址
NOP();
NOP();
NOP(); //
_DS12x887_AS_LO; //锁存信号低电平
NOP();
NOP();
NOP();
_DS12x887_RW_LO; //给出写信号
NOP();
NOP();
NOP();
_DS12x887_OUT_DATA = Data; //写出数据
NOP();
NOP();
NOP();
NOP();
_DS12x887_RW_HI; //给出读信号
NOP();
NOP();
NOP();
_DS12x887_CS_HI; //片选信号高电平
NOP();
NOP();
_DS12x887_AS_HI;
NOP();
NOP();
_DS12x887_AS_LO;
_DS12x887_DS_LO;
_DS12x887_RW_LO;
}
unsigned char DS12x887_Read(unsigned char Add)
{
unsigned char temp = 0;
_DS12x887_CS_LO;
NOP();
NOP();
NOP();
_DS12x887_DS_HI;
_DS12x887_RW_HI; //给出读信号
NOP();
NOP();
_DS12x887_AS_HI; //锁存信号高电平
NOP();
NOP();
_DS12x887_DATA_OUT; //数据口设置为输出
_DS12x887_OUT_DATA = Add; //给出地址
NOP();
NOP();
_DS12x887_AS_LO; //锁存信号低电平
NOP();
NOP();
_DS12x887_DS_LO; //给出写信号
NOP();
NOP();
_DS12x887_DATA_IN; //端口方向设置为输入
NOP();
NOP();
temp = _DS12x887_IN_DATA; //读入数据
NOP();
_DS12x887_DS_HI; //
NOP();
NOP();
_DS12x887_AS_HI;
NOP();
NOP();
_DS12x887_DATA_OUT; //端口保持输出状态
_DS12x887_CS_HI; //片选信号高电平
_DS12x887_AS_LO;
_DS12x887_DS_LO;
_DS12x887_RW_LO;
return temp;
}
void DS12x887_WriteData(unsigned char Add, unsigned char Data)
{
unsigned char temp;
while(DS12x887_Read(_REG_A) & 0x80); //先读一下A寄存器, 直到UIP位为零
DS12x887_Write(Add, Data);
}
unsigned char IsDS12x887OutOfPower(void)
{
return (DS12x887_Read(_REG_D) & 0x80 != 0x80);
}
void DS12x887_ReadInfo(void)
{
unsigned char ret, i, regB;
unsigned char DTIsBCD = 0;
regB = DS12x887_Read(_REG_B);//先读出B寄存器中的内容, 其中的设置是不受复位影响的, 所以不能乱改
regB |= 0x80; //设置 SET位, 这样就可以进入设置状态
DS12x887_Write(_REG_B, regB);//再写回去
DS12x887_Write(_REG_A, 0x70);//关闭时钟振荡器和方波输出
DTIsBCD = !(regB & 0x04); //数据格式是否是BCD格式
//校验一下时间是否清空
ret = DS12x887_Read(_REG_SEC);
ret = DS12x887_Read(_REG_SEC_ALM);
ret = DS12x887_Read(_REG_MIN);
ret = DS12x887_Read(_REG_MIN_ALM);
ret = DS12x887_Read(_REG_HOUR);
ret = DS12x887_Read(_REG_HOUR_ALM);
ret = DS12x887_Read(_REG_WKD);
ret = DS12x887_Read(_REG_DATE);
ret = DS12x887_Read(_REG_MONTH);
ret = DS12x887_Read(_REG_YEAR);
for(i = _REG_YEAR + 1; i < 128; ++i)
ret = DS12x887_Read(i);
regB &= ~0x80; //取消息SET位
DS12x887_Write(_REG_B, regB); //恢复为运行状态
}
void DS12x887_Clear(void)
{
unsigned char temp, i, regB;
unsigned char DTIsBCD = 0;
regB = DS12x887_Read(_REG_B);//先读出B寄存器中的内容, 其中的设置是不受复位影响的, 所以不能乱改
regB |= 0x80; //设置 SET位, 这样就可以进入设置状态
DS12x887_Write(_REG_B, regB);//再写回去
DS12x887_Write(_REG_A, 0x70);//关闭时钟振荡器和方波输出
DTIsBCD = !(regB & 0x04); //数据格式是否是BCD格式
DS12x887_Write(_REG_SEC, 0); //清除秒
DS12x887_Write(_REG_SEC_ALM, 0); //清除秒闹钟
DS12x887_Write(_REG_MIN, 0); //清除分
DS12x887_Write(_REG_MIN_ALM, 0); //清除分
DS12x887_Write(_REG_HOUR, 1); //清除时
DS12x887_Write(_REG_HOUR_ALM, 1); //清除时
DS12x887_Write(_REG_WKD, 2); //清除星期, 2008年一月一日为星期二
DS12x887_Write(_REG_DATE, 1); //清除日期
DS12x887_Write(_REG_MONTH, 1); //清除月
DS12x887_Write(_REG_YEAR, 8); //清除年
//清除数据
for(i = _REG_D + 1; i < 128; ++i)
DS12x887_Write(i, 0);
regB &= ~0x80; //取消息SET位
DS12x887_Write(_REG_B, regB); //恢复为运行状态
} |
|