请问为什么我跑程序后不管是读秒,读分,读时都是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;}
Susan Yang:
您可以在 www.ti.com/…/slaa443.pdf 下载例程参考一下
fet140_i2c_02.c I2C, Master Interface to PCF8574, Read/Write
user5767411:
回复 Susan Yang:
您好,我也参考过这个例程,但我用的是msp430f149 ,可是这里面一些关于I2C的宏定义用不了,只能在MSP430x15x和 MSP430x16x 里能用。
user5767411:
回复 灰小子:
您好,现在可以可以读秒 读分钟了,但是读到的秒不是从0开始的,是从80多开始往0度,初始的分钟也是85,秒跟分钟不是0~59BCD码吗,为什么会出现80多,我检查了一下读写程序,没发现什么错误,您遇见过这种情况吗?程序如下:
#include "msp430.h"
#define PCF8563_RTC0xA2/* 定义器件地址 */
#define SDA_1P3OUT |=BIT1//SDA = 1
#define SDA_0P3OUT &=~ BIT1//SDA = 0
#define SCL_1P3OUT |=BIT3//SCL = 1
#define SCL_0P3OUT &=~ BIT3//SCL = 0
#define DIR_INP3DIR &=~ BIT1//I/O口为输入
#define DIR_OUTP3DIR |=BIT1//I/0口为输出
#define SDA_IN((P3IN >> 1) & 0x01)//Read SDA#define over_time 255/*应答超时门限*/
unsigned char Seconds;
unsigned char Minutes;
unsigned char hour;
unsigned char month;
unsigned char day;
unsigned char week;
unsigned char year;
unsigned char shiwei;
unsigned char Seconds1;
unsigned char Minutes1;
unsigned char hour1;
unsigned char month1;
unsigned char day1;
unsigned char week1;
unsigned char year1;
unsigned char shiwei1;
unsigned char temp1;
unsigned char temp2;
unsigned int tol;/****************************************************************************
* 名称:Sys_Ini()
* 功能:系统初始化
* 入口参数:无
* 出口参数:无
****************************************************************************/
void Sys_Ini(void)
{unsigned int i;WDTCTL = WDTPW + WDTHOLD;// Stop WDTBCSCTL1 &= ~XT2OFF;// XT2ondo{IFG1 &= ~OFIFG;// Clear OSCFault flagfor (i = 0xFF; i > 0; i–);// Time for flag to set}while ((IFG1 & OFIFG));// OSCFault flag still set?BCSCTL2 |= SELM_2 + SELS + DIVS_3;// MCLK/8 = SMCLK = XT2/8 (safe)P3DIR |= 0xff;// P4output//P5DIR |= 0x0f;
}/****************************************************************************
* 名称:Delay1us()
* 功能:us单位的延时函数
* 入口参数:us
* 出口参数:无
****************************************************************************/
void Delay1us(unsigned char us)
{unsigned char i;while (us){for(i=0;i<20;i++);–us;}
}
/****************************************************************************
* 名称:DelayMS()
* 功能:ms级单位的延时函数
* 入口参数:dly
* 出口参数:无
****************************************************************************/
voidDelayMS(unsigned intdly)//延时1ms
{unsigned inti;
for(; dly>0; dly–) for(i=0; i<1135; i++);
}/*********************************************************************************
* 名称:Delay()
* 功能:短软件延时
* 入口参数:n延时参数 : 1us
* 出口参数:无
**********************************************************************************/void Delay(unsigned int n)
{unsigned int i;for (i=0; i<n;i++);
}/**——————————————————————————–
调用方式:void Init(void) ﹫2002/01/2 40 4
函数说明:私有函数,I2C专用,I2C初始化函数
———————————————————————————*/
void Init(void)
{SDA_1;//拉高数据线Delay(5);SCL_1;//时钟保持高电平Delay(5);
}/**——————————————————————————–
调用方式:void Start(void) ﹫2002/01/2 40 4
函数说明:私有函数,I2C专用,起始条件函数数据线下降沿而时钟线为高电平时为起始条件
———————————————————————————*/
void Start(void)
{DIR_OUT;SDA_1;SCL_1; Delay(5);//INISDA_0; Delay(5);//STARTSCL_0;
}
/**——————————————————————————*//**——————————————————————————–
调用方式:void Stop(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用,结束条件函数数据线上降沿而时钟线为高电平时为结束条件
———————————————————————————*/
void Stop(void)
{DIR_OUT;SCL_0; SDA_0; Delay(5); SCL_1; Delay(5);//INISDA_1;//STOPDelay(5);
}/**——————————————————————————–
调用方式:SendByte(unsigned char WriteData) ﹫2001/07/0 5
函数说明:私有函数,I2C专用,发送一字节
———————————————————————————*/
void SendByte(unsigned char WriteData)
{unsigned char i;for (i=0; i<8; i++){DIR_OUT;//把P4.7设为输出if (((WriteData >> 7) & 0x01) == 0x01)//输出8位到RTC{SDA_1;}else{SDA_0;}Delay(5);SCL_1;//时钟高电平WriteData = WriteData << 1;//待发数据左移一位Delay(5);//保证时钟高电平周期大于4μsSCL_0;//时钟置为低电平,发送一位Delay(5);}DIR_IN;//把P4.7设为输入Delay(5);SCL_0;//置时钟为低电平Delay(5);}/**——————————————————————————–
调用方式:unsigned char ReadByte(void) ﹫2001/07/0 5
函数说明:私有函数,I2C专用,接收一字节
———————————————————————————*/
unsigned char ReceiveByte(void)
{unsigned char i;unsigned char TempBit= 0;unsigned char TempData = 0;SDA_1;//拉高数据线Delay(5);DIR_IN;//把P4.7设为输入for (i=0; i<8; i++)//主机接收8位{SCL_1;//置时钟为高电平Delay(5);//时钟低电平周期大于4.7μsif (SDA_IN == 0x01 )//判断输入最低位是否为1{TempBit = 1;}else{TempBit = 0;}TempData = (TempData << 1) | TempBit;//数据左移一位且接收1位数据SCL_0;// 置时钟为低电平Delay(5);}DIR_OUT;//把P4.7设为输出return(TempData);//返回接收的数据
}
/**——————————————————————————–
调用方式:unsigned char ReceiveAck(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用,等待从器件接收方的应答
———————————————————————————*/
unsigned char ReceiveAck(void)
{//unsigned errtime=over_time;/*因故障接收方无ACK,超时值为255。*/SDA_1;//置高数据线 准备接收应答位Delay(5);//时钟低电平周期大于4μsSCL_1;Delay(5);DIR_IN;//把P4.7设为输入//while (SDA_IN == 0x01)/*此语句可有可无*///{// errtime–; //if (!errtime) // {//Stop();// return 0x00; // }//}*/SCL_0;Delay(5);return(0x01);//返回应答信号}/**——————————————————————————–
调用方式:void Acknowledge(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。
——————————————————————————–*/
void Acknowledge(void)
{DIR_OUT;//把P4.7设为输出 SDA_1;SCL_0;Delay(5);SDA_0;//置SDA为高电平 发出应答信号Delay(5);//时钟低电平周期大于4μsSCL_1;Delay(5);SCL_0;//清时钟线,钳住I2C总线以便继续接收Delay(5);SDA_1;
}/**——————————————————————————–
调用方式:void Acknowledge(void) ﹫2001/07/0 4
函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号(拒绝应答)。
——————————————————————————–*/
void NAcknowledge(void)
{DIR_OUT;//把P4.7设为输出SDA_0;SCL_0;Delay(5);SDA_1;//置SDA为高电平 发出应答信号Delay(5);SCL_1;Delay(5);//时钟低电平周期大于4μsSCL_0;//清时钟线,钳住I2C总线以便继续接收Delay(5);SDA_0;
}/*******************************************************************向有子地址器件发送1字节数据函数
函数原型: unsigned char ReadByte(unsigned char dev_address,unsigned char sub_address);
功能:从启动总线到发送地址,子地址,结束总线的全过程,从器件地址dev_address,子地址sub_address.如果返回1表示操作成功,否则操作有误。
注意:使用前必须已结束总线。
********************************************************************/
unsigned char ReadByte(unsigned char dev_address/*dev_address*/,unsigned char sub_address/*sub_address*/)
{unsigned char RecData= 0;Start();//启动总线SendByte(dev_address);//发送器件地址ReceiveAck();SendByte(sub_address);//发送器件子地址ReceiveAck();Delay(100);Start();//重新启动总线SendByte(dev_address + 0x01);ReceiveAck();RecData= ReceiveByte();NAcknowledge();Stop();//结束总线return(RecData);
}/*******************************************************************向有子地址器件读取1字节数据函数
函数原型: unsigned char WriteByte(unsigned char dev_address,unsigned char sub_address, unsigned char sendData);
功能:从启动总线到发送地址,子地址,结束总线的全过程,从器件地址sla,子地址suba.如果返回1表示操作成功,否则操作有误。
注意:使用前必须已结束总线。
********************************************************************/unsigned char WriteByte(unsigned char dev_address,unsigned char sub_address, unsigned char sendData){Start();//启动总线SendByte(dev_address);//发送器件地址if(ReceiveAck()==0x01)//判断是否出错{SendByte(sub_address);//发送器件子地址if(ReceiveAck()==0x01)//判断是否出错{SendByte(sendData);//发送数据if(ReceiveAck()==0x01)//判断是否出错 {Stop();//结束总线return(0x01);}else{Stop();//结束总线return(0x00);}}else{Stop();return(0x00);}}else{Stop();return(0x00);}
}/****************************************************************************
* 名称:DelayNS()
* 功能:长软件延时调试时用
* 入口参数:dly延时参数 : 1ms
* 出口参数:无
****************************************************************************/
voidDelayNS(unsigned intdly)
{unsigned inti,j;
for(j=0; j<=dly; j++) {for(i=0; i<1135; i++);}
}/********************************************************************************
*函数名: Rtc_ReadTime()
*参数: 无
*返回值: true(OK);false(ERROR)
*描述: 从Rtc读取时间
*编写: bobo.li
*版本信息:
********************************************************************************/
void Rtc_ReadTime(void)
{ Seconds = ReadByte(PCF8563_RTC,0x02)&0x7f; //读秒Minutes = ReadByte(PCF8563_RTC,0x03)&0x7f;//读分hour = ReadByte(PCF8563_RTC,0x04)&0x3f;//读时day= ReadByte(PCF8563_RTC,0x05)&0x3f;//读天week= ReadByte(PCF8563_RTC,0x06)&0x07;//读周month = ReadByte(PCF8563_RTC,0x07)&0x1f;//读月year = ReadByte(PCF8563_RTC,0x08);//读年
}
//—————-BCD转10进制———–
unsigned char bcd_dec(unsigned char bat)
{
/*unsigned char temp1,temp2,tol;*/
temp1=bat&0x0f;
temp2=(bat&0xf0)>>4;
tol=temp2*10+temp1;
return tol;
}void main (void)
{shiwei=0x00;Sys_Ini();Init();WriteByte(PCF8563_RTC,0x02, 0x00);//秒的初始值WriteByte(PCF8563_RTC,0x03, 0x00);//分的初始值WriteByte(PCF8563_RTC,0x04, 0x00);//时的初始值WriteByte(PCF8563_RTC,0x05, 0x00);//天的初始值WriteByte(PCF8563_RTC,0x06, 0x00);//周的初始值WriteByte(PCF8563_RTC,0x07, 0x00);//月的初始值WriteByte(PCF8563_RTC,0x08, 0x00);//年的初始值while(1){Rtc_ReadTime();Seconds1=bcd_dec(Seconds);Minutes1=bcd_dec(Minutes);hour1=bcd_dec(hour);month1= bcd_dec(month);day1=bcd_dec(day);week1=bcd_dec(week);year1=bcd_dec(year);//shiwei1=bcd_dec(shiwei);}}