mcp23008.lua 8.3 KB

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