#include "msp430x14x.h" #include "define.h"
//使用方式:以涵数方式调用,使用时程序关闭总中断,使用完后打开总中断. //占用资源为:使用两个IO口,本程序CPU主时钟MCLK=800K. //SDA 数据线定义 #define SDAOUT P1DIR |= BIT4 #define SDAIN P1DIR &= ~BIT4 #define SDA1 P1OUT |= BIT4 #define SDA0 P1OUT &= ~BIT4 //SCL 时钟线定义 #define SCLOUT P6DIR |= BIT3 #define SCL1 P6OUT |= BIT3 #define SCL0 P6OUT &= ~BIT3
#define SDA_STATE P1IN & BIT4 //读入SDA状态
//从器件接收方的应答返回标志 #define OK 0x01 //表示从器件有应答 #define NO 0x00 //表示从器件无应答
//IIC总线操作成失标志 #define error 0x01 //错误 #define right 0x00 //正确
//IIC总线操作成失标志 #define error 0x01 //错误 #define right 0x00 //正确
#define AT24_ADD 0xA0 //24c02芯片地址
#define write 0x00 //写 #define read 0x01 //读
#define Quantity 3 //操作数量 #define incept_add 0x10 //操作内部地址首址 //写入AT24C02数据表 // unsigned char write_table[3]={'a','e','d'}; //读出AT24C02数据缓冲区 //unsigned char read_Buff[3]={'x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x'}; unsigned char read_Buff[3]={'x','x','x'}; //****************************************************** //MSP430F14初始化 void init (void) { } //****************************************************** //小延时 nop_() {_NOP();_NOP();}
SomeNOP() {nop_();nop_();nop_();nop_();nop_();} //****************************************************** //软延时 void delay(unsigned int n) {unsigned int k; for(k=0;k<n;k++); } //************************************** void XCLR_LOW(void) { P1SEL &= ~BIT6; //P1.6普通IO P1DIR |= BIT6; //P1.6输出0 P1OUT &= ~BIT6; } void XCLR_HIGH(void) { P1SEL &= ~BIT6; //P6.1普通IO P1DIR |= BIT6; //P6.1输出1 P1OUT |= BIT6; } //****************************************************** void main(void) { WDTCTL=WDTPW+WDTHOLD; //停止WDT //P6SEL &= ~BIT3; //P1.6普通IO //P6DIR |= BIT3; //P1.6输出0 //P6OUT |= BIT3; //P6OUT &= ~BIT3; //P6OUT |= BIT3; XCLR_LOW(); init(); //初始化 // IIC(write_table,Quantity,incept_add,(AT24_ADD|write)); delay(500); //写入后,做一个适当的延时 IIC(read_Buff,Quantity,incept_add,(AT24_ADD|read)); LPM1; } //************************************** //起始信号 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; SDA1; SDAIN; //SDA口设为输入 while (i--) { ddata<<=1; //将ddata位向高位移,让位0 SCL0; SomeNOP(); SCL1; SomeNOP(); if(SDA_STATE) //读入SDA,后加 ddata|=1; } 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); //返回操作成败标志 } |