* AM2321的取温度间隔得大于2s,否则,i2c会不工作了 * SimpleTimer有个bug,会导致两次快速的读温度,现在读温度函数里加了保护 * Blynk有个bug,会导致无法把数据传到服务器 * 现在可以正常工作了
AM2321.cpp@1:e34100dd6532, 2016-06-24 (annotated)
- Committer:
- lixianyu
- Date:
- Fri Jun 24 02:06:43 2016 +0000
- Revision:
- 1:e34100dd6532
- Parent:
- 0:740c1eb2df13
?Arduino??????????0~255??????LPC824????????????????
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
lixianyu | 0:740c1eb2df13 | 1 | // |
lixianyu | 0:740c1eb2df13 | 2 | // AM2321 Temperature & Humidity Sensor library for Arduino |
lixianyu | 0:740c1eb2df13 | 3 | // |
lixianyu | 0:740c1eb2df13 | 4 | // The MIT License (MIT) |
lixianyu | 0:740c1eb2df13 | 5 | // |
lixianyu | 0:740c1eb2df13 | 6 | // Copyright (c) 2013 Wang Dong |
lixianyu | 0:740c1eb2df13 | 7 | // |
lixianyu | 0:740c1eb2df13 | 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
lixianyu | 0:740c1eb2df13 | 9 | // of this software and associated documentation files (the "Software"), to deal |
lixianyu | 0:740c1eb2df13 | 10 | // in the Software without restriction, including without limitation the rights |
lixianyu | 0:740c1eb2df13 | 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
lixianyu | 0:740c1eb2df13 | 12 | // copies of the Software, and to permit persons to whom the Software is |
lixianyu | 0:740c1eb2df13 | 13 | // furnished to do so, subject to the following conditions: |
lixianyu | 0:740c1eb2df13 | 14 | // |
lixianyu | 0:740c1eb2df13 | 15 | // The above copyright notice and this permission notice shall be included in |
lixianyu | 0:740c1eb2df13 | 16 | // all copies or substantial portions of the Software. |
lixianyu | 0:740c1eb2df13 | 17 | // |
lixianyu | 0:740c1eb2df13 | 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
lixianyu | 0:740c1eb2df13 | 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
lixianyu | 0:740c1eb2df13 | 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
lixianyu | 0:740c1eb2df13 | 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
lixianyu | 0:740c1eb2df13 | 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
lixianyu | 0:740c1eb2df13 | 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
lixianyu | 0:740c1eb2df13 | 24 | // THE SOFTWARE. |
lixianyu | 0:740c1eb2df13 | 25 | // |
lixianyu | 0:740c1eb2df13 | 26 | |
lixianyu | 0:740c1eb2df13 | 27 | #include "AM2321.h" |
lixianyu | 0:740c1eb2df13 | 28 | #include "mbed.h" |
lixianyu | 0:740c1eb2df13 | 29 | extern I2C g_i2c; |
lixianyu | 0:740c1eb2df13 | 30 | extern Serial pc; |
lixianyu | 0:740c1eb2df13 | 31 | |
lixianyu | 0:740c1eb2df13 | 32 | #define I2C_ADDR_AM2321 (0xB8 >> 1) //AM2321温湿度计I2C地址 |
lixianyu | 0:740c1eb2df13 | 33 | #define PARAM_AM2321_READ 0x03 //读寄存器命令 |
lixianyu | 0:740c1eb2df13 | 34 | #define REG_AM2321_HUMIDITY_MSB 0x00 //湿度寄存器高位 |
lixianyu | 0:740c1eb2df13 | 35 | #define REG_AM2321_HUMIDITY_LSB 0x01 //湿度寄存器低位 |
lixianyu | 0:740c1eb2df13 | 36 | #define REG_AM2321_TEMPERATURE_MSB 0x02 //温度寄存器高位 |
lixianyu | 0:740c1eb2df13 | 37 | #define REG_AM2321_TEMPERATURE_LSB 0x03 //温度寄存器低位 |
lixianyu | 0:740c1eb2df13 | 38 | #define REG_AM2321_DEVICE_ID_BIT_24_31 0x0B //32位设备ID高8位 |
lixianyu | 0:740c1eb2df13 | 39 | |
lixianyu | 0:740c1eb2df13 | 40 | template<int I2CADDR, int COMMAND, int REGADDR, int REGCOUNT> |
lixianyu | 0:740c1eb2df13 | 41 | class DataReader |
lixianyu | 0:740c1eb2df13 | 42 | { |
lixianyu | 0:740c1eb2df13 | 43 | protected: |
lixianyu | 0:740c1eb2df13 | 44 | enum { len = 32 }; |
lixianyu | 0:740c1eb2df13 | 45 | uint8_t buf[len]; |
lixianyu | 0:740c1eb2df13 | 46 | |
lixianyu | 0:740c1eb2df13 | 47 | protected: |
lixianyu | 0:740c1eb2df13 | 48 | DataReader() { |
lixianyu | 0:740c1eb2df13 | 49 | memset(buf, 0, len); |
lixianyu | 0:740c1eb2df13 | 50 | } |
lixianyu | 0:740c1eb2df13 | 51 | bool readRaw() { |
lixianyu | 0:740c1eb2df13 | 52 | // |
lixianyu | 0:740c1eb2df13 | 53 | // Wakeup |
lixianyu | 0:740c1eb2df13 | 54 | // |
lixianyu | 0:740c1eb2df13 | 55 | //Wire.beginTransmission(I2CADDR); |
lixianyu | 0:740c1eb2df13 | 56 | //Wire.endTransmission(); |
lixianyu | 0:740c1eb2df13 | 57 | g_i2c.write(I2CADDR<<1, (char*)&buf[0], 1); |
lixianyu | 0:740c1eb2df13 | 58 | wait_ms(2.9); |
lixianyu | 0:740c1eb2df13 | 59 | // |
lixianyu | 0:740c1eb2df13 | 60 | // Read Command |
lixianyu | 0:740c1eb2df13 | 61 | // |
lixianyu | 0:740c1eb2df13 | 62 | #if 0 |
lixianyu | 0:740c1eb2df13 | 63 | Wire.beginTransmission(I2CADDR); |
lixianyu | 0:740c1eb2df13 | 64 | Wire.write(COMMAND); |
lixianyu | 0:740c1eb2df13 | 65 | Wire.write(REGADDR); |
lixianyu | 0:740c1eb2df13 | 66 | Wire.write(REGCOUNT); |
lixianyu | 0:740c1eb2df13 | 67 | Wire.endTransmission(); |
lixianyu | 0:740c1eb2df13 | 68 | #else |
lixianyu | 0:740c1eb2df13 | 69 | char bu[3] = {COMMAND, REGADDR, REGCOUNT}; |
lixianyu | 0:740c1eb2df13 | 70 | g_i2c.write(I2CADDR<<1, bu, 3); |
lixianyu | 0:740c1eb2df13 | 71 | #endif |
lixianyu | 0:740c1eb2df13 | 72 | |
lixianyu | 0:740c1eb2df13 | 73 | // |
lixianyu | 0:740c1eb2df13 | 74 | // Waiting |
lixianyu | 0:740c1eb2df13 | 75 | // |
lixianyu | 0:740c1eb2df13 | 76 | //delayMicroseconds(1600); //>1.5ms |
lixianyu | 0:740c1eb2df13 | 77 | wait_ms(1.6); |
lixianyu | 0:740c1eb2df13 | 78 | |
lixianyu | 0:740c1eb2df13 | 79 | // |
lixianyu | 0:740c1eb2df13 | 80 | // Read |
lixianyu | 0:740c1eb2df13 | 81 | // |
lixianyu | 0:740c1eb2df13 | 82 | #if 0 |
lixianyu | 0:740c1eb2df13 | 83 | Wire.requestFrom(I2CADDR, 2 + REGCOUNT + 2); // COMMAND + REGCOUNT + DATA + CRCLSB + CRCMSB |
lixianyu | 0:740c1eb2df13 | 84 | int i = 0; |
lixianyu | 0:740c1eb2df13 | 85 | for (; i < 2 + REGCOUNT; ++i) |
lixianyu | 0:740c1eb2df13 | 86 | buf[i] = Wire.read(); |
lixianyu | 0:740c1eb2df13 | 87 | |
lixianyu | 0:740c1eb2df13 | 88 | unsigned short crc = 0; |
lixianyu | 0:740c1eb2df13 | 89 | crc = Wire.read(); //CRC LSB |
lixianyu | 0:740c1eb2df13 | 90 | crc |= Wire.read() << 8;//CRC MSB |
lixianyu | 0:740c1eb2df13 | 91 | |
lixianyu | 0:740c1eb2df13 | 92 | if (crc == crc16(buf, i)) |
lixianyu | 0:740c1eb2df13 | 93 | return true; |
lixianyu | 0:740c1eb2df13 | 94 | return false; |
lixianyu | 0:740c1eb2df13 | 95 | #else |
lixianyu | 0:740c1eb2df13 | 96 | uint8_t realAddr = (I2CADDR << 1) | 0x01; |
lixianyu | 0:740c1eb2df13 | 97 | //pc.printf("realAddr = 0x%x\r\n", realAddr); |
lixianyu | 0:740c1eb2df13 | 98 | g_i2c.read(realAddr, (char*)buf, 2 + REGCOUNT + 2); |
lixianyu | 0:740c1eb2df13 | 99 | unsigned short crc = 0; |
lixianyu | 0:740c1eb2df13 | 100 | crc = buf[2+REGCOUNT]; //CRC LSB |
lixianyu | 0:740c1eb2df13 | 101 | crc |= buf[2+REGCOUNT+1] << 8;//CRC MSB |
lixianyu | 0:740c1eb2df13 | 102 | #if 1 |
lixianyu | 0:740c1eb2df13 | 103 | for (int i = 0; i < 2 + REGCOUNT + 2; i++) { |
lixianyu | 0:740c1eb2df13 | 104 | pc.printf("0x%X ", buf[i]); |
lixianyu | 0:740c1eb2df13 | 105 | } |
lixianyu | 0:740c1eb2df13 | 106 | pc.printf("\r\n"); |
lixianyu | 0:740c1eb2df13 | 107 | #endif |
lixianyu | 0:740c1eb2df13 | 108 | if (crc == crc16(buf, 2 + REGCOUNT)) |
lixianyu | 0:740c1eb2df13 | 109 | return true; |
lixianyu | 0:740c1eb2df13 | 110 | return false; |
lixianyu | 0:740c1eb2df13 | 111 | #endif |
lixianyu | 0:740c1eb2df13 | 112 | } |
lixianyu | 0:740c1eb2df13 | 113 | |
lixianyu | 0:740c1eb2df13 | 114 | private: |
lixianyu | 0:740c1eb2df13 | 115 | unsigned short crc16(unsigned char *ptr, unsigned char len) { |
lixianyu | 0:740c1eb2df13 | 116 | unsigned short crc = 0xFFFF; |
lixianyu | 0:740c1eb2df13 | 117 | unsigned char i = 0; |
lixianyu | 0:740c1eb2df13 | 118 | while(len--) { |
lixianyu | 0:740c1eb2df13 | 119 | crc ^= *ptr++; |
lixianyu | 0:740c1eb2df13 | 120 | for(i = 0 ; i < 8 ; i++) { |
lixianyu | 0:740c1eb2df13 | 121 | if(crc & 0x01) { |
lixianyu | 0:740c1eb2df13 | 122 | crc >>= 1; |
lixianyu | 0:740c1eb2df13 | 123 | crc ^= 0xA001; |
lixianyu | 0:740c1eb2df13 | 124 | } else { |
lixianyu | 0:740c1eb2df13 | 125 | crc >>= 1; |
lixianyu | 0:740c1eb2df13 | 126 | } |
lixianyu | 0:740c1eb2df13 | 127 | } |
lixianyu | 0:740c1eb2df13 | 128 | } |
lixianyu | 0:740c1eb2df13 | 129 | return crc; |
lixianyu | 0:740c1eb2df13 | 130 | } |
lixianyu | 0:740c1eb2df13 | 131 | }; |
lixianyu | 0:740c1eb2df13 | 132 | |
lixianyu | 0:740c1eb2df13 | 133 | class UidReader : public DataReader<I2C_ADDR_AM2321, PARAM_AM2321_READ, REG_AM2321_DEVICE_ID_BIT_24_31, 4> |
lixianyu | 0:740c1eb2df13 | 134 | { |
lixianyu | 0:740c1eb2df13 | 135 | public: |
lixianyu | 0:740c1eb2df13 | 136 | unsigned int uid; |
lixianyu | 0:740c1eb2df13 | 137 | public: |
lixianyu | 0:740c1eb2df13 | 138 | bool read() { |
lixianyu | 0:740c1eb2df13 | 139 | if(!readRaw()) |
lixianyu | 0:740c1eb2df13 | 140 | return false; |
lixianyu | 0:740c1eb2df13 | 141 | uid = buf[2] << 24; |
lixianyu | 0:740c1eb2df13 | 142 | uid += buf[3] << 16; |
lixianyu | 0:740c1eb2df13 | 143 | uid += buf[4] << 8; |
lixianyu | 0:740c1eb2df13 | 144 | uid += buf[5]; |
lixianyu | 0:740c1eb2df13 | 145 | return true; |
lixianyu | 0:740c1eb2df13 | 146 | } |
lixianyu | 0:740c1eb2df13 | 147 | }; |
lixianyu | 0:740c1eb2df13 | 148 | |
lixianyu | 0:740c1eb2df13 | 149 | class AirConditionReader : public DataReader<I2C_ADDR_AM2321, PARAM_AM2321_READ, REG_AM2321_HUMIDITY_MSB, 4> |
lixianyu | 0:740c1eb2df13 | 150 | { |
lixianyu | 0:740c1eb2df13 | 151 | public: |
lixianyu | 0:740c1eb2df13 | 152 | unsigned int humidity; |
lixianyu | 0:740c1eb2df13 | 153 | int temperature; |
lixianyu | 0:740c1eb2df13 | 154 | public: |
lixianyu | 0:740c1eb2df13 | 155 | bool read() { |
lixianyu | 0:740c1eb2df13 | 156 | if(!readRaw()) |
lixianyu | 0:740c1eb2df13 | 157 | return false; |
lixianyu | 0:740c1eb2df13 | 158 | humidity = buf[2] << 8; |
lixianyu | 0:740c1eb2df13 | 159 | humidity += buf[3]; |
lixianyu | 0:740c1eb2df13 | 160 | temperature = (buf[4]&0x7F) << 8; |
lixianyu | 0:740c1eb2df13 | 161 | temperature += buf[5]; |
lixianyu | 0:740c1eb2df13 | 162 | if((buf[4]&0x80) == 0x80) |
lixianyu | 0:740c1eb2df13 | 163 | temperature = -temperature; |
lixianyu | 0:740c1eb2df13 | 164 | return true; |
lixianyu | 0:740c1eb2df13 | 165 | } |
lixianyu | 0:740c1eb2df13 | 166 | }; |
lixianyu | 0:740c1eb2df13 | 167 | |
lixianyu | 0:740c1eb2df13 | 168 | |
lixianyu | 0:740c1eb2df13 | 169 | AM2321::AM2321() |
lixianyu | 0:740c1eb2df13 | 170 | { |
lixianyu | 0:740c1eb2df13 | 171 | //Wire.begin(); |
lixianyu | 0:740c1eb2df13 | 172 | temperature = 0; |
lixianyu | 0:740c1eb2df13 | 173 | humidity = 0; |
lixianyu | 0:740c1eb2df13 | 174 | } |
lixianyu | 0:740c1eb2df13 | 175 | |
lixianyu | 0:740c1eb2df13 | 176 | unsigned long AM2321::uid() |
lixianyu | 0:740c1eb2df13 | 177 | { |
lixianyu | 0:740c1eb2df13 | 178 | UidReader reader; |
lixianyu | 0:740c1eb2df13 | 179 | if (reader.read()) |
lixianyu | 0:740c1eb2df13 | 180 | return reader.uid; |
lixianyu | 0:740c1eb2df13 | 181 | return -1; |
lixianyu | 0:740c1eb2df13 | 182 | } |
lixianyu | 0:740c1eb2df13 | 183 | |
lixianyu | 0:740c1eb2df13 | 184 | |
lixianyu | 0:740c1eb2df13 | 185 | bool AM2321::available() |
lixianyu | 0:740c1eb2df13 | 186 | { |
lixianyu | 0:740c1eb2df13 | 187 | return !(temperature == 0 && humidity == 0); |
lixianyu | 0:740c1eb2df13 | 188 | } |
lixianyu | 0:740c1eb2df13 | 189 | |
lixianyu | 0:740c1eb2df13 | 190 | bool AM2321::read() |
lixianyu | 0:740c1eb2df13 | 191 | { |
lixianyu | 0:740c1eb2df13 | 192 | AirConditionReader reader; |
lixianyu | 0:740c1eb2df13 | 193 | if (reader.read()) { |
lixianyu | 0:740c1eb2df13 | 194 | temperature = reader.temperature; |
lixianyu | 0:740c1eb2df13 | 195 | humidity = reader.humidity; |
lixianyu | 0:740c1eb2df13 | 196 | return true; |
lixianyu | 0:740c1eb2df13 | 197 | } |
lixianyu | 0:740c1eb2df13 | 198 | return false; |
lixianyu | 0:740c1eb2df13 | 199 | } |
lixianyu | 0:740c1eb2df13 | 200 | // |
lixianyu | 0:740c1eb2df13 | 201 | // END OF FILE |
lixianyu | 0:740c1eb2df13 | 202 | // |