2 qq 39535875 qq_39535875 于 2017.09.19 17:09 提问

msp430f149+ds3231 模拟iic 怎么没有sda信号?哪里不对了? 10C

#define DS_SCL BIT4 //DS_SCL = P5.4

#define DS_SDA BIT6 //DS_SDA = P2.6

#define DS_SCL_IN P5DIR &= ~DS_SCL

#define DS_SCL_OUT P5DIR |= DS_SCL

#define DS_SCL0 P5OUT &= ~DS_SCL

#define DS_SCL1 P5OUT |= DS_SCL

#define DS_SDA_IN P2DIR &= ~DS_SDA

#define DS_SDA_OUT P2DIR |= DS_SDA

#define DS_SDA0 P2OUT &= ~DS_SDA

#define DS_SDA1 P2OUT |= DS_SDA

#define DS_SDA_BIT P2IN & DS_SDA

void Init_CLK(void)

{

unsigned int i;

BCSCTL1 &= ~XTS;

do{

IFG1 &= ~OFIFG;

for(i=0xFF;i>0;i--);

}

while((IFG1 & OFIFG)!=0);

BCSCTL2 |= SELS+SELM1;

_EINT();

P5SEL|=0x30;

DS_SCL_OUT;  //SCLK对应的IO设置为输出状态

P2DIR&=0xbf;

P2OUT|=BIT6;

DS_SCL0;     //SCLK=0

delay_us(5);

}

void DS3231_Write(u8 write_address,u8 write_data)

{

u8 Device_Address = 0xD0; //DS3231写设备地址

iic_Start();                   //开始

iic_SendByte(Device_Address);  //发送设备地址

iic_Ack();



iic_SendByte(write_address);   //发送地址

iic_Ack();                     //应答



iic_SendByte(write_data);      //发送数据

iic_Ack();                     //应答



iic_Stop();                    //停止

}

u8 DS3231_Read(u8 read_address)

{

u8 Receive_Data; //数据接收

u8 Device_Address = 0xD0; //DS3231写设备地址



iic_Start();                   //开始

iic_SendByte(Device_Address);  //发送设备地址

iic_Ack();                     //应答



iic_SendByte(read_address);    //发送地址

iic_Ack();                     //应答



iic_Start();                   //重复开始

Device_Address = 0xD1;         //DS3231读设备地址

iic_SendByte(Device_Address);  //发送地址

iic_Ack();                     //应答



iic_in();

Receive_Data = iic_ReceiveByte();  //接收数据

iic_out();

iic_NAck();                    //不应答



iic_Stop();                    //停止



return Receive_Data;           //返回数据

}

void delay_us(u8 time)

{

for(int i=0;i<time;i++)

_NOP();

}

view plaincopy to clipboardprint?



//------------iic开始-----------

void iic_Start(void)

{

DS_SDA_OUT;

DS_SCL_OUT;

DS_SCL1;

delay_us(5);

DS_SDA1;

delay_us(10);

DS_SDA0;

delay_us(5);

DS_SCL0;

delay_us(5);

DS_SDA_IN;

}

//------------iic结束-----------

void iic_Stop(void)

{ DS_SDA_OUT;

DS_SCL_OUT;

DS_SCL1;

delay_us(10);    

DS_SDA0;

delay_us(5);

DS_SDA1;

delay_us(5); 

  DS_SDA_IN;

}

//------------iic应答-----------

void iic_Ack(void)

{

DS_SCL0;

DS_SDA0;

delay_us(5);

DS_SCL1;

delay_us(5);

DS_SCL0;

delay_us(5);

}

//------------iic不应答---------

void iic_NAck(void)

{

DS_SCL0;

DS_SDA1;

delay_us(5);

DS_SCL1;

delay_us(5);

DS_SCL0;

delay_us(5);

}

//------------iic发送-----------

void iic_SendByte(u8 SendData)

{

DS_SDA_OUT;

DS_SCL_OUT;

DS_SCL0;

u8 i;

for(i=0;i<8;i++)

{

    DS_SCL0;

delay_us(5);

if(SendData&0x80)         //MSB在前

        DS_SDA1;

else

                    DS_SDA0;

DS_SCL1;

delay_us(2);

DS_SCL0;

SendData<<=1;

}

//delay_us(5);

//DS_SDA1;

//delay_us(5);

//DS_SDA_IN;

}

//------------iic接收-----------

u8 iic_ReceiveByte(void)

{

u8 i,temp=0;

delay_us(5);

DS_SDA1;

delay_us(5);

for(i=0;i<8;i++)

{

    temp<<=1;

DS_SCL0;

delay_us(5);

DS_SCL1;

delay_us(2);

temp=DS_SDA_BIT;

if(temp==0x80)

        temp=temp|0x01;

else

        temp=temp&0xFE;

}

DS_SCL0;

delay_us(2);

return temp;

}

void iic_in()

{

DS_SCL_OUT;

DS_SDA_IN;

}

void iic_out()

{

DS_SCL_OUT;

DS_SDA_OUT;

DS_SCL1;

delay_us(5);

DS_SDA1;

delay_us(2);

}

1个回答

tianxj001
tianxj001   2017.09.19 19:40

我自己用的软IIC程序,IAR平台,芯片STM8f103,你稍作修改可以适用别的平台和芯片。
整个IIC驱动严格按照IIC标准时序做的,为了这个,连延时函数都是半周期。
你可以分析一下我程序里面延时函数是用法,来进一步了解IIC时钟、数据、ACK之间的时序关系。
被控制芯片我的程序里面是ADS1115 AD芯片,这个修改一下芯片地址就可以用到任何芯片上,控制指令每个芯片不同,必须按照你选择的芯片重新修改。
写IIC程序其实和传统软串口没什么本质区别,只是动作更多点而已,当然由于IIC通信速率比较高,因此对信号的时序要求就比较高,否则容易引起通信失败。
这个软IIC时序,是根据延时函数确定速率的,修改该函数,可以实现各种通信速率,按照我的程序里面,机器时钟是16MHz,速率大概近400KHz。
通过示波器观察过,我这个IIC程序的波形和标准IIC时序图比较非常标准。

 #define    ADS1115_ADD        0X90           
#define SCL              PB_ODR_ODR4
#define SDA              PB_ODR_ODR5
#define SDA_IN           PB_IDR_IDR5
#define SET_SCL_OUT()    {PB_DDR_DDR4=1;PB_CR1_C14=0;PB_CR2_C24=0;}
#define SET_SDA_OUT()    {PB_DDR_DDR5=1;PB_CR1_C15=0;PB_CR2_C25=0;}
#define SET_SDA_IN()    {PB_DDR_DDR5=0;PB_CR1_C15=0;PB_CR2_C25=0;}

void Init_IIC(void)
   {
      I2C_CR1 &= 0xFE;      //  PE=0, disable IIC module  
      SET_SDA_OUT();
      SDA=1;
      SET_SCL_OUT();
      SCL=1;
   }

//--------------------------------------------------------------
//IIC主时钟定时用延时函数
//--------------------------------------------------------------
void Delay_CLK()
   {
      NOP();NOP();NOP();NOP();NOP();
   }

//--------------------------------------------------------------
//IIC 启动信号发送
//--------------------------------------------------------------
void IIC_Start(void)
   {
      SDA = 0;                   
      Delay_CLK();                
      SCL = 0;                    
   }

//--------------------------------------------------------------
//IIC 停止信号发送
//-------------------------------------------------------------- 
void IIC_Stop(void)
   {
      SDA = 1;                   
      Delay_CLK();                
      SCL = 1;
   }

//--------------------------------------------------------------
//MASTER模式 发送ACK应答
//--------------------------------------------------------------
void IIC_SendACK(u8 ACK)
   {
      SDA = ACK;
      SCL = 1;                   
      Delay_CLK(); 
      Delay_CLK();
      SCL = 0;
   }

//--------------------------------------------------------------
//IIC单字节发送+ACK检测
//--------------------------------------------------------------

u8 IIC_SendByte(u8 Send_DAT)
   {
      u8    CHK_ACK;
      for (u8 i=0;i<8;i++)         
         {
            SCL = 0;                
            Delay_CLK();
            SDA=Send_DAT>>7;
            Send_DAT <<=  1;
            SCL = 1;                
            Delay_CLK();Delay_CLK(); 
         } 
      SCL = 0;                
      Delay_CLK();
      SET_SDA_IN();
      Delay_CLK(); 
      SCL = 1;    
      CHK_ACK = (u8)SDA_IN;
      SET_SDA_OUT();
      Delay_CLK();   
      SCL = 0;   
      Delay_CLK();  
      return CHK_ACK;   
   }

//--------------------------------------------------------------
//IIC 单字节接受
//--------------------------------------------------------------
u8 IIC_RecvByte()
   {
      u8 Recv_DAT = 0;
      SDA = 1;     
      SET_SDA_IN();
      for (u8 i=0; i<8; i++)         
         { 
            Recv_DAT <<= 1;
            SCL = 1;
            Delay_CLK(); 
            Recv_DAT+=(u8)SDA_IN;   
            NOP();NOP();
            SCL = 0;                
            Delay_CLK();  
         }
      SET_SDA_OUT();
      return Recv_DAT;
   }

//--------------------------------------------------------------
//ADS1115 写控制项
//--------------------------------------------------------------
void config_ads1115(u8 regadd,u8 wdata,u8 wdata1)
   {
      IIC_Start();
      IIC_SendByte(ADS1115_ADD);//根据需要,这里可以加上ACK检测
      IIC_SendByte(regadd);
      IIC_SendByte(wdata);
      IIC_SendByte(wdata1);
      IIC_Stop();             
   }
//--------------------------------------------------------------
//ADS1115 读转换结果
//--------------------------------------------------------------
int Read_ads1115(u8 REG_ADD)
   {
      int READ_TMP;
      IIC_Start();            
      IIC_SendByte(ADS1115_ADD);   //写地址为7位器件地址+读写位=0   
      IIC_SendByte(REG_ADD); 
      IIC_Stop();
      IIC_Start();    
      IIC_SendByte(ADS1115_ADD|1); //读地址为7位器件地址+读写位=1   
      *((u8*)(&READ_TMP))= IIC_RecvByte();
      IIC_SendACK(0);
      *((u8*)(&READ_TMP)+1)= IIC_RecvByte();
      IIC_SendACK(0);
      IIC_Stop();
      return READ_TMP;
   }
Csdn user default icon
上传中...
上传图片
插入图片