|
#include "msp430x14x.h"<br />#include "define.h"<br /><br />//使用方式:以涵数方式调用,使用时程序关闭总中断,使用完后打开总中断.<br />//占用资源为:使用两个IO口,本程序CPU主时钟MCLK=800K.<br />//SDA 数据线定义<br />#define SDAOUT P1DIR |= BIT4<br />#define SDAIN P1DIR &= ~BIT4<br />#define SDA1 P1OUT |= BIT4<br />#define SDA0 P1OUT &= ~BIT4<br />//SCL 时钟线定义<br />#define SCLOUT P6DIR |= BIT3<br />#define SCL1 P6OUT |= BIT3<br />#define SCL0 P6OUT &= ~BIT3<br /><br />#define SDA_STATE P1IN & BIT4 //读入SDA状态<br /><br />//从器件接收方的应答返回标志<br />#define OK 0x01 //表示从器件有应答<br />#define NO 0x00 //表示从器件无应答 <br /><br />//IIC总线操作成失标志<br />#define error 0x01 //错误<br />#define right 0x00 //正确<br /><br />//IIC总线操作成失标志<br /> #define error 0x01 //错误<br /> #define right 0x00 //正确<br /><br /> #define AT24_ADD 0xA0 //24c02芯片地址 <br /><br /> #define write 0x00 //写<br /> #define read 0x01 //读<br /><br /> #define Quantity 3 //操作数量<br /> #define incept_add 0x10 //操作内部地址首址<br /> <br />//写入AT24C02数据表<br />// unsigned char write_table[3]={'a','e','d'};<br />//读出AT24C02数据缓冲区<br /> //unsigned char read_Buff[3]={'x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x'}; <br />unsigned char read_Buff[3]={'x','x','x'};<br />//******************************************************<br />//MSP430F14初始化<br />void init (void)<br />{<br /> <br />}<br />//******************************************************<br />//小延时<br />nop_()<br />{_NOP();_NOP();}<br /><br />SomeNOP()<br /> {nop_();nop_();nop_();nop_();nop_();}<br />//******************************************************<br />//软延时<br />void delay(unsigned int n)<br />{unsigned int k;<br /> for(k=0;k<n;k++);<br />}<br />//**************************************<br />void XCLR_LOW(void)<br />{<br /> P1SEL &= ~BIT6; //P1.6普通IO<br /> P1DIR |= BIT6; //P1.6输出0<br /> P1OUT &= ~BIT6; <br />}<br />void XCLR_HIGH(void)<br />{<br /> P1SEL &= ~BIT6; //P6.1普通IO<br /> P1DIR |= BIT6; //P6.1输出1<br /> P1OUT |= BIT6; <br />}<br />//******************************************************<br />void main(void)<br />{<br /> WDTCTL=WDTPW+WDTHOLD; //停止WDT<br /> //P6SEL &= ~BIT3; //P1.6普通IO<br /> //P6DIR |= BIT3; //P1.6输出0<br /> //P6OUT |= BIT3; <br /> //P6OUT &= ~BIT3;<br /> //P6OUT |= BIT3; <br /> <br /> XCLR_LOW();<br /> init(); //初始化<br /> // IIC(write_table,Quantity,incept_add,(AT24_ADD|write));<br /> delay(500); //写入后,做一个适当的延时<br /> IIC(read_Buff,Quantity,incept_add,(AT24_ADD|read)); <br /> LPM1;<br />}<br />//**************************************<br />//起始信号<br />void I2CStart(void)<br /> {<br /> _DINT(); //关总中断;<br /> SCLOUT; //SCL口设为输出-------后加<br /> SDAOUT; //SDA口设为输出 <br /> SDA1; <br /> //SCLOUT; //SCL口设为输出 <br /> SCL1;<br /> SomeNOP(); SomeNOP(); //INI<br /> SDA0; <br /> SomeNOP(); SomeNOP(); //START<br /> SCL0; <br /> }<br />//**************************************<br />//结束信号<br />void I2CStop(void)<br /> {<br /> SCL0; <br /> SDA0; <br /> SomeNOP(); //INI<br /> SCL1; <br /> SomeNOP(); <br /> SDA1; //STOP<br /> _EINT(); //EA=1;<br /> }<br /><br />//**************************************<br />//等待从器件接收方的应答<br />unsigned char WaitAck(void)<br /> {<br /> unsigned char errtime=255; //因故障接收方无ACK,超时值为255。<br /> SDA1; <br /> SomeNOP();<br /> SCL1;<br /> SomeNOP();<br /> SDAIN; //SDA口设为输入<br /> while(SDA_STATE) //SDA出现为0时,则为有应答<br /> { errtime--; <br /> if (!errtime) //errtime是否为0<br /> {I2CStop(); <br /> return NO;} //返回为0(失败)<br /> }<br /> SDAOUT; //SDA口设为输出 <br /> SCL0; <br /> return OK; //返回为1(成功)<br /> }<br />//**************************************<br />//主器件为接收方,从器件为发送方时,单片机发出应答信号<br />//MCU Send to IC<br />void SendAck(void)<br /> {<br /> SDA0; <br /> SomeNOP();<br /> SCL1; <br /> SomeNOP();<br /> SCL0; <br /> }<br />//**************************************<br />//主器件为接收方,从器件为发送方时,非应答信号<br />void SendNotAck(void)<br /> {<br /> SDA1; <br /> SomeNOP();<br /> SCL1; <br /> SomeNOP();<br /> SCL0; <br /> }<br />//**************************************<br />//发送字节<br /> void I2CSendByte(unsigned char ch)<br /> {<br /> unsigned char i=8;<br /> while (i--)<br /> {<br /> SCL0; //SCL=0;<br /> nop_();<br /> if(ch&0x80)<br /> SDA1; //使SDA为1位<br /> else<br /> SDA0; //使SDA为0位<br /> ch<<=1; <br /> SomeNOP();<br /> SCL1; <br /> SomeNOP();<br /> }<br /> SCL0; <br /> }<br />//**************************************<br />//接收字节<br />unsigned char I2CReceiveByte(void)<br /> {<br /> unsigned char i=8; //接收8位<br /> unsigned char ddata;<br /> SDA1; <br /> SDAIN; //SDA口设为输入<br /> while (i--)<br /> {<br /> ddata<<=1; //将ddata位向高位移,让位0<br /> SCL0;<br /> SomeNOP();<br /> SCL1;<br /> SomeNOP();<br /> <br /> if(SDA_STATE) //读入SDA,后加<br /> ddata|=1; <br /> }<br /> SCL0; //SCL=0;<br /> SDAOUT; //(附加)SDA口设回为输出<br /> return ddata;<br /> }<br />//**********************************************************************<br />//正常操作时返回位值为0,有故障时返回位值为1.<br />//unsigned char *DataBuff数据缓冲区指针,char ByteQuantity字节数量,<br />//unsigned int Address IC片内地址,<br />//unsigned char ControlByte芯片控制字节-IC地址/读写位,<br />unsigned char IIC(unsigned char *DataBuff,char ByteQuantity,unsigned int Address,<br /> unsigned char ControlByte)<br />{<br /> unsigned char errorflag=error; //错误标志位,1为错误,0为正确<br /> unsigned char i; //i为允许本次操作的最大次数<br /> i=1;<br /> SCLOUT; //时钟口长设为输出<br /> while(i--)<br /> { <br /> I2CStart();<br /> I2CSendByte(ControlByte&0xfe);//指定芯片,此次必定为写<br /> if(!WaitAck()) //涵数返回一个1为成功<br /> continue; //结束写操作,并i-1后,再来一次<br /> I2CSendByte((unsigned char)Address); //发送片内地址<br /> if(!WaitAck()) //数返回一个1为成功 <br /> continue; //结束写操作,并i-1后,再来一次 <br /> <br /> //------------------------------已经选定好IC<br /> if(!(ControlByte&0x01)) //本次操作是读还是写<br /> { //写操作<br /> errorflag=right; //清错误标志位为0<br /> while(ByteQuantity--) //操作j个数字节<br /> {<br /> I2CSendByte(*DataBuff++);//发送 <br /> if(WaitAck()) //涵数返回一个1为成功,涵数返回一个0为失败<br /> continue; //成功,下一个数据循环(跳while)<br /> errorflag=error; //不应答,失败了. errorflag=1<br /> break; //退出写操作<br /> }<br /> if(errorflag==error) //经过写完后,如果最后errorflag标志为1,则表示有错误<br /> continue; //结束写操作,并i-1后,再来一次<br /> break; //写操作完成<br /> } <br /> else //则为读操作<br /> { I2CStart(); //开始 <br /> I2CSendByte(ControlByte);<br /> if(!WaitAck()) //涵数返回一个1为成功<br /> {continue;} //结束此操作,并i-1后,再来一次<br /> while(--ByteQuantity) //读入ByteQuantity个数字节<br /> {*DataBuff++=I2CReceiveByte();//连续读入ByteQuantity个数据<br /> SendAck();} //主机向从机发出应答,表示主机已接收 <br /> *DataBuff=I2CReceiveByte(); //读入最后个数据<br /> SendNotAck(); //最后发出不应答信号(位),表示主机不再读了.<br /> errorflag=right; //向错误标志位写0(right),表示读数据正确.<br /> break;} //读操作完成*/<br /> }<br /> I2CStop(); //停止,结束IIC总线<br /> return(errorflag); //返回操作成败标志<br />} |
|