* AM2321的取温度间隔得大于2s,否则,i2c会不工作了 * SimpleTimer有个bug,会导致两次快速的读温度,现在读温度函数里加了保护 * Blynk有个bug,会导致无法把数据传到服务器 * 现在可以正常工作了

Dependencies:   mbed

AM2321.cpp

Committer:
lixianyu
Date:
2016-06-24
Revision:
1:e34100dd6532
Parent:
0:740c1eb2df13

File content as of revision 1:e34100dd6532:

//
// AM2321 Temperature & Humidity Sensor library for Arduino
//
// The MIT License (MIT)
//
// Copyright (c) 2013 Wang Dong
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include "AM2321.h"
#include "mbed.h"
extern I2C g_i2c;
extern Serial pc;

#define I2C_ADDR_AM2321                 (0xB8 >> 1)          //AM2321温湿度计I2C地址
#define PARAM_AM2321_READ                0x03                //读寄存器命令
#define REG_AM2321_HUMIDITY_MSB          0x00                //湿度寄存器高位
#define REG_AM2321_HUMIDITY_LSB          0x01                //湿度寄存器低位
#define REG_AM2321_TEMPERATURE_MSB       0x02                //温度寄存器高位
#define REG_AM2321_TEMPERATURE_LSB       0x03                //温度寄存器低位
#define REG_AM2321_DEVICE_ID_BIT_24_31   0x0B                //32位设备ID高8位

template<int I2CADDR, int COMMAND, int REGADDR, int REGCOUNT>
class DataReader
{
protected:
    enum { len = 32 };
    uint8_t buf[len];

protected:
    DataReader() {
        memset(buf, 0, len);
    }
    bool readRaw() {
        //
        // Wakeup
        //
        //Wire.beginTransmission(I2CADDR);
        //Wire.endTransmission();
        g_i2c.write(I2CADDR<<1, (char*)&buf[0], 1);
        wait_ms(2.9);
        //
        // Read Command
        //
#if 0
        Wire.beginTransmission(I2CADDR);
        Wire.write(COMMAND);
        Wire.write(REGADDR);
        Wire.write(REGCOUNT);
        Wire.endTransmission();
#else
        char bu[3] = {COMMAND, REGADDR, REGCOUNT};
        g_i2c.write(I2CADDR<<1, bu, 3);
#endif

        //
        // Waiting
        //
        //delayMicroseconds(1600); //>1.5ms
        wait_ms(1.6);

        //
        // Read
        //
#if 0
        Wire.requestFrom(I2CADDR, 2 + REGCOUNT + 2); // COMMAND + REGCOUNT + DATA + CRCLSB + CRCMSB
        int i = 0;
        for (; i < 2 + REGCOUNT; ++i)
            buf[i] = Wire.read();

        unsigned short crc = 0;
        crc  = Wire.read();     //CRC LSB
        crc |= Wire.read() << 8;//CRC MSB

        if (crc == crc16(buf, i))
            return true;
        return false;
#else
        uint8_t realAddr = (I2CADDR << 1) | 0x01;
        //pc.printf("realAddr = 0x%x\r\n", realAddr);
        g_i2c.read(realAddr, (char*)buf, 2 + REGCOUNT + 2);
        unsigned short crc = 0;
        crc  = buf[2+REGCOUNT];       //CRC LSB
        crc |= buf[2+REGCOUNT+1] << 8;//CRC MSB
#if 1
        for (int i = 0; i < 2 + REGCOUNT + 2; i++) {
            pc.printf("0x%X ", buf[i]);
        }
        pc.printf("\r\n");
#endif
        if (crc == crc16(buf, 2 + REGCOUNT))
            return true;
        return false;
#endif
    }

private:
    unsigned short crc16(unsigned char *ptr, unsigned char len) {
        unsigned short crc = 0xFFFF;
        unsigned char  i   = 0;
        while(len--) {
            crc ^= *ptr++;
            for(i = 0 ; i < 8 ; i++) {
                if(crc & 0x01) {
                    crc >>= 1;
                    crc  ^= 0xA001;
                } else {
                    crc >>= 1;
                }
            }
        }
        return crc;
    }
};

class UidReader : public DataReader<I2C_ADDR_AM2321, PARAM_AM2321_READ, REG_AM2321_DEVICE_ID_BIT_24_31, 4>
{
public:
    unsigned int uid;
public:
    bool read() {
        if(!readRaw())
            return false;
        uid  = buf[2] << 24;
        uid += buf[3] << 16;
        uid += buf[4] << 8;
        uid += buf[5];
        return true;
    }
};

class AirConditionReader : public DataReader<I2C_ADDR_AM2321, PARAM_AM2321_READ, REG_AM2321_HUMIDITY_MSB, 4>
{
public:
    unsigned int humidity;
    int temperature;
public:
    bool read() {
        if(!readRaw())
            return false;
        humidity     = buf[2] << 8;
        humidity    += buf[3];
        temperature  = (buf[4]&0x7F) << 8;
        temperature += buf[5];
        if((buf[4]&0x80) == 0x80)
            temperature = -temperature;
        return true;
    }
};


AM2321::AM2321()
{
    //Wire.begin();
    temperature = 0;
    humidity    = 0;
}

unsigned long AM2321::uid()
{
    UidReader reader;
    if (reader.read())
        return reader.uid;
    return -1;
}


bool AM2321::available()
{
    return !(temperature == 0 && humidity == 0);
}

bool AM2321::read()
{
    AirConditionReader reader;
    if (reader.read()) {
        temperature = reader.temperature;
        humidity = reader.humidity;
        return true;
    }
    return false;
}
//
// END OF FILE
//