#include "main.h"
unsigned char send_data[8] = {0xFF,0xEE,0xDD,0xAA,0x43,0x20,0x76,0x92};
unsigned char rec_data[8] = {0};
unsigned char send_data1[8] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37};
unsigned char send_data2[8] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
enum ENUM_TWI_REPLY
{
TWI_NACK=0
,TWI_ACK=1
};
enum ENUM_TWI_BUS_STATE
{
TWI_READY=0
,TWI_BUS_BUSY=1
,TWI_BUS_ERROR=2
};
void TWI_delay(void)
{
Delay_us(4);
}
void I2C_SCL_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// Configure I2C1 pins: PB8->SCL and PB9->SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void I2C_SDA_Config(unsigned char dir)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// Configure I2C1 pins: PB8->SCL and PB9->SDA
if(dir == Write)
{
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
if(dir == Read)
{
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
}
uint8_t TWI_Start(void)
{
SDA_H;
SCL_H;
TWI_delay();
if(!SDA_read) //SDA为低电平,总线忙,退出
return TWI_BUS_BUSY;
SDA_L;
TWI_delay();
if(SDA_read) //SDA为高电平,总线出错,退出
return TWI_BUS_ERROR;
SCL_L;
TWI_delay();
return TWI_READY;
}
void TWI_Stop(void)
{
SDA_L;
SCL_L;
TWI_delay();
SCL_H;
TWI_delay();
SDA_H;
TWI_delay();
}
void TWI_Ack(void)
{
SCL_L;
TWI_delay();
SDA_L;
TWI_delay();
SCL_H;
TWI_delay();
SCL_L;
TWI_delay();
}
void TWI_NoAck(void)
{
SCL_L;
TWI_delay();
SDA_H;
TWI_delay();
SCL_H;
TWI_delay();
SCL_L;
TWI_delay();
}
uint8_t TWI_WaitAck(void) //1: has ACK, 0: no ACK
{
I2C_SDA_Config(Read);
SCL_L;
TWI_delay();
//SDA_H;
//TWI_delay();
//I2C_SDA_Config(Read);
//TWI_delay();TWI_delay();TWI_delay();
SCL_H;
TWI_delay();
//TWI_delay();
if(SDA_read)
{
SCL_L;
I2C_SDA_Config(Write);
TWI_delay();
return 0;
}
SCL_L;
I2C_SDA_Config(Write);
TWI_delay();
return 1;
}
void TWI_SendByte(uint8_t SendByte) //从高位开始,低位结束
{
uint8_t i=8;
while(i--)
{
SCL_L;
TWI_delay();
if(SendByte&0x80)
SDA_H;
else
SDA_L;
SendByte<<=1;
TWI_delay();
SCL_H;
TWI_delay();
}
SCL_L;
}
uint8_t TWI_ReceiveByte(void)
{
uint8_t i=8;
uint8_t ReceiveByte=0;
SDA_H;
while(i--)
{
ReceiveByte <<= 1;
SCL_L;
TWI_delay();
SCL_H;
TWI_delay();
if(SDA_read)
{
ReceiveByte |= 0x01;
}
}
SCL_L;
return ReceiveByte;
}
//返回值 3:写入成功,0:地址出错,1:总先忙,2:出错
uint8_t TWI_WriteByte(uint8_t SendByte, uint8_t WriteAddress)
{
uint8_t i;
//uint16_t j;
i = TWI_Start();
if(i)
return i;
TWI_SendByte( ADDR_24CXX & 0xFE);//写地址,写入:最低位0,读出:最低位1
if(!TWI_WaitAck())
{
TWI_Stop();
return 0;
}
TWI_SendByte(WriteAddress);
TWI_WaitAck();
TWI_SendByte(SendByte);
TWI_WaitAck();
TWI_Stop();
//等待EEPROM写完,可以采用查询方式,也可以采用延时方式
Delay_us(5000); //写周期大于10ms
return 3;
}
//返回值 0:地址出错,1:总线忙,2:出错
uint8_t TWI_ReadByte( uint8_t ReadAddress)
{
uint8_t i,temp;
i = TWI_Start();
if(i)
return i;
TWI_SendByte((ADDR_24CXX & 0xFE));//写器件地址,先进行一次伪写操作
if(!TWI_WaitAck())
{
TWI_Stop();
return 0;
}
TWI_SendByte(ReadAddress);
TWI_WaitAck();
TWI_Start();
TWI_SendByte((ADDR_24CXX & 0xFE)|0x01); //写:最低位0,读出:最低位1
TWI_WaitAck();
//*pDat = TWI_ReceiveByte();
temp = TWI_ReceiveByte();
TWI_NoAck();
TWI_Stop();
return temp;//返回值如果是012,则与错误代码相同,再考虑一下
}
/***************************************************************************
向EEPROM中写入多个数据
psrc_data:指向待写入数据数组指针
adr:24c256:待写入数据首地址
nbyte:字节数量
返回值:0 执行完毕,1 出错
***************************************************************************/
uint8_t I2C_EE_BufferWrite(uint8_t *psrc_data,uint8_t adr,uint8_t nbyte)
{
uint8_t i;
for(;nbyte!=0;nbyte--)
{
i = TWI_Start();
if(i)
return i;
TWI_SendByte( ADDR_24CXX & 0xFE);//写器件地址
if(!TWI_WaitAck())
{
TWI_Stop();
return 0;
}
TWI_SendByte(adr); //写首地址
TWI_WaitAck();
TWI_SendByte(*psrc_data); //写数据
TWI_WaitAck();
psrc_data++; //数据指针加1
adr++; //地址加1
TWI_Stop();
Delay_us(5000); //延时大于10ms
}
return 0;
}
/***************************************************************************
从EEPROM中读出多个数据
pdin_data:指向保存数据数组地址
adr:24c02:待读出数据的首地址
nbyte:字节数
返回值:0 执行完毕,1 执行出错
***************************************************************************/
uint8_t I2C_EE_BufferRead(uint8_t *pdin_data,uint8_t adr,uint8_t nbyte)
{
uint8_t i;
i = TWI_Start();
if(i)
return i;
TWI_SendByte((ADDR_24CXX & 0xFE));//执行伪写操作
if(!TWI_WaitAck())
{
TWI_Stop();
return 0;
}
TWI_SendByte(adr); //写首地址
TWI_WaitAck();
TWI_Start();
TWI_SendByte((ADDR_24CXX & 0xFE)|0x01); //读出:最低位1
TWI_WaitAck();
while(nbyte!=1) //读出前(nbyte-1)个字节
{
*pdin_data = TWI_ReceiveByte();
TWI_Ack();
pdin_data++;
nbyte--;
};
*pdin_data = TWI_ReceiveByte(); //读出最后一个字节
TWI_NoAck(); //TWI无应答操作
TWI_Stop();
return 0;
}
/***************************************
*PCA9554的读写操作函数
***************************************/
void PCA9554_delay(void)
{
Delay_us(20);
}
void PCA9554_start(void)
{
SDA_H;
PCA9554_delay();
SCL_H;
PCA9554_delay();
SDA_L;
PCA9554_delay();
SCL_L;
PCA9554_delay();
}
void PCA9554_stop(void)
{
SDA_L;
PCA9554_delay();
SCL_H;
PCA9554_delay();
SDA_H;
PCA9554_delay();
}
void PCA9554A_Write_Byte(unsigned char dat)
{
unsigned char i,temp;
temp=dat;
for(i=0;i<8;i++)
{
if(temp&0x80)
{
SDA_H;
}
else
{
SDA_L;
}
PCA9554_delay();
SCL_H;
PCA9554_delay();
SCL_L;
PCA9554_delay();
temp<<=1;
//PCA9554_delay();
}
SDA_L;
PCA9554_delay();
SCL_H;
PCA9554_delay();
SCL_L;
PCA9554_delay();
}
unsigned char PCA9554A_Read_Byte(void)
{
unsigned char i,temp;
temp=0;
SDA_H; //sda=1;
PCA9554_delay();
SCL_L; //scl=0;
PCA9554_delay();
I2C_SDA_Config(Read);
for(i=0;i<8;i++)
{
SCL_H; //scl=1;
PCA9554_delay();
temp = temp << 1;
if(SDA_read)
{
temp |= 0x01;
}
PCA9554_delay();
SCL_L; //scl=0;
PCA9554_delay();
}
I2C_SDA_Config(Write);
SDA_H; //sda=1;
PCA9554_delay();
return temp;
}
/*在主函数前加上PCA9554_Config()函数,写入0x00,否则PCA9554不工作*/
void PCA9554A_Config(unsigned char date,unsigned c
评论1