引脚配置,以及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);
};