qq_39535875 2017-09-19 09:09 采纳率: 0%
浏览 1281
已结题

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

#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 2017-09-19 11: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;
       }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序
  • ¥15 onvif+openssl,vs2022编译openssl64
  • ¥15 iOS 自定义输入法-第三方输入法
  • ¥15 很想要一个很好的答案或提示
  • ¥15 扫描项目中发现AndroidOS.Agent、Android/SmsThief.LI!tr
  • ¥15 怀疑手机被监控,请问怎么解决和防止
  • ¥15 Qt下使用tcp获取数据的详细操作
  • ¥15 idea右下角设置编码是灰色的
  • ¥15 全志H618ROM新增分区