pic 16 使用8563 rtc iic 通讯 内部iic

2019-04-15 14:44发布



void init_iic()
{
    
    time.second=57;
    time.minute=2;
    time.hour=12;
    time.day=1;
    time.week=3;
    time.month=3;
    time.year=17;//默认时间
    TRISCbits.TRISC3=1;  //iic主模式配置为输入
    TRISCbits.TRISC4=1;
    SSP1STAT=0x00;  
    SSP1CON1=0x38; //使能iic主模式
    SSP1CON2=0x00;  
    SSP1ADD=0x19;//波特率设置 400K HZ
}








void IIC_write_n(unsigned char addr,unsigned char length,unsigned char *pbuf)//写

    unsigned char send_da;
unsigned char i=0; 
    SSP1IF=0;  //MSSP 中断标志位 0 表示没有等待你相应的中断
 // SEN=1;//启动位  启动使能位仅在IIC主模式  //在SDA和SCL线上建立和发送一个启动信号时序
  SSP1CON2bits.SEN=1;
while(!SSP1IF); 
SSP1IF=0;  
SSP1BUF=0xA2;//写控制位 //发送外设IIC器件地址和写信号
while(!SSP1IF); 
SSP1IF=0; //软件清零 不会自动清零
SSP1BUF=addr;//起始地址
while(!SSP1IF); 
SSP1IF=0; 


for(i=0;i {
send_da=*(pbuf++);
SSP1BUF=send_da;
while(!SSP1IF); 
SSP1IF=0;
}
SSP1CON2bits.PEN=1;
//PEN=1;//停止位  //在SDA和SCL线上建立和发送一个停止信号时序
while(!SSP1IF); //如果收到停止信号同样会置位
SSP1IF=0; 


     
 } 






void IIC_write(unsigned char addr,unsigned char data)//写

    SSP1IF=0;  //MSSP 中断标志位 0 表示没有等待你相应的中断
    SSP1CON2bits.SEN=1;
 // SEN=1;//启动位  启动使能位仅在IIC主模式  //在SDA和SCL线上建立和发送一个启动信号时序
while(!SSP1IF); 
SSP1IF=0;  
SSP1BUF=0xA2;//写控制位 //发送外设IIC器件地址和写信号
while(!SSP1IF); 
SSP1IF=0; //软件清零 不会自动清零
SSP1BUF=addr;//写地址 //发送要读外设IIC器件数据的地址
while(!SSP1IF); 
SSP1IF=0;  
SSP1BUF=data;//写数据 //发送要读外设IIC器件要存储的数据或命令
while(!SSP1IF); 
SSP1IF=0;  
SSP1CON2bits.PEN=1;
//PEN=1;//停止位  //在SDA和SCL线上建立和发送一个停止信号时序
while(!SSP1IF); //如果收到停止信号同样会置位
SSP1IF=0; 
     
 } 






unsigned  char IIC_read_n(unsigned char addr,unsigned char length,unsigned char *pbuf)//读 
{  //unsigned char data;  
//unsigned int receive_da;
unsigned char i=0;
SSP1IF=0;  
SSP1CON2bits.SEN=1;
//SEN=1;//开始位 
while(!SSP1IF); 
SSP1IF=0; 
SSP1BUF=0xA2;//控制位写 
while(!SSP1IF);
SSP1IF=0;  
SSP1BUF=addr;//写地址  
while(!SSP1IF); 
SSP1IF=0; 
SSP1CON2bits.RSEN=1;
 // RSEN=1;//重新开始位
     while(!SSP1IF); 
     SSP1IF=0; 
     SSP1BUF=0xA3;//控制位读 
     while(!SSP1IF); 
     SSP1IF=0; 
//     RCEN=1;//使能接收 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
//     while(!SSPIF); 
     for(i=0;i {
         SSP1CON2bits.RCEN=1;//使能接收 
     while(!SSP1IF); 
*pbuf =SSP1BUF;
//SSPBUF=send_da;
while(!SSP1IF); 
SSP1IF=0;
SSP1CON2bits.ACKDT=0;
 //  ACKDT=0;
SSP1CON2bits.ACKEN=1;
    // ACKEN=1;//使能应答位 
      while(!SSP1IF); 
     SSP1IF=0;
     pbuf++;
}
     SSP1CON2bits.RCEN=0;
     // RCEN=0;
     SSP1CON2bits.PEN=1;
    // PEN=1;//停止位 
     while(!SSP1IF); 
     SSP1IF=0; 
     return *pbuf;   
     
}








//unsigned  char IIC_read(unsigned char addr)//读 
//{  unsigned char data;  
//
//SSP1IF=0;  
//SSP1CON2bits.SEN=1;
////SEN=1;//开始位 
//while(!SSP1IF); 
//SSP1IF=0; 
//SSP1BUF=0xA2;//控制位写 
//while(!SSP1IF);
//SSP1IF=0;  
//SSP1BUF=addr;//写地址  
//while(!SSP1IF); 
//SSP1IF=0;
//SSP1CON2bits.RSEN=1;
// // RSEN=1;//重新开始位
//     while(!SSP1IF); 
//     SSP1IF=0; 
//     SSP1BUF=0xA3;//控制位读 
//     while(!SSP1IF); 
//     SSP1IF=0; 
//     SSP1CON2bits.RCEN=1;
//    // RCEN=1;//使能接收 
//     while(!SSP1IF); 
//     data=SSP1BUF;//读数据 
//     while(!SSP1IF);
//     SSP1IF=0;
//     SSP1CON2bits.ACKDT=0;
//    // ACKDT=0;
//     //ACKEN=1;//使能应答位 
//     SSP1CON2bits.ACKEN=1;
//     while(!SSP1IF); 
//     SSP1IF=0;
//     SSP1CON2bits.RCEN=0;
//    // RCEN=0;
//     SSP1CON2bits.PEN=1;
//    // PEN=1;//停止位 
//     while(!SSP1IF); 
//     SSP1IF=0; 
//     return(data);  
//}


unsigned char BCD2Val(unsigned char x)   //BCD转十进制
{
    unsigned char tmp = 0;

tmp = ((unsigned char)(x & (unsigned char)0xF0) >> (unsigned char)0x04) * 10;
return (tmp + (x & (unsigned char)0x0F));


}


unsigned char Val2BCD(unsigned char x)   //十进制转BCD码子程序
{
    
    
    unsigned char bcdhigh = 0;

while (x >= 10)
{
bcdhigh++;
x -= 10;
}

return ((unsigned char)(bcdhigh << 4) | x);
 
}
unsigned char P8563_Read_Time()   //PCF8563读取时间子程序
{
    
    unsigned char temp[7];
IIC_read_n(0x02,0x07,temp);




time.second=BCD2Val(temp[0]&0x7f);
time.minute=BCD2Val(temp[1]&0x7f);
time.hour=BCD2Val(temp[2]&0x3f);
time.day=BCD2Val(temp[3]&0x3f);
time.week=BCD2Val(temp[4]&0x07);
time.month=BCD2Val(temp[5]&0x1f);
time.year=BCD2Val(temp[6]);
return 0;
 
}


void P8563_Set_Time()   //PCF8563设置时间子程序
{
unsigned char temp[7];
unsigned char i;
for(i=0;i<7;i++)
{
temp[i]=Val2BCD(((unsigned char *)(&time))[i]);
}
 IIC_write_n(0x02,7,temp);
}