哪位帮忙看看下,程序读取SHT20 的温度时就不行,无ACK反馈了

2019-12-18 18:52发布

同样的程序在ATMEGA169上可以读取,转到ATMEGA48上就不行了,到发送0XF5命令就无反馈了,谢谢

    #include "TIME.h"
        #include "UART.h"
    #include "SHT20.H" //sht20 head file
        unsigned char g_ucSegnumber1;
        unsigned char g_ucSegnumber2;
        unsigned char g_ucSegnumber3;
        unsigned char g_ucSegnumber4;
        unsigned char g_ucSegnumber5;
        unsigned char g_ucSegnumber6;
       
        //
        unsigned char g_ucTH_H , g_ucTH_L,g_ucTC_H , g_ucTC_L ,aa,bb;
    /*================================================================
    【  Name  】Pin Description
    【Function】模拟IIC使用的引脚定义,注意要上拉电阻,SDA和SCL均上拉10KΩ电阻
    【  Notes 】
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    /*************Pin Description*************
       P2.6------SCK     (SHT20)
       P2.7------DATA    (SHT20)
    *****************************************/
//    sbit SDA=P2^7;                 // define data pin
//    sbit SCL=P2^6;                 // define clock pin

    /*================================================================
    【  Name  】
    【Function】SHT20的I2C地址
    【  Notes 】
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    #define SHT20ADDR 0x80
    /*================================================================
    【  Name  】
    【Function】应答位电平定义
    【  Notes 】
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    #define ACK         0            //应答信号
    #define NACK        1            //非应答信号

    /*================================================================
    【  Name  】void Delay(uint t)
    【Function】delay Nms
    【  Notes 】
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
//    void Delay(uint t)
//    {
       //_delay_ms(t) ;                                         
//    }
    /*------------------------------------------------------------*/
    /**********************Simulation I2C Function*****************/
    /*------------------------------------------------------------*/

    /*================================================================
    【  Name  】void I2CDelay (uchar t)
    【Function】模拟IIC用的短延时 us
    【  Notes 】
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
//    void I2CDelay (uchar t)         
//    {
      //_delay_us(t);
//    }

    /*================================================================
    【  Name  】void I2CInit(void)
    【Function】I2C初始化,空闲状态
    【  Notes 】
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    void I2CInit(void)
    {
                SDADDROUT;//
                        SCLDDROUT;
                        _delay_us(20);//I2CDelay(1);
            SDASET;//SDA = 1;
//            _delay_us(20);//I2CDelay(10);
            SCLSET;//SCL = 1;
            _delay_ms(20);//I2CDelay(10);
   }

    /*================================================================
    【  Name  】void I2CStart(void)
    【Function】I2C起始信号
    【  Notes 】SCL、SDA同为高,SDA跳变成低之后,SCL跳变成低         
    【 Author 】dingshidong                                                                                                                        
    【  Data  】2012.08.07
    ================================================================*/
    void I2CStart(void)
    {      
            SDADDROUT;//
                SCLDDROUT;
                _delay_us(20);//I2CDelay(1);
        SDASET;//SDA = 1;                            //发送起始条件的数据信号--ZLG
        SCLSET;//SCL = 1;
        _delay_us(20);//I2CDelay(1);                    //起始条件建立时间大于4.7us,延时--ZLG
        SDACLR;//SDA = 0;                            //发送起始信号-ZLG
        _delay_us(20);//I2CDelay(1);                    //起始条件锁定时间大于4μs--ZLG
        SCLCLR;//SCL = 0;                            //钳住I2C总线,准备发送或接收数据--ZLG
        _delay_us(20);//I2CDelay(1);         
    }

    /*================================================================
    【  Name  】void I2CStop(void)
    【Function】I2C停止信号
    【  Notes 】SCL、SDA同为低,SCL跳变成高之后,SDA跳变成高           
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    void I2CStop(void)
    {     
            SDADDROUT;//
                SCLDDROUT;       
            _delay_us(20);//I2CDelay(1);
        SDACLR;//SDA = 0;                        //发送结束条件的数据信号--ZLG
        SCLCLR;//SCL = 0;
        _delay_us(20);//I2CDelay(1);
        SCLSET;//SCL = 1;                        //发送结束条件的时钟信号--ZLG
        _delay_us(20);//I2CDelay(1);                //结束条件建立时间大于4μs--ZLG
        SDASET;//SDA = 1;                        //发送I2C总线结束信号--ZLG
        _delay_us(20);//I2CDelay(1);
    }

    /*================================================================
    【  Name  】uchar I2C_Write_Byte(uchar WRByte)
    【Function】I2C写一个字节数据,返回ACK或者NACK
    【  Notes 】从高到低,依次发送
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    uchar I2C_Write_Byte(uchar Write_Byte)         //Sendbyte
    {
        uchar i;
                SDADDROUT;
                SCLDDROUT;
                _delay_us(20);//I2CDelay(1);     
        for(i=0;i<8;i++)              //要传送的数据长度为8位--ZLG
        {         
                if(Write_Byte&0x80)              //判断发送位--ZLG
                {
                        SDASET;//SDA = 1;      
                }
                else
                {
                        SDACLR;//SDA = 0;
                }
                _delay_us(10);//I2CDelay(1);               
                SCLSET;//SCL=1;                                  //输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样      
                _delay_us(10);//I2CDelay(5);                     //保证时钟高电平周期大于4μs--ZLG
                SCLCLR;//SCL=0;
                _delay_us(10);//I2CDelay(1);
                Write_Byte <<= 1;
        }
        _delay_us(40);//I2CDelay(4);
        SDASET;//SDA = 1;                                  //8位发送完后释放数据线,准备接收应答位-ZLG
        SCLSET;//SCL = 1; //MCU告知SHT2X数据发送完毕,等待从机的应答信号
                       
                SDADDRIN;              //SDA口转为输入                                    
        _delay_us(50);//I2CDelay(5);                  
        /*以下是判断I2C总线接收应到应答信号是ACK还是NACK*/
        asm("nop");
//                while(1)
//                {
                            //if((SDAIN)!=0x10)//(SDA==1)                                   //SDA为高,收到NACK
                            //{
                                        //SCLCLR;//SCL=0;
                                        //_delay_us(150);//I2CDelay(15);
                                        //return ACK;
                                //}
        if((SDAIN)==0x10)//(SDA==1)                     //SDA为高,收到NACK
            {   
                            SCLCLR;//SCL=0;
                _delay_us(50);//I2CDelay(15);
                                return NACK;  
                        }     
        else                                           //SDA为低,收到ACK               
            {   
                            SCLCLR;//SCL=0;
                _delay_us(50);//I2CDelay(15);
                                return ACK;
                        }
//                }
    }

    /*================================================================
    【  Name  】uchar I2C_Read_Byte(uchar AckValue)
    【Function】I2C读一个字节数据,入口参数用于控制应答状态,ACK或者NACK
    【  Notes 】从高到低,依次接收
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    uchar I2C_Read_Byte(uchar AckValue)//receivebyte
    {
        uchar i,RDByte=0;
                //管脚输出
        SCLDDROUT;
                SDADDROUT;

                SCLCLR;//SCL=0;                                                  //置时钟线为低,准备接收数据位--ZLG
        SDASET;//SDA = 1;                                  //释放总线,置数据线为输入方式--ZLG      
           
                //管脚输入
                SDADDRIN;
                for (i=0;i<8;i++)
        {      
                SCLSET;//SCL = 1;                          //SCL高电平期间,采集SDA信号,并作为有效数据 //置时钟线为高使数据线上数据有效--ZLG
                  
                                _delay_us(20);//I2CDelay(2);
                RDByte <<= 1;                  //移位
                                asm("nop");
                if((SDAIN)==0x10)//(SDA==1)                           //采样获取数据
                {
                        RDByte |= 0x01;
                }
                else
                {
                        RDByte &= 0xfe;
                }
                _delay_us(10);//I2CDelay(1);
                SCLCLR;//SCL = 0;                             //下降沿,从机给出下一位值
                _delay_us(60);//I2CDelay(6);
        }   
        /*以下是I2C总线发送应答信号ACK或者NACK*/
                        SDADDROUT;
                        if(AckValue==1)//SDA = AckValue;                      //应答状态
                        {
                SDASET;
                        }
                        else
                        {
                SDACLR;
                        }
              
                                
            _delay_us(30);//I2CDelay(3);
            SCLSET;//SCL = 1;                        
            _delay_us(50);//I2CDelay(5);                  //时钟低电平周期大于4μs--ZLG
            SCLCLR;//SCL = 0;                                  //清时钟线,钳住I2C总线以便继续接收--ZLG               
            _delay_us(150);//I2CDelay(15);
        //SDA = 1;      
        return RDByte;
    }

    /*================================================================
    【  Name  】void SoftReset(void)
    【Function】SHT20软件复位,主函数中调用
    【  Notes 】从高到低,依次接收
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    void SoftReset(void)                    
    {
        I2CInit();                       //I2C initialize
        I2CStart();                      //start I2C
        I2C_Write_Byte(SHT20ADDR&0xfe);  //I2C address + write
        I2C_Write_Byte(0xfe);                         //soft reset
        I2CStop();                       //stop I2C
    }

    /*================================================================
    【  Name  】void SET_Resolution(void)
    【Function】写寄存器,设置分辨率
    【  Notes 】
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    void SET_Resolution(void)                    
    {
      I2CStart();                                                                         //Start I2C
      if(I2C_Write_Byte(SHT20ADDR&0xfe)==ACK)       //I2C address + write + ACK
      {
       if(I2C_Write_Byte(0xe6)==ACK)                            //写用户寄存器
        {  
         //if(I2C_Write_Byte(0x83)==ACK);                            //设置分辨率   11bit RH% 测量时间:12ms(typ.) & 11bit T℃ 测量时间:9ms(typ.)
           if(I2C_Write_Byte(0x02)==ACK);
                 //if(I2C_Write_Byte(0x06)==ACK);  //自加热
                 _delay_ms(30);//Delay(6);
                }
      }
       I2CStop();                                   //Stop I2C         
    }

    /*================================================================
    【  Name  】float ReadSht20(char whatdo)
    【Function】非主机模式,读取函数函数
    【  Notes 】
    【 Author 】dingshidong
    【  Data  】2012.08.07
    ================================================================*/
    float ReadSht20(uchar whatdo)
    {
           // float temp,tttt,ttt,X;
                    unsigned long  ttemp=0,X;
            unsigned char MSB,LSB ,ZZ;// ,tt1,tt2,tt3,tt4;
            float Temperature,Humidity;

                        unsigned int tt;

            SET_Resolution();
            I2CStart();      
            if(I2C_Write_Byte(SHT20ADDR&0xfe)==ACK)                  //I2C address + write + ACK
            {     
                                   //_delay_ms(6);//Delay(6);
                                  ZZ=I2C_Write_Byte(whatdo);
                                  if(ZZ==ACK)
//                if(I2C_Write_Byte(0XF5)==ACK)                      //Command
                    {
                            do
                            {
                               _delay_ms(30);//Delay(6);
                               I2CStart();      
                            }while(I2C_Write_Byte(SHT20ADDR|0x01)==NACK);     //I2C address + read        + NACK

                            MSB = I2C_Read_Byte(ACK);                                              //Data(MSB)
                            LSB = I2C_Read_Byte(ACK);                                              //Data(LSB)
                            I2C_Read_Byte(NACK);                                                          //Checksum  + NACK
                            I2CStop();                                                                              //Stop I2C
                            LSB &= 0xfc;  //Data (LSB) 的后两位在进行物理计算前前须置‘0’
                                                                                      //十六进制转成十进制
                            if (whatdo==0xf5)                                          //No Hold Master Mode,read humidity
                            {
                                    /*-- calculate relative humidity [%RH] --*/
                                    ttemp= MSB*256 + LSB;
                                                                        ttemp =ttemp&0x0000ffff;
                                    //计算出发送的湿度值 001~~~999
                                    //ttemp=(((ttemp*125)&0x007dffff)*100)/65536-600;

                                                                        //
                                                                        ttemp=((((ttemp))*12500)/65536-600);
                                    ttemp=ttemp+1000;//1000比SHT10低10%
                                                                        //
                                                                        g_ucTH_H = ttemp/100;
                                    X=ttemp-g_ucTH_H*100;
                                    g_ucTH_L=X;
                                    //g_ucTH_L=LSB;//X;
                                                                        //ttemp=1000;
                                                                        //aa=MSB;
                                                                        //bb=LSB;
                                                                //        g_ucTC_H =(unsigned char)(ttemp>>24);;//ttt/100;
                                    //g_ucTC_L=(unsigned char)(ttemp>>16);;
                                                                        //g_ucTH_H =(unsigned char)(ttemp>>8);//MSB;//ttt/100;
                                    //g_ucTH_L=(unsigned char)(ttemp);

                                    //
                                                                           tt=((unsigned int)(ttemp/10 ));
                                    
                                                                        /*if(tt>1000)
                                                                          {
                                         tt=999;
                                                                          }

                                    if(tt<=1)
                                                                         {

                                        tt=1;
                                                                         }
                                    */
                                                                        //
                                                                        tt=tt%1000;                                                                       
                                                                        g_ucSegnumber1=tt/100;
                                                                        tt=tt%100;
                                                                        g_ucSegnumber2=tt/10;                              
                                                                        tt=tt%10;
                                                                        g_ucSegnumber3=tt;                                   
                                                                  
                                                                       
                                                                        return Humidity;                              //返回值:humidity
                            }                                                                                                  
                            else                                                                                      //No Hold Master Mode,read temperature
                            {      
                                     /*-- calculate temperature [°C] --*/
                                    //ttemp =0;
                                                                ttemp = MSB*256 + LSB;
                                    ttemp =ttemp&0x0000ffff;
                                    //公式:T= -46.85 + 175.72 * ST/2^16
                                                                        ttemp = ((ttemp*17572))/65536-4685;
                                                                        //
                                    g_ucTC_H = ttemp/100;
                                    X=ttemp-g_ucTC_H*100;
                                    g_ucTC_L=X;

                                                                        //aa=MSB;
                                                                        //bb=LSB;
                                                                        //g_ucTC_H =(unsigned char)(ttemp>>8);;//ttt/100;
                                    //g_ucTC_L=(unsigned char)(ttemp);;
                                                                        //g_ucTH_H =(unsigned char)(ttemp>>8);//MSB;//ttt/100;
                                    //g_ucTH_L=(unsigned char)(ttemp);
                                                                        //g_ucTC_H =(unsigned char)(ttemp>>24);;//ttt/100;
                                    //g_ucTC_L=(unsigned char)(ttemp>>16);;
                                                                        //g_ucTH_H =(unsigned char)(ttemp>>8);//MSB;//ttt/100;
                                    //g_ucTH_L=(unsigned char)(ttemp);
                                                                                                           
                                                                        /*Temperature =Temperature *10;
                                                                        if(Temperature>1000)
                                                                          {
                                         Temperature=1000;
                                                                          }

                                    if(Temperature<1)
                                                                         {

                                        Temperature=1;
                                                                         }*/


                                                                        tt=(unsigned int)(ttemp/10 );
                                                                        tt=tt%1000;       
                                                                        g_ucSegnumber4=tt/100;
                                                                        tt=tt%100;
                                                                        g_ucSegnumber5=tt/10;                                    
                                                                        tt=tt%10;
                                                                        g_ucSegnumber6=tt;
                                                                                                                                               
                                                                        return Temperature;        //返回值:temperature
                            }
                     }
         }
       return 0;
   }

//------------------------------------------------------------------------



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
2条回答
mandey
1楼-- · 2019-12-18 19:39
上逻辑分析仪啊,再不济也要上示波器
ersha4877
2楼-- · 2019-12-18 20:36
mandey 发表于 2018-4-29 18:02
上逻辑分析仪啊,再不济也要上示波器

逻辑分析仪看过就是发0xF5没返回ACK

一周热门 更多>