📄 m430iicbus.c
字号:
//模拟IIC,采用P22,23口
//描述:MSP430模拟IIC驱动程序
//编译环境:IAR EW430 V3.42A
// ACLK = LFXT1 = 32768Hz, MCLK = SMCLK = default DCO = 32 x ACLK = 1048576Hz
// //* An external watch crystal between XIN & XOUT is required for ACLK *//
#include<msp430x44x.h>
#include "cry1602.h" //包含液晶操作函数
//******************************************************************************
//-----------------------MAX5812专用变量定义------------------------------------
#define MAX5812_WRITE 0xa8 //1010100 0 写地址
#define MAX5812_READ 0xa9 //1010100 1(R/W/) 读地址
#define MAX5812_Wakeup 0x40 //01000000 唤醒命令字
//#define NUM 4 // 接收和发送缓存区的深度
//unsigned char idata receivebuf[NUM]; // 数据接收缓冲区
//bit bdata SystemError; // 从机错误标志位
//------------------------------------------------------------------------------
//SDA 数据线定义------------->P2.3
#define SDAOUT P2DIR |= BIT3
#define SDAIN P2DIR &= ~BIT3
#define SDA1 P2OUT |= BIT3
#define SDA0 P2OUT &= ~BIT3
//SCL 时钟线定义------------->P2.2
#define SCLOUT P2DIR |= BIT2
#define SCL1 P2OUT |= BIT2
#define SCL0 P2OUT &= ~BIT2
#define SDA_STATE P2IN & BIT3 //读入SDA状态
//******************************************************************************
#define SDA_MOV_BIT 1 //SDA 数据调整移位
//从器件接收方的应答返回标志
#define OK 0x01 //表示从器件有应答
#define NO 0x00 //表示从器件无应答
//IIC总线操作成失标志
#define error 0x01 //错误
#define right 0x00 //正确
//******************************************************************************
//小延时
nop_()
{_NOP();_NOP();}
SomeNOP()
{nop_();nop_();nop_();nop_();}
//******************************************************************************
// 函数名称: I2CStart()
// 函数功能: 启动I2C总线子程序
//起始信号
void I2CStart(void) //时钟保持高,数据线从高到低一次跳变,I2C通信开始
{
_DINT(); //关总中断;
SCLOUT; //SCL口设为输出-------后加
SDAOUT; //SDA口设为输出
SDA1;
//SCLOUT; //SCL口设为输出
SCL1;
SomeNOP(); SomeNOP(); //INI
SDA0;
SomeNOP(); SomeNOP(); //START
SCL0;
}
//******************************************************************************
// 函数名称: I2CStop()
// 函数功能: 停止I2C总线数据传送子程序
//结束信号
void I2CStop(void) //时钟保持高,数据线从低到高一次跳变,I2C通信停止
{
SCL0;
SDA0;
SomeNOP(); //INI
SCL1;
SomeNOP();
SDA1; //STOP
_EINT(); //EA=1;
}
//******************************************************************************
// 函数名称: WaitAck()
// 函数功能: 从机发送应答位子程序,等待从器件接收方的应答
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;
}
//******************************************************************************
// 函数名称: I2CSendByte
// 入口参数: ch
// 函数功能: 发送一个字节
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位
//-----------------------------------------SDA线上的数据变化应在SCL为低时进行
ch<<=1; //先发送一个字节的高位,然后发送低位
SomeNOP();
SCL1; //SCL为高时,数据有效
SomeNOP();
}
SCL0;
}
//******************************************************************************
// 函数名称: I2CreceiveByte
// 返回接收的数据
// 函数功能: 接收一字节子程序
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(); //i2c start>>>>>>>>>>
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); //返回操作成败标志
}
*/
//******************************************************************************
//------------------------------------------------------------------------------
// 函数名称: check_ACK
// 函数功能: 主机应答位检查子程序,迫使数据传输过程结束
//------------------------------------------------------------------------------
/*void check_ACK(void)
{
SDA1; // 将p1.0设置成输入,必须先向端口写1
SCL1;
F0 = 0;
if(SDA == 1) // 若SDA=1表明非应答,置位非应答标志F0
F0 = 1;
SCL0;
}
*/
//--------------------------------MAX5812唤醒程序-------------------------------
void DAC_MAX5812_Wakeup(void)
{
unsigned int i;
for(i=0;i<3;i++) //这里最多可以尝试唤醒3次
{
I2CStart(); // 启动I2C
I2CSendByte(MAX5812_WRITE); // 发送max5812写地址位
if(WaitAck()) //涵数返回一个1为成功,涵数返回一个0为失败,成功则发送唤醒命令字,否则什么也不做
{
I2CSendByte(MAX5812_Wakeup); //唤醒MAX5812
if(WaitAck())
{
I2CStop(); //唤醒成功,则推出总线操作
i=4; //如果成功,则i幅值大于3,则直接退出循环
//errorflag=right; //清错误标志位为0
DispNChar(0,1,15,"MAX5812 Success"); //显示提示文字
SomeNOP();
SomeNOP();
SomeNOP();
SomeNOP();
}
}
else
DispNChar(0,1,15,"DAC 5812 Faile."); //显示提示文字
}
Delay400ms(); //延迟一小段时间,以便于看清楚初始化的情况
}
//------------------------------MAX5812输出电压---------------------------------
//函数名称: DAC_MAX5812
// 入口参数: slave_add从机地址,n要发送的数据个数
// 函数功能: 发送n位数据子程序
//Slave Address Byte Definition S|A6|A5|A4|A3|A2|A1|A0|R/W!
//Command Byte Definiton C3|C2|C1|C0|D11|D10|D9|D8
//操作顺序:开始-》设备地址-》ACK-》命令字-》ACK-》数据-》停止
void DAC_MAX5812(unsigned char controlbyte,unsigned char wdata_high,unsigned char wdata_low)
{
//unsigned char errorflag; //错误标志位,1为错误,0为正确
//unsigned char i; //i为允许本次操作的最大次数
//i=1;
SCLOUT; //时钟口长设为输出
unsigned char i;
i=1;
//while(i--)
while(i)
{
I2CStart(); // 启动I2C
I2CSendByte(MAX5812_WRITE); // 发送max5812写地址位
if(WaitAck()) //涵数返回一个1为成功,涵数返回一个0为失败
{
I2CSendByte(controlbyte|wdata_high); //发送命令字+高字节数据,controlbyte=1100 0000=0xc0,数据同步更新模式
if(WaitAck()) //涵数返回一个1为成功,涵数返回一个0为失败
{
I2CSendByte(wdata_low); //发送低字节数据
if(WaitAck()) //涵数返回一个1为成功,涵数返回一个0为失败
{
I2CStop();
//i=0; //退出循环操作
//errorflag=right; //如果成功了,清错误标志位为0
SomeNOP();
SomeNOP();
SomeNOP();
SomeNOP();
i=0; // 全部操作完成,停止I2C总线的操作,退出循环!!!
}
else
{
//;
//errorflag=error; //不应答,失败了. errorflag=1;
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -