📄 ds1302.c
字号:
#include "includes.h"
/****************************************************************************/
/*************************DS1302******************************************/
/* 字节写 */ //把一个字节写进1302
void writeChar(unsigned char data)
{
unsigned char i;
for (i = 0; i < 8; i++)
{
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
CLR_TIMER_IO;
if (data & 0x01)
{
SET_TIMER_IO;//如果输入的第i位为1,则IO口置为1,否则为0
}
asm volatile ("nop \n\t" ::);
SET_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
data >>= 1;
}
}
/* 字节读 */
unsigned char readChar(void)
{
unsigned char i;
unsigned char retVal = 0;
DDRB &= ~(1<<DDB4);//PB4设为输入上拉 读IO时,PB4设为输入
PORTB |= (1<<PORTB4);
for (i = 0; i < 8; i++)
{
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
retVal >>= 1;
if (PINB & 0x10) // (PINB & (1<<PORTB4))
{
retVal |= 0x80;//PB4为0则retval的第i位为0,为1则第i位为1
}
asm volatile ("nop \n\t" ::);
SET_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
}
DDRB |= (1<<DDB4);//PB4输出为1 IO口输出1
PORTB |= (1<<PORTB4);
return retVal;
}
// 寄存器设置 感觉是用来校准时间的,也用来设置时间
void setChipReg(unsigned char addr,unsigned char data)
{
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
SET_TIMER_REST;
asm volatile ("nop \n\t" ::);
writeChar(addr);//地址中有控制命令
writeChar(data);
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
CLR_TIMER_REST;
asm volatile ("nop \n\t" ::);
}
/* 寄存器读取 */
unsigned char getChipReg(unsigned char addr)
{
unsigned char retVal;
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
SET_TIMER_REST;
asm volatile ("nop \n\t" ::);
writeChar(addr);
retVal = readChar();
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
CLR_TIMER_REST;
asm volatile ("nop \n\t" ::);
return retVal;
}
// 写保护控制
void chipWriteProtect(unsigned char condition)
{
if (!condition)//condition为0将写保护关闭,为1打开
{
setChipReg(0x8E,0x00);//将写保护关闭
}
else
{
setChipReg(0x8E,0x80);//将写保护打开
}
}
// 启动计时
void chipClockStart(unsigned char condition)
{
unsigned char tmpChar;
unsigned char tmpPB = PORTB & 0x18;//取PB3,PB4,为了操作完能恢复
setChipReg(0x8E,0x00);//将写保护关了
tmpChar = getChipReg(0x81);//读sec寄存器的值,用来判断时钟是否打开
if (tmpChar & 0x80)//如果sec寄存器的第7位为1,说明时钟关闭
{
if (condition)//condition为1,打开时钟
{
setChipReg(0x80,(tmpChar&0x7F));//打开时钟
setChipReg(0x90,CHARGE_ON_2_3); // Just For This Routine
}
}
else//时钟本来就打开
{
if (!condition)//condition为0,关掉时钟
{
setChipReg(0x80,(tmpChar|0x80));//关掉时钟
}
}
setChipReg(0x8E,0x80);//写保护打开
tmpChar = PORTB & 0xE7;//这两行主要是还原PORTB口的值
PORTB = tmpChar | tmpPB;
}
// 充电寄存器设置
void setChargeReg(unsigned char chargeMode)
{
setChipReg(0x8E,0x00); // 可写
setChipReg(0x90,chargeMode);
setChipReg(0x8E,0x80);//不可写,即写保护打开
}
/* burstMode 写 */
void burstModeTimeWrite(unsigned char *pClock)
{
unsigned char i;
unsigned char tmpPB = PORTB & 0x38;//取PB3,PB4,PB5,在操作完可恢复
DDRB |= (1<<DDB5);//PB5输出0,即处于复位状态
PORTB &= ~(1<<PORTB5);
setChipReg(0x8E,0x00);//将写保护关了,可写
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
SET_TIMER_REST;
asm volatile ("nop \n\t" ::);
writeChar(0xBE);//设置为BURSTMODE,这种模式连续读/写8个时钟寄存器
for(i = 8;i > 0;i--)//不需要写入地址,固定是对那8个地址的操作,只需写入数据
{
writeChar(*pClock);
pClock++;
}
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
CLR_TIMER_REST;
asm volatile ("nop \n\t" ::);
setChipReg(0x8E,0x80);//写保护打开,不可写
i = PORTB & 0xC7;//还原PORTB的值
PORTB = tmpPB | i;
DDRB &= ~(1<<DDB5);//PB5输入上拉,不处于复位状态
PORTB |= (1<<PORTB5);
}
/* burstMode 读 */
void burstModeTimeRead(unsigned char *pClock)
{
unsigned char i;
unsigned char tmpPB = PORTB & 0x38;
DDRB |= (1<<DDB5);
PORTB &= ~(1<<PORTB5);
setChipReg(0x8E,0x00);
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
SET_TIMER_REST;
asm volatile ("nop \n\t" ::);
writeChar(0xBF);
for(i = 8;i > 0;i--)
{
*pClock = readChar();
pClock++;
}
CLR_TIMER_SCLK;
asm volatile ("nop \n\t" ::);
CLR_TIMER_REST;
asm volatile ("nop \n\t" ::);
setChipReg(0x8E,0x80);
i = PORTB & 0xC7;
PORTB = tmpPB | i;
DDRB &= ~(1<<DDB5);
PORTB |= (1<<PORTB5);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -