Просмотр исходного кода

add: sensor库读取ds18b20时,默认校验crc值,以提供更可靠的输出

Wendal Chen 5 лет назад
Родитель
Сommit
ba393deef7
1 измененных файлов с 58 добавлено и 12 удалено
  1. 58 12
      luat/modules/luat_lib_sensor.c

+ 58 - 12
luat/modules/luat_lib_sensor.c

@@ -16,10 +16,6 @@
 #define CONNECT_SUCCESS  0
 #define CONNECT_FAILED   1
 
-#define W1_INPUT_MODE PIN_MODE_INPUT_PULLUP
-
-
-
 static void w1_reset(int pin)
 {
     luat_gpio_mode(pin, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
@@ -123,10 +119,30 @@ static void w1_write_byte(int pin, uint8_t dat)
     }
 }
 
-static int32_t ds18b20_get_temperature(int pin, int32_t *val)
+static uint8_t crc8_maxim[256] = {
+    0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
+	157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
+	35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
+	190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
+	70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
+	219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
+	101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
+	248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
+	140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
+	17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
+	175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
+	50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
+	202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
+	87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
+	233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
+	116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
+
+static int32_t ds18b20_get_temperature(int pin, int32_t *val, int check_crc)
 {
     uint8_t TL, TH;
     int32_t tem;
+
+    uint8_t data[9] = {0};
     
     //ds18b20_start(pin);
     w1_reset(pin);
@@ -146,9 +162,37 @@ static int32_t ds18b20_get_temperature(int pin, int32_t *val)
 
     w1_write_byte(pin, 0xcc);
     w1_write_byte(pin, 0xbe);
-    TL = w1_read_byte(pin);    /* LSB first */
-    TH = w1_read_byte(pin);
-    // TODO 9个字节都读出来,校验CRC
+    data[0] = w1_read_byte(pin);    /* LSB first */
+    data[1] = w1_read_byte(pin);
+
+    if (data[0] == 0xFF || data[1] == 0xFF) {
+        LLOGD("ds18b20 bad data, skip");
+        return -1;
+    }
+
+    // 9个字节都读出来,校验CRC
+    if (check_crc) {
+        for (size_t i = 2; i < 9; i++)
+        {
+            data[i] = w1_read_byte(pin);
+        }
+        uint8_t crc = 0;
+        for (size_t i = 0; i < 8; i++)
+        {
+            crc = crc8_maxim[crc ^ data[i]];
+        }
+        LLOGD("ds18b20 %02X%02X%02X%02X%02X%02X%02X%02X [%02X %02X]", 
+                   data[0], data[1], data[2], data[3], 
+                   data[4], data[5], data[6], data[7], 
+                   data[8], crc);
+        if (data[8] != crc) {
+            LLOGD("ds18b20 bad crc");
+            return -2;
+        }
+    }
+    TL = data[0];
+    TH = data[1];
+
     if (TH > 7)
     {
         TH =~ TH;
@@ -174,13 +218,14 @@ static int32_t ds18b20_get_temperature(int pin, int32_t *val)
 /*
 获取DS18B20的温度数据
 @api    sensor.ds18b20(pin)
-@int  gpio端口号
-@return int 温度数据
+@int    gpio端口号
+@boolean 是否校验crc值,默认为true. 不校验crc值能提高读取成功的概率,但可能会读取到错误的值
+@return int 温度数据,单位0.1摄氏度
 @return boolean 成功返回true,否则返回false
 --  如果读取失败,会返回nil
 while 1 do 
     sys.wait(5000) 
-    local val,result = sensor.ds18b20(17)
+    local val,result = sensor.ds18b20(17, true) -- GPIO17且校验CRC值
     -- val 301 == 30.1摄氏度
     -- result true 读取成功
     log.info("ds18b20", val, result)
@@ -188,7 +233,8 @@ end
 */
 static int l_sensor_ds18b20(lua_State *L) {
     int32_t val = 0;
-    int32_t ret = ds18b20_get_temperature(luaL_checkinteger(L, 1), &val);
+    int check_crc = lua_gettop(L) > 1 ? lua_toboolean(L, 2) : 1;
+    int32_t ret = ds18b20_get_temperature(luaL_checkinteger(L, 1), &val, check_crc);
     // -55°C ~ 125°C
     if (ret || !(val <= 1250 && val >= -550)) {
         LLOGI("ds18b20 read fail");