打印

I2C读PCF8596分享

[复制链接]
1288|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
qiangg|  楼主 | 2016-1-26 15:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 qiangg 于 2016-1-26 16:00 编辑

硬件连接
PE4------------SCL
PE5------------SDA
沙发
qiangg|  楼主 | 2016-1-26 15:41 | 只看该作者
unsigned char  g8563_Store[4];                                                                                                 /*ʱ¼ä½»»»Çø,È«¾Ö±äÁ¿ÉùÃ÷*/  
unsigned char  c8563_Store[4]={0x00,0x59,0x07,0x01};         /*дÈëʱ¼ä³õÖµ£ºÐÇÆÚÒ» 07:59:00*/  
//用于存储时间
typedef struct
{
        vu8 hour;
        vu8 min;
        vu8 sec;       
        //¹«ÀúÈÕÔÂÄêÖÜ
        vu16 w_year;
        vu8  w_month;
        vu8  w_date;
        vu8  week;          
}_calendar_obj;
_calendar_obj calendar;

使用特权

评论回复
板凳
qiangg|  楼主 | 2016-1-26 15:42 | 只看该作者
//SDA的方向初始化
void SDA_Dir(char bit)
{
        GPIO_InitTypeDef GPIO_InitStructure; //GPIOÀàÐÍ
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
        if(bit)
        {
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //ÍÆÍìÊä³ö       
        }
        else
        {
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //
        }
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOE,&GPIO_InitStructure);
}

使用特权

评论回复
地板
qiangg|  楼主 | 2016-1-26 15:43 | 只看该作者
//软件小限时
void delay_nop(void)
{   
        uint8_t i=10; //i=10延时1.5us//这里可以优化速度 ,经测试最低到5还能写入   
        while(i--);   
}

使用特权

评论回复
5
qiangg|  楼主 | 2016-1-26 15:44 | 只看该作者
//I2C起始位
void iic_start(void)  
{     //时钟保持高,数据线从高到低一次跳变,I2C通信开始  
        SDA(1);
  SCL(1);
        delay_nop();delay_nop();
  SDA(0);
  SCL(0);
}

使用特权

评论回复
6
qiangg|  楼主 | 2016-1-26 15:44 | 只看该作者
//I2C停止位

void iic_stop(void)  
{  
        SDA(0);
  SCL(0);
        delay_nop();delay_nop();
  SDA(1);
  SCL(1);
}  

使用特权

评论回复
7
qiangg|  楼主 | 2016-1-26 15:48 | 只看该作者
/--------------------------------------------------------------------------------------------------  
// 函数名称: slave_ACK  
// 函数功能: 从机发送应答位子程序  
//--------------------------------------------------------------------------------------------------  
void IIC_Ack(void)  
{
        SDA(0);
  SCL(1);delay_nop();
  SCL(0);delay_nop();
}  
void WaitACK()
{   
        unsigned char errtime=20;  
        SDA(1);   delay_nop();/*读ACK*/  
        SCL(1);  delay_nop();
        SDA_Dir(0);
        while(SDAIn)  
        {
    errtime--;
                if(!errtime)
                        iic_stop();  
        }   
        SCL(0);  delay_nop();
}

使用特权

评论回复
8
qiangg|  楼主 | 2016-1-26 15:48 | 只看该作者
//--------------------------------------------------------------------------------------------------  
// 函数名称: IICSendByte  
// 入口参数: ch  
// 函数功能: 发送一个字节  
//--------------------------------------------------------------------------------------------------  
void IIC_WriteByte(u8 dat)
{
  u8 i;  
  SCL(0);delay_nop();
  for(i=0;i<8;i++)
  {
                if(dat & 0x80)SDA(1)
                else SDA(0)
                dat <<= 1;
                delay_nop();delay_nop();
    SCL(1);delay_nop();
    SCL(0);delay_nop();
  }
        delay_nop();delay_nop();delay_nop();delay_nop();
        delay_nop();delay_nop();delay_nop();delay_nop();
}

使用特权

评论回复
9
qiangg|  楼主 | 2016-1-26 15:49 | 只看该作者
//--------------------------------------------------------------------------------------------------  
// 函数名称: IICreceiveByte  
// 返回接收的数据  
// 函数功能: 接收一字节子程序  
//--------------------------------------------------------------------------------------------------  
u8 IIC_ReadByte(void)
{
  u8 i, rst;  
  SDA(1);
  SDA_Dir(0);
        delay_nop();
  for(i=0;i<8;i++)
  {
                rst <<= 1;
    SCL(1);
                delay_nop();
                if(SDAIn)rst |= 1;
                else rst &= ~1;
                delay_nop();
    SCL(0);
                delay_nop();
  }
  SDA_Dir(1);
  
  return rst;
}

使用特权

评论回复
10
qiangg|  楼主 | 2016-1-26 15:51 | 只看该作者
//--------------------------------------------------------------------------------------------------  
// 用户调用子程序  
// 函数名称: write_CFGbyte  
// 入口参数: CFG_add寄存器地址,CFG_data要写入寄存器的数值  
// 函数功能: 发送n位数据子程序  
//--------------------------------------------------------------------------------------------------  
void write_CFGbyte(unsigned char CFG_add,unsigned char CFG_data)  
{            
        //unsigned char idata send_da,i=0;  
        iic_start();                // 启动I2C  
        IIC_WriteByte(0xa2);     // 发送器件写地址  

        IIC_Ack();             // 检查应答位  

        IIC_WriteByte(CFG_add);       // 发送寄存器地址  

        IIC_Ack();                // 检查应答位  

        IIC_WriteByte(CFG_data);       // 发送寄存器数据  

        IIC_Ack();                // 检查应答位  

        iic_stop();         // 全部发完则停止  
}  

使用特权

评论回复
11
qiangg|  楼主 | 2016-1-26 15:52 | 只看该作者
//--------------------------------------------------------------------------------------------------  
// 用户调用子程序  
// 函数名称: receiveNbyte  
// 入口参数: CFG_add寄存器地址地址  
// 出口参数: receive_da  
// 函数功能: 接收某个寄存器数据子程序  
//--------------------------------------------------------------------------------------------------  
unsigned char receive_CFGbyte(unsigned char  CFG_add)  
{   
                unsigned char  receive_da;  
                iic_start();  
                IIC_WriteByte(0xa2); //器件写地址  

                IIC_WriteByte(CFG_add); //寄存器地址  

                iic_start();  
                IIC_WriteByte(0xa3); //器件读地址  

                receive_da=IIC_ReadByte();  
                IIC_Ack();       // 收到最后一个字节后发送一个非应答位  
                iic_stop();  
                return(receive_da);  
}  

使用特权

评论回复
12
qiangg|  楼主 | 2016-1-26 15:53 | 只看该作者
/*********************************************************************
** 函数名称:  hex_to_bcd
** 函数类型:  void
** 功能描述:  十六进制数转换成BCD码格式
** 入口参数:  unsigned char condata
** 出口参数:  unsigned char
** 返回变量:  temp
** 返回类型:  无
***********************************************************************/
u8 hex_to_bcd(u8 hex)
{
  u8 temp;
  u8 temp0;
  u8 temp10;
  
  temp10 = hex / 10;
  temp0 = hex % 10;
  temp = (temp10<<4) | temp0;
  
  return temp;
}

/*********************************************************************
** 函数名称:  bcd_to_hex
** 函数类型:  void
** 功能描述:  BCD码格式转换成十六进制数
** 入口参数:  unsigned char condata
** 出口参数:  unsigned char
** 返回变量:  temp
** 返回类型:  无
***********************************************************************/
u8 bcd_to_hex(u8 bcd)
{
  u8 temp;
  u8 temp0;
  u8 temp10;
  
  temp10 = (bcd&0xF0) >> 4;
  temp0 = bcd & 0x0F;
  temp = temp10*10 + temp0;
  
  return temp;
}

使用特权

评论回复
13
qiangg|  楼主 | 2016-1-26 15:56 | 只看该作者
//--------------------------------------------------------------------------------------------------  
// 用户调用函数  
// 函数名称: receive_CFGNbyte  
// 入口参数: CFG_add寄存器地址地址,n连续读数位,* buff存储区地址  
// 函数功能: 接收n个寄存器数据子程序  
//--------------------------------------------------------------------------------------------------  
void receive_CFGNbyte(unsigned char CFG_add, unsigned char n,unsigned char * buff)
{   
        unsigned char receive_da=0;  
        iic_start();  
        IIC_WriteByte(write_ADD); //器件写地址  read_ADD
        IIC_Ack();
        IIC_WriteByte(CFG_add); //寄存器地址  
        IIC_Ack();
        iic_start();  
        IIC_WriteByte(read_ADD); //器件读地址  
        IIC_Ack();  
        receive_da=IIC_ReadByte();  
        buff[0]=receive_da;  
        IIC_Ack();    // 收到一个字节后发送一个应答位  
        receive_da=IIC_ReadByte();  
        buff[1]=receive_da;  
        IIC_Ack();    // 收到一个字节后发送一个应答位  
        receive_da=IIC_ReadByte();  
        buff[2]=receive_da;  
        IIC_Ack();    // 收到一个字节后发送一个应答位  
        receive_da=IIC_ReadByte();  
        buff[3]=receive_da;  
        IIC_Ack();    // 收到一个字节后发送一个应答位  
        receive_da=IIC_ReadByte();
        buff[4]=receive_da;
        IIC_Ack();    // 收到一个字节后发送一个应答位  
        receive_da=IIC_ReadByte();
        buff[5]=receive_da;
        IIC_Ack();    // 收到一个字节后发送一个应答位  
        receive_da=IIC_ReadByte();  
        buff[6]=receive_da;
        IIC_Ack();    // 收到最后一个字节后发送一个非应答位  
        iic_stop();
}  

使用特权

评论回复
14
qiangg|  楼主 | 2016-1-26 15:57 | 只看该作者
//--------------------------------------------------------------------------------------------------  
// 用户调用函数  
// 函数名称: P8563_Readtime  
// 函数功能: 读出时间信息  
//--------------------------------------------------------------------------------------------------  
void P8563_Readtime(void)  
{   
        unsigned char time[7];  
  receive_CFGNbyte(MIN,0x07,time);  
        calendar.sec = bcd_to_hex(time[0] & 0x7f);                /*秒*/
        calendar.min = bcd_to_hex(time[1] & 0x7f);                /*分*/  
        calendar.hour = bcd_to_hex(time[2] & 0x3f);                /*小时*/
        calendar.w_date=bcd_to_hex(time[3] & 0x3f);                /*天*/
        calendar.w_month=bcd_to_hex(time[5] & 0x1f);        /*月*/
        calendar.w_year=bcd_to_hex(time[6] );                                        /*年*/
}  

使用特权

评论回复
15
qiangg|  楼主 | 2016-1-26 15:58 | 只看该作者
//--------------------------------------------------------------------------------------------------  
// 用户调用函数  
// 函数名称: P8563_settime  
// 函数功能: 写时间修改值  
//--------------------------------------------------------------------------------------------------  

void P8563_settime(u16 nian,u8 yue,u8 libai,u8 ri,u8 shi,u8 fen,u8 miao)  
{  
        write_CFGbyte(0x02, hex_to_bcd(miao));  
        write_CFGbyte(0x03, hex_to_bcd(fen));  
        write_CFGbyte(0x04, hex_to_bcd(shi));  
        write_CFGbyte(0x05, hex_to_bcd(ri));  
        write_CFGbyte(0x06, hex_to_bcd(libai));  
        write_CFGbyte(0x07, hex_to_bcd(yue));  
        write_CFGbyte(0x08, hex_to_bcd(nian));  
//        write_CFGbyte(0x00, 0x00); //Enable RTC sorce clock
}  

使用特权

评论回复
16
qiangg|  楼主 | 2016-1-26 15:59 | 只看该作者
//--------------------------------------------------------------------------------------------------  
// 用户调用函数  
// 函数名称: P8563_init  
// 函数功能: 初始设置  
//--------------------------------------------------------------------------------------------------  
void P8563_init(void)  
{  
                GPIO_InitTypeDef GPIO_InitStructure; //GPIO类型
                RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);

                GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
                GPIO_Init(GPIOE,&GPIO_InitStructure);
                SDA_Dir(1);
    if((receive_CFGbyte(0x0a)&0x3f)!=0x8) /*检查是否第一次启动,是则初始化时间*/  
    {  
        write_CFGbyte(0x0,0x00);   //Enable RTC sorce clock
        write_CFGbyte(0xd,0xf0);  
    }  
}  

使用特权

评论回复
17
qiangg|  楼主 | 2016-1-26 16:00 | 只看该作者
pcf8596的头文件


#ifndef __I2C_H
#define __I2C_H
#include "stm32f10x.h"

#define SDAIn (GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_5))
#define SDA(n)   {if(n)GPIO_SetBits(GPIOE, GPIO_Pin_5); else GPIO_ResetBits(GPIOE, GPIO_Pin_5);}
#define SCL(n)    {if(n)GPIO_SetBits(GPIOE, GPIO_Pin_4); else GPIO_ResetBits(GPIOE, GPIO_Pin_4);}  
#define MIN    0x02 //秒寄存器  
#define SEC    0x03 //分寄存器  
#define HOUR   0x04 //时寄存器  
#define DAY    0x05 //日寄存器  
#define WEEK   0x06 //周寄存器  
#define MONTH         0x07 //月寄存器  
#define YEAR   0x08 //年寄存器  

#define read_ADD 0xA3 //写器件地址  
#define write_ADD 0xA2 //读器件地址  

void P8563_init(void);
void P8563_settime(u16 nian,u8 yue,u8 libai,u8 ri,u8 shi,u8 fen,u8 miao);
void P8563_Readtime(void);
#endif

使用特权

评论回复
18
justinlin2015| | 2016-1-26 17:05 | 只看该作者
学习学习了

使用特权

评论回复
19
heping517| | 2016-1-26 23:23 | 只看该作者
谢谢分享,DS1302其实也不错

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

260

帖子

0

粉丝