msp430——軟件模擬II2C實(shí)例
#include <msp430x22x4.h>
#define SDA BIT1
#define SCL BIT2
#define SEG_A 0xA0 //0x0200---0x027F
#define SEG_B 0xB0 //0x0280---0x02FF
#define SEG_C 0xC0 //0x0300---0x037F
//0x0380---0x0400
__no_init char wokao@0x243;
//=============================
char *send_ptr;
char DEVICE_ADR=0;
char WORD_ADR=0;
char REC_DATA=0;
char START_flag = 0;
char STOP_flag = 0;
char PreState = 0;
char NowState = 0;
//*********************函數(shù)聲明*************************************
void ACK(void);
//****************************************************************
void main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
//======================MCLK=16MHz=====================================
DCOCTL = CALDCO_16MHZ;
BCSCTL1 = CALBC1_16MHZ; //MCLK=DCO=16MHz
P3DIR &= ~(SDA+SCL);
while(1)
{
NN=10;
PreState = READ_SDA;
while(READ_SCL && NN--)
{
NowState = READ_SDA;
if(PreState && !NowState)
{
START_flag = 1;
_DINT();
}
if(!PreState && NowState)
{
STOP_flag = 1;
_EINT();
}
PreState = NowState;
if(START_flag)
{
START_flag=0;
while(READ_SCL); //START時(shí)的SCL高電平狀態(tài)就等待
for(gg=8;gg>0;gg--) //接收器件地址
{
while(!READ_SCL); //SCL低電平狀態(tài)就等待
DEVICE_ADR<<=1;
if(READ_SDA) //數(shù)據(jù)的第一個(gè)CLK高電平來(lái)臨
DEVICE_ADR |= 0x01;
while(READ_SCL); //SCL高電平狀態(tài)就等待
}
ACK(); //對(duì)設(shè)備地址ACK應(yīng)答信
//-----------以上收到了設(shè)備地址,并知曉主機(jī)要對(duì)從機(jī)進(jìn)行讀還是寫操作---
for(gg=8;gg>0;gg--) //接收內(nèi)存單元地址
{
while(!READ_SCL);
WORD_ADR<<=1;
if(READ_SDA)
WORD_ADR |= 0x01;
while(READ_SCL);
}
//-----------以上就已經(jīng)接收到內(nèi)存單元地址------------
ACK(); //對(duì)內(nèi)存單元ACK應(yīng)答信號(hào)
if(DEVICE_ADR & 0x01) //從機(jī)發(fā)數(shù)據(jù)給主機(jī) R/W=1
{
if(DEVICE_ADR==SEG_A+0x01)
{
send_ptr =(char*)(0x0200 + WORD_ADR);
}
else if(DEVICE_ADR==SEG_B+0x01)
{
send_ptr =(char*)(0x0280 + WORD_ADR);
}
else if(DEVICE_ADR==SEG_C+0x01)
{
send_ptr =(char*)(0x0300 + WORD_ADR);
}
//--------以上是判斷出為主機(jī)讀從機(jī),要把要讀的地址單元賦給指針---
for(gg=8;gg>0;gg--)
{
while(!READ_SCL);
if( *send_ptr & 0x80)
_NOP();
else
{
P3DIR |= SDA; //輸出0
}
while(READ_SCL); //SCL為1,就保持SDA輸出不變
P3DIR &= ~SDA; //SCL為0,就把SDA從新切換到接收狀態(tài)
*send_ptr <<=1;
}
ACK(); //從機(jī)數(shù)據(jù)發(fā)送完畢,應(yīng)答信號(hào)
_NOP();
//------------------以上是從機(jī)發(fā)數(shù)據(jù)給主機(jī)-----------------
}
else //主機(jī)寫從機(jī) R/W=0
{
for(gg=8;gg>0;gg--) //接收主機(jī)要寫到該器件內(nèi)存單元的數(shù)據(jù)
{
while(!READ_SCL);
REC_DATA <<=1;
if(READ_SDA)
REC_DATA |= 0x01;
while(READ_SCL);
}
if(DEVICE_ADR==SEG_A)
{
send_ptr =(char*)(0x0200 + WORD_ADR);
*send_ptr = REC_DATA;
}
else if(DEVICE_ADR==SEG_B)
{
send_ptr =(char*)(0x0280 + WORD_ADR);
*send_ptr = REC_DATA;
}
else if(DEVICE_ADR==SEG_C)
{
send_ptr =(char*)(0x0300 + WORD_ADR);
*send_ptr = REC_DATA;
}
ACK();
_NOP();
while(!READ_SCL);
}
}// if(START_flag)
}//while(NN--)
_EINT();
_NOP();
}//while(1)
}
//****************************************************
void ACK(void)
{
// while(READ_SCL);
while(!READ_SCL);
P3DIR |= SDA; //第9個(gè)CLK變高的情況下,SDA輸出0
while(READ_SCL);
P3DIR &= ~SDA; //第9個(gè)CLK變低的情況下,SDA輸出1
}