mcp23017.lua 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. --- 模块功能:MCP23017
  2. --- Author JWL 参考STM32 https://blog.csdn.net/lnniyunlong99/article/details/107728094
  3. module(..., package.seeall)
  4. require "utils"
  5. require "sys"
  6. require "pins"
  7. local MCP23017_IODIR = 0x00
  8. local MCP23017_IPOL = 0x02
  9. local MCP23017_GPINTEN = 0x04
  10. local MCP23017_DEFVAL = 0x06
  11. local MCP23017_INTCON = 0x08
  12. local MCP23017_IOCON = 0x0A
  13. local MCP23017_GPPU = 0x0C
  14. local MCP23017_INTF = 0x0E
  15. local MCP23017_INTCAP = 0x10
  16. local MCP23017_GPIO = 0x12
  17. local MCP23017_OLAT = 0x14
  18. local MCP23017_PORTA = 0x00
  19. local MCP23017_PORTB = 0x01
  20. local INPUT = 0x01
  21. local OUTPUT = 0x00
  22. local ENABLE = 0x01
  23. local DISABLE = 0x00
  24. local SET = 0x01
  25. local RESET = 0x00
  26. local POLARITY_REVERSE = 0x01
  27. local POLARITY_NON_REVERSE = 0x00
  28. local PIN0 = 0x01
  29. local PIN1 = 0x02
  30. local PIN2 = 0x04
  31. local PIN3 = 0x08
  32. local PIN4 = 0x10
  33. local PIN5 = 0x20
  34. local PIN6 = 0x40
  35. local PIN7 = 0x80
  36. local ALLPIN = 0xFF
  37. local DIS_INTERRUPT = 0x00
  38. local HIGHLEVEL_INTERRUPT = 0x01
  39. local LOWLEVEL_INTERRUPT = 0x02
  40. local CHANGE_INTERRUPT = 0x03
  41. local INTA_INTB_CONJUNCTION = 0x00
  42. local INTA_INTB_INDEPENDENT = 0x01
  43. local HWA_EN = 0x00
  44. local HWA_DIS = 0x01
  45. local INT_OD = 0x00
  46. local INT_PUSHPULL_HIGH = 0x01
  47. local INT_PUSHPULL_LOW = 0x02
  48. local I2C_READ = 0x01
  49. local I2C_WRITE = 0x00
  50. local DEV_ID = 0x20
  51. local I2C_ID = 0x02
  52. local function I2C_Open(id)
  53. if i2c.setup(id, i2c.SLOW) ~= i2c.SLOW then
  54. log.error("MCP23017", "I2C.init is: fail")
  55. i2c.close(id)
  56. return
  57. else
  58. log.error("MCP23017", "I2C.init is: succeed")
  59. end
  60. return i2c.SLOW
  61. end
  62. local function I2C_Write_Byte_MCP23017(deviceAddr, regAddress,content)
  63. local i2cslaveaddr = bit.bor(DEV_ID, deviceAddr)
  64. i2c.send(I2C_ID, i2cslaveaddr, {regAddress,content})
  65. end
  66. local function I2C_Read_Byte_MCP23017(deviceAddr, regAddress)
  67. local i2cslaveaddr =bit.bor(DEV_ID, deviceAddr)
  68. i2c.send(I2C_ID, i2cslaveaddr, regAddress)
  69. return i2c.recv(I2C_ID, i2cslaveaddr, 1):byte(1)
  70. end
  71. local function MCP23017_INIT(deviceAddr,intab,hwa,port, o)
  72. local state,res;
  73. --首先设置其他位的默认状态
  74. state = 0X22; --001011 10,BANK = 0,默认不关联AB(bit = 0),禁用顺序操作,使能变化率控制、使能硬件地址,开漏输出
  75. if intab==INTA_INTB_CONJUNCTION then
  76. state = bit.bor(state,0x40) -- state |= 0x40;
  77. end
  78. if hwa==HWA_DIS then
  79. state = bit.band( state, bit.bnot(0x08)) -- state &= (~0x08);
  80. end
  81. if o==INT_PUSHPULL_HIGH then
  82. state = bit.band(state, bit.bnot(0x04)) -- state &= (~0x04);
  83. state = bit.bor(state,0x02) -- state |= 0x02;
  84. end
  85. if o==INT_PUSHPULL_LOW then
  86. state = bit.band(state, bit.bnot(0x04)) -- state &= (~0x04);
  87. state = bit.band(state, bit.bnot(0x02)) -- state &= (~0x02);
  88. end
  89. --写回方向寄存器
  90. res = I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_IOCON +port,state)
  91. return res;
  92. end
  93. local function MCP23017_IO_DIR(deviceAddr,port,pin,dir)
  94. local portState = 0x00
  95. --首先读取当前端口方向的配置状态
  96. --因为B端口的地址比A端口的寄存器的地址都是大1,所以采用+的技巧切换寄存器
  97. --portState =I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_IODIR+port);
  98. if dir==INPUT then
  99. portState = bit.bor(portState, pin) --portState |= pin;
  100. else
  101. portState = bit.band(portState, bit.bnot(pin)) --portState &= (~pin);
  102. end
  103. --写回方向寄存器
  104. I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_IODIR+port,portState)
  105. end
  106. local function MCP23017_IO_PU(deviceAddr,port,pin,pu)
  107. local portState = 0x00
  108. if pu==ENABLE then
  109. portState = bit.bor(portState,pin) -- portState |= pin;
  110. else
  111. portState = bit.band(portState, bit.bnot(pin)) --portState &= (~pin);
  112. end
  113. I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_GPPU+port,portState)
  114. end
  115. local function MCP23017_IO_INT(deviceAddr, port, pin, intKind)
  116. local portState_GPINTEN = 0 -- 中断使能寄存器
  117. local portState_DEFVAL = 0 -- 中断默认值寄存器
  118. local portState_INTCON = 0 -- 中断控制寄存器
  119. --首先读取当前配置状态
  120. --因为B端口的地址比A端口的寄存器的地址都是大1,所以采用+的技巧切换寄存器
  121. portState_GPINTEN = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_GPINTEN +port)
  122. portState_DEFVAL = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_DEFVAL +port)
  123. portState_INTCON = I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_INTCON +port)
  124. log.info("portState_GPINTEN,portState_DEFVAL,portState_INTCON", portState_GPINTEN,portState_DEFVAL,portState_INTCON)
  125. --判断中断的类型
  126. --如果是关闭中断
  127. if intKind==DIS_INTERRUPT then
  128. portState_GPINTEN = bit.band(portState_GPINTEN,bit.bnot(pin)) -- portState_GPINTEN &= (~pin);
  129. end
  130. --如果是变化中断
  131. if intKind==CHANGE_INTERRUPT then
  132. portState_GPINTEN = bit.bor(portState_GPINTEN, pin) -- portState_GPINTEN |= pin;
  133. portState_INTCON = bit.band(portState_INTCON, bit.bnot(pin)) -- portState_INTCON &= (~pin);
  134. end
  135. --如果是高电平中断
  136. if intKind==HIGHLEVEL_INTERRUPT then
  137. portState_GPINTEN = bit.bor(portState_GPINTEN, pin) -- portState_GPINTEN |= pin;
  138. portState_INTCON = bit.bor(portState_INTCON, pin) -- portState_INTCON |= pin;
  139. portState_DEFVAL = bit.band(portState_DEFVAL, bit.bnot(pin)) -- portState_DEFVAL &= (~pin);
  140. end
  141. --如果是低电平中断
  142. if intKind==LOWLEVEL_INTERRUPT then
  143. portState_GPINTEN = bit.bor(portState_GPINTEN, pin) -- portState_GPINTEN |= pin;
  144. portState_INTCON = bit.bor(portState_INTCON, pin) -- portState_INTCON |= pin;
  145. portState_DEFVAL = bit.bor(portState_DEFVAL, pin) -- portState_DEFVAL |= pin;
  146. end
  147. --写回寄存器
  148. I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_GPINTEN+port,portState_GPINTEN)
  149. I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_INTCON+port,portState_INTCON)
  150. I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_DEFVAL+port,portState_DEFVAL)
  151. end
  152. local function MCP23017_WRITE_GPIO(deviceAddr,port,val)
  153. I2C_Write_Byte_MCP23017(deviceAddr,MCP23017_GPIO+port,val)
  154. end
  155. local function MCP23017_READ_GPIO(deviceAddr,port)
  156. return I2C_Read_Byte_MCP23017(deviceAddr,MCP23017_GPIO+port)
  157. end
  158. local flag_interrupt=0
  159. pins.setup(
  160. pio.P0_13,
  161. function(msg)
  162. flag_interrupt = 1
  163. log.info("flag_interrupt, msg", flag_interrupt, msg )
  164. end,
  165. pio.PULLUP
  166. )
  167. sys.taskInit(function()
  168. sys.wait(2000)
  169. I2C_Open(I2C_ID)
  170. sys.wait(500)
  171. --16路输出初始化
  172. MCP23017_INIT(0x00,INTA_INTB_INDEPENDENT,HWA_EN, MCP23017_PORTB,INT_OD)
  173. sys.wait(100)
  174. MCP23017_IO_DIR(0x00,MCP23017_PORTB,ALLPIN,INPUT)
  175. sys.wait(50)
  176. MCP23017_IO_PU(0x00,MCP23017_PORTB,ALLPIN,ENABLE)
  177. sys.wait(50)
  178. MCP23017_IO_INT(0x00,MCP23017_PORTB,ALLPIN,CHANGE_INTERRUPT)
  179. sys.wait(2500)
  180. local val = MCP23017_READ_GPIO(0x00,MCP23017_PORTB)
  181. log.info("port B=",string.format("%02X",val))
  182. while true do
  183. --对PORT A 写入高低电平
  184. MCP23017_WRITE_GPIO(0x00,MCP23017_PORTA,0x01)
  185. log.info("set high")
  186. sys.wait(1000)
  187. log.info("set low")
  188. MCP23017_WRITE_GPIO(0x00,MCP23017_PORTA,0x00)
  189. sys.wait(1000)
  190. --读取端口的值日
  191. local val = MCP23017_READ_GPIO(0x00,MCP23017_PORTB)
  192. log.info("port B=",string.format("%02X",val))
  193. -- if flag_interrupt ==1 then
  194. -- flag_interrupt = 0
  195. -- local val = MCP23017_READ_GPIO(0x00,MCP23017_PORTB)
  196. -- log.info("port B=",string.format("%02X",val))
  197. -- else
  198. -- sys.wait(2000)
  199. -- end
  200. sys.wait(2000)
  201. end
  202. end)