#include "msp430x54x.h"
#include "myfunction.h"
#include "iic_c.h"
#define Write24c02 0xA0 //24C02器件地址+写操作使能
#define Read24c02 0xA1 //24C02器件地址+读操作使能
#define SDA_OUT (P9DIR |= BIT1) //p9.1=out/in
#define SDA_IN (P9DIR &=~BIT1)
#define SDA_1 (P9OUT |= BIT1)
#define SDA_0 (P9OUT &=~BIT1)
#define SDA_INPUT P9IN
#define SDA BIT1
#define SCL_1 (P9OUT |= BIT2) //p9.2=out
#define SCL_0 (P9OUT &=~BIT2)
#define SCL_IN (P9DIR &=~BIT2)
#define SCL_OUT (P9DIR |= BIT2)
unsigned char ErrorBit=0; //读写错误标志 0 正确,!=错误
/*******************************************************************************
函数名称:delayus
函数功能:I2C驱动的延时程序
入口参数:i,在主时钟周期为16MHz时,i=20,延时6us
出口参数:无
备 注:
*******************************************************************************/
void delayus(unsigned int i)
{
unsigned int j;
for(j=0;j<i;j++)
;;
}
/*******************************************************************************
函数名称:I2C_Initial
函数功能:I2C总线初始化
入口参数:无
出口参数:无
备 注:I2C总线初始化时必须拉高时钟线和数据线
*******************************************************************************/
void I2C_Initial(void)
{
SCL_OUT; //SCL管脚为输出
SDA_OUT; //SDA管脚为输出
SCL_1;
SDA_1;
Stop();
}
/*******************************************************************************
函数名称:Start
函数功能:I2C起始信号
入口参数:无
出口参数:无
备 注:时钟线保持高电平期间,数据线由高到低跳变则为起始信号
*******************************************************************************/
void Start(void) //scl为高电平期间,sda产生一个下降沿
{
SDA_OUT;
SDA_1; //起始条件的数据信号
_NOP();
SCL_1; //起始条件时钟信号
delayus(20); //起始条件建立时间大于4.7us
SDA_0; //起始信号
delayus(20); //
SCL_0; //钳住I2C总线, 准备发送或者接受数据
delayus(20);
}
/*******************************************************************************
函数名称:Stop
函数功能:I2C停止信号
入口参数:无
出口参数:无
备 注:时钟线保持高电平期间,数据线由低到高跳变则为停止信号
*******************************************************************************/
void Stop(void) //scl高电平期间,sda产生一上升沿
{
SDA_OUT;
SDA_0; //结束条件的数据信号
_NOP();
SCL_1; //结束条件的时钟信号
delayus(20);
SDA_1; //结束信号
delayus(20);
SDA_IN;
}
/*******************************************************************************
函数名称:Ack
函数功能:IIC总线应答
入口参数:无
出口参数:无
备 注:SCL为高电平时,SDA为低电平
*******************************************************************************/
void Ack(void)
{
SDA_OUT;
SDA_0;
delayus(20);
SCL_1;
delayus(20);
SCL_0;
delayus(20);
SDA_1;
}
/*******************************************************************************
函数名称:NoAck
函数功能:IIC总线无应答
入口参数:无
出口参数:无
备 注:SDA维持高电平,SCL产生一个脉冲
*******************************************************************************/
void NoAck(void)
{
SDA_OUT;
SDA_1;
delayus(20);
SCL_1;
delayus(20);
SCL_0;
delayus(20);
}
/*******************************************************************************
函数名称:TestAck
函数功能:测试从器件是否应答
入口参数:无
出口参数:ErrorBit,是否应答,ErrorBit!=0则为无应答
备 注:
*******************************************************************************/
unsigned char TestAck(void)
{
SDA_IN; //SDA设为输入
delayus(20);
SCL_1;
delayus(20);
delayus(20);
ErrorBit = SDA_INPUT & SDA;
delayus(20);
SCL_0;
delayus(20);
return(ErrorBit);
}
/*******************************************************************************
函数名称:Write_I2c
函数功能:向I2C总线写入一个字节数据
入口参数:待写入的数据data
出口参数:无
备 注:一个字节为8位,单片机分8次写入I2C总线
*******************************************************************************/
void Write_I2c(unsigned char data)
{
SDA_OUT;
unsigned char i,temp;
for(i=0;i<8;i++)
{
temp=data&0x80;
if(temp==0x80) SDA_1; //判断发送位,送数据到数据线上
else SDA_0;
delayus(20);
SCL_1; //置时钟信号为高电平,使数据有效
delayus(20);
SCL_0;
delayus(20);
data=data<<1;
}
SCL_0;
delayus(20);
SDA_IN;
delayus(20);
_NOP();
_NOP();
}
/*******************************************************************************
函数名称:Read_I2c
函数功能:从I2C总线读出一个字节数据
入口参数:无
出口参数:读出的数据byte
备 注:一个字节为8位,单片机分8次从I2C总线上读出
*******************************************************************************/
unsigned char Read_I2c(void)
{
SDA_IN; //置数据线为输入方向
unsigned char i,q0;
unsigned char byte=0;
for(i=0;i<8;i++)
{
SCL_1; //置时钟为高电平,使数据线数据有效
delayus(20);
byte=byte<<1;
q0=(SDA_INPUT & SDA);
if(q0==SDA) byte=(byte|0x01); //将数据存入byte
delayus(20);
SCL_0;
delayus(20);
}
return(byte);
}
/*******************************************************************************
函数名称:WriteSig
函数功能:向I2C总线写入单个字节数据
入口参数:从器件内部字节地址StartAddress,带写入数据date,待写入的字节数bytes
出口参数:无
备 注:向器件发送写操作控制字,0xa0是芯片地址,这里是EEPROM的地址,1010(前四个固定)
000(中间三个是可编程地址)0(最后一个0是R/W位写)
*******************************************************************************/
unsigned char WriteSig(unsigned char StartAddress,unsigned char date)
{
Start(); //启动IIC总线
Write_I2c(Write24c02); //向器件发送写操作控制字:0xa0是芯片的地址,这里R/W=0为写
if(TestAck()!=0) //检验应答
return 1; //若应答错误,则退出函数,返回错误
Write_I2c(StartAddress); //写对24C02操作的地址
if(TestAck()!=0)
return 1;
Write_I2c(date); //向24C02中写数据
if(TestAck()!=0)
return 1;
Stop();
delay_ms(10); //延时10ms
return 0;
}
/*******************************************************************************
函数名称:WriteSeq2
函数功能:向I2C总线连续写入多个字节数据
入口参数:从器件内部字节地址StartAddress,带写入数据date,待写入的字节数bytes
出口参数:无
备 注:向器件发送写操作控制字,0xa0是芯片地址,这里是EEPROM的地址,1010(前四个固定)
000(中间三个是可编程地址)0(最后一个0是R/W位写)
*******************************************************************************/
unsigned char WriteSeq2(unsigned char StartAddress,unsigned char *date,unsigned char bytes)
{
unsigned char i=0;
for(i=0;i<bytes;i++)
{
WriteSig(StartAddress,*date); //向24C02中写数据
date++; //指向待写数据的指针加1
StartAddress++; //对24C02的操作地址加1
}
Stop();
return 0;
}
/*******************************************************************************
函数名称:WriteSeq
函数功能:向I2C总线连续写入多个字节数据
入口参数:从器件内部字节地址StartAddress,带写入数据date,待写入的字节数bytes
出口参数:无
备 注:向器件发送写操作控制字,0xa0是芯片地址,这里是EEPROM的地址,1010(前四个固定)
000(中间三个是可编程地址)0(最后一个0是R/W位写)
此函数仅限在存储器一页中连续写,24lc