网上基本都提倡用软件模拟I2C,之前读温湿度传感器也是用模拟的。这次有时间和机会再次用上I2C,固决定用硬件I2C调试下,目前看来没有问题,读写设备都正常。
一、注意事项
1、I2C硬件上需要外部上拉,单纯软件上拉不行。
2、如连续读个字节如8563的second~years数据共7 bytes,中间需要delay。否则只能成功读取前两个byte, clock会断掉。具体delay时间没有确切的验证,用如下实例代码测试OK。
3、查看是否有time定时中断,读写过程最好先关中断。
二、工程下载
https://download.csdn.net/download/xqw19891201/11267260
三、参考代码
1、IIC初始化
#include "main.h"
#include "bm8563.h"
#include "key.h"
TimeApi TimeTag;
TimeApi* pTimeTag = &TimeTag;
#define IIC_SDA_PORT GPIOC
#define IIC_SDA_PIN GPIO_Pin_0
#define IIC_SCL_PORT GPIOC
#define IIC_SCL_PIN GPIO_Pin_1
#define IIC_FREQ 40000
#define BM8563_ADDR 0xA2
#define BM8563_REG_CTRL_1 0x00
#define BM8563_REG_CTRL_2 0x01
#define BM8563_REG_WATCH_SEC 0x02
#define BM8563_REG_WATCH_MIN 0x03
#define BM8563_REG_WATCH_HOUR 0x04
#define BM8563_REG_WATCH_DATE 0x05
#define BM8563_REG_WATCH_DAY 0x06
#define BM8563_REG_WATCH_MON 0x07
#define BM8563_REG_WATCH_YEAR 0x08
enum{
Sec = 0x00,
Min,
Hour,
Days,
WeekDays,
Mon,
Years,
MaxIndex,
};
/**********************************************************************/
//Description: Bm8563Init()
//Parameters:
//Return:
//Date:
//Author: quanwu.xu
/**********************************************************************/
void Bm8563Init(void)
{
pTimeTag->TimeArray[Sec] = 0;
pTimeTag->TimeArray[Min] = 0;
pTimeTag->TimeArray[Hour] = 0;
pTimeTag->TimeArray[Days] = 0;
pTimeTag->TimeArray[WeekDays] = 0;
pTimeTag->TimeArray[Mon] = 0;
pTimeTag->TimeArray[Years] = 0;
pTimeTag->SetIndex = Years;
GPIO_Init(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_Mode_Out_PP_High_Fast);
GPIO_Init(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_Mode_Out_PP_High_Fast);
I2C_DeInit(I2C1);
CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, ENABLE);
I2C_Init(I2C1, IIC_FREQ, BM8563_ADDR, I2C_Mode_I2C, I2C_DutyCycle_2,
I2C_Ack_Enable, I2C_AcknowledgedAddress_7bit);
}
2、时间读取
/**********************************************************************/
//Description: GetBm8563Data()
//Parameters:
//Return:
//Date:
//Author: quanwu.xu
/**********************************************************************/
void GetBm8563Data(TimeApi* pTime)
{
uint8_t i = 0;
uint8_t ReadBuf[BUF_LENGTH] = {0};
disableInterrupts();
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
//1、start
I2C_GenerateSTART(I2C1,ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
//2、write addr
I2C_Send7bitAddress(I2C1, BM8563_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
//3、write data reg
I2C_SendData(I2C1, BM8563_REG_WATCH_SEC);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
//4、start
I2C_GenerateSTART(I2C1,ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
//5、read addr reg
I2C_Send7bitAddress(I2C1, BM8563_ADDR, I2C_Direction_Receiver);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
//6、read data
DelayMs(1);
for(i=0; i<BUF_LENGTH; i++)
{
if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
{
ReadBuf[i]=I2C_ReceiveData(I2C1);
}
if(i == (BUF_LENGTH-1))
{
I2C_AcknowledgeConfig(I2C1,DISABLE);
}
else
{
I2C_AcknowledgeConfig(I2C1,ENABLE);
}
Delay(1000);
}
//7、stop
I2C_GenerateSTOP(I2C1,ENABLE);
I2C_AcknowledgeConfig(I2C1,ENABLE);
enableInterrupts();
BcdToDecConversion(pTime, ReadBuf);
printflog("20%d%d-%d-%d\n", pTime->TimeArray[Years]/10, pTime->TimeArray[Years]%10, pTime->TimeArray[Mon], pTime->TimeArray[Days]);
printflog("%d:%d:%d\n", pTime->TimeArray[Hour], pTime->TimeArray[Min], pTime->TimeArray[Sec]);
}
3、时间设定
/**********************************************************************/
//Description: SetBm8563Data()
//Parameters:
//Return:
//Date:
//Author: quanwu.xu
/**********************************************************************/
void SetBm8563Data(TimeApi* pTime)
{
uint8_t i = 0;
uint8_t WriteBuf[BUF_LENGTH] = {0};
pTime->SetIndex = Years;
DecToBcdConversion(pTime, WriteBuf);
disableInterrupts();
while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
//1、start
I2C_GenerateSTART(I2C1,ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
//2、write addr
I2C_Send7bitAddress(I2C1, BM8563_ADDR, I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
//3、write data reg
I2C_SendData(I2C1, BM8563_REG_WATCH_SEC);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
//write data
DelayMs(1);
for(i=0; i<BUF_LENGTH; i++)
{
I2C_SendData(I2C1,WriteBuf[i]);
if(i == BUF_LENGTH-1)
{
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
else
{
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING));
}
}
I2C_GenerateSTOP(I2C1,ENABLE);
enableInterrupts();
}