can_self_test.lua 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. --[[
  2. @module can_self_test
  3. @summary CAN总线自测模式使用示例
  4. @version 1.0
  5. @date 2025.11.25
  6. @author 魏健强
  7. @usage
  8. 本文件为CAN总线自测模式使用示例,核心业务逻辑为:
  9. 1. 初始化CAN总线
  10. 2. 启用测试模式测试数据自发自收
  11. 本文件没有对外接口,直接在main.lua模块中require "can_self_test"就可以加载运行;
  12. ]]
  13. local can_id = 0
  14. local stb_pin = 27 -- Air8000开发板上STB引脚为GPIO27
  15. local tx_id = 0x12345677
  16. local test_cnt = 0
  17. local tx_buf = zbuff.create(8) --创建zbuff
  18. local function can_cb(id, cb_type, param)
  19. if cb_type == can.CB_MSG then
  20. log.info("有新的消息")
  21. local succ, id, id_type, rtr, data = can.rx(id)
  22. while succ do
  23. log.info(mcu.x32(id), #data, data:toHex())
  24. succ, id, id_type, rtr, data = can.rx(id)
  25. end
  26. end
  27. if cb_type == can.CB_TX then
  28. if param then
  29. log.info("发送成功")
  30. else
  31. log.info("发送失败")
  32. end
  33. end
  34. if cb_type == can.CB_ERR then
  35. -- param参数就是4字节错误码
  36. log.error("CAN错误", "错误码:", string.format("0x%08X", param))
  37. -- 解析错误码
  38. local direction = (param >> 16) & 0xFF -- byte2: 方向
  39. local error_type = (param >> 8) & 0xFF -- byte1: 错误类型
  40. local position = param & 0xFF -- byte0: 错误位置
  41. -- 判断错误方向
  42. if direction == 0 then
  43. log.info("错误方向", "发送错误")
  44. else
  45. log.info("错误方向", "接收错误")
  46. end
  47. -- 判断错误类型
  48. if error_type == 0 then
  49. log.info("错误类型", "位错误")
  50. elseif error_type == 1 then
  51. log.info("错误类型", "格式错误")
  52. elseif error_type == 2 then
  53. log.info("错误类型", "填充错误")
  54. end
  55. -- 输出错误位置
  56. log.info("错误位置", string.format("0x%02X", position))
  57. end
  58. if cb_type == can.CB_STATE then
  59. -- 获取总线状态
  60. local state = can.state(can_id)
  61. log.info("can.state", "当前状态", state)
  62. -- 根据状态处理
  63. if state == can.STATE_ACTIVE then
  64. log.info("can.state", "总线正常")
  65. elseif state == can.STATE_PASSIVE then
  66. log.warn("can.state", "被动错误状态")
  67. elseif state == can.STATE_BUSOFF then
  68. log.error("can.state", "总线离线")
  69. -- 需要手动恢复
  70. can.reset(can_id)
  71. end
  72. end
  73. end
  74. local function can_tx_test()
  75. log.info("can tx")
  76. test_cnt = test_cnt + 1
  77. if test_cnt > 8 then
  78. test_cnt = 1
  79. end
  80. tx_buf:set(0,test_cnt) --zbuff的类似于memset操作,类似于memset(&buff[start], num, len)
  81. tx_buf:seek(test_cnt) --zbuff设置光标位置(可能与当前指针位置有关;执行后指针会被设置到指定位置)
  82. can.tx(can_id, tx_id, can.EXT, false, true, tx_buf)
  83. end
  84. -- can.debug(true)
  85. gpio.setup(stb_pin,0) -- 配置STB引脚为输出低电平
  86. can.init(can_id, 128) -- 初始化CAN,参数为CAN ID,接收缓存消息数的最大值
  87. can.on(can_id, can_cb) -- 注册CAN的回调函数
  88. can.timing(can_id, 1000000, 6, 6, 4, 2) --CAN总线配置时序
  89. can.node(can_id, tx_id, can.EXT) -- 测试模式下,允许接收的ID和发送ID一致才会有新数据提醒
  90. can.mode(can_id, can.MODE_TEST) -- 如果只是自身测试硬件好坏,可以用测试模式来验证,如果发送成功就OK
  91. sys.timerLoopStart(can_tx_test, 2000)