luat_lib_i2c.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. @module i2c
  3. @summary I2C操作
  4. @version 1.0
  5. @date 2020.03.30
  6. */
  7. #include "luat_base.h"
  8. #include "luat_log.h"
  9. #include "luat_timer.h"
  10. #include "luat_malloc.h"
  11. #include "luat_i2c.h"
  12. #define LUAT_LOG_TAG "luat.i2c"
  13. #include "luat_log.h"
  14. /*
  15. i2c编号是否存在
  16. @api i2c.exist(id)
  17. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  18. @return int 存在就返回1,否则返回0
  19. @usage
  20. -- 检查i2c1是否存在
  21. if i2c.exist(1) then
  22. log.info("存在 i2c1")
  23. end
  24. */
  25. static int l_i2c_exist(lua_State *L) {
  26. int re = luat_i2c_exist(luaL_checkinteger(L, 1));
  27. lua_pushinteger(L, re);
  28. return 1;
  29. }
  30. /*
  31. i2c初始化
  32. @api i2c.setup(id, speed, slaveAddr)
  33. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  34. @int I2C速度, 例如i2c.FAST
  35. @int 从设备地址(7位), 例如0x38
  36. @return int 成功就返回1,否则返回0
  37. @usage
  38. -- 初始化i2c1
  39. if i2c.setup(1, i2c.FAST, 0x38) == 1 then
  40. log.info("存在 i2c1")
  41. else
  42. i2c.close(1) -- 关掉
  43. end
  44. */
  45. static int l_i2c_setup(lua_State *L) {
  46. int re = luat_i2c_setup(luaL_checkinteger(L, 1), luaL_optinteger(L, 2, 0), luaL_optinteger(L, 3, 0));
  47. lua_pushinteger(L, re == 0 ? luaL_optinteger(L, 2, 0) : -1);
  48. return 1;
  49. }
  50. /*
  51. i2c发送数据
  52. @api i2c.send(id, addr, data)
  53. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  54. @int I2C子设备的地址, 7位地址
  55. @string 待发送的数据
  56. @return true/false 发送是否成功
  57. @usage
  58. -- 往i2c1发送2个字节的数据
  59. i2c.send(1, 0x5C, string.char(0x0F, 0x2F))
  60. */
  61. static int l_i2c_send(lua_State *L) {
  62. int id = luaL_checkinteger(L, 1);
  63. int addr = luaL_checkinteger(L, 2);
  64. size_t len = 0;
  65. int result = 0;
  66. if (lua_isstring(L, 3)) {
  67. const char* buff = luaL_checklstring(L, 3, &len);
  68. result = luat_i2c_send(id, addr, (char*)buff, len);
  69. }
  70. else if (lua_isinteger(L, 3)) {
  71. len = lua_gettop(L) - 2;
  72. char buff[len+1];
  73. for (size_t i = 0; i < len; i++)
  74. {
  75. buff[i] = lua_tointeger(L, 3+i);
  76. }
  77. result = luat_i2c_send(id, addr, buff, len);
  78. }
  79. lua_pushboolean(L, result == 0);
  80. return 1;
  81. }
  82. /*
  83. i2c接收数据
  84. @api i2c.recv(id, addr, len)
  85. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  86. @int I2C子设备的地址, 7位地址
  87. @int 手机数据的长度
  88. @return string 收到的数据
  89. @usage
  90. -- 从i2c1读取2个字节的数据
  91. local data = i2c.recv(1, 0x5C, 2)
  92. */
  93. static int l_i2c_recv(lua_State *L) {
  94. int id = luaL_checkinteger(L, 1);
  95. int addr = luaL_checkinteger(L, 2);
  96. int len = luaL_checkinteger(L, 3);
  97. char buf[len];
  98. int result = luat_i2c_recv(id, addr, &buf[0], len);
  99. if(result!=0){//如果返回值不为0,说明收失败了
  100. len = 0;
  101. LLOGD("i2c receive result %d", result);
  102. }
  103. lua_pushlstring(L, buf, len);
  104. return 1;
  105. }
  106. /*
  107. i2c写寄存器数据
  108. @api i2c.writeReg(id, addr, reg, data)
  109. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  110. @int I2C子设备的地址, 7位地址
  111. @int 寄存器地址
  112. @string 待发送的数据
  113. @return true/false 发送是否成功
  114. @usage
  115. -- 从i2c1的地址为0x5C的设备的寄存器0x01写入2个字节的数据
  116. i2c.writeReg(1, 0x5C, 0x01, string.char(0x00, 0xF2))
  117. */
  118. static int l_i2c_write_reg(lua_State *L) {
  119. int id = luaL_checkinteger(L, 1);
  120. int addr = luaL_checkinteger(L, 2);
  121. int reg = luaL_checkinteger(L, 3);
  122. size_t len;
  123. const char* lb = luaL_checklstring(L, 4, &len);
  124. char* buff = (char*)luat_heap_malloc(sizeof(char)*len+1);
  125. *buff = (char)reg;
  126. memcpy(buff+1,lb,sizeof(char)+len+1);
  127. int result = luat_i2c_send(id, addr, buff, len+1);
  128. luat_heap_free(buff);
  129. lua_pushboolean(L, result == 0);
  130. return 1;
  131. }
  132. /*
  133. i2c读寄存器数据
  134. @api i2c.readReg(id, addr, reg, len)
  135. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  136. @int I2C子设备的地址, 7位地址
  137. @int 寄存器地址
  138. @int 待接收的数据长度
  139. @return string 收到的数据
  140. @usage
  141. -- 从i2c1的地址为0x5C的设备的寄存器0x01读出2个字节的数据
  142. i2c.readReg(1, 0x5C, 0x01, 2)
  143. */
  144. static int l_i2c_read_reg(lua_State *L) {
  145. int id = luaL_checkinteger(L, 1);
  146. int addr = luaL_checkinteger(L, 2);
  147. int reg = luaL_checkinteger(L, 3);
  148. int len = luaL_checkinteger(L, 4);
  149. char temp = (char)reg;
  150. int result = luat_i2c_send(id, addr, &temp, 1);
  151. if(result!=0){//如果返回值不为0,说明收失败了
  152. LLOGD("i2c send result %d", result);
  153. lua_pushlstring(L, NULL, 0);
  154. return 1;
  155. }
  156. char* buff = (char*)luat_heap_malloc(sizeof(char)*len);
  157. result = luat_i2c_recv(id, addr, buff, len);
  158. if(result!=0){//如果返回值不为0,说明收失败了
  159. len = 0;
  160. LLOGD("i2c receive result %d", result);
  161. }
  162. lua_pushlstring(L, buff, len);
  163. luat_heap_free(buff);
  164. return 1;
  165. }
  166. /*
  167. 关闭i2c设备
  168. @api i2c.close(id)
  169. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  170. @return nil 无返回值
  171. @usage
  172. -- 关闭i2c1
  173. i2c.close(1)
  174. */
  175. static int l_i2c_close(lua_State *L) {
  176. int id = luaL_checkinteger(L, 1);
  177. luat_ic2_close(id);
  178. return 0;
  179. }
  180. /*
  181. 从i2c总线读取DHT12的温湿度数据
  182. @api i2c.readDHT12(id)
  183. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  184. @int DHT12的设备地址,默认0x5C
  185. @return boolean 读取成功返回true,否则返回false
  186. @return int 湿度值,单位0.1%, 例如 591 代表 59.1%
  187. @return int 温度值,单位0.1摄氏度, 例如 292 代表 29.2摄氏度
  188. @usage
  189. -- 从i2c0读取DHT12
  190. i2c.setup(0)
  191. local re, H, T = i2c.readDHT12(0)
  192. if re then
  193. log.info("dht12", H, T)
  194. end
  195. */
  196. static int l_i2c_readDHT12(lua_State *L) {
  197. int id = luaL_checkinteger(L, 1);
  198. int addr = luaL_optinteger(L, 2, 0x5C);
  199. char buff[5] = {0};
  200. char temp = 0x00;
  201. int result = luat_i2c_send(id, addr, &temp, 1);
  202. if (result) {
  203. LLOGD("DHT12 i2c bus write fail");
  204. lua_pushboolean(L, 0);
  205. return 1;
  206. }
  207. result = luat_i2c_recv(id, addr, buff, 5);
  208. if (result) {
  209. lua_pushboolean(L, 0);
  210. return 1;
  211. }
  212. else {
  213. if (buff[0] == 0 && buff[1] == 0 && buff[2] == 0 && buff[3] == 0 && buff[4] == 0) {
  214. LLOGD("DHT12 DATA emtry");
  215. lua_pushboolean(L, 0);
  216. return 1;
  217. }
  218. // 检查crc值
  219. LLOGD("DHT12 DATA %02X%02X%02X%02X%02X", buff[0], buff[1], buff[2], buff[3], buff[4]);
  220. uint8_t crc_act = (uint8_t)buff[0] + (uint8_t)buff[1] + (uint8_t)buff[2] + (uint8_t)buff [3];
  221. uint8_t crc_exp = (uint8_t)buff[4];
  222. if (crc_act != crc_exp) {
  223. LLOGD("DATA12 DATA crc not ok");
  224. lua_pushboolean(L, 0);
  225. return 1;
  226. }
  227. lua_pushboolean(L, 1);
  228. lua_pushinteger(L, (uint8_t)buff[0] * 10 + (uint8_t)buff[1]);
  229. if (((uint8_t)buff[2]) > 127)
  230. lua_pushinteger(L, ((uint8_t)buff[2] - 128) * -10 + (uint8_t)buff[3]);
  231. else
  232. lua_pushinteger(L, (uint8_t)buff[2] * 10 + (uint8_t)buff[3]);
  233. return 3;
  234. }
  235. }
  236. /*
  237. 从i2c总线读取DHT30的温湿度数据(由"好奇星"贡献)
  238. @api i2c.readSHT30(id,addr)
  239. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  240. @int 设备addr,SHT30的设备地址,默认0x44 bit7
  241. @return boolean 读取成功返回true,否则返回false
  242. @return int 湿度值,单位0.1%, 例如 591 代表 59.1%
  243. @return int 温度值,单位0.1摄氏度, 例如 292 代表 29.2摄氏度
  244. @usage
  245. -- 从i2c0读取SHT30
  246. i2c.setup(0)
  247. local re, H, T = i2c.readSHT30(0)
  248. if re then
  249. log.info("sht30", H, T)
  250. end
  251. */
  252. static int l_i2c_readSHT30(lua_State *L){
  253. int id = luaL_checkinteger(L, 1);
  254. int addr = luaL_optinteger(L, 2, 0x44);
  255. char buff[7] = {0x2c, 0x06};
  256. char temp = 0x00;
  257. char hum = 0x00;
  258. luat_i2c_send(id, addr, &buff, 2);
  259. luat_timer_us_delay(1000);
  260. int result = luat_i2c_recv(id, addr, buff, 6);
  261. if (result) {
  262. lua_pushboolean(L, 0);
  263. return 1;
  264. }
  265. else {
  266. if (buff[0] == 0 && buff[1] == 0 && buff[2] == 0 && buff[3] == 0 && buff[4] == 0) {
  267. LLOGD("SHT30 DATA emtry");
  268. lua_pushboolean(L, 0);
  269. return 1;
  270. }
  271. // 检查crc值
  272. //LLOGD("SHT30 DATA %02X %02X %02X %02X %02X %02X", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5]);
  273. temp = ((((buff[0] * 256) + buff[1]) * 175) / 65535) - 45;
  274. hum = ((((buff[3] * 256) + buff[4]) * 100) / 65535);
  275. //LLOGD("\r\n SHT30 %d deg %d Hum ", temp, hum);
  276. // 跳过CRC
  277. // uint8_t crc_act = (uint8_t)buff[0] + (uint8_t)buff[1] + (uint8_t)buff[2] + (uint8_t)buff [3];
  278. // uint8_t crc_exp = (uint8_t)buff[4];
  279. // if (crc_act != crc_exp) {
  280. // LLOGD("DATA12 DATA crc not ok");
  281. // lua_pushboolean(L, 0);
  282. // return 1;
  283. // }
  284. // Convert the data
  285. lua_pushboolean(L, 1);
  286. lua_pushinteger(L, (int)hum);
  287. lua_pushinteger(L, (int)temp);
  288. return 3;
  289. // 华氏度
  290. // fTemp = (cTemp * 1.8) + 32;
  291. }
  292. }
  293. #include "rotable.h"
  294. static const rotable_Reg reg_i2c[] =
  295. {
  296. { "exist", l_i2c_exist, 0},
  297. { "setup", l_i2c_setup, 0},
  298. { "send", l_i2c_send, 0},
  299. { "recv", l_i2c_recv, 0},
  300. { "writeReg", l_i2c_write_reg, 0},
  301. { "readReg", l_i2c_read_reg, 0},
  302. { "close", l_i2c_close, 0},
  303. { "readDHT12", l_i2c_readDHT12, 0},
  304. { "readSHT30", l_i2c_readSHT30, 0},
  305. { "FAST", NULL, 1},
  306. { "SLOW", NULL, 0},
  307. { NULL, NULL, 0}
  308. };
  309. LUAMOD_API int luaopen_i2c( lua_State *L ) {
  310. luat_newlib(L, reg_i2c);
  311. return 1;
  312. }