//描述:微控设计网 www.microcontrol.cn MSP430单片机模拟IIC(Inter IC)总线程序.
//编写:微控设计网 DC版主,如有问题,欢迎到微控技术论坛来讨论.
//使用方式:以涵数方式调用,使用时程序关闭总中断,使用完后打开总中断.
//占用资源为:使用两个IO口,本程序CPU主时钟MCLK=800K.
//本程序已在微控MC430F14实验板上验证通过,也可以应到其它设计中.
//以下程序如有不明之处欢迎讨论
#include<msp430x14x.h>
//--------------------------------------
//SDA 数据线定义
#define SDAOUT P5DIR |= BIT6
#define SDAIN P5DIR &= ~BIT6
#define SDA1 P5OUT |= BIT6
#define SDA0 P5OUT &= ~BIT6
//SCL 时钟线定义
#define SCLOUT P5DIR |= BIT5
#define SCL1 P5OUT |= BIT5
#define SCL0 P5OUT &= ~BIT5
#define SDA_STATE P5IN & BIT6 //读入SDA状态
//--------------------------------------
#define SDA_MOV_BIT 6 //SDA 数据调整移位
//从器件接收方的应答返回标志
#define OK 0x01 //表示从器件有应答
#define NO 0x00 //表示从器件无应答
//IIC总线操作成失标志
#define error 0x01 //错误
#define right 0x00 //正确
//小延时********************************
nop_()
{_NOP();_NOP();}
SomeNOP()
{nop_();nop_();nop_();nop_();}
//**************************************
//起始信号
void I2CStart(void)
{
_DINT(); //关总中断;
SCLOUT; //SCL口设为输出-------后加
SDAOUT; //SDA口设为输出
SDA1;
//SCLOUT; //SCL口设为输出
SCL1;
SomeNOP(); SomeNOP(); //INI
SDA0;
SomeNOP(); SomeNOP(); //START
SCL0;
}
//**************************************
//结束信号
void I2CStop(void)
{
SCL0;
SDA0;
SomeNOP(); //INI
SCL1;
SomeNOP();
SDA1; //STOP
_EINT(); //EA=1;
}
//**************************************
//等待从器件接收方的应答
unsigned char WaitAck(void)
{
unsigned char errtime=255; //因故障接收方无ACK,超时值为255。
SDA1;
SomeNOP();
SCL1;
SomeNOP();
SDAIN; //SDA口设为输入
while(SDA_STATE) //SDA出现为0时,则为有应答
{ errtime--;
if (!errtime) //errtime是否为0
{I2CStop();
return NO;} //返回为0(失败)
}
SDAOUT; //SDA口设为输出
SCL0;
return OK; //返回为1(成功)
}
//**************************************
//主器件为接收方,从器件为发送方时,单片机发出应答信号
//MCU Send to IC
void SendAck(void)
{
SDA0;
SomeNOP();
SCL1;
SomeNOP();
SCL0;
}
//**************************************
//主器件为接收方,从器件为发送方时,非应答信号
void SendNotAck(void)
{
SDA1;
SomeNOP();
SCL1;
SomeNOP();
SCL0;
}
//**************************************
//发送字节
void I2CSendByte(unsigned char ch)
{
unsigned char i=8;
while (i--)
{
SCL0; //SCL=0;
nop_();
if(ch&0x80)
SDA1; //使SDA为1位
else
SDA0; //使SDA为0位
//---------------
ch<<=1;
SomeNOP();
SCL1;
SomeNOP();
}
SCL0;
}
//**************************************
//接收字节
unsigned char I2CReceiveByte(void)
{
unsigned char i=8; //接收8位
unsigned char ddata,timp;
ddata=0;
SDA1;
SDAIN; //SDA口设为输入
while (i--)
{
ddata<<=1; //将ddata位向高位移,于让位0
SCL0;
SomeNOP();
SCL1;
SomeNOP();
timp = SDA_STATE; //读入SDA,后加
timp>>=SDA_MOV_BIT; //将timp的SDA位数据移到位0
ddata|=timp; //将timp的SDA位数据移到ddata位0
}
SCL0; //SCL=0;
SDAOUT; //(附加)SDA口设回为输出
return ddata;
}
//**********************************************************************
//描述:微控设计网 www.microcontrol.cn MSP430单片机模拟IIC(Inter IC)总线程序
//编写:微控设计网 DC 版主,如有问题,欢迎到微控技术论坛来讨论
//正常操作时返回位值为0,有故障时返回位值为1.
//unsigned char *DataBuff数据缓冲区指针,char ByteQuantity字节数量,
//unsigned int Address IC片内地址,
//unsigned char ControlByte芯片控制字节-IC地址/读写位,
unsigned char IIC(unsigned char *DataBuff,char ByteQuantity,unsigned int Address,
unsigned char ControlByte)
{
unsigned char errorflag=error; //错误标志位,1为错误,0为正确
unsigned char i; //i为允许本次操作的最大次数
i=1;
SCLOUT; //时钟口长设为输出
while(i--)
{
I2CStart();
I2CSendByte(ControlByte&0xfe);//指定芯片,此次必定为写
if(!WaitAck()) //涵数返回一个1为成功
continue; //结束写操作,并i-1后,再来一次
I2CSendByte((unsigned char)Address); //发送片内地址
if(!WaitAck()) //数返回一个1为成功
continue; //结束写操作,并i-1后,再来一次
//------------------------------已经选定好IC
if(!(ControlByte&0x01)) //本次操作是读还是写
{ //写操作
errorflag=right; //清错误标志位为0
while(ByteQuantity--) //操作j个数字节
{
I2CSendByte(*DataBuff++);//发送
if(WaitAck()) //涵数返回一个1为成功,涵数返回一个0为失败
continue; //成功,下一个数据循环(跳while)
errorflag=error; //不应答,失败了. errorflag=1
break; //退出写操作
}
if(errorflag==error) //经过写完后,如果最后errorflag标志为1,则表示有错误
continue; //结束写操作,并i-1后,再来一次
break; //写操作完成
}
else //则为读操作
{ I2CStart(); //开始
I2CSendByte(ControlByte);
if(!WaitAck()) //涵数返回一个1为成功
{continue;} //结束此操作,并i-1后,再来一次
while(--ByteQuantity) //读入ByteQuantity个数字节
{*DataBuff++=I2CReceiveByte();//连续读入ByteQuantity个数据
SendAck();} //主机向从机发出应答,表示主机已接收
*DataBuff=I2CReceiveByte(); //读入最后个数据
SendNotAck(); //最后发出不应答信号(位),表示主机不再读了.
errorflag=right; //向错误标志位写0(right),表示读数据正确.
break;} //读操作完成*/
}
I2CStop(); //停止,结束IIC总线
return(errorflag); //返回操作成败标志
}
//***********************************************************************