RX8010SJ +STM32F4 模拟IIC读取时钟

引脚配置,以及IIC配置

/*************************************************************
*Softi2c部分
*
*************************************************************/
extern "C"
{
	void I2C_GPIO_Init(void)
	{
			GPIO_InitTypeDef  GPIO_InitStructure;

			RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE时钟

			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;             //SCL
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;         //普通输出模式
			GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;        //推挽输出
			GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;    //100MHz
			GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;          //上拉
			GPIO_Init(GPIOE, &GPIO_InitStructure);                //初始化GPIO
			
			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;            //SDA
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;        //普通输出模式
			GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;       //开漏输出
			GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;   //100MHz
			GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;         //上拉
			GPIO_Init(GPIOE, &GPIO_InitStructure);               //初始化GPIO	
		
			GPIO_SetBits(GPIOE,GPIO_Pin_2);                      //设置高
			GPIO_SetBits(GPIOE,GPIO_Pin_3);                      //设置高
	}		
}


void Softi2c::Begin(void)//初始化
{
	I2C_GPIO_Init();
}

void Softi2c::I2C_Delay(void)//I2C总线位延迟,最快400KHz
{
	uint8_t i;
//	/**************************************** 
//	 	下面的时间是通过逻辑分析仪测试得到的。
//		CPU主频72MHz时,在内部Flash运行, MDK工程不优化
//		循环次数为10时,SCL频率 = 205KHz 
//		循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 
//	 	循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us 
//        
//    IAR工程编译效率高,不能设置为7
//	****************************************/
	for (i = 0; i < 180; i++);
}

void Softi2c::Write_Delay(void)
{
	uint16_t i;

	for (i = 0; i < 65000; i++);
}

void Softi2c::I2C_Start(void)//CPU发起I2C总线启动信号
{
	SDA_OUT();     //sda线输出
  I2C_SCL_LOW();
  I2C_Delay();
  I2C_SDA_HIGH();
  I2C_Delay();
  I2C_SCL_HIGH();
  I2C_Delay();
  I2C_SDA_LOW();
  I2C_Delay();
  I2C_SCL_LOW();
  I2C_Delay();
}

void Softi2c::I2C_Stop(void)//CPU发起I2C总线停止信号
{
	SDA_OUT();//sda线输出
  I2C_SCL_LOW();
  I2C_Delay();
  I2C_SDA_LOW();
  I2C_Delay();
  I2C_SCL_HIGH();
  I2C_Delay();
  I2C_SDA_HIGH();
  I2C_Delay();
}

void Softi2c::I2C_SendByte(uint8_t Byte)//CPU向I2C总线设备发送8bit数据
{
	uint8_t i;
	SDA_OUT(); 	
	/* 先发送字节的高位bit7 */
	for (i = 0; i < 8; i++)
	{		
		if (Byte & 0x80)
		{
			I2C_SDA_HIGH();
		}
		else
		{
			I2C_SDA_LOW();
		}
		I2C_Delay();
		I2C_SCL_HIGH();
		I2C_Delay();	
		I2C_SCL_LOW();
		Byte <<= 1;	/* 左移一个bit */
		I2C_Delay();
	}

    I2C_SCL_LOW();
    I2C_Delay();
    I2C_WaitAck();
}

uint8_t Softi2c::I2C_ReadByte(unsigned char ack)//CPU从I2C总线设备读取8bit数据
{
    uint8_t cnt;
    uint8_t data = 0xFF;
    I2C_SCL_LOW();
    I2C_Delay();
    SDA_IN();//SDA设置为输入
    for(cnt=0; cnt<8; cnt++)
    {
        I2C_SCL_HIGH();                //SCL高(读取数据)
        I2C_Delay();

        data <<= 1;
        if(I2C_SDA_READ())
        {
            data |= 0x01;        //SDA高(数据有效)
        }
        I2C_SCL_LOW();
        I2C_Delay();
    }
    //发送应答信号,为低代表应答,高代表非应答
    if(ack == 0)
    {
        I2C_NAck();
    }
    else
    {
        I2C_Ack();
    }
    return data;                 //返回数据
}

uint8_t Softi2c::I2C_WaitAck(void)//CPU产生一个时钟,并读取器件的ACK应答信号
{
	uint8_t ucErrTime=0; 
	I2C_SDA_HIGH();
  I2C_Delay();
  SDA_IN();      //SDA设置为输入  	
	I2C_SCL_HIGH();
  I2C_Delay();	
	while(I2C_SDA_READ())
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			I2C_Stop();
			return 1;
		}
	}
	I2C_SCL_LOW();//时钟输出0 	   
	return 0; 
}

void Softi2c::I2C_Ack(void)//CPU产生一个ACK信号
{
  I2C_SCL_LOW();
	SDA_OUT();
  I2C_Delay();
  I2C_SDA_LOW();
  I2C_Delay();
  I2C_SCL_HIGH();
  I2C_Delay();
  I2C_SCL_LOW();
  I2C_Delay();
	I2C_SDA_HIGH();	/* CPU释放SDA总线 */
}

void Softi2c::I2C_NAck(void)//CPU产生1个NACK信号
{
  I2C_SCL_LOW();
	SDA_OUT();
  I2C_Delay();
  I2C_SDA_HIGH();
  I2C_Delay();
  I2C_SCL_HIGH();
  I2C_Delay();
  I2C_SCL_LOW();
  I2C_Delay();
}
/**************从RAM指定地址读出数据************/
//slv_addr  器件地址
//sub_addr  内部寄存器地址
void Softi2c::RX8010_Write_Bytes(unsigned int sub_addr,unsigned char *s,unsigned char no)
{
  uint8_t i;

  I2C_Start();
  I2C_SendByte(RX8010_WRITE);
  I2C_SendByte(sub_addr);
  for(i=0;i<no;i++)
  {
    I2C_SendByte(*(s + i));
    //*s=I2C_Read_Byte(1);
    s++;
  }
  I2C_Stop();
}

/**************向RAM指定地址写入数据************/
//slv_addr  器件地址
//sub_addr  内部寄存器地址
void Softi2c::RX8010_Read_Bytes(unsigned int sub_addr,unsigned char *s,unsigned char no)
{
  uint8_t i;
  I2C_Start(); //*发送启动信号*/
  I2C_SendByte(RX8010_WRITE);//*发送SLA+W*///0x64	
  I2C_SendByte(sub_addr);
  I2C_Start();
  I2C_SendByte(RX8010_READ);	
  for(i=0;i<no-1;i++)
  {
  *(s + i) = I2C_ReadByte(1);
  }
  *(s + no-1) = I2C_ReadByte(0);
  I2C_Stop();
}

/**************向时钟写入时间************/
void Softi2c::RX8010_Write_Time(struct CLK_Time* SetRtc)
{
  uint8_t buf[7];
  //IntToBcd(&SetRtc);
  buf[0] = (SetRtc->second);
  RX8010_Write_Bytes(0x10,buf,1);
  buf[0] = (SetRtc->minute);
  RX8010_Write_Bytes(0x11,buf,1);
  buf[0] = (SetRtc->hour);
  RX8010_Write_Bytes(0x12,buf,1);
  buf[0] = (SetRtc->week);
  RX8010_Write_Bytes(0x13,buf,1);
  buf[0] = (SetRtc->day);
  RX8010_Write_Bytes(0x14,buf,1);
  buf[0] = (SetRtc->month);
  RX8010_Write_Bytes(0x15,buf,1);
  buf[0] = (SetRtc->year);
  RX8010_Write_Bytes(0x16,buf,1);
  buf[0] = 0x00;
  RX8010_Write_Bytes(0x1F,buf,1);
}

/**************从时钟读出时间************/
void Softi2c::RX8010_Read_Time (struct CLK_Time* GetRtc)
{
  uint8_t buf[7];
  RX8010_Read_Bytes(0x10,buf,7);//读出温度值(器件地址,子地址,数据储存器,字节数)
  GetRtc->second = (buf[0]&0x7f); //秒,低七位有效
  GetRtc->minute = (buf[1]&0x7f); //分,低七位有效
  GetRtc->hour   = (buf[2]&0x3f); //时,低六位有效
  GetRtc->week   = (buf[3]&0x7f);//RX8010_Week_Translate(ReadWeek,buf[3]&0x7f); //周,低七位有效
  GetRtc->day    = (buf[4]&0x3f); //日,低六位有效
  GetRtc->month  = (buf[5]&0x1f); //月,低五位有效
  GetRtc->year   = (buf[6]&0xff); //年,低八位有效
}

void Softi2c::RTC_Set_Time(struct CLK_Time* rtc_wtime)
{
  struct CLK_Time rtctime;
  
  rtctime.year = DEC_TO_BCD(rtc_wtime->year);
  rtctime.month = DEC_TO_BCD(rtc_wtime->month);
  rtctime.day = DEC_TO_BCD(rtc_wtime->day);
  rtctime.hour = DEC_TO_BCD(rtc_wtime->hour);
  rtctime.minute = DEC_TO_BCD(rtc_wtime->minute);
  rtctime.second = DEC_TO_BCD(rtc_wtime->second);
	
  switch(rtc_wtime->week)	 				
	{
		case 0x00:	rtctime.week = 0x01;break;
		case 0x01:	rtctime.week = 0x02;break;
		case 0x02:	rtctime.week = 0x04;break;
		case 0x03:	rtctime.week = 0x08;break;
		case 0x04:	rtctime.week = 0x10;break;
		case 0x05:	rtctime.week = 0x20;break;
		case 0x06:	rtctime.week = 0x40;break;
		default:break;
	}
  RX8010_Write_Time(&rtctime);
}

void Softi2c::RTC_Get_Time(struct TIME* rtctime)
{
  struct CLK_Time rtc_rtime;

  RX8010_Read_Time(&rtc_rtime);
  //showtime(&rtc_rtime);
  rtctime->year = BCD_TO_DEC(rtc_rtime.year);
  rtctime->month = BCD_TO_DEC(rtc_rtime.month);
  rtctime->day = BCD_TO_DEC(rtc_rtime.day);
  rtctime->hour = BCD_TO_DEC(rtc_rtime.hour);
  rtctime->minute = BCD_TO_DEC(rtc_rtime.minute);
  rtctime->second = BCD_TO_DEC(rtc_rtime.second);

  switch(rtc_rtime.week)	 				
	{
		case 0x01:	rtctime->dayofweek = 0;break;           //星期日
		case 0x02:	rtctime->dayofweek = 1;break;           //星期一
		case 0x04:	rtctime->dayofweek = 2;break;           //星期二
		case 0x08:	rtctime->dayofweek = 3;break;           //星期三
		case 0x10:	rtctime->dayofweek = 4;break;           //星期四
		case 0x20:	rtctime->dayofweek = 5;break;           //星期五
		case 0x40:	rtctime->dayofweek = 6;break;           //星期六
		default:	break;
	}
}

部分头文件:

//RX8010SJ 部分
#define RX8010_READ   0x65
#define RX8010_WRITE  0x64
#define BCD_TO_DEC(x)            ((x >> 4) * 10 + (x & 0x0F))
#define DEC_TO_BCD(x)            (((x / 10) << 4) + (x % 10))
// register address , for RX-8010SJ
#define RX8010_ADDR_SECOND      ( 0x10 )
#define RX8010_ADDR_MINUTE      ( 0x11 )
#define RX8010_ADDR_HOUR        ( 0x12 )
#define RX8010_ADDR_WEEK        ( 0x13 )
#define RX8010_ADDR_DATE        ( 0x14 )
#define RX8010_ADDR_MONTH       ( 0x15 )
#define RX8010_ADDR_YEAR        ( 0x16 )
#define RX8010_ADDR_RSV17       ( 0x17 )
#define RX8010_ADDR_ALM_MINUTE  ( 0x18 )
#define RX8010_ADDR_ALM_HOUR    ( 0x19 )
#define RX8010_ADDR_ALM_WEEK    ( 0x1A )
#define RX8010_ADDR_ALM_DATE    ( 0x1A )
#define RX8010_ADDR_TMR_CNT0    ( 0x1B )
#define RX8010_ADDR_TMR_CNT1    ( 0x1C )
#define RX8010_ADDR_EXT_REG     ( 0x1D )
#define RX8010_ADDR_FLAG_REG    ( 0x1E )
#define RX8010_ADDR_CTRL_REG    ( 0x1F )

//IO方向设置
#define SDA_IN()  {GPIOE->MODER&=~(3<<(3*2));GPIOE->MODER|=0<<3*2;}	//PE3输入模式
#define SDA_OUT() {GPIOE->MODER&=~(3<<(3*2));GPIOE->MODER|=1<<3*2;} //PE3输出模式
#define I2C_SDA_HIGH()	PEout(3) = 1
#define I2C_SCL_HIGH()	PEout(2) = 1
#define I2C_SDA_READ()	PEin(3)
#define I2C_SDA_LOW()	  PEout(3) = 0
#define I2C_SCL_LOW()	  PEout(2) = 0

struct CLK_Time
{
	uint8_t second;
	uint8_t minute;
	uint8_t hour;
	uint8_t week;
  uint8_t day;
	uint8_t month;
	uint8_t year;
};

struct TIME
{
    uint8_t year;
    uint8_t month;
    uint8_t day;
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
    uint8_t week;
    uint8_t dayofweek;
};
 
class Softi2c
{
	private:	
		
		void I2C_Delay(void);
		void Write_Delay(void);
		void I2C_Start(void);
		void I2C_Stop(void);
		void I2C_SendByte(uint8_t Byte);
		uint8_t I2C_ReadByte(unsigned char ack);
		uint8_t I2C_WaitAck(void);
		void I2C_Ack(void);
		void I2C_NAck(void);
	  void RX8010_Write_Bytes(unsigned int sub_addr,unsigned char *s,unsigned char no);
	  void RX8010_Read_Bytes(unsigned int sub_addr,unsigned char *s,unsigned char no);
	  void RX8010_Write_Time(struct CLK_Time* SetRtc);
	  void RX8010_Read_Time (struct CLK_Time* GetRtc);
	public:
		void Begin();
	  void RTC_Set_Time(struct CLK_Time* rtc_wtime);
    void RTC_Get_Time(struct TIME* rtctime);
};

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值