主机:SPCA2688A
从机:MCP9808、SHT3XA
通信速率:400KHz
1. 状态定义
/*SCL,SDA状态定义*/
#define SCL_OUT_HIGH NBYTE[0x2043] |= 0x04 //SCL输出高电平
#define SCL_OUT_LOW NBYTE[0x2043] &= ~0x04 //SCL输出低电平
#define SDA_OUT_HIGH NBYTE[0x2043] |= 0x08 //SDA输出高电平
#define SDA_OUT_LOW NBYTE[0x2043] &= ~0x08 //SDA输出低电平
2. 设备地址
/*定义设备地址(7位地址)*/
#define ADDR1_SHT3XA 0x44
#define ADDR2_SHT3XA 0x45
#define ADDR_MCP9808 0x18
3. 延时时间
/*定义延时时间*/
void iicDelay(void)
{
_nop_(); //基于C251的空指令延时
_nop_();
_nop_();
_nop_();
}
4. 初始化
/*IIC初始化*/
void iicInit(void)
{
NBYTE[0x20E8] |= 0x18; //使能GPIO下拉功能
NBYTE[0x2041] |= 0x0C; //配置SDA,SCL为输出
NBYTE[0x2043] |= 0x0C; //默认输出高电平
NBYTE[0x2074] &= ~0x0C; //失能相关中断
pcaDelayUsec_ROM(2); //延时2ms
}
5. 起始条件
/*起始条件*/
void iicStart(void)
{
NBYTE[0x2041] |= 0x0C; //配置SDA,SCL为输出模式
SDA_OUT_HIGH;
SCL_OUT_HIGH;
iicDelay();
SDA_OUT_LOW;
iicDelay();
SCL_OUT_LOW;
}
6. 停止条件
/*停止条件*/
void iicStop(void)
{
NBYTE[0x2041] |= 0x0C; //配置SDA,SCL为输出模式
SDA_OUT_LOW;
SCL_OUT_LOW;
iicDelay();
SCL_OUT_HIGH;
iicDelay();
SDA_OUT_HIGH;
}
7. 接收应答
/*接收应答ACK*/
uint8_t getACK(void)
{
uint8_t errTime = 10;
NBYTE[0x2041] &= ~0x08; //配置SDA为输入模式
SDA_OUT_HIGH;
iicDelay();
SCL_OUT_HIGH;
iicDelay();
while(NBYTE[0x2045] & 0x08)
{
errTime--;
if(!errTime)
return 0;
}
SCL_OUT_LOW;
return 1;
}
8. 发送应答
/*发送应答ACK*/
void sendACK(void)
{
NBYTE[0x2041] |= 0x0C; //配置SCL,SDA为输出模式
SDA_OUT_LOW;
iicDelay();
SCL_OUT_HIGH;
iicDelay();
SCL_OUT_LOW;
}
9. 发送非应答
/*发送非应答NAK*/
void sendNAK(void)
{
NBYTE[0x2041] |= 0x0C; //配置SCL,SDA为输出模式
SDA_OUT_HIGH;
iicDelay();
SCL_OUT_HIGH;
iicDelay();
SCL_OUT_LOW;
}
10. 发送数据
/*发送1字节数据*/
void iicSendData(uint8_t paraData)
{
uint8_t j = 8;
NBYTE[0x2041] |= 0x08; //配置SDA为输出模式
while(j--)
{
SCL_OUT_LOW;
_nop_();
if(paraData & 0x80)
SDA_OUT_HIGH;
else
SDA_OUT_LOW;
paraData <<= 1;
iicDelay();
SCL_OUT_HIGH;
iicDelay();
}
SCL_OUT_LOW;
SDA_OUT_HIGH;
NBYTE[0x2041] &= ~0x08; //配置SDA为输入模式
}
11. 接收数据
/*接收1字节数据并返回接收到的数据*/
uint8_t iicRecvData(void)
{
uint8_t i=8;
uint8_t ddata=0;
NBYTE[0x2041] &= ~0x08; //配置SDA为输入模式
SDA_OUT_HIGH;
while(i--)
{
ddata <<= 1;
SCL_OUT_LOW;
iicDelay();
SCL_OUT_HIGH;
iicDelay();
if(NBYTE[0x2045] & 0x08) //读取SDA输入电平状态
ddata |= 0x01;
}
SCL_OUT_LOW;
return ddata;
}
12. 测试代码I
/*以温度传感器MCP9808作代码测试*/
/*buffer:保存MCP9808返回的16bit温度数据*/
void getMCP9808(uint8_t buffer[])
{
uint8_t ret, *pBuffer = buffer;
uint8_t num = 0;
iicInit(); //初始化
iicStart(); //起始条件
iicSendData((ADDR_MCP9808 << 1) & 0xFE); //发送地址和写操作
NBYTE[0x2108] = getACK(); //等待从机应答
iicSendData(0x05); //发送命令
getACK(); //等待从机应答
iicStart(); //IIC重启条件
iicSendData((ADDR_MCP9808 << 1) | 0x01); //发送地址和读操作
getACK(); //等待从机应答
num = 0;
*pBuffer = iicRecvData(); //接收从机发送的数据高字节
pBuffer++;
sendACK();
*pBuffer = iicRecvData(); //接收从机发送的数据低字节
sendNAK();
iicStop();
}
13. 测试代码II
/*以温湿度传感器SHT3XA作代码测试*/
/**********************************
buffer:保存SHT3XA返回的16bit温度数据 +
8bit CRC校验 + 16bit湿度数据 + 8bit CRC
**********************************/
void getSHT3XA(uint8_t * buffer)
{
uint8_t ret,i = 0;
uint8_t *pBuffer = buffer;
static unsigned char count = 0;
iicInit();
iicStart();
iicSendData(ADDR1_SHT3XA << 1);
getACK();
iicSendData(0x27);
getACK();
iicSendData(0x37);
getACK();
iicStop();
if(count)
{
iicStart();
iicSendData((ADDR1_SHT3XA << 1) | 0x01);
getACK();
for(i = 0, pBuffer = buffer; i < 6; i++, pBuffer++)
{
*pBuffer = iicRecvData();
if(i < 5)
sendACK();
else
sendNAK();
}
iicStop();
count = 0;
}
else
count++;
}