AirGPIO_1000.lua 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. --本文件中的主机是指I2C主机,具体指Air8000
  2. --本文件中的从机是指I2C从机,具体指AirGPIO_1000配件板上的IO扩展芯片
  3. local AirGPIO_1000 =
  4. {
  5. -- i2c_id:主机的i2c id;
  6. -- gpio_int_id:主机的GPIO中断引脚id;
  7. -- slave_address:从机地址;
  8. -- ints = --从机各个扩展IO配置为中断时的处理函数以及上一次的输入电平
  9. -- {
  10. -- [0x00] = {cb_func=, old_level=},
  11. -- [0x01] = {cb_func=, old_level=},
  12. -- [0x02] = {cb_func=, old_level=},
  13. -- [0x03] = {cb_func=, old_level=},
  14. -- [0x04] = {cb_func=, old_level=},
  15. -- [0x05] = {cb_func=, old_level=},
  16. -- [0x06] = {cb_func=, old_level=},
  17. -- [0x07] = {cb_func=, old_level=},
  18. -- [0x10] = {cb_func=, old_level=},
  19. -- [0x11] = {cb_func=, old_level=},
  20. -- [0x12] = {cb_func=, old_level=},
  21. -- [0x13] = {cb_func=, old_level=},
  22. -- [0x14] = {cb_func=, old_level=},
  23. -- [0x15] = {cb_func=, old_level=},
  24. -- [0x16] = {cb_func=, old_level=},
  25. -- [0x17] = {cb_func=, old_level=},
  26. -- }
  27. }
  28. -- 从机硬件上有三个引脚A0 A1 A2可以配置I2C从设备的地址
  29. -- 当A0 A1 A2都接地时的从设备基地址为(0x40 >> 1)
  30. -- A0 A1 A2有0到7一共八种排序组合,基地址+0/1/2/3/4/5/6/7即为八种从设备的地址
  31. -- AirGPIO_1000默认A0 A1 A2都接地,所以AirGPIO_1000的从设备地址默认也为(0x40 >> 1)
  32. local SALVE_ADDRESS_HIGH_4BIT = (0x40 >> 1)
  33. -- 寄存器地址
  34. local REG_INPUT_PORT_0 = 0x00 -- 输入端口0
  35. local REG_INPUT_PORT_1 = 0x01 -- 输入端口1
  36. local REG_OUTPUT_PORT_0 = 0x02 -- 输出端口0
  37. local REG_OUTPUT_PORT_1 = 0x03 -- 输出端口1
  38. local REG_POL_INV_0 = 0x04 -- 极性反转端口0
  39. local REG_POL_INV_1 = 0x05 -- 极性反转端口1
  40. local REG_CONFIG_0 = 0x06 -- 配置端口0
  41. local REG_CONFIG_1 = 0x07 -- 配置端口1
  42. -- 写入AirGPIO_1000的寄存器
  43. --reg:number类型;
  44. -- 表示AirGPIO_1000上的寄存器地址;
  45. -- 取值范围:0x00到0x07,参考本文件上方的寄存器地址列表;
  46. -- 必须传入,不允许为空;
  47. --value:number类型;
  48. -- 表示要写入到AirGPIO_1000寄存器中的数据;
  49. -- 取值范围:0x00到0xFF,1个字节的长度;
  50. -- 必须传入,不允许为空;
  51. --返回值:成功返回true,失败返回false
  52. local function write_register(reg, value)
  53. local data = {reg, value}
  54. local result = i2c.send(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, data)
  55. return result
  56. end
  57. -- 读取AirGPIO_1000的寄存器
  58. --reg:number类型;
  59. -- 表示AirGPIO_1000上的寄存器地址;
  60. -- 取值范围:0x00到0x07,参考本文件上方的寄存器地址列表;
  61. -- 必须传入,不允许为空;
  62. --返回值:成功返回1个字节的number类型,失败返回nil
  63. local function read_register(reg)
  64. i2c.send(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, reg)
  65. local data = i2c.recv(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, 1)
  66. if data and #data == 1 then
  67. return string.byte(data, 1)
  68. end
  69. return nil
  70. end
  71. --主机上的中断引脚处理函数
  72. local function gpio_int_callback()
  73. log.info("gpio_int_callback")
  74. --在中断处理函数中不能直接执行耗时较长的动作
  75. --所以在此处publish一个"AirGPIO_1000_INT"消息
  76. --在其他位置订阅这个消息,进行异步处理
  77. --异步处理这个消息的函数可以直接执行耗时较长的动作
  78. sys.publish("AirGPIO_1000_INT")
  79. end
  80. --遍历用户扩展GPIO中断函数表,进行处理
  81. local function user_gpio_int_callback()
  82. if AirGPIO_1000.ints then
  83. --遍历用户扩展GPIO中断函数表
  84. for k,v in pairs(AirGPIO_1000.ints) do
  85. if v then
  86. --读取扩展GPIO的输入电平
  87. local cur_level = AirGPIO_1000.get(k)
  88. --如果输入电平和上一次输入电平不一致
  89. --则执行用户扩展GPIO中断函数
  90. if v.old_level~=cur_level then
  91. v.old_level = cur_level
  92. if v.cb_func then v.cb_func(k, cur_level) end
  93. end
  94. end
  95. end
  96. end
  97. end
  98. --订阅"AirGPIO_1000_INT"消息的处理函数user_gpio_int_callback
  99. --当其他位置publish "AirGPIO_1000_INT"消息时,会执行user_gpio_int_callback
  100. sys.subscribe("AirGPIO_1000_INT", user_gpio_int_callback)
  101. --检查AirGPIO_1000上的扩展GPIO ID是否有效
  102. --gpio_id:number类型;
  103. -- 表示AirGPIO_1000上的扩展GPIO ID;
  104. -- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
  105. -- 必须传入,不允许为空;
  106. --返回值:有效返回true,无效返回false
  107. local function check_gpio_id_valid(gpio_id)
  108. return (gpio_id>=0x00 and gpio_id<=0x07 or gpio_id>=0x10 and gpio_id<=0x17)
  109. end
  110. --配置主机和AirGPIO_1000之间的通信参数;
  111. --i2c_id:number类型;
  112. -- 主机使用的I2C ID,用来控制AirGPIO_1000;
  113. -- 取值范围:仅支持0和1;
  114. -- 如果没有传入此参数,则默认为0;
  115. --int_id:number类型;
  116. -- 主机使用的中断引脚GPIO ID,和AirGPIO_1000上的INT引脚相连;
  117. -- AirGPIO_1000可以扩展出来16个GPIO,这些GPIO支持配置为输入;
  118. -- AirGPIO_1000上的任意一个输入GPIO的状态发生上升沿或者下降沿变化时,会通过INT引脚通知到主机的int_id中断引脚;
  119. -- 此时主机可以通过I2C接口立即读取AirGPIO_1000上配置为输入模式的扩展GPIO的电平状态,从而判断是哪些扩展GPIO的输入电平发生了变化;
  120. -- 取值范围:nil或者空,或者0到9,或者12到55,注意不要使用已经复用为其他功能的引脚;nil或者空时,表示不使用中断通知功能;
  121. -- 如果没有传入此参数,则默认为空,表示不使用中断通知功能;
  122. --返回值:成功返回true,失败返回false
  123. function AirGPIO_1000.init(i2c_id, gpio_int_id)
  124. --检查参数的合法性
  125. if not (i2c_id == 0 or i2c_id == 1) then
  126. log.error("AirGPIO_1000.init", "invalid i2c_id", i2c_id)
  127. return false
  128. end
  129. if not (gpio_int_id==nil or gpio_int_id>=0 and gpio_int_id<=9 or gpio_int_id>=12 and gpio_int_id<=55) then
  130. log.error("AirGPIO_1000.init", "invalid gpio_int_id", gpio_int_id)
  131. return false
  132. end
  133. AirGPIO_1000.i2c_id = i2c_id
  134. AirGPIO_1000.gpio_int_id = gpio_int_id
  135. --初始化I2C
  136. if i2c.setup(i2c_id, i2c.FAST) ~= 1 then
  137. log.error("AirGPIO_1000.init", "i2c.setup error", i2c_id)
  138. return false
  139. end
  140. --自动识别从设备地址
  141. --AirGPIO_1000上使用的TCA9555芯片有三个引脚,A2 A1 A0,可以配置三个bit的I2C从设备地址
  142. --从 0 0 0 到 1 1 1,也就是十进制的0到7,一共可以配置8种;
  143. --依次读取这8个从设备地址上的一个寄存器地址数据
  144. --如果返回应答数据,则从设备地址自动识别成功
  145. for i=0,7 do
  146. i2c.send(i2c_id, SALVE_ADDRESS_HIGH_4BIT+i, REG_INPUT_PORT_0)
  147. local data = i2c.recv(i2c_id, SALVE_ADDRESS_HIGH_4BIT+i, 1)
  148. if data~=nil then
  149. AirGPIO_1000.slave_address = SALVE_ADDRESS_HIGH_4BIT+i
  150. log.error("AirGPIO_1000.init", "slave_address", SALVE_ADDRESS_HIGH_4BIT+i, data:byte())
  151. break
  152. end
  153. end
  154. --自动识别从设备地址失败
  155. if not AirGPIO_1000.slave_address then
  156. log.error("AirGPIO_1000.init", "slave_address unknown")
  157. i2c.close(i2c_id)
  158. return false
  159. end
  160. --配置主机上的中断GPIO,用来实时检测从机上扩展GPIO的输入电平变化
  161. if gpio_int_id then
  162. gpio.setup(gpio_int_id, gpio_int_callback, gpio.PULLUP, gpio.FALLING)
  163. end
  164. return true
  165. end
  166. --关闭主机和AirGPIO_1000之间的通信;
  167. --返回值:成功返回true,失败返回false
  168. function AirGPIO_1000.deinit()
  169. --关闭主机I2C
  170. if AirGPIO_1000.i2c_id then
  171. i2c.close(AirGPIO_1000.i2c_id)
  172. AirGPIO_1000.i2c_id = nil
  173. AirGPIO_1000.slave_address = nil
  174. end
  175. --关闭主机中断GPIO
  176. if AirGPIO_1000.gpio_int_id then
  177. gpio.close(AirGPIO_1000.gpio_int_id)
  178. AirGPIO_1000.gpio_int_id = nil
  179. end
  180. --清空用户注册的扩展GPIO中断处理表
  181. if type(AirGPIO_1000.ints)=="table" then
  182. for k,v in pairs(AirGPIO_1000.ints) do
  183. AirGPIO_1000.ints[k] = nil
  184. end
  185. AirGPIO_1000.ints = nil
  186. end
  187. end
  188. --[[
  189. 配置AirGPIO_1000上的扩展GPIO管脚功能;
  190. 支持配置为输出,输入和中断三种模式;
  191. @api AirGPIO_1000.setup(gpio_id, gpio_mode)
  192. @number
  193. gpio_id
  194. 表示AirGPIO_1000上的扩展GPIO ID;
  195. 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
  196. 必须传入,不允许为空或者nil;
  197. @number or function or nil or 空
  198. gpio_mode
  199. number类型时,表示输出模式,取值范围为0和1,0表示默认输出低电平,1表示默认输出高电平;
  200. nil或者空类型时,表示输入模式;
  201. function类型时,表示中断模式,此function为中断回调函数,函数的定义格式如下:
  202. function cb_func(id, level)
  203. --id:表示触发中断的AirGPIO_1000上的扩展GPIO ID,取值范围为0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
  204. --level:触发中断后,某一时刻,扩展GPIO输入的电平状态,高电平为1, 低电平为0;并不是指触发中断的电平状态;
  205. end
  206. @return bool
  207. 成功返回true,失败返回false
  208. @usage
  209. -- GPIO ID 0x00配置为输出模式,默认输出低电平
  210. AirGPIO_1000.setup(0x00, 0)
  211. -- GPIO ID 0x11配置为输入模式
  212. AirGPIO_1000.setup(0x11)
  213. --P04引脚中断处理函数
  214. --id:0x04
  215. --level:触发中断后,某一时刻,扩展GPIO输入的电平状态,高电平为1, 低电平为0
  216. local function P04_int_cbfunc(id, level)
  217. log.info("P04_int_cbfunc", id, level)
  218. end
  219. -- GPIO ID 0x04配置为中断模式,中断处理函数为P04_int_cbfunc
  220. AirGPIO_1000.setup(0x04, P04_int_cbfunc)
  221. ]]
  222. function AirGPIO_1000.setup(gpio_id, gpio_mode)
  223. --检查参数的合法性
  224. if not check_gpio_id_valid(gpio_id) then
  225. log.error("AirGPIO_1000.setup", "invalid gpio_id", gpio_id)
  226. return false
  227. end
  228. if not (gpio_mode==0 or gpio_mode==1 or gpio_mode==nil or type(gpio_mode)=="function") then
  229. log.error("AirGPIO_1000.setup", "invalid gpio_mode", type(gpio_mode), gpio_mode)
  230. return false
  231. end
  232. log.info("AirGPIO_1000.setup", "enter", gpio_id, type(gpio_mode), gpio_mode)
  233. --根据扩展GPIO ID识别当前扩展GPIO使用的配置寄存器地址
  234. --0x0x开头的ID为REG_CONFIG_0,0x01开头的ID为REG_CONFIG_1
  235. local reg_addr = ((gpio_id>>4) == 0) and REG_CONFIG_0 or REG_CONFIG_1
  236. --读取从机中输出寄存器当前的值
  237. local reg_data = read_register(reg_addr)
  238. if reg_data==nil then
  239. log.error("AirGPIO_1000.setup", "read config register error", reg_addr)
  240. return false
  241. end
  242. local mask = 1<<(gpio_id&0x0F)
  243. local value
  244. --GPIO配置为输出模式
  245. if gpio_mode==0 or gpio_mode==1 then
  246. value = reg_data & (~mask)
  247. --GPIO配置为输入模式
  248. elseif gpio_mode==nil or type(gpio_mode)=="function" then
  249. value = reg_data | mask
  250. end
  251. --如果寄存器新值和旧值相比,发生变化
  252. --写新值到从机的配置寄存器中
  253. if reg_data~=value then
  254. if not write_register(reg_addr, value) then
  255. log.error("AirGPIO_1000.setup", "config write error", reg_addr, value)
  256. return false
  257. end
  258. end
  259. log.info("AirGPIO_1000.setup", "config", reg_addr, reg_data, value)
  260. --如果是中断模式,并且用户注册了中断处理函数
  261. if type(gpio_mode)=="function" then
  262. if AirGPIO_1000.ints==nil then
  263. AirGPIO_1000.ints = {}
  264. end
  265. if AirGPIO_1000.ints[gpio_id]==nil then
  266. AirGPIO_1000.ints[gpio_id] = {}
  267. end
  268. --存储中断处理函数
  269. AirGPIO_1000.ints[gpio_id].cb_func = gpio_mode
  270. --读取当前时刻GPIO的输入电平状态
  271. AirGPIO_1000.ints[gpio_id].old_level = AirGPIO_1000.get(gpio_id)
  272. end
  273. --如果配置的是输入模式或者中断模式,可以直接返回了
  274. if gpio_mode~=0 and gpio_mode~=1 then return true end
  275. --如果配置的输出模式,初始化输出的电平为gpio_mode
  276. if not AirGPIO_1000.set(gpio_id, gpio_mode) then
  277. log.error("AirGPIO_1000.setup", "output set error")
  278. return false
  279. end
  280. log.info("AirGPIO_1000.setup", "output", reg_addr, reg_data, value)
  281. return true
  282. end
  283. --设置AirGPIO_1000上配置为输出模式的扩展GPIO的输出电平
  284. --gpio_id:number类型;
  285. -- 表示AirGPIO_1000上的扩展GPIO ID;
  286. -- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
  287. -- 必须传入,不允许为空;
  288. --output_level:number类型;
  289. -- 表示配置为输出模式的扩展GPIO对外输出的电平;
  290. -- 取值范围:0和1,0表示输出低电平,1表示输出高电平;
  291. -- 必须传入,不允许为空;
  292. --返回值:成功返回true,失败返回false
  293. function AirGPIO_1000.set(gpio_id, output_level)
  294. --检查参数的合法性
  295. if not check_gpio_id_valid(gpio_id) then
  296. log.error("AirGPIO_1000.set", "invalid gpio_id", gpio_id)
  297. return false
  298. end
  299. if not (output_level==0 or output_level==1) then
  300. log.error("AirGPIO_1000.set", "invalid output_level", type(output_level), output_level)
  301. return false
  302. end
  303. log.info("AirGPIO_1000.set", "enter", gpio_id, output_level)
  304. --根据扩展GPIO ID识别当前扩展GPIO使用的输出寄存器地址
  305. --0x0x开头的ID为REG_OUTPUT_PORT_0,0x01开头的ID为REG_OUTPUT_PORT_1
  306. local reg_addr = ((gpio_id>>4) == 0) and REG_OUTPUT_PORT_0 or REG_OUTPUT_PORT_1
  307. --读取从机中输出寄存器当前的值
  308. local reg_data = read_register(reg_addr)
  309. if reg_data==nil then
  310. log.error("AirGPIO_1000.set", "read output register error", reg_addr)
  311. return false
  312. end
  313. local mask = 1<<(gpio_id&0x0F)
  314. local value
  315. --输出低电平
  316. if output_level==0 then
  317. value = reg_data & (~mask)
  318. --输出高电平
  319. elseif output_level==1 then
  320. value = reg_data | mask
  321. end
  322. --如果寄存器新值和旧值相比,发生变化
  323. --写新值到从机的输出寄存器中
  324. if reg_data~=value then
  325. if not write_register(reg_addr, value) then
  326. log.error("AirGPIO_1000.set", "output write error", reg_addr, value)
  327. return false
  328. end
  329. end
  330. log.info("AirGPIO_1000.set", "output", reg_addr, reg_data, value)
  331. return true
  332. end
  333. --读取AirGPIO_1000上配置为输入或者中断模式的扩展GPIO的输入电平
  334. --gpio_id:number类型;
  335. -- 表示AirGPIO_1000上的扩展GPIO ID;
  336. -- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
  337. -- 必须传入,不允许为空;
  338. --返回值:number类型,表示输入的电平,0表示低电平,1表示高电平;如果读取失败,返回false
  339. function AirGPIO_1000.get(gpio_id)
  340. --检查参数的合法性
  341. if not check_gpio_id_valid(gpio_id) then
  342. log.error("AirGPIO_1000.get", "invalid gpio_id", gpio_id)
  343. return false
  344. end
  345. --根据扩展GPIO ID识别当前扩展GPIO使用的输入寄存器地址
  346. --0x0x开头的ID为REG_INPUT_PORT_0,0x01开头的ID为REG_INPUT_PORT_1
  347. local reg_addr = ((gpio_id>>4) == 0) and REG_INPUT_PORT_0 or REG_INPUT_PORT_1
  348. --读取从机中输入寄存器当前的值
  349. local value = read_register(reg_addr)
  350. if not value then
  351. log.error("AirGPIO_1000.get", "read_register error", reg_addr)
  352. return false
  353. end
  354. --返回输入寄存器的值和GPIO对应的bit位的值
  355. return ((value>>(gpio_id&0x0F)) & 0x01)
  356. end
  357. --关闭AirGPIO_1000上的扩展GPIO功能
  358. --实际上是恢复为默认状态(配置为输入)
  359. --gpio_id:number类型;
  360. -- 表示AirGPIO_1000上的扩展GPIO ID;
  361. -- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
  362. -- 必须传入,不允许为空;
  363. --返回值:成功返回true,失败返回false
  364. function AirGPIO_1000.close(gpio_id)
  365. local result = AirGPIO_1000.setup(gpio_id)
  366. if not result then
  367. log.error("AirGPIO_1000.close", "error", gpio_id)
  368. end
  369. return result
  370. end
  371. return AirGPIO_1000