📄 m430iicbus.c
字号:
#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;
}
//正常操作时返回位值为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); //返回操作成败标志
}
//******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -