Quantcast
Channel: MSP 低功耗微控制器论坛 - 最近的话题
Viewing all articles
Browse latest Browse all 3634

msp430f149 外接时钟芯片PCF8563问题

$
0
0

请问为什么我跑程序后不管是读秒,读分,读时都是0x01,然后就不动了,用的是PCF8563,希望发现问题的朋友给下建议,谢谢!

程序如下
#include "msp430.h"
#define uchar unsigned char
#define uint unsigned int
#define PCF8563_RTC 0xA3 /* 定义器件地址 */
#define SDA_1 P3OUT |= BIT1 //SDA = 1
#define SDA_0 P3OUT &=~ BIT1 //SDA = 0
#define SCL_1 P3OUT |= BIT3 //SCL = 1
#define SCL_0 P3OUT &=~ BIT3 //SCL = 0
#define DIR_IN P3DIR &=~ BIT1 //I/O口为输入
#define DIR_OUT P3DIR |= BIT1 //I/0口为输出
#define SDA_IN ((P3IN >> 6) & 0x01) //Read SDA
//#define SDA_IN (P3IN & 0x01) //Read SDA

#define over_time 255 /*应答超时门限*/
unsigned char sec;
unsigned char min;
unsigned char hour;
unsigned char month;
unsigned char day;
//unsigned char week;
unsigned char year;
void Delay();
void iic_start(void);
void iic_stop(void);
void iic_ack();
void iic_Send_byte(uchar WriteData);
uchar rev(void);
void iic_send_add_byte(uchar add,uchar bat);
uchar iic_rec_add_byte(uchar add);
void time_init();
void pcf_init();
uchar bcd_dec(uchar bat);
void delay_kk(uint k);
uchar sec1,min1,hour1,day1,month1,year1; //PCF8563读出的变量和代转换成的十进制变量
void chushi(void);
void DelayNus(uint n);
void chushi(void)
{
uchar i;
//unsigned char g,s;

//WDTCTL = WDTPW + WDTHOLD; //关狗
/*------选择系统主时钟为8MHz-------*/
BCSCTL1 &= ~XT2OFF; //打开XT2高频晶体振荡器
do
{
IFG1 &= ~OFIFG; //清除晶振失败标志
for (i = 0xFF; i > 0; i--); //等待8MHz晶体起振
}
while ((IFG1 & OFIFG)); //晶振失效标志仍然存在?
BCSCTL2 |= SELM_2 + SELS; //MCLK和SMCLK选择高频晶振
TACTL |= TASSEL_2 + ID_3; //计数时钟选择SMLK=8MHz,1/8分频后为1MHz
}
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
chushi();
//uchar sec1,min1,hour1,day1,month1,year1; //PCF8563读出的变量和代转换成的十进制变量
//LCD1602_Init();
iic_send_add_byte(0x00,0x20); // 关闭时钟
//delay_kk(1000);
DelayNus(6);
time_init(); //时钟芯片初始时间设置
pcf_init();
DelayNus(6);
//delay_kk(1000);
while(1)
{
sec=0x7f&iic_rec_add_byte(0x02); //读取秒
min=0x7f&iic_rec_add_byte(0x03); //读取分钟
hour=0x3f&iic_rec_add_byte(0x04); //读取小时
day=0x3f&iic_rec_add_byte(0x05); //读取天数
month=0x1f&iic_rec_add_byte(0x07); //读取月
year=0xff&iic_rec_add_byte(0x08); //读取年
sec1=bcd_dec(sec); //将读取的BCD码秒转换成十进制秒以便运算
min1=bcd_dec(min);
hour1=bcd_dec(hour);
day1=bcd_dec(day);
month1=bcd_dec(month);
year1=bcd_dec(year);
//display_time(sec1,min1,hour1,dat1,moom1,year1); //LCD1602显示时间
}
}

/*******************************************
函数名称:DelayNus
功 能:实现N个微秒的延时
参 数:n--延时长度
返回值 :无
说明 :定时器A的计数时钟是1MHz,CPU主频8MHz
所以通过定时器延时能够得到极为精确的
us级延时
********************************************/
void DelayNus(uint n)
{
CCR0 = n;
TACTL |= MC_1; //增计数到CCR0
while(!(TACTL & BIT0)); //等待
TACTL &= ~MC_1; //停止计数
TACTL &= ~BIT0; //清除中断标志
}

//-----------延时用于稳定-------------
void delay_kk(uint k)
{
while(k--);
}

void Delay() //略微延时 6us约>4.7us
{
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
_NOP();
}


/**--------------------------------------------------------------------------------
调用方式:void Start(void) ﹫2002/01/2 40 4
函数说明:私有函数,I2C专用,起始条件函数
数据线下降沿而时钟线为高电平时为起始条件
---------------------------------------------------------------------------------*/
void iic_start(void)
{
DIR_OUT;
SDA_1;
SCL_1;
DelayNus(6); //INI
SDA_0;
DelayNus(6); //START
SCL_0;

}


/**--------------------------------------------------------------------------------
调用方式:void Stop(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用,结束条件函数
数据线上降沿而时钟线为高电平时为结束条件
---------------------------------------------------------------------------------*/
void iic_stop(void)
{
DIR_OUT;
SCL_0;
SDA_0;
DelayNus(6);
SCL_1;
DelayNus(6); //INI
SDA_1; //STOP
DelayNus(6);
}

void iic_ack() //应答信号
{

/*DIR_OUT; //把P3.3设为输出
SDA_1;
SCL_0;
DelayNus(6);
SDA_0; //置SDA为高电平 发出应答信号
DelayNus(6); //时钟低电平周期大于4μs
SCL_1;
DelayNus(6);
SCL_0; //清时钟线,钳住I2C总线以便继续接收
DelayNus(6);
SDA_1;*/
uchar i=0;
SCL_1;
DelayNus(6);
while((P3OUT==BIT1)&&(i<255))
i++;
SCL_0;
DelayNus(6);
}

/**--------------------------------------------------------------------------------
调用方式:Sendbyte(unsigned char WriteData) ﹫2001/07/0 5
函数说明:私有函数,I2C专用,发送一字节
---------------------------------------------------------------------------------*/
void iic_Send_byte(uchar WriteData)
{
unsigned char i;
for (i=0; i<8; i++)
{

DIR_OUT; //把P3.1设为输出
if (((WriteData >> 7) & 0x01) == 0x01) //输出8位到RTC
{
SDA_1;
}
else
{
SDA_0;
}
DelayNus(6);
SCL_1; //时钟高电平
WriteData = WriteData << 1; //待发数据左移一位
DelayNus(6); //保证时钟高电平周期大于4μs
SCL_0; //时钟置为低电平,发送一位
DelayNus(6);
}

DIR_IN; //把P3.3设为输入
DelayNus(6);
SCL_0; //置时钟为低电平
DelayNus(6);
}

uchar rev(void)
{
//unsigned errtime=over_time; /*因故障接收方无ACK,超时值为255。*/
SDA_1; //置高数据线 准备接收应答位
DelayNus(6); //时钟低电平周期大于4μs
SCL_1;
DelayNus(6);
DIR_IN; //把P3.3设为输入

//while (SDA_IN == 0x01) /*此语句可有可无*/
//{
// errtime--;
//if (!errtime)
// {
// Stop();
// return 0x00;
// }
//}*/

SCL_0;
DelayNus(6);
return(0x01); //返回应答信号
}

void iic_send_add_byte(uchar add,uchar bat) //向某个地址发送某数据
{
iic_start();
iic_Send_byte(0xa3);
iic_ack();
iic_Send_byte(add);
iic_ack();
iic_Send_byte(bat);
iic_ack();
iic_stop();
}


uchar iic_rec_add_byte(uchar add) //从某个地址读出数据
{
uchar temp;
iic_start();
iic_Send_byte(0xa2);
iic_ack();
iic_Send_byte(add);
iic_ack();
iic_start();
iic_Send_byte(0xa3);
iic_ack();
temp=rev();
iic_stop();
return temp;
}

//-----------时间预设定值---------
void time_init()
{
iic_send_add_byte(0x02,0x50); //0秒
iic_send_add_byte(0x03,0x59); //0分钟
iic_send_add_byte(0x04,0x23); //0小时
iic_send_add_byte(0x05,0x26); //26号
iic_send_add_byte(0x07,0x05); //5月 20世纪的
iic_send_add_byte(0x08,0x14); //2014年
}

//----------------PCF8563初始化-----------------
void pcf_init()
{
iic_send_add_byte(0x00,0x00); //启动时钟
}


//----------------BCD转10进制-----------
uchar bcd_dec(uchar bat)
{
uchar temp1,temp2,tol;
temp1=bat&0x0f;
temp2=(bat&0xf0)>>4;
tol=temp2*10+temp1;
return tol;
}


Viewing all articles
Browse latest Browse all 3634

Trending Articles