MSP430f149 I2C通讯(hut21d温湿度)读数总是返回0xff

2019-03-24 09:06发布

大家好:我最近在做MSP430F149的I2C通讯, 从HTU21D模块中读取湿度,用P3.3和P3.3口做SCL和SDA。从单片机向模块写地址和命令时,模块能正确响应,即能返回ACK,但是读到的数据都是0xff。求高手解答~!万分感激~!
下面是我编写的代码,只读取湿度:

#include <msp430x14x.h>
#include "config.h"

#define SDA_1   P3OUT |= BIT3
#define SDA_0   P3OUT &= ~BIT3
#define SCL_1   P3OUT |= BIT2
#define SCL_0   P3OUT &= ~BIT2
#define DIR_IN  P3DIR &= ~BIT3; SDA_1;
#define DIR_OUT  P3DIR |= BIT3;
#define SDA_IN  ((P3IN>>3)&0x01)

uchar ack; //0 为ACK,1 为NACK
uint shidu;

void I2C_init(void)
{
   P3SEL=0;
   P3DIR |= BIT2+BIT3;  //输出
}


void I2C_Start()         
{
  DIR_OUT;
  SDA_1;      //发送起始条件的数据信号
  SCL_1;
  delay_us(10);       //起始条件建立时间大于4.7us,延时
  SDA_0;      //发送起始信号
  delay_us(10);      //起始条件建立时间大于4us,延时
  SCL_0;     //钳住I2C总线准备发送或接收数据
  delay_us(10);
}

void I2C_Stop()
{
  DIR_OUT;
  SDA_0;      //发送结束条件的数据信号
  delay_us(10);
  SCL_1;      //发送结束条件的时钟信号
  delay_us(10);      //结束条件建立时间大于4us,延时
  SDA_1;      //发送I2C总线结束信号
  delay_us(10);
}


//完成IIC的主机应答操作
void Mack()
{
  DIR_OUT;
  SDA_0;      //发送结束条件的数据信号
  delay_us(10);
  SCL_1;      //发送结束条件的时钟信号
  delay_us(10);      //结束条件建立时间大于4us,延时
  SCL_0;
  delay_us(10);
  SDA_1;
  delay_us(10);
}


//完成IIC的主机无应答操作
void MNack()
{
  DIR_OUT;
  SDA_1;     
  delay_us(10);
  SCL_1;   
  delay_us(10);   
  SCL_0;
  delay_us(10);
  SDA_0;
  delay_us(10);
}

//从机发送的应答信号
void check()
{
    SDA_1;      //释放数据线
    delay_us(20);
    SCL_1;      //发送结束条件的时钟信号
    delay_us(20);
    DIR_IN;
    ack=SDA_IN;
    SCL_0;
    delay_us(20);
    DIR_OUT;
}         

uchar I2C_writebyte(uchar a)
{
  uchar i;
  DIR_OUT;
  //SDA_0;
  //delay_us(10);
  for(i=0;i<8;i++)
  {
    if((a<<i)&0x80)
    {
      SDA_1;
    }
    else
    {
      SDA_0;
    }
    delay_us(20);
    SCL_1;
    delay_us(20);   
    SCL_0;
    delay_us(20);
  }
  SCL_0;
  delay_us(20);
  check();
  return ack;
}

uchar I2C_readbyte(void)//读一个字节  
{  
    uchar i,k; //i读取位数,k存储读到的字节
    k=0x00;
    DIR_IN;
    for(i=0;i<8;i++)  
    {   

        SCL_0;//拉低SCL,使发送端可以把数据放在SDA上
        delay_us(20);
        SDA_1;//释放数据线
        delay_us(20);
        SCL_1;//上升沿时,IIC设备将数据放在sda线上,并在高电平期间数据已经稳定,可以接收啦  
        delay_us(20);
        //DIR_IN;
        k=(k<<1);
        if(SDA_IN==0)
        {
          k=k+0x00;
        }
        else
        {k=k+0x01;}
        //DIR_OUT;
        SCL_0;//拉低SCL,使发送端可以把数据放在SDA上
        delay_us(20);
    }   
    return k;
}  


ulong I2C_readword(uchar address)//读取一个16为数字
{  
    ulong date;
    uchar MSB,LSB;  
    I2C_Start();//启动  
    if(I2C_writebyte(0x80)==0)
    {
       if(I2C_writebyte(address)==0) //发送芯片内地址
       {
          delay_ms(20);
          I2C_Start();//启动
          while(I2C_writebyte(0x81)==0);
          MSB=I2C_readbyte();//获取数据  
          Mack();
          LSB=I2C_readbyte();//获取数据
          MNack();
          I2C_Stop();//停止  
       }
      else
      {I2C_readword(address);}
    }
    else
    {
      I2C_readword(address);
    }

   date=(ulong)MSB*256+(LSB&0xfc);
   delay_us(20);
   return date;//返回数据
}



void main()
{
   WDT_Init();                                   //看门狗设置
   Clock_Init();                                 //系统时钟设置
   I2C_init();
   Close_LED();                                  //关闭LED数码管,避免显示乱码
   delay_ms(100);                                //延时100ms
   LCD_init();                                   //液晶参数初始化设置
   LCD_clear();                                  //清屏
   delay_us(5);
   while(1)
   {
     ulong m=I2C_readword(0xf5);
     m=m*1250/65536-60;
     shidu=(uint)m;  
   }
}




此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
5条回答
Mango_baby
2019-03-24 11:25
< :TI_MSP430_内容页_SA7 -->
数码小叶 发表于 2016-3-21 10:41
看了几遍,觉得这个读时序是不是乱了啊,在写完地址后再次启动。。。。你把date直接复制0,看最后的数据是 ...


谢谢~!
确实是 写完地址后再次启动 时出错了。修改后可以正常读数了~!

修改后的I2C_readword(uchar)函数是:

ulong I2C_readword(uchar address)//读取一个16位数字
{  
    ulong date;
    uchar MSB,LSB;  
    I2C_Start();//启动  
    if(I2C_writebyte(0x80)==0)
    {
       if(I2C_writebyte(address)==0) //发送芯片内地址
       {
          delay_ms(10);
          I2C_Start();//启动
          while(I2C_writebyte(0x81)==1)
          {
            delay_us(100);
            I2C_Start();
          }

          MSB=I2C_readbyte();//获取数据  
          Mack();
          LSB=I2C_readbyte();//获取数据
          MNack();
          I2C_Stop();//停止  
          LSB=LSB&0xfc;
       }
      else
      {I2C_readword(address);}
    }
    else
    {
      I2C_readword(address);
    }
   date=(ulong)MSB*256+LSB;
   delay_us(10);
   return date;//返回数据
}

一周热门 更多>

相关问题

    相关文章