|
发表于 2012-2-22 15:16:33
|
显示全部楼层
// ===============================================================================================
// 文件名称:PCF8563.c
// 芯片类型: MSP430F149
// 开发软件: IAR Embedded Workbench V3.2 , Windows XP
// 开发时间:2007年07月08日 --- 2007年07月10日
// 程序功能:使用M430的P4.6、P4.7对外部的IIC时钟进行读写操作
// 编写人员:吕云曾
// 联系方式:13845052176 lvyunzeng@163.com
//=================================================================================================
//==连接芯片的管脚连接==
// --- --- --- VCC
// PCF8563 | 10k 10k MSP430
// |--------| | | | |----------|
// 32.768KHz---|OSI VDD|--- | | | |
// |------|OSO CLK| | | | |
// P1.7-+-------|INT SCL|<-----+---|-|P4.7 |
// | |--|VSS SDA|<---------+>|P4.6 |
// 10K | |--------| |----------|
// VCC--- \|/ GND
//========================================= 头文件 ================================================
#include <msp430x14x.h>
//========================================== 宏定义 ===============================================
//========================== 宏定义 =================================
#define Uchar unsigned char
#define uchar unsigned char
#define Uint unsigned int
#define Ulong unsigned long
//== PCF8563 定义 ==
#define SCL0 ClrP2(2)
#define SCL1 SetP2(2)
#define SDA0 ClrP2(1)
#define SDA1 SetP2(1)
#define DIR_IN P2DIR &=~ BIT1 //I/O口为输入
#define DIR_OUT P2DIR |= BIT1 //I/0口为输出
#define SDA_IN ((P2IN >> 1) & 0x01) //Read SDA
#define ClrP2(n) P2OUT&=(~(1<<n))
#define SetP2(n) P2OUT|=(1<<n)
//======================================= 变量定义 =================================================
uchar g8563_Store[4]; //== 时间交换区,全局变量声明 ==
/*
PCF8563_time[0] --- 秒 ;
PCF8563_time[1] --- 分 ;
PCF8563_time[2] --- 小时 ;
PCF8563_time[3] --- 日 ;
PCF8563_time[4] --- 星期 ;
PCF8563_time[5] --- 月 ;
PCF8563_time[6] --- 年 ;
*/
uchar PCF8563_time[7];
//uchar c8563_Store[4]={0x00,0x59,0x07,0x01}; //== 写入时间初值:星期一 07:59:00 ==
uchar Set8563_time[7]={0x00,0x59,0x07,0x0A,0x02,0x07,0x07}; //==写入时间初值:2007年07月星期二 10日 07:59:00 ==
//======================================== 函数声明 ================================================
void InitMain (void); //=== 系统初始化函数 ===
void delayX10ms(int count); //===延迟===
void Delay();
void Start();
void Stop();
void WriteACK();
void writenoack();
void WaitACK();
void writebyte(uchar wdata);
uchar Readbyte();
void writeData(uchar address,uchar mdata);
uchar ReadData(uchar address) ; /*单字节*/
void ReadData1(uchar address,uchar count,uchar * buff); /*多字节*/
void P8563_Read();
void P8563_gettime();
void P8563_settime();
void P8563_init(); //== 初始化时间 ==
//=================================================================================================
//========================================== 主函数 ==============================================
//=================================================================================================
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; //=== Stop watchdog timer ===
InitMain (); //=== 系统初始化函数 ===
P8563_init(); //== 初始化时间 ==
_EINT(); //== Enable interrupts ===
while (1)
{
P8563_gettime();
P1OUT ^= BIT6; //===P4.0取反输出===
delayX10ms(50);
P1OUT ^= BIT7; //===P4.0取反输出===
delayX10ms(50);
}
}
//=============================================================================
//函 数 名: void InitMain (void)
//功 能:系统初始化
//入口参数:NO
//返 回 值:NO
//=============================================================================
//----------------------- 系统初始化函数 ----------------------------
void InitMain (void)
{
unsigned int i;
WDTCTL=WDTPW+WDTHOLD; //停止看门狗
//--- 系统时钟配置 ---
BCSCTL2 |= SELS; //SMCLK = XT2 -----
//MCLK = DCOCLK
do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
for (i = 0xFF; i > 0; i--); // Time for flag to set
}
while ((IFG1 & OFIFG)); // OSCFault flag still set?
BCSCTL2 |= SELM_2 + SELS; // MCLK = SMCLK = XT2 (safe)
BCSCTL2 |= DIVM1 + DIVM0; // MCLK = XT2/8
//-----PCF8563 INT中断 ----
P2DIR &= ~BIT0;
P2DIR &= ~BIT3;
P2DIR |= BIT1;
P2DIR |= BIT2;
P1DIR = 0xff;
/*
//--- 4X4按键I/O配置 ---
P2DIR = 0; //== 将P2口所有的管脚在初始化的时候设置为输入方式 ==
P2SEL = 0; //== 将P2口所有的管脚设置为一般I/O口 ==
P2DIR |= BIT4; //== 将P2.4 P2.5 P2.6 P2.7设置为输出方向 ==
P2DIR |= BIT5;
P2DIR |= BIT6;
P2DIR |= BIT7;
P2OUT = 0xF0; //== 先输出低电平 ==
//-----PCF8563 INT中断 ----
P1DIR = 0x00;
P1IES = 0Xff;
P1IE = 0x80; //列线上升沿允许P1中断
//--- LED 测试端口 ---
//P4DIR |= 0x01; //== Set P4.0 to output direction ==
//--- 液晶数据线接口 ---
P5DIR=0xff; //== 设置IO口的方向为输出 ==
P4DIR=0xff; //== 设置IO口的方向为输出 ==
*/
}
//=============================================================================
//函 数 名: delayX10ms(int count)
//功 能:延时子函数
//入口参数:int count
//返 回 值:NO
//=============================================================================
void delayX10ms(int count) //===延迟===
{
unsigned int i,j,k;
for (i=0; i<count; i++)
for(j=0; j<10; j++)
for(k=0; k<120; k++);
}
//===================================================================
//============= 内部函数,延时1 ====================================
//===================================================================
void Delay()
{
int i ; //== IIC的读写速度小于400KHz ==
for(i=0;i<20;i++); //== 根据晶振频率制定延时时间 ==
} //== 此程序采用 8MHz 系统时钟 ==
//===================================================================
//============= 内部函数,I2C开始 =================================
//===================================================================
void Start()
{
SDA1 ;
SCL1 ;
Delay();
SDA0 ;
Delay();
SCL0 ;
}
//===================================================================
//============= 内部函数,I2C结束 ===============================
//===================================================================
void Stop()
{
SDA0 ;
SCL0 ;
Delay();
SCL1 ;
Delay();
SDA1 ;
Delay();
}
//===================================================================
//============= 内部函数,输出ACK=0 ============================
//===================================================================
void WriteACK()
{
SDA0 ;
Delay();
SCL1 ;
Delay();
SCL0 ;
}
//===================================================================
//============= 内部函数,输出ACK=1 ============================
//===================================================================
void writenoack()
{
SDA1 ;
Delay();
SCL1 ;
Delay();
SCL0 ;
}
//===================================================================
//============= 内部函数,等待ACK ================================
//===================================================================
void WaitACK()
{
uchar errtime = 0 ;
SDA1 ;
Delay(); //== 读ACK ==
SCL1 ;
Delay();
DIR_IN;
while((SDA_IN == 0x01)&(errtime<=50)) //== 防止读取信号出现死循环==
{
errtime++;
if(errtime==50)
{
Stop();
}
}
errtime = 0 ;
DIR_OUT;
SCL0 ;
Delay();
}
//===================================================================
//============= 内部函数.输出数据字节 ==============================
//===================================================================
void writebyte(uchar wdata)
{
uchar i;
for(i=0;i<8;i++)
{
if(wdata&0x80) SDA1 ;
else SDA0 ;
wdata<<=1;
SCL1 ;
Delay();
SCL0 ;
}
WaitACK();
}
//===================================================================
//============= 内部函数.输入数据 ================================
//===================================================================
uchar Readbyte()
{
uchar i,bytedata;
SDA1 ;
DIR_IN ;
for(i=0;i<8;i++)
{
SCL1 ;
bytedata<<=1;
bytedata|=SDA_IN;
SCL0 ;
Delay();
}
DIR_OUT ;
return(bytedata);
}
//===================================================================
//============= 输出数据->pcf8563 ================================
//===================================================================
void writeData(uchar address,uchar mdata)
{
Start();
writebyte(0xa2); //== 写命令 ==
writebyte(address); //== 写地址 ==
writebyte(mdata); //== 写数据 ==
Stop();
}
//===================================================================
//============= 输入数据<-pcf8563 ===============================
//===================================================================
uchar ReadData(uchar address) //== 单字节 ==
{ uchar rdata;
Start();
writebyte(0xa2); //== 写命令 ==
writebyte(address); //== 写地址 ==
Start();
writebyte(0xa3); //== 读命令 ==
rdata=Readbyte();
writenoack();
Stop();
return(rdata);
}
void ReadData1(uchar address,uchar count,uchar * buff) //== 多字节 ==
{ uchar i;
Start();
writebyte(0xa2); //== 写命令 ==
writebyte(address); //== 写地址 ==
Start();
writebyte(0xa3); //== 读命令 ==
for(i=0;i<count;i++)
{
buff=Readbyte();
if(i<count-1) WriteACK();
}
writenoack();
Stop();
}
//===================================================================
//============= 内部函数,读入时间到内部缓冲区 ====================
//===================================================================
void P8563_Read()
{ uchar time[7];
ReadData1(0x02,0x07,time);
//g8563_Store[0]=time[0]&0x7f; //== 秒 ==
//g8563_Store[1]=time[1]&0x7f; //== 分 ==
//g8563_Store[2]=time[2]&0x3f; //== 小时 ==
//g8563_Store[3]=time[4]&0x07; //== 星期 ==
PCF8563_time[0]=time[0]&0x7f; //== 秒 ==
PCF8563_time[1]=time[1]&0x7f; //== 分 ==
PCF8563_time[2]=time[2]&0x3f; //== 小时 ==
PCF8563_time[3]=time[3]&0x7f; //== 日 ==
PCF8563_time[4]=time[4]&0x07; //== 星期 ==
PCF8563_time[5]=time[5]&0x7f; //== 月 ==
PCF8563_time[6]=time[6]&0x7f; //== 年 ==
}
//===================================================================
//============= 读入时间到内部缓冲区----外部调用 ================
//===================================================================
void P8563_gettime()
{
P8563_Read();
if(g8563_Store[0]==0)
P8563_Read(); //== 如果为秒=0,为防止时间变化,再读一次 ==
}
//===================================================================
//============= 写时间修改值 =====================================
//===================================================================
void P8563_settime()
{
uchar i;
//for(i=2;i<=4;i++) { writeData(i,g8563_Store[i-2]); }
//writeData(6,g8563_Store[3]);
for(i=2;i<=8;i++)
writeData(i, PCF8563_time[i-2]);
}
//===================================================================
//==================== 初始化时间 ===================================
//===================================================================
void P8563_init()
{
uchar i;
// if((ReadData(0xa)&0x3f)!=0x8)
//== 检查是否第一次启动,是则初始化时间 ==
// {
for(i=0;i<=6;i++) PCF8563_time=Set8563_time; //== 初始化时间 ==
P8563_settime();
writeData(0x0,0x00); //== control1=0x00 ==
writeData(0x9,0x00); //== 0分 报警 ==
//writeData(0xa,0x8); //== 8:00报警 ==
writeData(0x1,0x12); //== control2 报警有效 ==
//writeData(0xd,0xf0); //== 频率输出 ==
// }
}
//=============================================================================
//端口1中断函数
//多中断中断源:P1IFG.0~P1IFG7
//进入中断后应首先判断中断源,退出中断前应清除中断标志,否则将再次引发中断
//=============================================================================
#pragma vector=PORT1_VECTOR
__interrupt void Port1()
{
//== 以下为参考处理程序,不使用的端口应当删除其对于中断源的判断 ==
if((P1IFG&BIT7) ==BIT7)//== 处理P1IN.7中断 ==
{
P1IFG &= ~BIT7; //== 清除中断标志 ==
//以下填充用户代码
writeData(0x1,0x12); //== 清除分中断标志位 令AF=0 ==
P4OUT ^= 0x01; //== P4.0取反输出===
}
} |
|