luat_lib_i2c.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. /*
  2. @module i2c
  3. @summary I2C操作
  4. @version 1.0
  5. @date 2020.03.30
  6. @demo i2c
  7. @tag LUAT_USE_I2C
  8. */
  9. #include "luat_base.h"
  10. #include "luat_log.h"
  11. #include "luat_timer.h"
  12. #include "luat_mem.h"
  13. #include "luat_i2c.h"
  14. #include "luat_gpio.h"
  15. #include "luat_zbuff.h"
  16. #include "luat_irq.h"
  17. #define LUAT_LOG_TAG "i2c"
  18. #include "luat_log.h"
  19. void i2c_soft_start(luat_ei2c_t *ei2c)
  20. {
  21. luat_gpio_mode(ei2c->sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  22. luat_timer_us_delay(ei2c->udelay);
  23. luat_gpio_set(ei2c->scl, Luat_GPIO_HIGH);
  24. luat_timer_us_delay(ei2c->udelay);
  25. luat_gpio_set(ei2c->sda, Luat_GPIO_LOW);
  26. luat_timer_us_delay(ei2c->udelay);
  27. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  28. luat_timer_us_delay(ei2c->udelay);
  29. }
  30. static void i2c_soft_stop(luat_ei2c_t *ei2c)
  31. {
  32. luat_gpio_mode(ei2c->sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  33. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  34. luat_timer_us_delay(ei2c->udelay);
  35. luat_gpio_set(ei2c->sda, Luat_GPIO_LOW);
  36. luat_timer_us_delay(ei2c->udelay);
  37. luat_gpio_set(ei2c->scl, Luat_GPIO_HIGH);
  38. luat_timer_us_delay(ei2c->udelay);
  39. luat_gpio_set(ei2c->sda, Luat_GPIO_HIGH);
  40. luat_timer_us_delay(ei2c->udelay);
  41. }
  42. static unsigned char i2c_soft_wait_ack(luat_ei2c_t *ei2c)
  43. {
  44. luat_gpio_set(ei2c->sda, Luat_GPIO_HIGH);
  45. luat_gpio_mode(ei2c->sda, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 1);
  46. luat_timer_us_delay(ei2c->udelay);
  47. luat_gpio_set(ei2c->scl, Luat_GPIO_HIGH);
  48. luat_timer_us_delay(ei2c->udelay * 3);
  49. int max_wait_time = 3000;
  50. while (max_wait_time--)
  51. {
  52. if (luat_gpio_get(ei2c->sda) == Luat_GPIO_LOW)
  53. {
  54. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  55. return 1;
  56. }
  57. luat_timer_us_delay(1);
  58. }
  59. i2c_soft_stop(ei2c);
  60. return 0;
  61. }
  62. static void i2c_soft_send_ack(luat_ei2c_t *ei2c)
  63. {
  64. luat_gpio_mode(ei2c->sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  65. luat_timer_us_delay(ei2c->udelay);
  66. luat_gpio_set(ei2c->scl, Luat_GPIO_HIGH);
  67. luat_timer_us_delay(ei2c->udelay);
  68. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  69. }
  70. static void i2c_soft_send_noack(luat_ei2c_t *ei2c)
  71. {
  72. luat_gpio_mode(ei2c->sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  73. luat_timer_us_delay(ei2c->udelay);
  74. luat_gpio_set(ei2c->scl, Luat_GPIO_HIGH);
  75. luat_timer_us_delay(ei2c->udelay);
  76. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  77. }
  78. static void i2c_soft_send_byte(luat_ei2c_t *ei2c, unsigned char data)
  79. {
  80. unsigned char i = 8;
  81. luat_gpio_mode(ei2c->sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 0);
  82. while (i--)
  83. {
  84. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  85. luat_timer_us_delay(ei2c->udelay * 2);
  86. if (data & 0x80)
  87. {
  88. luat_gpio_set(ei2c->sda, Luat_GPIO_HIGH);
  89. }
  90. else
  91. {
  92. luat_gpio_set(ei2c->sda, Luat_GPIO_LOW);
  93. }
  94. luat_timer_us_delay(ei2c->udelay);
  95. data <<= 1;
  96. luat_gpio_set(ei2c->scl, Luat_GPIO_HIGH);
  97. luat_timer_us_delay(ei2c->udelay);
  98. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  99. luat_timer_us_delay(ei2c->udelay);
  100. }
  101. }
  102. static char i2c_soft_recv_byte(luat_ei2c_t *ei2c)
  103. {
  104. unsigned char i = 8;
  105. unsigned char data = 0;
  106. luat_gpio_set(ei2c->sda, Luat_GPIO_HIGH);
  107. luat_gpio_mode(ei2c->sda, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, 1);
  108. while (i--)
  109. {
  110. data <<= 1;
  111. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  112. luat_timer_us_delay(ei2c->udelay);
  113. luat_gpio_set(ei2c->scl, Luat_GPIO_HIGH);
  114. luat_timer_us_delay(ei2c->udelay);
  115. if (luat_gpio_get(ei2c->sda))
  116. data |= 0x01;
  117. }
  118. luat_gpio_set(ei2c->scl, Luat_GPIO_LOW);
  119. return (data);
  120. }
  121. LUAT_WEAK int i2c_soft_recv(luat_ei2c_t *ei2c, unsigned char addr, char *buff, size_t len)
  122. {
  123. size_t i;
  124. i2c_soft_start(ei2c);
  125. i2c_soft_send_byte(ei2c, (addr << 1) + 1);
  126. if (!i2c_soft_wait_ack(ei2c))
  127. {
  128. i2c_soft_stop(ei2c);
  129. return -1;
  130. }
  131. luat_timer_us_delay(ei2c->udelay * 10);
  132. for (i = 0; i < len; i++)
  133. {
  134. *buff++ = i2c_soft_recv_byte(ei2c);
  135. if (i < (len - 1))
  136. i2c_soft_send_ack(ei2c);
  137. }
  138. i2c_soft_send_noack(ei2c);
  139. i2c_soft_stop(ei2c);
  140. return 0;
  141. }
  142. LUAT_WEAK int i2c_soft_send(luat_ei2c_t *ei2c, unsigned char addr, char *data, size_t len, uint8_t stop)
  143. {
  144. size_t i;
  145. i2c_soft_start(ei2c);
  146. i2c_soft_send_byte(ei2c, addr << 1);
  147. if (!i2c_soft_wait_ack(ei2c))
  148. {
  149. i2c_soft_stop(ei2c);
  150. return -1;
  151. }
  152. for (i = 0; i < len; i++)
  153. {
  154. i2c_soft_send_byte(ei2c, data[i]);
  155. if (!i2c_soft_wait_ack(ei2c))
  156. {
  157. i2c_soft_stop(ei2c);
  158. return -1;
  159. }
  160. }
  161. if (stop){
  162. i2c_soft_stop(ei2c);
  163. }
  164. return 0;
  165. }
  166. /*
  167. i2c编号是否存在
  168. @api i2c.exist(id)
  169. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  170. @return bool 存在就返回true,否则返回false
  171. @usage
  172. -- 检查i2c1是否存在
  173. if i2c.exist(1) then
  174. log.info("存在 i2c1")
  175. end
  176. */
  177. static int l_i2c_exist(lua_State *L)
  178. {
  179. int re = luat_i2c_exist(luaL_checkinteger(L, 1));
  180. lua_pushboolean(L, re == 0 ? 0 : 1);
  181. return 1;
  182. }
  183. LUAT_WEAK int luat_i2c_set_polling_mode(int id, uint8_t on_off){
  184. return -1;
  185. }
  186. /*
  187. i2c初始化
  188. @api i2c.setup(id, speed, pullup)
  189. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  190. @int I2C速度, 例如i2c.FAST
  191. @bool 是否使用轮询模式,true是,false不是。默认状态具体平台决定,除非使用中有问题,否则留空!!!
  192. @return int 成功就返回1,否则返回0
  193. @usage
  194. -- 初始化i2c1
  195. i2c.setup(1, i2c.FAST) -- id正确就一定成功
  196. -- 如需判断i2c id是否合法, 请使用 i2c.exist 函数
  197. */
  198. static int l_i2c_setup(lua_State *L)
  199. {
  200. if (lua_isuserdata(L, 1)) {
  201. LLOGD("软件i2c不需要再执行i2c.setup");
  202. lua_pushinteger(L, 1);
  203. return 1;
  204. }
  205. int re = luat_i2c_setup(luaL_checkinteger(L, 1), luaL_optinteger(L, 2, 0));
  206. if (lua_isboolean(L, 3) && lua_toboolean(L, 3)) {
  207. luat_i2c_set_polling_mode(luaL_checkinteger(L, 1), lua_toboolean(L, 3));
  208. }
  209. lua_pushinteger(L, re == 0 ? 1 : 0);
  210. return 1;
  211. }
  212. LUAT_WEAK int i2c_soft_setup(luat_ei2c_t *ei2c){
  213. luat_gpio_mode(ei2c->scl, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  214. luat_gpio_mode(ei2c->sda, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, 1);
  215. i2c_soft_stop(ei2c);
  216. return 0;
  217. }
  218. LUAT_WEAK int i2c_soft_close(luat_ei2c_t *ei2c){
  219. luat_gpio_close(ei2c->scl);
  220. luat_gpio_close(ei2c->sda);
  221. return 0;
  222. }
  223. /*
  224. 新建一个软件i2c对象
  225. @api i2c.createSoft(scl,sda,delay)
  226. @int i2c SCL引脚编号(GPIO编号)
  227. @int i2c SDA引脚编号(GPIO编号)
  228. @int 每个操作的延时, 单位us, 默认5
  229. @return 软件I2C对象 可当作i2c的id使用
  230. @usage
  231. -- 注意!这个接口是软件模拟i2c,速度可能会比硬件的慢
  232. -- 不需要调用i2c.close接口
  233. -- 初始化软件i2c
  234. local softI2C = i2c.createSoft(1, 2, 5)
  235. i2c.send(softI2C, 0x5C, string.char(0x0F, 0x2F))
  236. -- 注意, 第3个参数是 2023.06.19 添加的delay
  237. -- 通过调整delay参数的值, 可增加或降低I2C的速度
  238. */
  239. static int l_i2c_soft(lua_State *L)
  240. {
  241. luat_ei2c_t *ei2c = (luat_ei2c_t *)lua_newuserdata(L, sizeof(luat_ei2c_t));
  242. ei2c->scl = luaL_checkinteger(L, 1);
  243. ei2c->sda = luaL_checkinteger(L, 2);
  244. if (lua_isinteger(L, 3)) {
  245. ei2c->udelay = luaL_checkinteger(L, 3);
  246. if (ei2c->udelay < 1)
  247. ei2c->udelay = 1;
  248. }
  249. else {
  250. ei2c->udelay = 5;
  251. }
  252. i2c_soft_setup(ei2c);
  253. luaL_setmetatable(L, LUAT_EI2C_TYPE);
  254. return 1;
  255. }
  256. /*
  257. i2c发送数据
  258. @api i2c.send(id, addr, data,stop)
  259. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  260. @int I2C子设备的地址, 7位地址
  261. @integer/string/table 待发送的数据,自适应参数类型
  262. @integer 可选参数 是否发送停止位 1发送 0不发送 默认发送(105不支持)
  263. @return true/false 发送是否成功
  264. @usage
  265. -- 往i2c0发送1个字节的数据
  266. i2c.send(0, 0x68, 0x75)
  267. -- 往i2c1发送2个字节的数据
  268. i2c.send(1, 0x5C, string.char(0x0F, 0x2F))
  269. i2c.send(1, 0x5C, {0x0F, 0x2F})
  270. */
  271. static int l_i2c_send(lua_State *L)
  272. {
  273. int id = 0;
  274. if (!lua_isuserdata(L, 1))
  275. {
  276. id = luaL_checkinteger(L, 1);
  277. }
  278. int addr = luaL_checkinteger(L, 2);
  279. size_t len = 0;
  280. int result = 0;
  281. int stop = luaL_optnumber(L, 4 , 1);
  282. if (lua_isinteger(L, 3))
  283. {
  284. char buff = (char)luaL_checkinteger(L, 3);
  285. if (lua_isuserdata(L, 1))
  286. {
  287. luat_ei2c_t *ei2c = toei2c(L);
  288. result = i2c_soft_send(ei2c, addr, &buff, 1,stop);
  289. }
  290. else
  291. {
  292. result = luat_i2c_send(id, addr, &buff, 1,stop);
  293. }
  294. // luat_heap_free(buff);
  295. }
  296. else if (lua_isstring(L, 3))
  297. {
  298. const char *buff = luaL_checklstring(L, 3, &len);
  299. if (lua_isuserdata(L, 1))
  300. {
  301. luat_ei2c_t *ei2c = toei2c(L);
  302. result = i2c_soft_send(ei2c, addr, (char *)buff, len,stop);
  303. }
  304. else
  305. {
  306. result = luat_i2c_send(id, addr, (char *)buff, len,stop);
  307. }
  308. }
  309. else if (lua_istable(L, 3))
  310. {
  311. const int len = lua_rawlen(L, 3); //返回数组的长度
  312. char *buff = (char *)luat_heap_malloc(len);
  313. for (size_t i = 0; i < len; i++)
  314. {
  315. lua_rawgeti(L, 3, 1 + i);
  316. buff[i] = (char)lua_tointeger(L, -1);
  317. lua_pop(L, 1); //将刚刚获取的元素值从栈中弹出
  318. }
  319. if (lua_isuserdata(L, 1))
  320. {
  321. luat_ei2c_t *ei2c = toei2c(L);
  322. result = i2c_soft_send(ei2c, addr, buff, len,stop);
  323. }
  324. else
  325. {
  326. result = luat_i2c_send(id, addr, buff, len,stop);
  327. }
  328. luat_heap_free(buff);
  329. }
  330. else
  331. {
  332. if (lua_isuserdata(L, 1))
  333. {
  334. luat_ei2c_t *ei2c = toei2c(L);
  335. result = i2c_soft_send(ei2c, addr, NULL, 0,stop);
  336. }
  337. else
  338. {
  339. result = luat_i2c_send(id, addr, NULL, 0,stop);
  340. }
  341. }
  342. lua_pushboolean(L, result == 0);
  343. return 1;
  344. }
  345. /*
  346. i2c接收数据
  347. @api i2c.recv(id, addr, len)
  348. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  349. @int I2C子设备的地址, 7位地址
  350. @int 接收数据的长度
  351. @return string 收到的数据
  352. @usage
  353. -- 从i2c1读取2个字节的数据
  354. local data = i2c.recv(1, 0x5C, 2)
  355. */
  356. static int l_i2c_recv(lua_State *L)
  357. {
  358. int id = 0;
  359. if (!lua_isuserdata(L, 1))
  360. {
  361. id = luaL_checkinteger(L, 1);
  362. }
  363. int addr = luaL_checkinteger(L, 2);
  364. int len = luaL_checkinteger(L, 3);
  365. char *buff = (char *)luat_heap_malloc(len);
  366. int result;
  367. if (lua_isuserdata(L, 1))
  368. {
  369. luat_ei2c_t *ei2c = toei2c(L);
  370. result = i2c_soft_recv(ei2c, addr, buff, len);
  371. }
  372. else
  373. {
  374. result = luat_i2c_recv(id, addr, buff, len);
  375. }
  376. if (result != 0)
  377. { //如果返回值不为0,说明收失败了
  378. len = 0;
  379. LLOGD("i2c receive result %d", result);
  380. }
  381. lua_pushlstring(L, buff, len);
  382. luat_heap_free(buff);
  383. return 1;
  384. }
  385. /*
  386. i2c写寄存器数据
  387. @api i2c.writeReg(id, addr, reg, data,stop)
  388. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  389. @int I2C子设备的地址, 7位地址
  390. @int 寄存器地址
  391. @string 待发送的数据
  392. @integer 可选参数 是否发送停止位 1发送 0不发送 默认发送(105不支持)
  393. @return true/false 发送是否成功
  394. @usage
  395. -- 从i2c1的地址为0x5C的设备的寄存器0x01写入2个字节的数据
  396. i2c.writeReg(1, 0x5C, 0x01, string.char(0x00, 0xF2))
  397. */
  398. static int l_i2c_write_reg(lua_State *L)
  399. {
  400. int id = 0;
  401. if (!lua_isuserdata(L, 1))
  402. {
  403. id = luaL_checkinteger(L, 1);
  404. }
  405. int addr = luaL_checkinteger(L, 2);
  406. int reg = luaL_checkinteger(L, 3);
  407. size_t len;
  408. const char *lb = luaL_checklstring(L, 4, &len);
  409. int stop = luaL_optnumber(L, 5 , 1);
  410. char *buff = (char *)luat_heap_malloc(len + 1);
  411. *buff = (char)reg;
  412. memcpy(buff + 1, lb, len);
  413. int result;
  414. if (lua_isuserdata(L, 1))
  415. {
  416. luat_ei2c_t *ei2c = toei2c(L);
  417. result = i2c_soft_send(ei2c, addr, buff, len + 1,stop);
  418. }
  419. else
  420. {
  421. result = luat_i2c_send(id, addr, buff, len + 1,stop);
  422. }
  423. luat_heap_free(buff);
  424. lua_pushboolean(L, result == 0);
  425. return 1;
  426. }
  427. /*
  428. i2c读寄存器数据
  429. @api i2c.readReg(id, addr, reg, len)
  430. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  431. @int I2C子设备的地址, 7位地址
  432. @int 寄存器地址
  433. @int 待接收的数据长度
  434. @integer 可选参数 是否发送停止位 1发送 0不发送 默认发送(105不支持)
  435. @return string 收到的数据
  436. @usage
  437. -- 从i2c1的地址为0x5C的设备的寄存器0x01读出2个字节的数据
  438. i2c.readReg(1, 0x5C, 0x01, 2)
  439. */
  440. static int l_i2c_read_reg(lua_State *L)
  441. {
  442. int id = 0;
  443. if (!lua_isuserdata(L, 1))
  444. {
  445. id = luaL_checkinteger(L, 1);
  446. }
  447. int addr = luaL_checkinteger(L, 2);
  448. int reg = luaL_checkinteger(L, 3);
  449. int len = luaL_checkinteger(L, 4);
  450. int stop = luaL_optnumber(L, 5 , 0);
  451. char temp = (char)reg;
  452. int result;
  453. if (lua_isuserdata(L, 1))
  454. {
  455. luat_ei2c_t *ei2c = toei2c(L);
  456. result = i2c_soft_send(ei2c, addr, &temp, 1,stop);
  457. }
  458. else
  459. {
  460. result = luat_i2c_send(id, addr, &temp, 1,stop);
  461. }
  462. if (result != 0)
  463. { //如果返回值不为0,说明收失败了
  464. LLOGD("i2c send result %d", result);
  465. lua_pushlstring(L, NULL, 0);
  466. return 1;
  467. }
  468. char *buff = (char *)luat_heap_malloc(sizeof(char) * len);
  469. if (lua_isuserdata(L, 1))
  470. {
  471. luat_ei2c_t *ei2c = toei2c(L);
  472. result = i2c_soft_recv(ei2c, addr, buff, len);
  473. }
  474. else
  475. {
  476. result = luat_i2c_recv(id, addr, buff, len);
  477. }
  478. if (result != 0)
  479. { //如果返回值不为0,说明收失败了
  480. len = 0;
  481. LLOGD("i2c receive result %d", result);
  482. }
  483. lua_pushlstring(L, buff, len);
  484. luat_heap_free(buff);
  485. return 1;
  486. }
  487. /*
  488. 关闭i2c设备
  489. @api i2c.close(id)
  490. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  491. @return nil 无返回值
  492. @usage
  493. -- 关闭i2c1
  494. i2c.close(1)
  495. */
  496. static int l_i2c_close(lua_State *L)
  497. {
  498. int id = luaL_checkinteger(L, 1);
  499. luat_i2c_close(id);
  500. return 0;
  501. }
  502. /*
  503. 从i2c总线读取DHT12的温湿度数据
  504. @api i2c.readDHT12(id)
  505. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  506. @int DHT12的设备地址,默认0x5C
  507. @return boolean 读取成功返回true,否则返回false
  508. @return int 湿度值,单位0.1%, 例如 591 代表 59.1%
  509. @return int 温度值,单位0.1摄氏度, 例如 292 代表 29.2摄氏度
  510. @usage
  511. -- 从i2c0读取DHT12
  512. i2c.setup(0)
  513. local re, H, T = i2c.readDHT12(0)
  514. if re then
  515. log.info("dht12", H, T)
  516. end
  517. */
  518. static int l_i2c_readDHT12(lua_State *L)
  519. {
  520. int id = 0;
  521. if (!lua_isuserdata(L, 1))
  522. {
  523. id = luaL_checkinteger(L, 1);
  524. }
  525. int addr = luaL_optinteger(L, 2, 0x5C);
  526. char buff[5] = {0};
  527. char temp = 0x00;
  528. int result = -1;
  529. if (lua_isuserdata(L, 1))
  530. {
  531. luat_ei2c_t *ei2c = toei2c(L);
  532. result = i2c_soft_send(ei2c, addr, &temp, 1,1);
  533. }
  534. else
  535. {
  536. result = luat_i2c_send(id, addr, &temp, 1,1);
  537. }
  538. if (result != 0)
  539. {
  540. LLOGD("DHT12 i2c bus write fail");
  541. lua_pushboolean(L, 0);
  542. return 1;
  543. }
  544. if (lua_isuserdata(L, 1))
  545. {
  546. luat_ei2c_t *ei2c = toei2c(L);
  547. result = i2c_soft_recv(ei2c, addr, buff, 5);
  548. }
  549. else
  550. {
  551. result = luat_i2c_recv(id, addr, buff, 5);
  552. }
  553. if (result != 0)
  554. {
  555. lua_pushboolean(L, 0);
  556. return 1;
  557. }
  558. else
  559. {
  560. if (buff[0] == 0 && buff[1] == 0 && buff[2] == 0 && buff[3] == 0 && buff[4] == 0)
  561. {
  562. LLOGD("DHT12 DATA emtry");
  563. lua_pushboolean(L, 0);
  564. return 1;
  565. }
  566. // 检查crc值
  567. LLOGD("DHT12 DATA %02X%02X%02X%02X%02X", buff[0], buff[1], buff[2], buff[3], buff[4]);
  568. uint8_t crc_act = (uint8_t)buff[0] + (uint8_t)buff[1] + (uint8_t)buff[2] + (uint8_t)buff[3];
  569. uint8_t crc_exp = (uint8_t)buff[4];
  570. if (crc_act != crc_exp)
  571. {
  572. LLOGD("DATA12 DATA crc not ok");
  573. lua_pushboolean(L, 0);
  574. return 1;
  575. }
  576. lua_pushboolean(L, 1);
  577. lua_pushinteger(L, (uint8_t)buff[0] * 10 + (uint8_t)buff[1]);
  578. if (((uint8_t)buff[2]) > 127)
  579. lua_pushinteger(L, ((uint8_t)buff[2] - 128) * -10 + (uint8_t)buff[3]);
  580. else
  581. lua_pushinteger(L, (uint8_t)buff[2] * 10 + (uint8_t)buff[3]);
  582. return 3;
  583. }
  584. }
  585. /*
  586. 从i2c总线读取DHT30的温湿度数据(由"好奇星"贡献)
  587. @api i2c.readSHT30(id,addr)
  588. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  589. @int 设备addr,SHT30的设备地址,默认0x44 bit7
  590. @return boolean 读取成功返回true,否则返回false
  591. @return int 湿度值,单位0.1%, 例如 591 代表 59.1%
  592. @return int 温度值,单位0.1摄氏度, 例如 292 代表 29.2摄氏度
  593. @usage
  594. -- 从i2c0读取SHT30
  595. i2c.setup(0)
  596. local re, H, T = i2c.readSHT30(0)
  597. if re then
  598. log.info("sht30", H, T)
  599. end
  600. */
  601. static int l_i2c_readSHT30(lua_State *L)
  602. {
  603. char buff[7] = {0x2c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00};
  604. float temp = 0x00;
  605. float hum = 0x00;
  606. int result = -1;
  607. int addr = luaL_optinteger(L, 2, 0x44);
  608. if (lua_isuserdata(L, 1))
  609. {
  610. luat_ei2c_t *ei2c = toei2c(L);
  611. i2c_soft_send(ei2c, addr, buff, 2,1);
  612. luat_timer_mdelay(13);
  613. result = i2c_soft_recv(ei2c, addr, buff, 6);
  614. }
  615. else
  616. {
  617. int id = luaL_optinteger(L, 1, 0);
  618. luat_i2c_send(id, addr, buff, 2, 1);
  619. luat_timer_mdelay(1);
  620. result = luat_i2c_recv(id, addr, buff, 6);
  621. }
  622. if (result != 0)
  623. {
  624. lua_pushboolean(L, 0);
  625. return 1;
  626. }
  627. else
  628. {
  629. if (buff[0] == 0 && buff[1] == 0 && buff[2] == 0 && buff[3] == 0 && buff[4] == 0)
  630. {
  631. LLOGD("SHT30 DATA emtry");
  632. lua_pushboolean(L, 0);
  633. return 1;
  634. }
  635. // 检查crc值
  636. // LLOGD("SHT30 DATA %02X %02X %02X %02X %02X %02X", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5]);
  637. temp = ((((buff[0] * 256) + buff[1]) * 175) / 6553.5) - 450;
  638. hum = ((((buff[3] * 256) + buff[4]) * 100) / 6553.5);
  639. // LLOGD("\r\n SHT30 %d deg %d Hum ", temp, hum);
  640. // 跳过CRC
  641. // uint8_t crc_act = (uint8_t)buff[0] + (uint8_t)buff[1] + (uint8_t)buff[2] + (uint8_t)buff [3];
  642. // uint8_t crc_exp = (uint8_t)buff[4];
  643. // if (crc_act != crc_exp) {
  644. // LLOGD("DATA12 DATA crc not ok");
  645. // lua_pushboolean(L, 0);
  646. // return 1;
  647. // }
  648. // Convert the data
  649. lua_pushboolean(L, 1);
  650. lua_pushinteger(L, (int)hum);
  651. lua_pushinteger(L, (int)temp);
  652. return 3;
  653. // 华氏度
  654. // fTemp = (cTemp * 1.8) + 32;
  655. }
  656. }
  657. #ifndef LUAT_COMPILER_NOWEAK
  658. LUAT_WEAK int luat_i2c_transfer(int id, int addr, uint8_t *reg, size_t reg_len, uint8_t *buff, size_t len)
  659. {
  660. int result;
  661. result = luat_i2c_send(id, addr, reg, reg_len, 0);
  662. if (result != 0) return-1;
  663. return luat_i2c_recv(id, addr, buff, len);
  664. }
  665. LUAT_WEAK int luat_i2c_no_block_transfer(int id, int addr, uint8_t is_read, uint8_t *reg, size_t reg_len, uint8_t *buff, size_t len, uint16_t Toms, void *CB, void *pParam)
  666. {
  667. return -1;
  668. }
  669. #endif
  670. /**
  671. i2c通用传输,包括发送N字节,发送N字节+接收N字节,接收N字节三种功能,在发送转接收过程中发送reStart信号,解决类似mlx90614必须带restart信号,但是又不能用i2c.send来控制的,比如air105
  672. @api i2c.transfer(id, addr, txBuff, rxBuff, rxLen)
  673. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  674. @int I2C子设备的地址, 7位地址
  675. @integer/string/zbuff 待发送的数据,自适应参数类型,如果为nil,则不发送数据
  676. @zbuff 待接收数据的zbuff 如果不用zbuff,则接收数据将在return返回
  677. @int 需要接收的数据长度,如果为0或nil,则不接收数据
  678. @return boolean true/false 发送是否成功
  679. @return string or nil 如果参数5是interger,则返回接收到的数据
  680. @usage
  681. local result, _ = i2c.transfer(0, 0x11, txbuff, rxbuff, 1)
  682. local result, _ = i2c.transfer(0, 0x11, txbuff, nil, 0) --只发送txbuff里的数据,不接收数据,典型应用就是写寄存器了,这里寄存器地址和值都放在了txbuff里
  683. local result, _ = i2c.transfer(0, 0x11, "\x01\x02\x03", nil, 1) --发送0x01, 0x02,0x03,不接收数据,如果是eeprom,就是往0x01的地址写02和03,或者往0x0102的地址写03,看具体芯片了
  684. local result, rxdata = i2c.transfer(0, 0x11, "\x01\x02", nil, 1) --发送0x01, 0x02,然后接收1个字节,典型应用就是eeprom
  685. local result, rxdata = i2c.transfer(0, 0x11, 0x00, nil, 1) --发送0x00,然后接收1个字节,典型应用各种传感器
  686. */
  687. static int l_i2c_transfer(lua_State *L)
  688. {
  689. int addr = luaL_checkinteger(L, 2);
  690. size_t tx_len = 0;
  691. size_t rx_len = 0;
  692. int result = -1;
  693. uint8_t temp[1];
  694. uint8_t *tx_buff = NULL;
  695. uint8_t *rx_buff = NULL;
  696. uint8_t tx_heap_flag = 0;
  697. if (lua_isnil(L, 3)) {
  698. tx_len = 0;
  699. }
  700. else if (lua_isinteger(L, 3)) {
  701. temp[0] = luaL_checkinteger(L, 3);
  702. tx_buff = temp;
  703. tx_len = 1;
  704. }
  705. else if (lua_isstring(L, 3)) {
  706. tx_buff = (uint8_t*)luaL_checklstring(L, 3, &tx_len);
  707. }
  708. else if (lua_istable(L, 3)) {
  709. const int tx_len = lua_rawlen(L, 3); //返回数组的长度
  710. tx_buff = (uint8_t *)luat_heap_malloc(tx_len);
  711. tx_heap_flag = 1;
  712. for (size_t i = 0; i < tx_len; i++)
  713. {
  714. lua_rawgeti(L, 3, 1 + i);
  715. tx_buff[i] = (char)lua_tointeger(L, -1);
  716. lua_pop(L, 1); //将刚刚获取的元素值从栈中弹出
  717. }
  718. }
  719. else {
  720. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
  721. tx_buff = buff->addr;
  722. tx_len = buff->used;
  723. }
  724. luat_zbuff_t *rbuff = ((luat_zbuff_t *)luaL_testudata(L, 4, LUAT_ZBUFF_TYPE));
  725. if (lua_isnil(L, 5)) {
  726. rx_len = 0;
  727. }
  728. else if (lua_isinteger(L, 5)) {
  729. rx_len = luaL_checkinteger(L, 5);
  730. if (rx_len) {
  731. if (!rbuff) {
  732. rx_buff = luat_heap_malloc(rx_len);
  733. }
  734. else {
  735. if ((rbuff->used + rx_len) > rbuff->len) {
  736. __zbuff_resize(rbuff, rbuff->len + rx_len);
  737. }
  738. rx_buff = rbuff->addr + rbuff->used;
  739. }
  740. }
  741. }
  742. int id = 0;
  743. if (!lua_isuserdata(L, 1)) {
  744. id = luaL_checkinteger(L, 1);
  745. if (rx_buff && rx_len) {
  746. result = luat_i2c_transfer(id, addr, tx_buff, tx_len, rx_buff, rx_len);
  747. } else {
  748. result = luat_i2c_transfer(id, addr, NULL, 0, tx_buff, tx_len);
  749. }
  750. }else if (lua_isuserdata(L, 1)){
  751. luat_ei2c_t *ei2c = toei2c(L);
  752. if (tx_buff && tx_len) {
  753. result = i2c_soft_send(ei2c, addr, (char*)tx_buff, tx_len,0);
  754. }
  755. result = i2c_soft_recv(ei2c, addr, (char*)rx_buff, rx_len);
  756. }
  757. if (tx_heap_flag) {
  758. luat_heap_free(tx_buff);
  759. }
  760. lua_pushboolean(L, !result);
  761. if (rx_buff && rx_len) {
  762. if (rbuff) {
  763. rbuff->used += rx_len;
  764. lua_pushnil(L);
  765. } else {
  766. lua_pushlstring(L, (const char *)rx_buff, rx_len);
  767. luat_heap_free(rx_buff);
  768. }
  769. } else {
  770. lua_pushnil(L);
  771. }
  772. return 2;
  773. }
  774. /**
  775. i2c非阻塞通用传输,类似transfer,但是不会等到I2C传输完成才返回,调用本函数会立刻返回,I2C传输完成后,通过消息回调
  776. @api i2c.xfer(id, addr, txBuff, rxBuff, rxLen, transfer_done_topic, timeout)
  777. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  778. @int I2C子设备的地址, 7位地址
  779. @zbuff 待发送的数据,由于用的非阻塞模型,为保证动态数据的有效性,只能使用zbuff,发送的数据从zbuff.addr开始,长度为zbuff.used
  780. @zbuff 待接收数据的zbuff,如果为nil,则忽略后面参数, 不接收数据。接收的数据会放在zbuff.addr开始的位置,会覆盖掉之前的数据,注意zhuff的预留空间要足够
  781. @int 需要接收的数据长度,如果为0或nil,则不接收数据
  782. @string 传输完成后回调的消息
  783. @int 超时时间,如果填nil,则为100ms
  784. @return boolean true/false 本次传输是否正确启动,true,启动,false,有错误无法启动。传输完成会发布消息transfer_done_topic和boolean型结果
  785. @usage
  786. local result = i2c.xfer(0, 0x11, txbuff, rxbuff, 1, "I2CDONE") if result then result, i2c_id, succ, error_code = sys.waitUntil("I2CDONE") end if not result or not succ then log.info("i2c fail, error code", error_code) else log.info("i2c ok") end
  787. */
  788. static int l_i2c_no_block_transfer(lua_State *L)
  789. {
  790. size_t topic_len = 0;
  791. const char *topic = luaL_checklstring(L, 6, &topic_len);
  792. int id = luaL_checkinteger(L, 1);
  793. int addr = luaL_checkinteger(L, 2);
  794. size_t tx_len = 0;
  795. size_t rx_len = 0;
  796. int result = -1;
  797. uint8_t *tx_buff = NULL;
  798. uint8_t *rx_buff = NULL;
  799. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_testudata(L, 3, LUAT_ZBUFF_TYPE));
  800. if (buff) {
  801. tx_buff = buff->addr;
  802. tx_len = buff->used;
  803. }
  804. luat_zbuff_t *rbuff = ((luat_zbuff_t *)luaL_testudata(L, 4, LUAT_ZBUFF_TYPE));
  805. if (lua_isinteger(L, 5) && rbuff) {
  806. rx_len = luaL_checkinteger(L, 5);
  807. rx_buff = rbuff->addr;
  808. rbuff->used = rx_len;
  809. }
  810. uint32_t timeout = luaL_optinteger(L, 7, 100);
  811. char *cb_topic = luat_heap_malloc(topic_len + 1);
  812. memcpy(cb_topic, topic, topic_len);
  813. cb_topic[topic_len] = 0;
  814. if (rx_buff && rx_len) {
  815. result = luat_i2c_no_block_transfer(id, addr, 1, tx_buff, tx_len, rx_buff, rx_len, timeout, luat_irq_hardware_cb_handler, cb_topic);
  816. } else {
  817. result = luat_i2c_no_block_transfer(id, addr, 0, NULL, 0, tx_buff, tx_len, timeout, luat_irq_hardware_cb_handler, cb_topic);
  818. }
  819. if (result) {
  820. luat_heap_free(cb_topic);
  821. }
  822. lua_pushboolean(L, !result);
  823. return 1;
  824. }
  825. /**
  826. 扫描i2c设备
  827. @api i2c.scan(id,speed)
  828. @int 设备id, 例如i2c1的id为1, i2c2的id为2
  829. @int 速度, 可选i2c.SLOW i2c.FAST i2c.PLUS i2c.HSMODE 默认为i2c.SLOW,如探测不到则修改此项
  830. @return nil 当前无返回值
  831. @usage
  832. -- 本函数于2023.07.04添加
  833. -- 这个函数的主要目标是为了在开发期扫描i2c设备
  834. -- 有些BSP在指定addr无响应时会输出日志,导致输出会被打乱
  835. i2c.scan()
  836. */
  837. #if defined(LUA_USE_WINDOWS) || defined(LUA_USE_LINUX) || defined(LUA_USE_MACOS)
  838. static int l_i2c_scan(lua_State *L) {
  839. return 0;
  840. }
  841. #else
  842. #include "i2c_utils.h"
  843. static int l_i2c_scan(lua_State *L) {
  844. int id = luaL_optinteger(L, 1, 0);
  845. i2c_init(id,luaL_optinteger(L, 2, 0));
  846. i2c_scan();
  847. return 0;
  848. }
  849. #endif
  850. #include "rotable2.h"
  851. static const rotable_Reg_t reg_i2c[] =
  852. {
  853. { "exist", ROREG_FUNC(l_i2c_exist)},
  854. { "setup", ROREG_FUNC(l_i2c_setup)},
  855. { "createSoft", ROREG_FUNC(l_i2c_soft)},
  856. #ifdef __F1C100S__
  857. #else
  858. { "send", ROREG_FUNC(l_i2c_send)},
  859. { "recv", ROREG_FUNC(l_i2c_recv)},
  860. #endif
  861. { "transfer", ROREG_FUNC(l_i2c_transfer)},
  862. { "writeReg", ROREG_FUNC(l_i2c_write_reg)},
  863. { "readReg", ROREG_FUNC(l_i2c_read_reg)},
  864. { "close", ROREG_FUNC(l_i2c_close)},
  865. { "readDHT12", ROREG_FUNC(l_i2c_readDHT12)},
  866. { "readSHT30", ROREG_FUNC(l_i2c_readSHT30)},
  867. { "xfer", ROREG_FUNC(l_i2c_no_block_transfer)},
  868. { "scan", ROREG_FUNC(l_i2c_scan)},
  869. { "HSMODE", ROREG_INT(I2C_SPEED_HSMODE)},
  870. { "PLUS", ROREG_INT(I2C_SPEED_PLUS)},
  871. //@const FAST number 高速
  872. { "FAST", ROREG_INT(I2C_SPEED_FAST)},
  873. //@const SLOW number 低速
  874. { "SLOW", ROREG_INT(I2C_SPEED_SLOW)},
  875. { NULL, ROREG_INT(0) }
  876. };
  877. LUAMOD_API int luaopen_i2c(lua_State *L)
  878. {
  879. luat_newlib2(L, reg_i2c);
  880. luaL_newmetatable(L, LUAT_EI2C_TYPE);
  881. lua_pop(L, 1);
  882. return 1;
  883. }