luat_lib_can.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*
  2. @module can
  3. @summary can操作库
  4. @version 1.0
  5. @date 2025.2.24
  6. @demo can
  7. @tag LUAT_USE_CAN
  8. @usage
  9. --[[
  10. 错误码介绍
  11. 错误码由4byte组成小端格式的uint32
  12. byte3预留无意义
  13. byte2方向,0TX 1RX
  14. byte1类型,0bit 1form 2stuff
  15. byte0位置:
  16. 0x03 start of frame
  17. 0x02 extended: ID bits 28 - 21, standard: 10 - 3
  18. 0x06 extended: ID bits 20 - 18, standard: 2 - 0
  19. 0x04 extended: substitute RTR, standard: RTR
  20. 0x05 identifier extension
  21. 0x07 extended: ID bits 17 - 13
  22. 0x0f extended: ID bits 12 - 5
  23. 0x0e extended: ID bits 4 - 0
  24. 0x0C RTR
  25. 0x0D reserved bit 1
  26. 0x09 reserved bit 0
  27. 0x0b data length code
  28. 0x0a data section
  29. 0x08 CRC sequence
  30. 0x18 CRC delimiter
  31. 0x19 ACK slot
  32. 0x1b ACK delimiter
  33. 0x1a end of frame
  34. 0x12 intermission
  35. 0x00 unspecified
  36. ]]
  37. */
  38. #include "luat_base.h"
  39. #include "luat_sys.h"
  40. #include "luat_msgbus.h"
  41. #include "luat_mem.h"
  42. #include "luat_can.h"
  43. #include "luat_zbuff.h"
  44. #include "c_common.h"
  45. #define LUAT_LOG_TAG "can"
  46. #include "luat_log.h"
  47. #include "rotable2.h"
  48. #define MAX_DEVICE_COUNT 2
  49. static int l_can_cb[MAX_DEVICE_COUNT];
  50. static uint8_t l_can_debug_flag;
  51. static int l_can_handler(lua_State *L, void* ptr)
  52. {
  53. (void)ptr;
  54. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  55. lua_pop(L, 1);
  56. int can_id = msg->arg1;
  57. if (l_can_debug_flag) LLOGD("callback %d,%d,%x", can_id, msg->arg2, msg->ptr);
  58. if (l_can_cb[can_id])
  59. {
  60. lua_geti(L, LUA_REGISTRYINDEX, l_can_cb[can_id]);
  61. if (lua_isfunction(L, -1))
  62. {
  63. lua_pushinteger(L, can_id);
  64. switch(msg->arg2)
  65. {
  66. case LUAT_CAN_CB_NEW_MSG:
  67. lua_pushinteger(L, msg->arg2);
  68. lua_pushnil(L);
  69. break;
  70. case LUAT_CAN_CB_TX_OK:
  71. lua_pushinteger(L, msg->arg2);
  72. lua_pushboolean(L, 1);
  73. break;
  74. case LUAT_CAN_CB_TX_FAILED:
  75. lua_pushinteger(L, LUAT_CAN_CB_TX_OK);
  76. lua_pushboolean(L, 0);
  77. break;
  78. case LUAT_CAN_CB_ERROR_REPORT:
  79. lua_pushinteger(L, msg->arg2);
  80. lua_pushinteger(L, (uint32_t)msg->ptr);
  81. break;
  82. case LUAT_CAN_CB_STATE_CHANGE:
  83. lua_pushinteger(L, msg->arg2);
  84. lua_pushinteger(L, (uint32_t)msg->ptr);
  85. break;
  86. }
  87. lua_call(L, 3, 0);
  88. }
  89. }
  90. // 给rtos.recv方法返回个空数据
  91. lua_pushinteger(L, 0);
  92. return 1;
  93. }
  94. static void l_can_callback(int can_id, LUAT_CAN_CB_E cb_type, void *cb_param)
  95. {
  96. rtos_msg_t msg;
  97. msg.handler = l_can_handler;
  98. msg.ptr = cb_param;
  99. msg.arg1 = can_id;
  100. msg.arg2 = cb_type;
  101. luat_msgbus_put(&msg, 0);
  102. }
  103. /*
  104. CAN总线初始化
  105. @api can.init(id, rx_message_cache_max)
  106. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  107. @int rx_message_cache_max,接收缓存消息数的最大值,写0或者留空则使用平台默认值
  108. @return boolean 成功返回true,失败返回false
  109. @usage
  110. can.init()
  111. */
  112. static int l_can_init(lua_State *L)
  113. {
  114. int ret = luat_can_base_init(luaL_optinteger(L, 1, 0), luaL_optinteger(L, 2, 0));
  115. if (ret)
  116. {
  117. LLOGE("init failed %d", ret);
  118. lua_pushboolean(L, 0);
  119. }
  120. else
  121. {
  122. lua_pushboolean(L, 1);
  123. }
  124. return 1;
  125. }
  126. /*
  127. 注册CAN事件回调
  128. @api can.on(id, func)
  129. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  130. @function 回调方法
  131. @return nil 无返回值
  132. @usage
  133. can.on(1, function(id, type, param)
  134. log.info("can", id, type, param)
  135. end)
  136. */
  137. static int l_can_on(lua_State *L) {
  138. int id = luaL_optinteger(L, 1, 0);
  139. if (id >= MAX_DEVICE_COUNT)
  140. {
  141. id = 0;
  142. }
  143. if (l_can_cb[id] != 0)
  144. {
  145. luaL_unref(L, LUA_REGISTRYINDEX, l_can_cb[id]);
  146. }
  147. if (lua_isfunction(L, 2))
  148. {
  149. lua_pushvalue(L, 2);
  150. luat_can_set_callback(id, l_can_callback);
  151. l_can_cb[id] = luaL_ref(L, LUA_REGISTRYINDEX);
  152. }
  153. else
  154. {
  155. luat_can_set_callback(id, NULL);
  156. }
  157. return 0;
  158. }
  159. /*
  160. CAN总线配置时序
  161. @api can.timing(id, br, PTS, PBS1, PBS2, SJW)
  162. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  163. @int br, 波特率, 默认1Mbps
  164. @int PTS, 传播时间段, 范围1~8
  165. @int PBS1, 相位缓冲段1,范围1~8
  166. @int PBS2, 相位缓冲段2,范围2~8
  167. @int SJW, 同步补偿宽度值,范围1~4,默认2
  168. @return boolean 成功返回true,失败返回false
  169. @usage
  170. -- air780EPM参考,不一定适合其他平台,CAN的实际波特率=基础时钟/分频系数/(1+PTS+PBS1+PBS2),详见can.capacity
  171. can.timing(0, 100000, 6, 6, 3, 2)
  172. can.timing(0, 125000, 6, 6, 4, 2)
  173. */
  174. static int l_can_timing(lua_State *L)
  175. {
  176. int ret = luat_can_set_timing(luaL_optinteger(L, 1, 0), luaL_optinteger(L, 2, 1000000),
  177. luaL_optinteger(L, 3, 6), luaL_optinteger(L, 4, 6), luaL_optinteger(L, 5, 4),
  178. luaL_optinteger(L, 6, 2));
  179. if (ret)
  180. {
  181. LLOGE("set timing failed %d", ret);
  182. lua_pushboolean(L, 0);
  183. }
  184. else
  185. {
  186. lua_pushboolean(L, 1);
  187. }
  188. return 1;
  189. }
  190. /*
  191. CAN总线设置工作模式
  192. @api can.mode(id, mode)
  193. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  194. @int mode, 见MODE_XXX,默认是MODE_NORMAL
  195. @return boolean 成功返回true,失败返回false
  196. @usage
  197. can.mode(0, CAN.MODE_NORMAL)
  198. */
  199. static int l_can_mode(lua_State *L)
  200. {
  201. int ret = luat_can_set_work_mode(luaL_optinteger(L, 1, 0), luaL_optinteger(L, 2, LUAT_CAN_WORK_MODE_NORMAL));
  202. if (ret)
  203. {
  204. LLOGE("set mode failed %d", ret);
  205. lua_pushboolean(L, 0);
  206. }
  207. else
  208. {
  209. lua_pushboolean(L, 1);
  210. }
  211. return 1;
  212. }
  213. /*
  214. CAN总线设置节点ID,这是一种简易的过滤规则,只接收和ID完全匹配的消息,和can.filter选择一个使用
  215. @api can.node(id, node_id, id_type)
  216. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  217. @int node_id, 节点ID, 标准格式11位或者扩展格式29位,根据id_type决定,默认值是0x1fffffff,id值越小,优先级越高
  218. @int id_type,ID类型,填1或者CAN.EXT为扩展格式,填0或者CAN.STD为标准格式
  219. @return boolean 成功返回true,失败返回false
  220. @usage
  221. can.node(0, 0x12345678, CAN.EXT)
  222. can.node(0, 0x123, CAN.STD)
  223. */
  224. static int l_can_node(lua_State *L)
  225. {
  226. int ret = luat_can_set_node(luaL_optinteger(L, 1, 0), luaL_optinteger(L, 2, 0x1fffffff), luaL_optinteger(L, 3, 1));
  227. if (ret)
  228. {
  229. LLOGE("set node failed %d", ret);
  230. lua_pushboolean(L, 0);
  231. }
  232. else
  233. {
  234. lua_pushboolean(L, 1);
  235. }
  236. return 1;
  237. }
  238. /*
  239. CAN总线设置接收过滤模式,当can.node不满足需求时才使用这个,和can.node选择一个使用,过滤模式比较复杂,请参考SJA1000的Pelican模式下滤波
  240. @api can.filter(id, dual_mode, ACR, AMR)
  241. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  242. @boolean dual_mode, 是否是双过滤模式,true是,false不是,默认是false
  243. @int ACR, 接收代码寄存器值,必须写0xnnnnnnnn这样的格式,大端格式赋值到4个ACR寄存器上,默认值是0
  244. @int AMR, 接收屏蔽寄存器值,必须写0xnnnnnnnn这样的格式,大端格式赋值到4个AMR寄存器上,对应bit写0表示需要检测,写1表示不检测,默认是0xffffffff,不过滤全接收
  245. @return boolean 成功返回true,失败返回false
  246. @usage
  247. can.filter(0, false, 0x12345678 << 3, 0x07) --效果等同于can.node(0, 0x12345678, CAN.EXT)
  248. can.filter(0, false, 0x123 << 21, 0x0001fffff) --效果等同于can.node(0, 0x123, CAN.STD)
  249. */
  250. static int l_can_filter(lua_State *L)
  251. {
  252. uint32_t mask = luaL_optinteger(L, 4, 0xffffffff);
  253. uint32_t node_id = luaL_optinteger(L, 3, 0);
  254. uint8_t ACR[4];
  255. uint8_t AMR[4];
  256. uint8_t dual_mode = lua_toboolean(L,2);
  257. BytesPutBe32(ACR, node_id);
  258. BytesPutBe32(AMR, mask);
  259. int ret = luat_can_set_filter(luaL_optinteger(L, 1, 0), dual_mode, ACR, AMR);
  260. if (ret)
  261. {
  262. LLOGE("set filter failed %d", ret);
  263. lua_pushboolean(L, 0);
  264. }
  265. else
  266. {
  267. lua_pushboolean(L, 1);
  268. }
  269. return 1;
  270. }
  271. /*
  272. CAN工作状态
  273. @api can.state(id)
  274. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  275. @return int 返回值见STATE_XXX
  276. @usage
  277. can.state(0)
  278. */
  279. static int l_can_state(lua_State *L)
  280. {
  281. lua_pushinteger(L, luat_can_get_state(luaL_optinteger(L, 1, 0)));
  282. return 1;
  283. }
  284. /*
  285. CAN发送一条消息
  286. @api can.tx(id, msg_id, id_type, RTR, need_ack, data)
  287. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  288. @int msg_id, 节点ID, 标准格式11位或者扩展格式29位,根据id_type决定,默认值是0x1fffffff,id值越小,优先级越高
  289. @int id_type, ID类型,填1或者CAN.EXT为扩展格式,填0或者CAN.STD为标准格式
  290. @boolean RTR, 是否是遥控帧,true是,false不是,默认是false
  291. @boolean need_ack,是否需要应答,true是,false不需要,默认是true
  292. @string/zbuff data, 需要发送的数据, 如果是zbuff会从指针起始位置开始发送,最多发送8字节
  293. @return boolean 成功返回true,失败返回false
  294. @usage
  295. can.tx(id, 0x12345678, CAN.EXT, false, true, "\x00\x01\x02\x03\0x04\x05\0x6\x07")
  296. */
  297. static int l_can_tx(lua_State *L)
  298. {
  299. size_t len;
  300. const char *buf;
  301. uint32_t id = luaL_optinteger(L, 2, 0x1fffffff);
  302. if(lua_isuserdata(L, 6))
  303. {
  304. luat_zbuff_t *buff = ((luat_zbuff_t *)luaL_checkudata(L, 6, LUAT_ZBUFF_TYPE));
  305. len = buff->used;
  306. buf = (const char *)(buff->addr);
  307. }
  308. else
  309. {
  310. buf = lua_tolstring(L, 6, &len);//取出字符串数据
  311. }
  312. if (len > 8) len = 8;
  313. lua_pushinteger(L, luat_can_tx_message(luaL_optinteger(L, 1, 0), id, luaL_optinteger(L, 3, 0), lua_toboolean(L, 4), lua_toboolean(L, 5), len, buf));
  314. return 1;
  315. }
  316. /*
  317. 从缓存里读出一条消息
  318. @api can.rx(id)
  319. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  320. @return boolean 是否读出数据,true读出,false没有读出,缓存已经空了,或者id不对
  321. @return int 消息ID
  322. @return int ID类型,1或者CAN.EXT为扩展格式,0或者CAN.STD为标准格式
  323. @return boolean 是否是遥控帧,true是,false不是
  324. @return string 数据
  325. @usage
  326. local succ, id, type, rtr, data = can.rx(0)
  327. */
  328. static int l_can_rx(lua_State *L)
  329. {
  330. luat_can_message_t msg = {0};
  331. int id = luaL_optinteger(L, 1, 0);
  332. if (luat_can_rx_message_from_cache(id, &msg) > 0)
  333. {
  334. lua_pushboolean(L, 1);
  335. lua_pushinteger(L, msg.id);
  336. lua_pushinteger(L, msg.is_extend);
  337. lua_pushboolean(L, msg.RTR);
  338. lua_pushlstring(L, (const char*)msg.data, msg.len);
  339. }
  340. else
  341. {
  342. lua_pushboolean(L, 0);
  343. lua_pushnil(L);
  344. lua_pushnil(L);
  345. lua_pushnil(L);
  346. lua_pushnil(L);
  347. }
  348. return 5;
  349. }
  350. /*
  351. 立刻停止当前的发送
  352. @api can.stop(id)
  353. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  354. @return boolean 成功返回true,失败返回false
  355. @usage
  356. can.stop(0)
  357. */
  358. static int l_can_stop(lua_State *L)
  359. {
  360. int id = luaL_optinteger(L, 1, 0);
  361. if (luat_can_tx_stop(id))
  362. {
  363. lua_pushboolean(L, 0);
  364. }
  365. else
  366. {
  367. lua_pushboolean(L, 1);
  368. }
  369. return 1;
  370. }
  371. /*
  372. CAN总线复位,一般用于从总线关闭状态恢复成主动错误
  373. @api can.reset(id)
  374. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  375. @return boolean 成功返回true,失败返回false
  376. @usage
  377. can.reset(0)
  378. */
  379. static int l_can_reset(lua_State *L)
  380. {
  381. if (luat_can_reset(luaL_optinteger(L, 1, 0)))
  382. {
  383. lua_pushboolean(L, 0);
  384. }
  385. else
  386. {
  387. lua_pushboolean(L, 1);
  388. }
  389. return 1;
  390. }
  391. /*
  392. CAN总线关闭,此时可以重新进行timing,filter,node等配置
  393. @api can.busOff(id)
  394. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  395. @return boolean 成功返回true,失败返回false
  396. @usage
  397. can.busOff(0)
  398. */
  399. static int l_can_bus_off(lua_State *L)
  400. {
  401. if (luat_can_bus_off(luaL_optinteger(L, 1, 0)))
  402. {
  403. lua_pushboolean(L, 0);
  404. }
  405. else
  406. {
  407. lua_pushboolean(L, 1);
  408. }
  409. return 1;
  410. }
  411. /*
  412. CAN完全关闭
  413. @api can.deinit(id)
  414. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  415. @return boolean 成功返回true,失败返回false
  416. @usage
  417. can.deinit(0)
  418. */
  419. static int l_can_deinit(lua_State *L)
  420. {
  421. if (luat_can_close(luaL_optinteger(L, 1, 0)))
  422. {
  423. lua_pushboolean(L, 0);
  424. }
  425. else
  426. {
  427. lua_pushboolean(L, 1);
  428. }
  429. return 1;
  430. }
  431. /*
  432. CAN debug开关,打开后有更详细的打印
  433. @api can.debug(on_off)
  434. @boolean true打开,false关闭
  435. @return nil
  436. @usage
  437. can.debug(true)
  438. */
  439. static int l_can_debug(lua_State *L)
  440. {
  441. l_can_debug_flag = lua_toboolean(L, 1);
  442. luat_can_set_debug(l_can_debug_flag);
  443. return 0;
  444. }
  445. /*
  446. 获取CAN时钟特性,包括基础时钟,分频系数范围,CAN的实际波特率=基础时钟/分频系数/(1+PTS+PBS1+PBS2),从时钟特性里能看出对应平台是否能配置出需要的波特率
  447. @api can.capacity(id)
  448. @int id, 如果只有一条总线写0或者留空, 有多条的,can0写0,can1写1, 如此类推, 一般情况只有1条
  449. @return boolean 成功返回true,失败返回false,如果失败就不用看后面的参数了
  450. @return int,基础时钟
  451. @return int,最小分频系数
  452. @return int,最大分频系数
  453. @return int,分频系数步进,一般为1
  454. @usage
  455. local res, clk, div_min, div_max, div_step = can.capacity(0)
  456. */
  457. static int l_can_capacity(lua_State *L)
  458. {
  459. uint32_t clk, div_min, div_max, div_step;
  460. if (luat_can_get_capacity(luaL_optinteger(L, 1, 0), &clk, &div_min, &div_max, &div_step))
  461. {
  462. lua_pushboolean(L, 0);
  463. }
  464. else
  465. {
  466. lua_pushboolean(L, 1);
  467. }
  468. lua_pushinteger(L, clk);
  469. lua_pushinteger(L, div_min);
  470. lua_pushinteger(L, div_max);
  471. lua_pushinteger(L, div_step);
  472. return 5;
  473. }
  474. static const rotable_Reg_t reg_can[] =
  475. {
  476. { "init", ROREG_FUNC(l_can_init)},
  477. { "on", ROREG_FUNC(l_can_on)},
  478. { "timing", ROREG_FUNC(l_can_timing)},
  479. { "mode", ROREG_FUNC(l_can_mode)},
  480. { "node", ROREG_FUNC(l_can_node)},
  481. { "filter", ROREG_FUNC(l_can_filter)},
  482. { "state", ROREG_FUNC(l_can_state)},
  483. { "tx", ROREG_FUNC(l_can_tx)},
  484. { "rx", ROREG_FUNC(l_can_rx)},
  485. { "stop", ROREG_FUNC(l_can_stop)},
  486. { "reset", ROREG_FUNC(l_can_reset)},
  487. { "busOff", ROREG_FUNC(l_can_bus_off)},
  488. { "deinit", ROREG_FUNC(l_can_deinit)},
  489. { "debug", ROREG_FUNC(l_can_debug)},
  490. { "capacity", ROREG_FUNC(l_can_capacity)},
  491. //@const MODE_NORMAL number 正常工作模式
  492. { "MODE_NORMAL", ROREG_INT(LUAT_CAN_WORK_MODE_NORMAL)},
  493. //@const MODE_LISTEN number 监听模式
  494. { "MODE_LISTEN", ROREG_INT(LUAT_CAN_WORK_MODE_ONLY_LISTEN)},
  495. //@const MODE_TEST number 自测模式
  496. { "MODE_TEST", ROREG_INT(LUAT_CAN_WORK_MODE_SELF_TEST)},
  497. //@const MODE_SLEEP number 休眠模式
  498. { "MODE_SLEEP", ROREG_INT(LUAT_CAN_WORK_MODE_SLEEP)},
  499. //@const STATE_STOP number 停止工作状态
  500. { "STATE_STOP", ROREG_INT(LUAT_CAN_STOP)},
  501. //@const STATE_ACTIVE number 主动错误状态,一般都是这个状态
  502. { "STATE_ACTIVE", ROREG_INT(LUAT_CAN_ACTIVE_ERROR)},
  503. //@const STATE_PASSIVE number 被动错误状态,总线上错误多会进入这个状态,但是还能正常收发
  504. { "STATE_PASSIVE", ROREG_INT(LUAT_CAN_PASSIVE_ERROR)},
  505. //@const STATE_BUSOFF number 离线状态,总线上错误非常多会进入这个状态,不能收发,需要手动退出
  506. { "STATE_BUSOFF", ROREG_INT(LUAT_CAN_BUS_OFF)},
  507. //@const STATE_LISTEN number 监听状态,选择监听模式时进入这个状态
  508. { "STATE_LISTEN", ROREG_INT(LUAT_CAN_ONLY_LISTEN)},
  509. //@const STATE_TEST number 自收自发状态,选择自测模式时进入这个状态
  510. { "STATE_TEST", ROREG_INT(LUAT_CAN_SELF_TEST)},
  511. //@const STATE_SLEEP number 休眠状态,选择休眠模式时进入这个状态
  512. { "STATE_SLEEP", ROREG_INT(LUAT_CAN_SLEEP)},
  513. //@const CB_MSG number 回调消息类型,有新数据写入缓存
  514. { "CB_MSG", ROREG_INT(LUAT_CAN_CB_NEW_MSG)},
  515. //@const CB_TX number 回调消息类型,数据发送结束,需要根据后续param确定发送成功还是失败
  516. { "CB_TX", ROREG_INT(LUAT_CAN_CB_TX_OK)},
  517. //@const CB_ERR number 回调消息类型,有错误报告,后续param是错误码,具体见错误码介绍
  518. { "CB_ERR", ROREG_INT(LUAT_CAN_CB_ERROR_REPORT)},
  519. //@const CB_STATE number 回调消息类型,总线状态变更,后续param是新的状态,也可以用can.state读出
  520. { "CB_STATE", ROREG_INT(LUAT_CAN_CB_STATE_CHANGE)},
  521. //@const EXT number 扩展帧
  522. { "EXT", ROREG_INT(1)},
  523. //@const STD number 标准帧
  524. { "STD", ROREG_INT(0)},
  525. { NULL, ROREG_INT(0) }
  526. };
  527. LUAMOD_API int luaopen_can( lua_State *L )
  528. {
  529. luat_newlib2(L, reg_can);
  530. return 1;
  531. }