Răsfoiți Sursa

change: libs,将部分扩展库变更为demolib,不再作为扩展库存在

Wendal Chen 8 luni în urmă
părinte
comite
32c5500c0c
53 a modificat fișierele cu 933 adăugiri și 933 ștergeri
  1. 0 0
      script/demolib/ads1115.lua
  2. 0 0
      script/demolib/ads1115plus.lua
  3. 0 0
      script/demolib/adxl34x.lua
  4. 0 0
      script/demolib/aht10.lua
  5. 0 0
      script/demolib/ak8963.lua
  6. 0 0
      script/demolib/aliyun.lua
  7. 0 0
      script/demolib/am2320.lua
  8. 0 0
      script/demolib/ap3216c.lua
  9. 0 0
      script/demolib/bh1750.lua
  10. 0 0
      script/demolib/bmx.lua
  11. 0 0
      script/demolib/cht8305c.lua
  12. 0 0
      script/demolib/ds3231.lua
  13. 0 0
      script/demolib/ec11.lua
  14. 0 0
      script/demolib/espblufi.lua
  15. 0 0
      script/demolib/fm17622.lua
  16. 0 0
      script/demolib/fota_wifi.lua
  17. 0 0
      script/demolib/gnss.lua
  18. 0 0
      script/demolib/gt911.lua
  19. 0 0
      script/demolib/gy53l1.lua
  20. 0 0
      script/demolib/ina226.lua
  21. 0 0
      script/demolib/joystick.lua
  22. 0 0
      script/demolib/l3g4200d.lua
  23. 0 0
      script/demolib/lis2dh12.lua
  24. 0 0
      script/demolib/lm75.lua
  25. 0 0
      script/demolib/max31856.lua
  26. 0 0
      script/demolib/mcp2515.lua
  27. 0 0
      script/demolib/mlx90614.lua
  28. 0 0
      script/demolib/modbus_rtu.lua
  29. 0 0
      script/demolib/mpu6xxx.lua
  30. 305 305
      script/demolib/necir.lua
  31. 0 0
      script/demolib/netLed.lua
  32. 0 0
      script/demolib/onenetcoap.lua
  33. 0 0
      script/demolib/openai.lua
  34. 0 0
      script/demolib/pac9685.lua
  35. 0 0
      script/demolib/pca9555.lua
  36. 0 0
      script/demolib/pca9685.lua
  37. 0 0
      script/demolib/pcf8563t.lua
  38. 0 0
      script/demolib/pcf8574.lua
  39. 0 0
      script/demolib/qmc5883l.lua
  40. 0 0
      script/demolib/rc522.lua
  41. 0 0
      script/demolib/rtkv.lua
  42. 0 0
      script/demolib/sc7a20.lua
  43. 102 102
      script/demolib/shift595.lua
  44. 0 0
      script/demolib/si24r1.lua
  45. 0 0
      script/demolib/spl06.lua
  46. 0 0
      script/demolib/tcs3472.lua
  47. 0 0
      script/demolib/tm1637.lua
  48. 225 225
      script/demolib/tm1640.lua
  49. 301 301
      script/demolib/tm1650.lua
  50. 0 0
      script/demolib/tsl2561.lua
  51. 0 0
      script/demolib/vl6180.lua
  52. 0 0
      script/demolib/ze08g_ch2o.lua
  53. 0 0
      script/demolib/zh07.lua

+ 0 - 0
script/libs/ads1115.lua → script/demolib/ads1115.lua


+ 0 - 0
script/libs/ads1115plus.lua → script/demolib/ads1115plus.lua


+ 0 - 0
script/libs/adxl34x.lua → script/demolib/adxl34x.lua


+ 0 - 0
script/libs/aht10.lua → script/demolib/aht10.lua


+ 0 - 0
script/libs/ak8963.lua → script/demolib/ak8963.lua


+ 0 - 0
script/libs/aliyun.lua → script/demolib/aliyun.lua


+ 0 - 0
script/libs/am2320.lua → script/demolib/am2320.lua


+ 0 - 0
script/libs/ap3216c.lua → script/demolib/ap3216c.lua


+ 0 - 0
script/libs/bh1750.lua → script/demolib/bh1750.lua


+ 0 - 0
script/libs/bmx.lua → script/demolib/bmx.lua


+ 0 - 0
script/libs/cht8305c.lua → script/demolib/cht8305c.lua


+ 0 - 0
script/libs/ds3231.lua → script/demolib/ds3231.lua


+ 0 - 0
script/libs/ec11.lua → script/demolib/ec11.lua


+ 0 - 0
script/libs/espblufi.lua → script/demolib/espblufi.lua


+ 0 - 0
script/libs/fm17622.lua → script/demolib/fm17622.lua


+ 0 - 0
script/libs/fota_wifi.lua → script/demolib/fota_wifi.lua


+ 0 - 0
script/libs/gnss.lua → script/demolib/gnss.lua


+ 0 - 0
script/libs/gt911.lua → script/demolib/gt911.lua


+ 0 - 0
script/libs/gy53l1.lua → script/demolib/gy53l1.lua


+ 0 - 0
script/libs/ina226.lua → script/demolib/ina226.lua


+ 0 - 0
script/libs/joystick.lua → script/demolib/joystick.lua


+ 0 - 0
script/libs/l3g4200d.lua → script/demolib/l3g4200d.lua


+ 0 - 0
script/libs/lis2dh12.lua → script/demolib/lis2dh12.lua


+ 0 - 0
script/libs/lm75.lua → script/demolib/lm75.lua


+ 0 - 0
script/libs/max31856.lua → script/demolib/max31856.lua


+ 0 - 0
script/libs/mcp2515.lua → script/demolib/mcp2515.lua


+ 0 - 0
script/libs/mlx90614.lua → script/demolib/mlx90614.lua


+ 0 - 0
script/libs/modbus_rtu.lua → script/demolib/modbus_rtu.lua


+ 0 - 0
script/libs/mpu6xxx.lua → script/demolib/mpu6xxx.lua


+ 305 - 305
script/libs/necir.lua → script/demolib/necir.lua

@@ -1,306 +1,306 @@
---[[
-@module necir
-@summary necir NEC协议红外接收
-@version 3.5
-@date    2023.09.03
-@author  lulipro
-@usage
---注意:
---1、本库在Air101和Air103测试通过,Air105由于SPI传输帧与帧之间存在间隔因此暂不支持。
---2、本库实现了NEC红外数据接收,发送请使用LuatOS底层固件自带的ir.sendNEC()函数。
---3、由于本库基于标准四线SPI接口实现,所以虽然只用到了MISO引脚,但是其他3个SPI相关引脚在使用期间
---  无法作为其他用途,除非执行necir.close()并等待necir.isClosed()为true后,SPI将完全释放,才可以用于其他用途。
---硬件模块:VS1838及其兼容的一体化接收头
---接线示意图:
---1、支持单IO模式,即仅使用一个SPI_MISO引脚,此时necir.init的irq_pin参数必须是SPI_MISO所在引脚。
---2、支持多从机,如果SPI总线上需要挂接其他从设备,为了在不使用红外通信期间,避免VS1838干扰总线的MISO,则可以用
---  一个NMOS(例如AO3400)控制VS1838的电源地,如下所示,GPIO充当VS1838的片选信号,当GPIO输出低
---  则禁用VS1838,此时VS1838不工作,其OUT引脚为高阻,不会干扰MISO;当GPIO输出高,则启用VS1838,
---  此时其OUT引脚会输出红外通信信号到单片机。由于一般的SPI从机片选逻辑为低使能,因此这样可以用
---  同一个片选GPIO来控制VS1838以及另一个SPI从机,因为片选逻辑是相反的。配合necir库的necir.close()
---  和necir.isClosed()可以最大化的复用SPI接口,避免SPI的独占而浪费。
---  ____________________                ____________________
--- |                    |    单IO      |                    |
--- |           SPI_MISO |--------------| OUT                |
--- | Air10x             |              |       VS1838       |
--- |                    |              |     一体化接收头    |
--- |               GPIO |----      ----| GND                |
--- |____________________|   |      |   |____________________| 
---                          |      |
---                          |  ____|________ 
---                          | |    D        |
---                          --| G      NMOS | 
---                            |____S________|
---                                 |
---                                GND
---用法实例:演示用同一个SPI接口驱动VS1838和W25QXX
---用法实例:
-local necir = require("necir")
-
---定义用户回调函数
-local function my_ir_cb(frameTab)
-    log.info('get ir msg','addr=',frameTab[1],frameTab[2],'data=',frameTab[3])
-end
-
-sys.taskInit(function()
-    local CS = gpio.setup(pin.PA07,0)  --VS1838(NMOS控制其GND)与W25QXX共用的片选引脚
-    necir.init(spi.SPI_0,pin.PB03,my_ir_cb)
-
-    while 1 do
-        --===============================
-        log.info('------necir start------')
-        CS(1)     --使能VS1838
-        necir.start()  --开启necir数据接收过程
-        sys.wait(10000)
-        log.info('necir request to close')
-        necir.close()   --请求关闭necir
-        while not (necir.isClosed()) do
-            sys.wait(200)
-        end
-        CS(0)    --除能VS1838
-        log.info('necir closed')
-        sys.wait(1000)
-
-        --===============================
-        log.info('------setup to read w25qxx chip id------')
-        spi.setup(spi.SPI_0,nil,
-            0,--CPHA
-            0,--CPOL
-            8,--数据宽度
-            100000,--频率
-            spi.MSB,--高低位顺序  
-            spi.master,--主模式
-            spi.full--全双工
-        )
-        --读取W25QXX chi id,0XEF15,表示芯片型号为W25Q32,0XEF16,表示芯片型号为W25Q64
-        CS(0)   --片选W25QXX
-        spi.send(spi.SPI_0,string.char(0x90)..string.char(0x00)..string.char(0x00)..string.char(0x00))
-        local chip_id = spi.recv(spi.SPI_0,2)
-        log.info('w25qxx id=',chip_id:toHex())
-        CS(1)   --取消片选W25QXX
-        sys.wait(1000)
-    end
-end)
-]]
-
-local necir = {}
-
-local sys = require "sys"
-
-local NECIR_IRQ_PIN               --上升沿中断检测引脚
-local NECIR_SPI_ID                --使用的SPI接口的ID
-local NECIR_SPI_BAUDRATE       = (14222*4)        --SPI时钟频率,单位HZ
-local NECIR_SPI_RECV_BUFF_LEN  = (32+192+192)     --SPI接收数据的长度  
-
-local recvBuff              --SPI接收数据缓冲区
-local recvNECFrame={}       --依次存储:地址码,地址码取反,数据码,数据码取反
-
-local recvCallback          --NEC报文接收成功后的用户回调函数
-local isNeedTaskFlag        --接收任务是否需要运行的标志
-local isClosedFlag          --necir是否已经完全关闭的标志
---[[
-==============实现原理================================================
-NEC协议中无论是引导信号,逻辑0还是逻辑1,都由若干个562.5us的周期组成。
-例如
-  引导信号: 16个562.5us的低电平+8个562.5us的高电平组成  
-  逻 辑 1 :1个562.5us的低电平+3个562.5us的高电平组成 
-  逻 辑 0 :1个562.5us的低电平+1个562.5us的高电平组成
-
-采样定理告诉我们,一切数字信号,都可以通过高倍速采样还原。
-我们使用SPI的MISO引脚对红外接收管的输出进行【连续采样】。
-我们使用4个SPI字节去采样一个562.5us的红外信号周期,因此SPI的时钟频率设置为 (14222*4) Hz
-则
-  引导信号: 16*4个0x00 + 8*4个0xff组成
-  逻 辑 1 :1*4个0x00 + 3*4个0xff组成,共16字节
-  逻 辑 0 :1*4个0x00 + 1*4个0xff组成 ,共8字节
-
-NEC的引导信号由一段低电平+一段高电平组成,为了降低采样深度,避免空间占用,我们选择
-从后面的高电平产生的上升沿开始进行SPI接收采样 而不是从第一个下降沿就开始。
-
-确定采样深度。NEC协议中,地址码和数据码都是连续传输2次,连续的2个字节是相互取反的关系,
-因此这2个字节的总的传输时间是固定,因为前一个字节的某个位是1,则必定后一个字节对应位是0,
-则总传输时间就是 = (逻辑1传输时间+逻辑0传输时间)* 8,
-则(地址码+ 地址码取反) 和 (数据码+数据码取反)的采样深度都是 (16+8)*8 = 192字节。
-引导码高电平部分则是8*4字节。这样我们就确定了SPI的总传输字节数= 32 + 192 + 192=416字节。
-
-理想情况下中断检测到引导码产生的上升沿就会立刻开始SPI数据采集,这样SPI传输 416 字节
-能刚好采集引导码的4.5ms高电平加后面的4字节数据,但由于LuatOS中断响应存在一定延迟,导致真正开始
-SPI采集会在引导码上升沿开始后的若干个毫秒延迟后才开始,经过测试一般延迟在1ms以内,但具体延迟取决于
-LuatOS的行为,只要这个延迟能让SPI采集到完整的引导码后面的4字节数据就都是可以接受的,即延迟不能超过
-4.5ms,一般这个情况是能满足的。
-
-本方法需要的SPI频率为56888Hz,而Air101和Air103的SPI频率 = 40MHz/(2*(div_REG+1)),
-则div_REG = 350即可实现。如果芯片的SPI无法配置频率也将不支持此方案。
-
-考虑到LuatOS中断响应存在一定延迟,导致SPI接收的信号与实际输出的信号存在一定的
-滞后导致字节错位。因此对接收到的SPI字节数据 依次向后 采用16字节长度的窗口切出子串,
-对这个子串进行模式匹配,来确定当前片段对应是NEC的逻辑1还是逻辑0。
-即:
-  在当前位置开始的后面的16个字节形成的子串中,如果存在连续的9个0xff,
-  则认为当前位置是逻辑1,否则认为是逻辑0。
-  为什什么是9个,考虑下面的情形:
-        
-逻辑1: 0x00 0x00 0x00 0x00  0xff 0xff 0xff 0xff ... 0xff 
-       [     4  个       ]  [         12 个            ]
-                           
-逻辑0: 0x00 0x00 0x00 0x00  0xff 0xff 0xff 0xff  0x00 0x00 0x00 0x00 0xff 0xff 0xff 0xff
-       [     4  个       ]  [       4 个      ]  [    下一个逻辑位(部分)               ]
-
-可以发现,如果是逻辑0,则连续的16个字节窗口中最多出现4个连续的0xff,因此可以作为区分。
-lua中的string.find()可以方便的实现字符串模式匹配,因此代码实现很简单。
-]]
-
-
---从收到的SPI数据中解析出NEC报文
-local function parseRecvData()
-    local fs,fe
-    local si
-
-    --数据重新初始化
-    recvNECFrame[1] = 0
-    recvNECFrame[2] = 0
-    recvNECFrame[3] = 0
-    recvNECFrame[4] = 0
-
-    --尝试找到第一个不是0xff出现的位置,用于跳过引导信号字节,这部分最多32字节
-    si=1
-    while si <= 32+5 do
-        if 0xff ~= string.byte(string.sub(recvBuff,si,si)) then
-            break
-        end
-        si = si + 1
-    end
-    
-    --32+5个0xff后依然没有出现地址数据,属于不正常的信号,直接退出
-    if 0xff == string.byte(string.sub(recvBuff,si,si)) then
-        return
-    end
-
-    --遍历引导信号后续的信号,整个收到的SPI数据进行NEC数据解析还原
-    while si<=NECIR_SPI_RECV_BUFF_LEN do
-
-        for k = 1, 4, 1 do  --解析出NEC报文的4个字节
-            for i = 0, 7, 1 do  --每个字节8位
-                --在当前位置开始的后面的16个字节中,如果存在连续的9个0xff的值,
-                --则认为当前位置是逻辑1
-                fs,fe = string.find(
-                    string.sub(recvBuff,si,si+16-1),
-                    '\xff\xff\xff\xff\xff\xff\xff\xff\xff'
-                )
-                if fs and fe then --找到这种模式
-                    --这个bit为1(NEC协议大小端为LSB First)
-                    recvNECFrame[k] = (recvNECFrame[k] | (1<<i))
-                    si = si + 16
-                else  --没找到这种模式
-                    --这个bit为0
-                    si = si + 8
-                end
-            end  --每个字节8位
-        end --解析出NEC报文的4个字节
-
-        break  --成功解析出4个字节后跳出循环
-
-    end --遍历整个收到的SPI数据
-
-    --对收到的红外数据进行校验并调用 用户回调函数
-    --有的遥控的2个地址字节不是相互取反的关系,因此这里不对地址码校验
-    if ((recvNECFrame[3]+recvNECFrame[4]) == 255) then
-        --log.info('necir','DataValid,go CallBack')
-        if recvCallback then recvCallback(recvNECFrame) end
-    end
-    --log.info('necir',recvNECFrame[1],recvNECFrame[2],recvNECFrame[3],recvNECFrame[4])
-end
-
-
---检测引导产生的上升沿的的中断函数
-local function irq_func()    
-    gpio.close(NECIR_IRQ_PIN)  --关闭GPIO功能,防止中断反复触发
-    spi.setup(NECIR_SPI_ID,nil,0,0,8,NECIR_SPI_BAUDRATE,spi.MSB,spi.master,spi.full)--重新打开SPI接口
-    
-    recvBuff =  spi.recv(NECIR_SPI_ID, NECIR_SPI_RECV_BUFF_LEN) --通过SPI接收红外接收头输出的解调数据
-    sys.publish('NECIR_SPI_DONE')  --发布消息,让任务对收到的SPI数据分析处理
-end
-
-
-local function recvTaskFunc()
-
-    while true do
-        sys.waitUntil('NECIR_START',5000)
-
-        while isNeedTaskFlag do
-            spi.close(NECIR_SPI_ID)  --关闭SPI接口在,这样才能把MISO空出来做中断检测
-            gpio.setup(NECIR_IRQ_PIN,irq_func,gpio.PULLUP ,gpio.RISING)--打开GPIO中断检测功能
-    
-            local result, _ = sys.waitUntil('NECIR_SPI_DONE',1000)
-            if result then  --SPI完成采集,开始解析数据
-                parseRecvData()
-            end
-        end
-        --关闭接收过程时做清理工作
-        if not isClosedFlag then
-            gpio.close(NECIR_IRQ_PIN)  --关闭GPIO功能
-            spi.close(NECIR_SPI_ID)   --关闭SPI接口
-            isClosedFlag = true
-            --log.info('necir','recv task closed')
-        end
-    end --task main loop
-end
-
---[[
-necir初始化
-@api necir.init(spi_id,irq_pin,recv_cb)
-@number spi_id,使用的SPI接口的ID
-@number irq_pin,使用的中断引脚,在单IO模式下这个引脚必须是SPI的MISO引脚
-@function recv_cb,红外数据接收完成后的回调函数,回调函数有1个table类型参数,分别存储了地址码,地址码取反,数据码,数据码取反
-@usage
-local function my_ir_cb(frameTab)
-    log.info('get ir msg','addr=',frameTab[1],frameTab[2],'data=',frameTab[3])
-end
-
-necir.init(spi.SPI_0,pin.PB03,my_ir_cb)
-]]
-function necir.init(spi_id,irq_pin,recv_cb)
-    NECIR_SPI_ID     = spi_id
-    NECIR_IRQ_PIN    = irq_pin
-    recvCallback     = recv_cb
-
-    isNeedTaskFlag = false      --接收任务是否需要运行的标志
-    isClosedFlag   = true       --necir是否已经完全关闭的标志
-    --启动红外数据接收任务
-    sys.taskInit(recvTaskFunc)
-end
-
---[[
-开启necir数据接收过程
-@api necir.start()
-@usage
-necir.start()
-]]
-function necir.start()
-    isNeedTaskFlag     = true
-    isClosedFlag       = false
-    sys.publish('NECIR_START')
-end
-
---[[
-请求关闭necir数据接收过程。此函数执行后并不能保证立刻关闭,具体是否已经关闭需要使用necir.isClosed()来查询。
-@api necir.close()
-@usage
-necir.close()
-]]
-function necir.close()
-    isNeedTaskFlag = false
-end
-
---[[
-判断necir是否已经完全关闭,关闭后所使用的SPI接口将释放,可以复用为其他功能。如需再次开启,则需要再次调用necir.start()
-@api necir.isClosed()
-@return bool   关闭成功返回true
-@usage
-necir.isClosed()
-]]
-function necir.isClosed()
-    return isClosedFlag
-end
-
+--[[
+@module necir
+@summary necir NEC协议红外接收
+@version 3.5
+@date    2023.09.03
+@author  lulipro
+@usage
+--注意:
+--1、本库在Air101和Air103测试通过,Air105由于SPI传输帧与帧之间存在间隔因此暂不支持。
+--2、本库实现了NEC红外数据接收,发送请使用LuatOS底层固件自带的ir.sendNEC()函数。
+--3、由于本库基于标准四线SPI接口实现,所以虽然只用到了MISO引脚,但是其他3个SPI相关引脚在使用期间
+--  无法作为其他用途,除非执行necir.close()并等待necir.isClosed()为true后,SPI将完全释放,才可以用于其他用途。
+--硬件模块:VS1838及其兼容的一体化接收头
+--接线示意图:
+--1、支持单IO模式,即仅使用一个SPI_MISO引脚,此时necir.init的irq_pin参数必须是SPI_MISO所在引脚。
+--2、支持多从机,如果SPI总线上需要挂接其他从设备,为了在不使用红外通信期间,避免VS1838干扰总线的MISO,则可以用
+--  一个NMOS(例如AO3400)控制VS1838的电源地,如下所示,GPIO充当VS1838的片选信号,当GPIO输出低
+--  则禁用VS1838,此时VS1838不工作,其OUT引脚为高阻,不会干扰MISO;当GPIO输出高,则启用VS1838,
+--  此时其OUT引脚会输出红外通信信号到单片机。由于一般的SPI从机片选逻辑为低使能,因此这样可以用
+--  同一个片选GPIO来控制VS1838以及另一个SPI从机,因为片选逻辑是相反的。配合necir库的necir.close()
+--  和necir.isClosed()可以最大化的复用SPI接口,避免SPI的独占而浪费。
+--  ____________________                ____________________
+-- |                    |    单IO      |                    |
+-- |           SPI_MISO |--------------| OUT                |
+-- | Air10x             |              |       VS1838       |
+-- |                    |              |     一体化接收头    |
+-- |               GPIO |----      ----| GND                |
+-- |____________________|   |      |   |____________________| 
+--                          |      |
+--                          |  ____|________ 
+--                          | |    D        |
+--                          --| G      NMOS | 
+--                            |____S________|
+--                                 |
+--                                GND
+--用法实例:演示用同一个SPI接口驱动VS1838和W25QXX
+--用法实例:
+local necir = require("necir")
+
+--定义用户回调函数
+local function my_ir_cb(frameTab)
+    log.info('get ir msg','addr=',frameTab[1],frameTab[2],'data=',frameTab[3])
+end
+
+sys.taskInit(function()
+    local CS = gpio.setup(pin.PA07,0)  --VS1838(NMOS控制其GND)与W25QXX共用的片选引脚
+    necir.init(spi.SPI_0,pin.PB03,my_ir_cb)
+
+    while 1 do
+        --===============================
+        log.info('------necir start------')
+        CS(1)     --使能VS1838
+        necir.start()  --开启necir数据接收过程
+        sys.wait(10000)
+        log.info('necir request to close')
+        necir.close()   --请求关闭necir
+        while not (necir.isClosed()) do
+            sys.wait(200)
+        end
+        CS(0)    --除能VS1838
+        log.info('necir closed')
+        sys.wait(1000)
+
+        --===============================
+        log.info('------setup to read w25qxx chip id------')
+        spi.setup(spi.SPI_0,nil,
+            0,--CPHA
+            0,--CPOL
+            8,--数据宽度
+            100000,--频率
+            spi.MSB,--高低位顺序  
+            spi.master,--主模式
+            spi.full--全双工
+        )
+        --读取W25QXX chi id,0XEF15,表示芯片型号为W25Q32,0XEF16,表示芯片型号为W25Q64
+        CS(0)   --片选W25QXX
+        spi.send(spi.SPI_0,string.char(0x90)..string.char(0x00)..string.char(0x00)..string.char(0x00))
+        local chip_id = spi.recv(spi.SPI_0,2)
+        log.info('w25qxx id=',chip_id:toHex())
+        CS(1)   --取消片选W25QXX
+        sys.wait(1000)
+    end
+end)
+]]
+
+local necir = {}
+
+local sys = require "sys"
+
+local NECIR_IRQ_PIN               --上升沿中断检测引脚
+local NECIR_SPI_ID                --使用的SPI接口的ID
+local NECIR_SPI_BAUDRATE       = (14222*4)        --SPI时钟频率,单位HZ
+local NECIR_SPI_RECV_BUFF_LEN  = (32+192+192)     --SPI接收数据的长度  
+
+local recvBuff              --SPI接收数据缓冲区
+local recvNECFrame={}       --依次存储:地址码,地址码取反,数据码,数据码取反
+
+local recvCallback          --NEC报文接收成功后的用户回调函数
+local isNeedTaskFlag        --接收任务是否需要运行的标志
+local isClosedFlag          --necir是否已经完全关闭的标志
+--[[
+==============实现原理================================================
+NEC协议中无论是引导信号,逻辑0还是逻辑1,都由若干个562.5us的周期组成。
+例如
+  引导信号: 16个562.5us的低电平+8个562.5us的高电平组成  
+  逻 辑 1 :1个562.5us的低电平+3个562.5us的高电平组成 
+  逻 辑 0 :1个562.5us的低电平+1个562.5us的高电平组成
+
+采样定理告诉我们,一切数字信号,都可以通过高倍速采样还原。
+我们使用SPI的MISO引脚对红外接收管的输出进行【连续采样】。
+我们使用4个SPI字节去采样一个562.5us的红外信号周期,因此SPI的时钟频率设置为 (14222*4) Hz
+则
+  引导信号: 16*4个0x00 + 8*4个0xff组成
+  逻 辑 1 :1*4个0x00 + 3*4个0xff组成,共16字节
+  逻 辑 0 :1*4个0x00 + 1*4个0xff组成 ,共8字节
+
+NEC的引导信号由一段低电平+一段高电平组成,为了降低采样深度,避免空间占用,我们选择
+从后面的高电平产生的上升沿开始进行SPI接收采样 而不是从第一个下降沿就开始。
+
+确定采样深度。NEC协议中,地址码和数据码都是连续传输2次,连续的2个字节是相互取反的关系,
+因此这2个字节的总的传输时间是固定,因为前一个字节的某个位是1,则必定后一个字节对应位是0,
+则总传输时间就是 = (逻辑1传输时间+逻辑0传输时间)* 8,
+则(地址码+ 地址码取反) 和 (数据码+数据码取反)的采样深度都是 (16+8)*8 = 192字节。
+引导码高电平部分则是8*4字节。这样我们就确定了SPI的总传输字节数= 32 + 192 + 192=416字节。
+
+理想情况下中断检测到引导码产生的上升沿就会立刻开始SPI数据采集,这样SPI传输 416 字节
+能刚好采集引导码的4.5ms高电平加后面的4字节数据,但由于LuatOS中断响应存在一定延迟,导致真正开始
+SPI采集会在引导码上升沿开始后的若干个毫秒延迟后才开始,经过测试一般延迟在1ms以内,但具体延迟取决于
+LuatOS的行为,只要这个延迟能让SPI采集到完整的引导码后面的4字节数据就都是可以接受的,即延迟不能超过
+4.5ms,一般这个情况是能满足的。
+
+本方法需要的SPI频率为56888Hz,而Air101和Air103的SPI频率 = 40MHz/(2*(div_REG+1)),
+则div_REG = 350即可实现。如果芯片的SPI无法配置频率也将不支持此方案。
+
+考虑到LuatOS中断响应存在一定延迟,导致SPI接收的信号与实际输出的信号存在一定的
+滞后导致字节错位。因此对接收到的SPI字节数据 依次向后 采用16字节长度的窗口切出子串,
+对这个子串进行模式匹配,来确定当前片段对应是NEC的逻辑1还是逻辑0。
+即:
+  在当前位置开始的后面的16个字节形成的子串中,如果存在连续的9个0xff,
+  则认为当前位置是逻辑1,否则认为是逻辑0。
+  为什什么是9个,考虑下面的情形:
+        
+逻辑1: 0x00 0x00 0x00 0x00  0xff 0xff 0xff 0xff ... 0xff 
+       [     4  个       ]  [         12 个            ]
+                           
+逻辑0: 0x00 0x00 0x00 0x00  0xff 0xff 0xff 0xff  0x00 0x00 0x00 0x00 0xff 0xff 0xff 0xff
+       [     4  个       ]  [       4 个      ]  [    下一个逻辑位(部分)               ]
+
+可以发现,如果是逻辑0,则连续的16个字节窗口中最多出现4个连续的0xff,因此可以作为区分。
+lua中的string.find()可以方便的实现字符串模式匹配,因此代码实现很简单。
+]]
+
+
+--从收到的SPI数据中解析出NEC报文
+local function parseRecvData()
+    local fs,fe
+    local si
+
+    --数据重新初始化
+    recvNECFrame[1] = 0
+    recvNECFrame[2] = 0
+    recvNECFrame[3] = 0
+    recvNECFrame[4] = 0
+
+    --尝试找到第一个不是0xff出现的位置,用于跳过引导信号字节,这部分最多32字节
+    si=1
+    while si <= 32+5 do
+        if 0xff ~= string.byte(string.sub(recvBuff,si,si)) then
+            break
+        end
+        si = si + 1
+    end
+    
+    --32+5个0xff后依然没有出现地址数据,属于不正常的信号,直接退出
+    if 0xff == string.byte(string.sub(recvBuff,si,si)) then
+        return
+    end
+
+    --遍历引导信号后续的信号,整个收到的SPI数据进行NEC数据解析还原
+    while si<=NECIR_SPI_RECV_BUFF_LEN do
+
+        for k = 1, 4, 1 do  --解析出NEC报文的4个字节
+            for i = 0, 7, 1 do  --每个字节8位
+                --在当前位置开始的后面的16个字节中,如果存在连续的9个0xff的值,
+                --则认为当前位置是逻辑1
+                fs,fe = string.find(
+                    string.sub(recvBuff,si,si+16-1),
+                    '\xff\xff\xff\xff\xff\xff\xff\xff\xff'
+                )
+                if fs and fe then --找到这种模式
+                    --这个bit为1(NEC协议大小端为LSB First)
+                    recvNECFrame[k] = (recvNECFrame[k] | (1<<i))
+                    si = si + 16
+                else  --没找到这种模式
+                    --这个bit为0
+                    si = si + 8
+                end
+            end  --每个字节8位
+        end --解析出NEC报文的4个字节
+
+        break  --成功解析出4个字节后跳出循环
+
+    end --遍历整个收到的SPI数据
+
+    --对收到的红外数据进行校验并调用 用户回调函数
+    --有的遥控的2个地址字节不是相互取反的关系,因此这里不对地址码校验
+    if ((recvNECFrame[3]+recvNECFrame[4]) == 255) then
+        --log.info('necir','DataValid,go CallBack')
+        if recvCallback then recvCallback(recvNECFrame) end
+    end
+    --log.info('necir',recvNECFrame[1],recvNECFrame[2],recvNECFrame[3],recvNECFrame[4])
+end
+
+
+--检测引导产生的上升沿的的中断函数
+local function irq_func()    
+    gpio.close(NECIR_IRQ_PIN)  --关闭GPIO功能,防止中断反复触发
+    spi.setup(NECIR_SPI_ID,nil,0,0,8,NECIR_SPI_BAUDRATE,spi.MSB,spi.master,spi.full)--重新打开SPI接口
+    
+    recvBuff =  spi.recv(NECIR_SPI_ID, NECIR_SPI_RECV_BUFF_LEN) --通过SPI接收红外接收头输出的解调数据
+    sys.publish('NECIR_SPI_DONE')  --发布消息,让任务对收到的SPI数据分析处理
+end
+
+
+local function recvTaskFunc()
+
+    while true do
+        sys.waitUntil('NECIR_START',5000)
+
+        while isNeedTaskFlag do
+            spi.close(NECIR_SPI_ID)  --关闭SPI接口在,这样才能把MISO空出来做中断检测
+            gpio.setup(NECIR_IRQ_PIN,irq_func,gpio.PULLUP ,gpio.RISING)--打开GPIO中断检测功能
+    
+            local result, _ = sys.waitUntil('NECIR_SPI_DONE',1000)
+            if result then  --SPI完成采集,开始解析数据
+                parseRecvData()
+            end
+        end
+        --关闭接收过程时做清理工作
+        if not isClosedFlag then
+            gpio.close(NECIR_IRQ_PIN)  --关闭GPIO功能
+            spi.close(NECIR_SPI_ID)   --关闭SPI接口
+            isClosedFlag = true
+            --log.info('necir','recv task closed')
+        end
+    end --task main loop
+end
+
+--[[
+necir初始化
+@api necir.init(spi_id,irq_pin,recv_cb)
+@number spi_id,使用的SPI接口的ID
+@number irq_pin,使用的中断引脚,在单IO模式下这个引脚必须是SPI的MISO引脚
+@function recv_cb,红外数据接收完成后的回调函数,回调函数有1个table类型参数,分别存储了地址码,地址码取反,数据码,数据码取反
+@usage
+local function my_ir_cb(frameTab)
+    log.info('get ir msg','addr=',frameTab[1],frameTab[2],'data=',frameTab[3])
+end
+
+necir.init(spi.SPI_0,pin.PB03,my_ir_cb)
+]]
+function necir.init(spi_id,irq_pin,recv_cb)
+    NECIR_SPI_ID     = spi_id
+    NECIR_IRQ_PIN    = irq_pin
+    recvCallback     = recv_cb
+
+    isNeedTaskFlag = false      --接收任务是否需要运行的标志
+    isClosedFlag   = true       --necir是否已经完全关闭的标志
+    --启动红外数据接收任务
+    sys.taskInit(recvTaskFunc)
+end
+
+--[[
+开启necir数据接收过程
+@api necir.start()
+@usage
+necir.start()
+]]
+function necir.start()
+    isNeedTaskFlag     = true
+    isClosedFlag       = false
+    sys.publish('NECIR_START')
+end
+
+--[[
+请求关闭necir数据接收过程。此函数执行后并不能保证立刻关闭,具体是否已经关闭需要使用necir.isClosed()来查询。
+@api necir.close()
+@usage
+necir.close()
+]]
+function necir.close()
+    isNeedTaskFlag = false
+end
+
+--[[
+判断necir是否已经完全关闭,关闭后所使用的SPI接口将释放,可以复用为其他功能。如需再次开启,则需要再次调用necir.start()
+@api necir.isClosed()
+@return bool   关闭成功返回true
+@usage
+necir.isClosed()
+]]
+function necir.isClosed()
+    return isClosedFlag
+end
+
 return necir

+ 0 - 0
script/libs/netLed.lua → script/demolib/netLed.lua


+ 0 - 0
script/libs/onenetcoap.lua → script/demolib/onenetcoap.lua


+ 0 - 0
script/libs/openai.lua → script/demolib/openai.lua


+ 0 - 0
script/libs/pac9685.lua → script/demolib/pac9685.lua


+ 0 - 0
script/libs/pca9555.lua → script/demolib/pca9555.lua


+ 0 - 0
script/libs/pca9685.lua → script/demolib/pca9685.lua


+ 0 - 0
script/libs/pcf8563t.lua → script/demolib/pcf8563t.lua


+ 0 - 0
script/libs/pcf8574.lua → script/demolib/pcf8574.lua


+ 0 - 0
script/libs/qmc5883l.lua → script/demolib/qmc5883l.lua


+ 0 - 0
script/libs/rc522.lua → script/demolib/rc522.lua


+ 0 - 0
script/libs/rtkv.lua → script/demolib/rtkv.lua


+ 0 - 0
script/libs/sc7a20.lua → script/demolib/sc7a20.lua


+ 102 - 102
script/libs/shift595.lua → script/demolib/shift595.lua

@@ -1,103 +1,103 @@
---[[
-@module shift595
-@summary shift595 74HC595芯片
-@version 1.0
-@date    2023.08.30
-@author  lulipro
-@usage
---注意:
---1、初始化时必须提供sclk移位时钟引脚和dat数据引脚,rclk根据应用需求可选
---2、AIR101官方核心板,底层为LuatOS-SoC_V0017_AIR101.soc,经测试此脚本库的串行时钟频率为18KHz
---用法实例:
---硬件模块:双595驱动的共阳极4位数码管
-local shift595 = require("shift595")
-sys.taskInit(function() 
-
-    shift595.init(pin.PB08,pin.PB09,pin.PB10)  -- sclk,dat,rclk
-    
-    while 1 do
-        local wei = 1
-        for i = 0, 3, 1 do
-            shift595.out(0x82,shift595.MSB)--发送段数据 ,然后是位选数据
-            shift595.out(wei,shift595.MSB)--发送段数据 ,然后是位选数据
-            shift595.latch() --锁存
-            wei = wei<<1
-            sys.wait(500)
-        end
-        sys.wait(1000)
-    end
-end
-)
-]]
-
-local shift595 = {}
-
-local sys = require "sys"
-
-shift595.MSB=0     --字节串行输出时先发送最高位
-shift595.LSB=1     --字节串行输出时先发送最低位
-
-local SHIFT595_SCLK     --串行移位时钟引脚
-local SHIFT595_DAT      --串行数据引脚
-local SHIFT595_RCLK     --锁存信号时钟引脚
-
-
---[[
-75hc595芯片初始化
-@api shift595.init(sclk,dat,rclk)
-@number sclk,定义驱动595串行时钟信号的引脚
-@number dat,定义驱动595串行数据的引脚
-@number rclk,定义驱动595锁存信号的引脚,可选
-@usage
-shift595.init(pin.PB08,pin.PB09,pin.PB10)  -- sclk,dat,rclk
-]]
-function shift595.init(sclk,dat,rclk)
-    SHIFT595_SCLK = gpio.setup(sclk, 1)
-    SHIFT595_DAT  = gpio.setup(dat, 1)
-    
-    if rclk then
-        SHIFT595_RCLK = gpio.setup(rclk, 1)
-    else
-        SHIFT595_RCLK = nil
-    end
-end
-
-
---[[
-串行输出一个字节到74hc595芯片的移位寄存器中
-@api shift595.out(dat,endian)
-@number dat,发送的字节数据
-@number endian,指定发送字节数据时的大小端模式,有shift595.MSB和shift595.LSB两种参数可选。默认shift595.MSB
-@usage
-shift595.out(0x82,shift595.MSB)
-shift595.out(0x82)  --默认shift595.MSB,与上面等价
-]]
-function shift595.out(dat,endian)
-    local mbit
-    for i = 0, 7, 1 do
-        SHIFT595_SCLK(0)
-        if endian == shift595.LSB then
-            mbit = ((dat>>i)&0x01~=0) and 1 or 0
-        else
-            mbit = ((dat<<i)&0x80~=0) and 1 or 0
-        end
-        SHIFT595_DAT(mbit)
-        SHIFT595_SCLK(1)
-    end
-end
-
-
---[[
-给74hc595芯片的RCLK线一个高脉冲,使得移位寄存器中的数据转移到锁存器中,当OE使能时,数据就输出到QA~QH引脚上。如果初始化时没用到rclk引脚则此函数调用无效。
-@api shift595.latch()
-@usage
-shift595.latch()
-]]
-function shift595.latch()
-    if SHIFT595_RCLK then
-        SHIFT595_RCLK(0)
-        SHIFT595_RCLK(1)
-    end
-end
-
+--[[
+@module shift595
+@summary shift595 74HC595芯片
+@version 1.0
+@date    2023.08.30
+@author  lulipro
+@usage
+--注意:
+--1、初始化时必须提供sclk移位时钟引脚和dat数据引脚,rclk根据应用需求可选
+--2、AIR101官方核心板,底层为LuatOS-SoC_V0017_AIR101.soc,经测试此脚本库的串行时钟频率为18KHz
+--用法实例:
+--硬件模块:双595驱动的共阳极4位数码管
+local shift595 = require("shift595")
+sys.taskInit(function() 
+
+    shift595.init(pin.PB08,pin.PB09,pin.PB10)  -- sclk,dat,rclk
+    
+    while 1 do
+        local wei = 1
+        for i = 0, 3, 1 do
+            shift595.out(0x82,shift595.MSB)--发送段数据 ,然后是位选数据
+            shift595.out(wei,shift595.MSB)--发送段数据 ,然后是位选数据
+            shift595.latch() --锁存
+            wei = wei<<1
+            sys.wait(500)
+        end
+        sys.wait(1000)
+    end
+end
+)
+]]
+
+local shift595 = {}
+
+local sys = require "sys"
+
+shift595.MSB=0     --字节串行输出时先发送最高位
+shift595.LSB=1     --字节串行输出时先发送最低位
+
+local SHIFT595_SCLK     --串行移位时钟引脚
+local SHIFT595_DAT      --串行数据引脚
+local SHIFT595_RCLK     --锁存信号时钟引脚
+
+
+--[[
+75hc595芯片初始化
+@api shift595.init(sclk,dat,rclk)
+@number sclk,定义驱动595串行时钟信号的引脚
+@number dat,定义驱动595串行数据的引脚
+@number rclk,定义驱动595锁存信号的引脚,可选
+@usage
+shift595.init(pin.PB08,pin.PB09,pin.PB10)  -- sclk,dat,rclk
+]]
+function shift595.init(sclk,dat,rclk)
+    SHIFT595_SCLK = gpio.setup(sclk, 1)
+    SHIFT595_DAT  = gpio.setup(dat, 1)
+    
+    if rclk then
+        SHIFT595_RCLK = gpio.setup(rclk, 1)
+    else
+        SHIFT595_RCLK = nil
+    end
+end
+
+
+--[[
+串行输出一个字节到74hc595芯片的移位寄存器中
+@api shift595.out(dat,endian)
+@number dat,发送的字节数据
+@number endian,指定发送字节数据时的大小端模式,有shift595.MSB和shift595.LSB两种参数可选。默认shift595.MSB
+@usage
+shift595.out(0x82,shift595.MSB)
+shift595.out(0x82)  --默认shift595.MSB,与上面等价
+]]
+function shift595.out(dat,endian)
+    local mbit
+    for i = 0, 7, 1 do
+        SHIFT595_SCLK(0)
+        if endian == shift595.LSB then
+            mbit = ((dat>>i)&0x01~=0) and 1 or 0
+        else
+            mbit = ((dat<<i)&0x80~=0) and 1 or 0
+        end
+        SHIFT595_DAT(mbit)
+        SHIFT595_SCLK(1)
+    end
+end
+
+
+--[[
+给74hc595芯片的RCLK线一个高脉冲,使得移位寄存器中的数据转移到锁存器中,当OE使能时,数据就输出到QA~QH引脚上。如果初始化时没用到rclk引脚则此函数调用无效。
+@api shift595.latch()
+@usage
+shift595.latch()
+]]
+function shift595.latch()
+    if SHIFT595_RCLK then
+        SHIFT595_RCLK(0)
+        SHIFT595_RCLK(1)
+    end
+end
+
 return shift595

+ 0 - 0
script/libs/si24r1.lua → script/demolib/si24r1.lua


+ 0 - 0
script/libs/spl06.lua → script/demolib/spl06.lua


+ 0 - 0
script/libs/tcs3472.lua → script/demolib/tcs3472.lua


+ 0 - 0
script/libs/tm1637.lua → script/demolib/tm1637.lua


+ 225 - 225
script/libs/tm1640.lua → script/demolib/tm1640.lua

@@ -1,226 +1,226 @@
---[[
-@module tm1640
-@summary tm1640 数码管和LED驱动芯片
-@version 1.0
-@date    2023.08.29
-@author  lulipro
-@usage
---注意:
---1、tm1640驱动的数码管应该选用共阴数码管
---2、tm1640也可以驱动LED,如果是LED,则应该将LED连接成共阴数码管内部相同的电路
---3、AIR101官方核心板,底层为LuatOS-SoC_V0017_AIR101.soc,经测试此脚本库的串行时钟频率为20KHz
--- 用法实例:
-local tm1640 = require("tm1640")
-
-sys.taskInit(function ()
-    --共阴段码表,0~9的数字
-    local NUM_TABLE_AX = {
-        [0]=0x3f,[1]=0x06,[2]=0x5b,[3]=0x4f,[4]=0x66,
-        [5]=0x6d,[6]=0x7d,[7]=0x07,[8]=0x7f,[9]=0x6f
-    };   
-
-    tm1640.init(pin.PB06,pin.PB07)  --clk,dat
-    
-    while 1 do
-        for i = 0, 9, 1 do
-            tm1640.setBright(tm1640.BRIGHT1)
-            for grid = tm1640.GRID1, tm1640.GRID16, 1 do
-                tm1640.sendDisplayData(grid,NUM_TABLE_AX[i])
-            end
-            sys.wait(200)
-            tm1640.setBright(tm1640.BRIGHT3)
-            sys.wait(200)
-            tm1640.setBright(tm1640.BRIGHT5)
-            sys.wait(200)
-            tm1640.setBright(tm1640.BRIGHT8)
-            sys.wait(200)
-        end
-
-        sys.wait(1000)
-
-        tm1640.setBright(tm1640.BRIGHT5)
-        for i = 0, 9, 1 do
-            tm1640.clear()
-            for grid = tm1640.GRID1, tm1640.GRID16, 1 do
-                tm1640.sendDisplayData(grid,NUM_TABLE_AX[i])
-                sys.wait(100)
-            end
-        end
-    end
-end)
-]]
-local tm1640 = {}
-
-local sys = require "sys"
-
---数码管位选常量定义
-tm1640.GRID1 = 0
-tm1640.GRID2 = 1
-tm1640.GRID3 = 2
-tm1640.GRID4 = 3
-tm1640.GRID5 = 4
-tm1640.GRID6 = 5
-tm1640.GRID7 = 6
-tm1640.GRID8 = 7
-tm1640.GRID9 = 8
-tm1640.GRID10 = 9
-tm1640.GRID11 = 10
-tm1640.GRID12 = 11
-tm1640.GRID13 = 12
-tm1640.GRID14 = 13
-tm1640.GRID15 = 14
-tm1640.GRID16 = 15
-
---八级亮度常量定义
-tm1640.BRIGHT1 = 0
-tm1640.BRIGHT2 = 1
-tm1640.BRIGHT3 = 2
-tm1640.BRIGHT4 = 3
-tm1640.BRIGHT5 = 4
-tm1640.BRIGHT6 = 5
-tm1640.BRIGHT7 = 6
-tm1640.BRIGHT8 = 7
-
-local is_display_on = 1                --显示开关标志变量
-local bright        = tm1640.BRIGHT5   --亮度级别变量
-
-local TM1640_CLK    --驱动时钟线的引脚
-local TM1640_DAT    --驱动数据线的引脚
-
-
---串行通信起始条件
-local function tm1640_strat()
-    TM1640_CLK(1)
-    TM1640_DAT(1)
-    TM1640_DAT(0)
-    TM1640_CLK(0)
-end
---串行通信结束条件
-local function tm1640_stop()
-    TM1640_CLK(0)
-    TM1640_DAT(0)
-    TM1640_CLK(1)
-    TM1640_DAT(1)
-end
-
---串行发送一个字节,LSB First
-local function tm1640_writeByte(data)
-  if data~=nil then--防止未接入数码管或者测试时接线不稳定,传来空数据导致程序运行异常
-    for i = 0, 7, 1 do
-        local mbit = (data&0x01~=0) and 1 or 0
-        TM1640_DAT(mbit)
-        TM1640_CLK(1)
-        data = data>>1
-        TM1640_CLK(0)
-        --data = data>>1 将这句话放在上面是为了尽量让时钟接近50%占空比
-    end
-  end
-end
-
-
-
---[[
-向TM1640的一个指定的位(grid)对应的显存发送指定的段数据进行显示
-@api tm1640.sendDisplayData(grid,seg_data)
-@number grid,定义位选参数,取值为tm1640.GRID1~tm1640.GRID16
-@number seg_data,定义段数据参数
-@usage
-tm1640.sendDisplayData(tm1640.GRID1,0xff)
-]]
-function tm1640.sendDisplayData(grid,seg_data)
-    if (grid >= tm1640.GRID1) and (grid <= tm1640.GRID16) then
-        tm1640_strat()
-        tm1640_writeByte(0xc0|grid)
-        tm1640_writeByte(seg_data)
-        tm1640_stop()
-    end
-end
-
---[[
-清除TM1640的所有位(grid)对应的显存数据,即全部刷写为0
-@api tm1640.clear()
-@usage
-tm1640.clear()
-]]
-function tm1640.clear()
-    for i = tm1640.GRID1, tm1640.GRID16, 1 do
-        tm1640.sendDisplayData(i,0)
-    end
-end
-
---[[
-打开TM1640的显示,此操作不影响显存中的数据
-@api tm1640.open()
-@usage
-tm1640.open()
-]]
-function tm1640.open()
-    is_display_on=1
-    tm1640_strat()
-    tm1640_writeByte(0x80|(is_display_on<<3)|(bright))
-    tm1640_stop()
-end
-
---[[
-关闭TM1640的显示,此操作不影响显存中的数据
-@api tm1640.close()
-@usage
-tm1640.close()
-]]
-function tm1640.close()
-    is_display_on=0
-    tm1640_strat()
-    tm1640_writeByte(0x80|(is_display_on<<3)|(bright))
-    tm1640_stop()
-end
-
---[[
-设置TM1640的显示亮度,此操作不影响显存中的数据
-@api tm1640.setBright(bri)
-@number 亮度参数,取值为tm1640.BRIGHT1~tm1640.BRIGHT8
-@usage
-tm1640.setBright(tm1640.BRIGHT8)
-]]
-function tm1640.setBright(bri)
-    if bri>tm1640.BRIGHT8 then bri = tm1640.BRIGHT8 end
-    if bri<tm1640.BRIGHT1 then bri = tm1640.BRIGHT1 end
-
-    bright = bri
-    tm1640_strat()
-    tm1640_writeByte(0x80|(is_display_on<<3)|(bright))
-    tm1640_stop()
-end
-
-
---[[
-TM1640的初始化
-@api tm1640.init(clk,dat,bri)
-@number clk,定义了时钟线驱动引脚
-@number dat,定义了数据线驱动引脚
-@number bri,初始亮度参数,可取的值为tm1640.BRIGHT1~tm1640.BRIGHT8。可选,默认值为tm1640.BRIGHT5。
-@usage
-tm1640.init(pin.PB06,pin.PB07)
-tm1640.init(pin.PB06,pin.PB07,tm1640.BRIGHT8)
-]]
-function tm1640.init(clk,dat,bri)
-    TM1640_CLK = gpio.setup(clk, 1)
-    TM1640_DAT = gpio.setup(dat, 1)
-
-    --设置为固定地址模式
-    tm1640_strat()
-    tm1640_writeByte(0x44)
-    tm1640_stop()
-
-    --如果设置了初始亮度
-    if bri then
-        if bri>tm1640.BRIGHT8 then bri = tm1640.BRIGHT8 end
-        if bri<tm1640.BRIGHT1 then bri = tm1640.BRIGHT1 end
-        bright = bri
-    end
-
-    tm1640.open()  --打开显示
-    tm1640.clear() --清除显存数据
-end
-
-
+--[[
+@module tm1640
+@summary tm1640 数码管和LED驱动芯片
+@version 1.0
+@date    2023.08.29
+@author  lulipro
+@usage
+--注意:
+--1、tm1640驱动的数码管应该选用共阴数码管
+--2、tm1640也可以驱动LED,如果是LED,则应该将LED连接成共阴数码管内部相同的电路
+--3、AIR101官方核心板,底层为LuatOS-SoC_V0017_AIR101.soc,经测试此脚本库的串行时钟频率为20KHz
+-- 用法实例:
+local tm1640 = require("tm1640")
+
+sys.taskInit(function ()
+    --共阴段码表,0~9的数字
+    local NUM_TABLE_AX = {
+        [0]=0x3f,[1]=0x06,[2]=0x5b,[3]=0x4f,[4]=0x66,
+        [5]=0x6d,[6]=0x7d,[7]=0x07,[8]=0x7f,[9]=0x6f
+    };   
+
+    tm1640.init(pin.PB06,pin.PB07)  --clk,dat
+    
+    while 1 do
+        for i = 0, 9, 1 do
+            tm1640.setBright(tm1640.BRIGHT1)
+            for grid = tm1640.GRID1, tm1640.GRID16, 1 do
+                tm1640.sendDisplayData(grid,NUM_TABLE_AX[i])
+            end
+            sys.wait(200)
+            tm1640.setBright(tm1640.BRIGHT3)
+            sys.wait(200)
+            tm1640.setBright(tm1640.BRIGHT5)
+            sys.wait(200)
+            tm1640.setBright(tm1640.BRIGHT8)
+            sys.wait(200)
+        end
+
+        sys.wait(1000)
+
+        tm1640.setBright(tm1640.BRIGHT5)
+        for i = 0, 9, 1 do
+            tm1640.clear()
+            for grid = tm1640.GRID1, tm1640.GRID16, 1 do
+                tm1640.sendDisplayData(grid,NUM_TABLE_AX[i])
+                sys.wait(100)
+            end
+        end
+    end
+end)
+]]
+local tm1640 = {}
+
+local sys = require "sys"
+
+--数码管位选常量定义
+tm1640.GRID1 = 0
+tm1640.GRID2 = 1
+tm1640.GRID3 = 2
+tm1640.GRID4 = 3
+tm1640.GRID5 = 4
+tm1640.GRID6 = 5
+tm1640.GRID7 = 6
+tm1640.GRID8 = 7
+tm1640.GRID9 = 8
+tm1640.GRID10 = 9
+tm1640.GRID11 = 10
+tm1640.GRID12 = 11
+tm1640.GRID13 = 12
+tm1640.GRID14 = 13
+tm1640.GRID15 = 14
+tm1640.GRID16 = 15
+
+--八级亮度常量定义
+tm1640.BRIGHT1 = 0
+tm1640.BRIGHT2 = 1
+tm1640.BRIGHT3 = 2
+tm1640.BRIGHT4 = 3
+tm1640.BRIGHT5 = 4
+tm1640.BRIGHT6 = 5
+tm1640.BRIGHT7 = 6
+tm1640.BRIGHT8 = 7
+
+local is_display_on = 1                --显示开关标志变量
+local bright        = tm1640.BRIGHT5   --亮度级别变量
+
+local TM1640_CLK    --驱动时钟线的引脚
+local TM1640_DAT    --驱动数据线的引脚
+
+
+--串行通信起始条件
+local function tm1640_strat()
+    TM1640_CLK(1)
+    TM1640_DAT(1)
+    TM1640_DAT(0)
+    TM1640_CLK(0)
+end
+--串行通信结束条件
+local function tm1640_stop()
+    TM1640_CLK(0)
+    TM1640_DAT(0)
+    TM1640_CLK(1)
+    TM1640_DAT(1)
+end
+
+--串行发送一个字节,LSB First
+local function tm1640_writeByte(data)
+  if data~=nil then--防止未接入数码管或者测试时接线不稳定,传来空数据导致程序运行异常
+    for i = 0, 7, 1 do
+        local mbit = (data&0x01~=0) and 1 or 0
+        TM1640_DAT(mbit)
+        TM1640_CLK(1)
+        data = data>>1
+        TM1640_CLK(0)
+        --data = data>>1 将这句话放在上面是为了尽量让时钟接近50%占空比
+    end
+  end
+end
+
+
+
+--[[
+向TM1640的一个指定的位(grid)对应的显存发送指定的段数据进行显示
+@api tm1640.sendDisplayData(grid,seg_data)
+@number grid,定义位选参数,取值为tm1640.GRID1~tm1640.GRID16
+@number seg_data,定义段数据参数
+@usage
+tm1640.sendDisplayData(tm1640.GRID1,0xff)
+]]
+function tm1640.sendDisplayData(grid,seg_data)
+    if (grid >= tm1640.GRID1) and (grid <= tm1640.GRID16) then
+        tm1640_strat()
+        tm1640_writeByte(0xc0|grid)
+        tm1640_writeByte(seg_data)
+        tm1640_stop()
+    end
+end
+
+--[[
+清除TM1640的所有位(grid)对应的显存数据,即全部刷写为0
+@api tm1640.clear()
+@usage
+tm1640.clear()
+]]
+function tm1640.clear()
+    for i = tm1640.GRID1, tm1640.GRID16, 1 do
+        tm1640.sendDisplayData(i,0)
+    end
+end
+
+--[[
+打开TM1640的显示,此操作不影响显存中的数据
+@api tm1640.open()
+@usage
+tm1640.open()
+]]
+function tm1640.open()
+    is_display_on=1
+    tm1640_strat()
+    tm1640_writeByte(0x80|(is_display_on<<3)|(bright))
+    tm1640_stop()
+end
+
+--[[
+关闭TM1640的显示,此操作不影响显存中的数据
+@api tm1640.close()
+@usage
+tm1640.close()
+]]
+function tm1640.close()
+    is_display_on=0
+    tm1640_strat()
+    tm1640_writeByte(0x80|(is_display_on<<3)|(bright))
+    tm1640_stop()
+end
+
+--[[
+设置TM1640的显示亮度,此操作不影响显存中的数据
+@api tm1640.setBright(bri)
+@number 亮度参数,取值为tm1640.BRIGHT1~tm1640.BRIGHT8
+@usage
+tm1640.setBright(tm1640.BRIGHT8)
+]]
+function tm1640.setBright(bri)
+    if bri>tm1640.BRIGHT8 then bri = tm1640.BRIGHT8 end
+    if bri<tm1640.BRIGHT1 then bri = tm1640.BRIGHT1 end
+
+    bright = bri
+    tm1640_strat()
+    tm1640_writeByte(0x80|(is_display_on<<3)|(bright))
+    tm1640_stop()
+end
+
+
+--[[
+TM1640的初始化
+@api tm1640.init(clk,dat,bri)
+@number clk,定义了时钟线驱动引脚
+@number dat,定义了数据线驱动引脚
+@number bri,初始亮度参数,可取的值为tm1640.BRIGHT1~tm1640.BRIGHT8。可选,默认值为tm1640.BRIGHT5。
+@usage
+tm1640.init(pin.PB06,pin.PB07)
+tm1640.init(pin.PB06,pin.PB07,tm1640.BRIGHT8)
+]]
+function tm1640.init(clk,dat,bri)
+    TM1640_CLK = gpio.setup(clk, 1)
+    TM1640_DAT = gpio.setup(dat, 1)
+
+    --设置为固定地址模式
+    tm1640_strat()
+    tm1640_writeByte(0x44)
+    tm1640_stop()
+
+    --如果设置了初始亮度
+    if bri then
+        if bri>tm1640.BRIGHT8 then bri = tm1640.BRIGHT8 end
+        if bri<tm1640.BRIGHT1 then bri = tm1640.BRIGHT1 end
+        bright = bri
+    end
+
+    tm1640.open()  --打开显示
+    tm1640.clear() --清除显存数据
+end
+
+
 return tm1640

+ 301 - 301
script/libs/tm1650.lua → script/demolib/tm1650.lua

@@ -1,302 +1,302 @@
-
---[[
-@module tm1650
-@summary tm1650 数码管和按键扫描芯片
-@version 1.0
-@date    2023.09.07
-@author  lulipro
-@usage
---注意:
---1、tm1650驱动的数码管应该选用共阴数码管
---2、tm1650也可以驱动LED,如果是LED,则应该将LED连接成共阴数码管内部相同的电路
---3、支持按键扫描,此模式下tm1650的DP/KP引脚为中断输出引脚
---=========按键扫描例子==========
-local function tm1650_kcb(key_code)
-    log.info('tm1650 user cb,key code=',string.format("%02X",key_code))
-end
-sys.taskInit(function()
-    tm1650.init(pin.PB06,pin.PB07,tm1650.MODE_KEY_INPUT,pin.PB08,tm1650_kcb)
-    while 1 do
-        sys.wait(2000)
-    end
-end)
---==========数码管显示例子===========
-sys.taskInit(function()
-    --共阴段码表,0~9的数字
-    local NUM_TABLE_AX = {
-        [0]=0x3f,[1]=0x06,[2]=0x5b,[3]=0x4f,[4]=0x66,
-        [5]=0x6d,[6]=0x7d,[7]=0x07,[8]=0x7f,[9]=0x6f
-    };   
-    tm1650.init(pin.PB06,pin.PB07,tm1650.MODE_LED_OUTPUT)
-    while 1 do
-        for i = tm1650.DIG1, tm1650.DIG4, 1 do
-            tm1650.print(i,NUM_TABLE_AX[6])
-            sys.wait(500)
-        end
-        sys.wait(1000)
-        for i = tm1650.BRIGHT1, tm1650.BRIGHT8, 1 do
-            tm1650.setBright(i)
-            sys.wait(500)
-        end
-        for i = 1, 8, 1 do
-            sys.wait(500)
-            tm1650.close()    
-            sys.wait(500)
-            tm1650.open()
-        end
-        sys.wait(2000)
-        tm1650.clear()
-    end
-end)
-]]
-
-local tm1650 = {}
-
-local sys = require "sys"
-
---数码管位选定义
-tm1650.DIG1 = 0
-tm1650.DIG2 = 1
-tm1650.DIG3 = 2
-tm1650.DIG4 = 3
-
---八级亮度常量定义
-tm1650.BRIGHT1 = 1
-tm1650.BRIGHT2 = 2
-tm1650.BRIGHT3 = 3
-tm1650.BRIGHT4 = 4
-tm1650.BRIGHT5 = 5
-tm1650.BRIGHT6 = 6
-tm1650.BRIGHT7 = 7
-tm1650.BRIGHT8 = 8   --第8级亮度时寄存器二进制位为000
-
-
---工作模式定义
-tm1650.MODE_LED_OUTPUT = 0x71   --数码管LED驱动模式(7级亮度,8段模式,打开显示)
-tm1650.MODE_KEY_INPUT  = 0x79   --按键扫描模式
-
-
-
-local TM1650_SCL
-local TM1650_SDA
-local TM1650_SDA_PIN      --SDA引脚
-local TM1650_IRQ_PIN      --按键检测使用的中断引脚号
-local TM1650_KEY_CALLBACK --按键回调函数
-
-local bright          = tm1650.BRIGHT7   --亮度变量
-local is_display_on   = 1                --显示开关标志变量
-
-local function tm1650_writeReg(reg,value)
-    local dat
-    local mbit
-    --=====start========
-    TM1650_SCL(1)
-    TM1650_SDA(1)
-    TM1650_SDA(0)
-    TM1650_SCL(0)
-
-    --======写寄存器地址==========
-    dat = reg
-    for i = 0, 7, 1 do
-        TM1650_SCL(0)
-        mbit = (((dat<<i)&0x80) ~= 0) and 1 or 0
-        TM1650_SDA(mbit)
-        TM1650_SCL(1)
-        TM1650_SCL(0)
-    end
-    TM1650_SDA(1)  --释放 SDA
-    TM1650_SCL(0)
-    TM1650_SCL(1)
-    TM1650_SCL(0)
-
-    --======写数据==========
-    dat = value
-    for i = 0, 7, 1 do
-        TM1650_SCL(0)
-        mbit = (((dat<<i)&0x80) ~= 0) and 1 or 0
-        TM1650_SDA(mbit)
-        TM1650_SCL(1)
-        TM1650_SCL(0)
-    end
-    TM1650_SDA(1)  --释放 SDA
-    TM1650_SCL(0)
-    TM1650_SCL(1)
-    TM1650_SCL(0)
-
-    --=======stop=======
-    TM1650_SCL(0)
-    TM1650_SDA(0)
-    TM1650_SCL(1)
-    TM1650_SDA(1)
-end
-
-
-local function tm1650_readReg(reg)
-    local dat
-    local mbit
-    --=====start========
-    TM1650_SCL(1)
-    TM1650_SDA(1)
-    TM1650_SDA(0)
-    TM1650_SCL(0)
-
-    --======写寄存器地址==========
-    dat = reg
-    for i = 0, 7, 1 do
-        TM1650_SCL(0)
-        mbit = (((dat<<i)&0x80) ~= 0) and 1 or 0
-        TM1650_SDA(mbit)
-        TM1650_SCL(1)
-        TM1650_SCL(0)
-    end
-    TM1650_SDA(1)  --释放 SDA
-    TM1650_SCL(0)
-    TM1650_SCL(1)
-    TM1650_SCL(0)
-
-    --=======读数据=========
-    dat = 0
-    gpio.setup(TM1650_SDA_PIN,nil,gpio.PULLUP)  --SDA输入模式
-    for i = 0, 7, 1 do
-        TM1650_SCL(0)
-        dat = (dat << 1)
-        TM1650_SCL(1)
-        if gpio.HIGH ==  gpio.get(TM1650_SDA_PIN) then
-            dat = ( dat | 0x01)
-        end 
-        TM1650_SCL(0)
-    end
-
-    TM1650_SCL(0)
-    TM1650_SCL(1)
-    TM1650_SCL(0)
-
-    TM1650_SDA = gpio.setup(TM1650_SDA_PIN,1)  --SDA重新设置为输出模式
-    --=======stop=======
-    TM1650_SCL(0)
-    TM1650_SDA(0)
-    TM1650_SCL(1)
-    TM1650_SDA(1)
-
-    return dat
-end
-
-
---[[
-TM1650初始化,根据mode参数可以设置为数码管显示或者按键扫描模式
-@api tm1650.init(scl_pin,sda_pin,mode,irq_pin,key_cb)
-@number scl_pin,定义了时钟线驱动引脚
-@number sda_pin,定义了数据线驱动引脚
-@number mode,定义了工作模式,tm1650.MODE_LED_OUTPUT,数码管LED驱动模式;tm1650.MODE_KEY_INPUT,按键检测模式
-@number irq_pin,定义按键中断引脚
-@function key_cb,按键用户回调函数,此函数有一个number类型参数,为按下的按键的按键代码
-@usage
-tm1650.init(pin.PB06,pin.PB07,tm1650.MODE_LED_OUTPUT) --数码管显示模式
-tm1650.init(pin.PB06,pin.PB07,tm1650.MODE_KEY_INPUT,pin.PB08,tm1650_kcb)  --按键扫描模式
-]]
-function tm1650.init(scl_pin,sda_pin,mode,irq_pin,key_cb)
-
-    TM1650_SCL =  gpio.setup(scl_pin, 1)
-    TM1650_SDA =  gpio.setup(sda_pin, 1)
-    TM1650_SDA_PIN = sda_pin
-
-    if mode == tm1650.MODE_KEY_INPUT then
-        TM1650_IRQ_PIN      = irq_pin
-        TM1650_KEY_CALLBACK = key_cb
-
-        --配置为按键扫描模式
-        tm1650_writeReg(0x48,tm1650.MODE_KEY_INPUT)
-
-        gpio.setup(
-            TM1650_IRQ_PIN,       --中断gpio编号
-            function (val)        --中断处理函数,下降沿触发时
-                local key_code = tm1650_readReg(0x49)  --读按键代码
-                if TM1650_KEY_CALLBACK then
-                    TM1650_KEY_CALLBACK(key_code)
-                end
-                --log.info('tm1650 key get',string.format("%02X",key_code))   --输出按键值
-            end,
-            gpio.PULLUP,    --启用上拉
-            gpio.FALLING   --下降沿触发
-        )
-    else
-        --配置为数码管LED驱动模式,7级亮度,打开显示
-        tm1650_writeReg(0x48,tm1650.MODE_LED_OUTPUT)
-        tm1650.clear()
-    end
-
-end
-
---[[
-设置TM1650的显示亮度,此操作不影响显存中的数据
-@api tm1650.setBright(bri)
-@number 亮度参数,取值为tm1650.BRIGHT1~tm1650.BRIGHT8
-@usage
-tm1650.setBright(tm1650.BRIGHT8)
-]]
-function tm1650.setBright(bri)
-    if bri>tm1650.BRIGHT8 then bri = tm1650.BRIGHT8 end
-    if bri<tm1650.BRIGHT1 then bri = tm1650.BRIGHT1 end
-    bright = bri
-
-    local bright_bits = bright
-    if bright == tm1650.BRIGHT8 then bright_bits=0 end  --亮度8的寄存器二进制为000
-    
-    tm1650_writeReg(0x48,((bright_bits<<4)|is_display_on))
-end
-
---[[
-打开TM1650的显示,此操作不影响显存中的数据
-@api tm1650.open()
-@usage
-tm1650.open()
-]]
-function tm1650.open()
-    local bright_bits = bright
-    if bright == tm1650.BRIGHT8 then bright_bits=0 end  --亮度8的寄存器二进制为000
-    is_display_on=1
-
-    tm1650_writeReg(0x48,((bright_bits<<4)|is_display_on))
-end
-
---[[
-关闭TM1650的显示,此操作不影响显存中的数据
-@api tm1650.close()
-@usage
-tm1650.close()
-]]
-function tm1650.close()
-    local bright_bits = bright
-    if bright == tm1650.BRIGHT8 then bright_bits=0 end  --亮度8的寄存器二进制为000
-    is_display_on=0
-
-    tm1650_writeReg(0x48,((bright_bits<<4)|is_display_on))
-end
-
---[[
-向TM1650的一个指定的位对应的显存发送指定的段数据进行显示
-@api tm1650.print(dig,seg_data)
-@number dig,定义位选参数,取值为tm1650.DIG1~tm1650.DIG4
-@number seg_data,定义段数据参数
-@usage
-tm1650.print(tm1650.DIG1,0x3f)
-]]
-function tm1650.print(dig,seg_data)
-    if (dig>=tm1650.DIG1) and (dig<=tm1650.DIG4) then
-        tm1650_writeReg(dig*2+0x68,seg_data)
-    end
-end
-
---[[
-清除TM1650的所有位对应的显存数据,即全部刷写为0
-@api tm1650.clear()
-@usage
-tm1650.clear()
-]]
-function tm1650.clear()
-    for i = tm1650.DIG1, tm1650.DIG4, 1 do
-        tm1650.print(i,0)
-    end
-end
-
+
+--[[
+@module tm1650
+@summary tm1650 数码管和按键扫描芯片
+@version 1.0
+@date    2023.09.07
+@author  lulipro
+@usage
+--注意:
+--1、tm1650驱动的数码管应该选用共阴数码管
+--2、tm1650也可以驱动LED,如果是LED,则应该将LED连接成共阴数码管内部相同的电路
+--3、支持按键扫描,此模式下tm1650的DP/KP引脚为中断输出引脚
+--=========按键扫描例子==========
+local function tm1650_kcb(key_code)
+    log.info('tm1650 user cb,key code=',string.format("%02X",key_code))
+end
+sys.taskInit(function()
+    tm1650.init(pin.PB06,pin.PB07,tm1650.MODE_KEY_INPUT,pin.PB08,tm1650_kcb)
+    while 1 do
+        sys.wait(2000)
+    end
+end)
+--==========数码管显示例子===========
+sys.taskInit(function()
+    --共阴段码表,0~9的数字
+    local NUM_TABLE_AX = {
+        [0]=0x3f,[1]=0x06,[2]=0x5b,[3]=0x4f,[4]=0x66,
+        [5]=0x6d,[6]=0x7d,[7]=0x07,[8]=0x7f,[9]=0x6f
+    };   
+    tm1650.init(pin.PB06,pin.PB07,tm1650.MODE_LED_OUTPUT)
+    while 1 do
+        for i = tm1650.DIG1, tm1650.DIG4, 1 do
+            tm1650.print(i,NUM_TABLE_AX[6])
+            sys.wait(500)
+        end
+        sys.wait(1000)
+        for i = tm1650.BRIGHT1, tm1650.BRIGHT8, 1 do
+            tm1650.setBright(i)
+            sys.wait(500)
+        end
+        for i = 1, 8, 1 do
+            sys.wait(500)
+            tm1650.close()    
+            sys.wait(500)
+            tm1650.open()
+        end
+        sys.wait(2000)
+        tm1650.clear()
+    end
+end)
+]]
+
+local tm1650 = {}
+
+local sys = require "sys"
+
+--数码管位选定义
+tm1650.DIG1 = 0
+tm1650.DIG2 = 1
+tm1650.DIG3 = 2
+tm1650.DIG4 = 3
+
+--八级亮度常量定义
+tm1650.BRIGHT1 = 1
+tm1650.BRIGHT2 = 2
+tm1650.BRIGHT3 = 3
+tm1650.BRIGHT4 = 4
+tm1650.BRIGHT5 = 5
+tm1650.BRIGHT6 = 6
+tm1650.BRIGHT7 = 7
+tm1650.BRIGHT8 = 8   --第8级亮度时寄存器二进制位为000
+
+
+--工作模式定义
+tm1650.MODE_LED_OUTPUT = 0x71   --数码管LED驱动模式(7级亮度,8段模式,打开显示)
+tm1650.MODE_KEY_INPUT  = 0x79   --按键扫描模式
+
+
+
+local TM1650_SCL
+local TM1650_SDA
+local TM1650_SDA_PIN      --SDA引脚
+local TM1650_IRQ_PIN      --按键检测使用的中断引脚号
+local TM1650_KEY_CALLBACK --按键回调函数
+
+local bright          = tm1650.BRIGHT7   --亮度变量
+local is_display_on   = 1                --显示开关标志变量
+
+local function tm1650_writeReg(reg,value)
+    local dat
+    local mbit
+    --=====start========
+    TM1650_SCL(1)
+    TM1650_SDA(1)
+    TM1650_SDA(0)
+    TM1650_SCL(0)
+
+    --======写寄存器地址==========
+    dat = reg
+    for i = 0, 7, 1 do
+        TM1650_SCL(0)
+        mbit = (((dat<<i)&0x80) ~= 0) and 1 or 0
+        TM1650_SDA(mbit)
+        TM1650_SCL(1)
+        TM1650_SCL(0)
+    end
+    TM1650_SDA(1)  --释放 SDA
+    TM1650_SCL(0)
+    TM1650_SCL(1)
+    TM1650_SCL(0)
+
+    --======写数据==========
+    dat = value
+    for i = 0, 7, 1 do
+        TM1650_SCL(0)
+        mbit = (((dat<<i)&0x80) ~= 0) and 1 or 0
+        TM1650_SDA(mbit)
+        TM1650_SCL(1)
+        TM1650_SCL(0)
+    end
+    TM1650_SDA(1)  --释放 SDA
+    TM1650_SCL(0)
+    TM1650_SCL(1)
+    TM1650_SCL(0)
+
+    --=======stop=======
+    TM1650_SCL(0)
+    TM1650_SDA(0)
+    TM1650_SCL(1)
+    TM1650_SDA(1)
+end
+
+
+local function tm1650_readReg(reg)
+    local dat
+    local mbit
+    --=====start========
+    TM1650_SCL(1)
+    TM1650_SDA(1)
+    TM1650_SDA(0)
+    TM1650_SCL(0)
+
+    --======写寄存器地址==========
+    dat = reg
+    for i = 0, 7, 1 do
+        TM1650_SCL(0)
+        mbit = (((dat<<i)&0x80) ~= 0) and 1 or 0
+        TM1650_SDA(mbit)
+        TM1650_SCL(1)
+        TM1650_SCL(0)
+    end
+    TM1650_SDA(1)  --释放 SDA
+    TM1650_SCL(0)
+    TM1650_SCL(1)
+    TM1650_SCL(0)
+
+    --=======读数据=========
+    dat = 0
+    gpio.setup(TM1650_SDA_PIN,nil,gpio.PULLUP)  --SDA输入模式
+    for i = 0, 7, 1 do
+        TM1650_SCL(0)
+        dat = (dat << 1)
+        TM1650_SCL(1)
+        if gpio.HIGH ==  gpio.get(TM1650_SDA_PIN) then
+            dat = ( dat | 0x01)
+        end 
+        TM1650_SCL(0)
+    end
+
+    TM1650_SCL(0)
+    TM1650_SCL(1)
+    TM1650_SCL(0)
+
+    TM1650_SDA = gpio.setup(TM1650_SDA_PIN,1)  --SDA重新设置为输出模式
+    --=======stop=======
+    TM1650_SCL(0)
+    TM1650_SDA(0)
+    TM1650_SCL(1)
+    TM1650_SDA(1)
+
+    return dat
+end
+
+
+--[[
+TM1650初始化,根据mode参数可以设置为数码管显示或者按键扫描模式
+@api tm1650.init(scl_pin,sda_pin,mode,irq_pin,key_cb)
+@number scl_pin,定义了时钟线驱动引脚
+@number sda_pin,定义了数据线驱动引脚
+@number mode,定义了工作模式,tm1650.MODE_LED_OUTPUT,数码管LED驱动模式;tm1650.MODE_KEY_INPUT,按键检测模式
+@number irq_pin,定义按键中断引脚
+@function key_cb,按键用户回调函数,此函数有一个number类型参数,为按下的按键的按键代码
+@usage
+tm1650.init(pin.PB06,pin.PB07,tm1650.MODE_LED_OUTPUT) --数码管显示模式
+tm1650.init(pin.PB06,pin.PB07,tm1650.MODE_KEY_INPUT,pin.PB08,tm1650_kcb)  --按键扫描模式
+]]
+function tm1650.init(scl_pin,sda_pin,mode,irq_pin,key_cb)
+
+    TM1650_SCL =  gpio.setup(scl_pin, 1)
+    TM1650_SDA =  gpio.setup(sda_pin, 1)
+    TM1650_SDA_PIN = sda_pin
+
+    if mode == tm1650.MODE_KEY_INPUT then
+        TM1650_IRQ_PIN      = irq_pin
+        TM1650_KEY_CALLBACK = key_cb
+
+        --配置为按键扫描模式
+        tm1650_writeReg(0x48,tm1650.MODE_KEY_INPUT)
+
+        gpio.setup(
+            TM1650_IRQ_PIN,       --中断gpio编号
+            function (val)        --中断处理函数,下降沿触发时
+                local key_code = tm1650_readReg(0x49)  --读按键代码
+                if TM1650_KEY_CALLBACK then
+                    TM1650_KEY_CALLBACK(key_code)
+                end
+                --log.info('tm1650 key get',string.format("%02X",key_code))   --输出按键值
+            end,
+            gpio.PULLUP,    --启用上拉
+            gpio.FALLING   --下降沿触发
+        )
+    else
+        --配置为数码管LED驱动模式,7级亮度,打开显示
+        tm1650_writeReg(0x48,tm1650.MODE_LED_OUTPUT)
+        tm1650.clear()
+    end
+
+end
+
+--[[
+设置TM1650的显示亮度,此操作不影响显存中的数据
+@api tm1650.setBright(bri)
+@number 亮度参数,取值为tm1650.BRIGHT1~tm1650.BRIGHT8
+@usage
+tm1650.setBright(tm1650.BRIGHT8)
+]]
+function tm1650.setBright(bri)
+    if bri>tm1650.BRIGHT8 then bri = tm1650.BRIGHT8 end
+    if bri<tm1650.BRIGHT1 then bri = tm1650.BRIGHT1 end
+    bright = bri
+
+    local bright_bits = bright
+    if bright == tm1650.BRIGHT8 then bright_bits=0 end  --亮度8的寄存器二进制为000
+    
+    tm1650_writeReg(0x48,((bright_bits<<4)|is_display_on))
+end
+
+--[[
+打开TM1650的显示,此操作不影响显存中的数据
+@api tm1650.open()
+@usage
+tm1650.open()
+]]
+function tm1650.open()
+    local bright_bits = bright
+    if bright == tm1650.BRIGHT8 then bright_bits=0 end  --亮度8的寄存器二进制为000
+    is_display_on=1
+
+    tm1650_writeReg(0x48,((bright_bits<<4)|is_display_on))
+end
+
+--[[
+关闭TM1650的显示,此操作不影响显存中的数据
+@api tm1650.close()
+@usage
+tm1650.close()
+]]
+function tm1650.close()
+    local bright_bits = bright
+    if bright == tm1650.BRIGHT8 then bright_bits=0 end  --亮度8的寄存器二进制为000
+    is_display_on=0
+
+    tm1650_writeReg(0x48,((bright_bits<<4)|is_display_on))
+end
+
+--[[
+向TM1650的一个指定的位对应的显存发送指定的段数据进行显示
+@api tm1650.print(dig,seg_data)
+@number dig,定义位选参数,取值为tm1650.DIG1~tm1650.DIG4
+@number seg_data,定义段数据参数
+@usage
+tm1650.print(tm1650.DIG1,0x3f)
+]]
+function tm1650.print(dig,seg_data)
+    if (dig>=tm1650.DIG1) and (dig<=tm1650.DIG4) then
+        tm1650_writeReg(dig*2+0x68,seg_data)
+    end
+end
+
+--[[
+清除TM1650的所有位对应的显存数据,即全部刷写为0
+@api tm1650.clear()
+@usage
+tm1650.clear()
+]]
+function tm1650.clear()
+    for i = tm1650.DIG1, tm1650.DIG4, 1 do
+        tm1650.print(i,0)
+    end
+end
+
 return tm1650

+ 0 - 0
script/libs/tsl2561.lua → script/demolib/tsl2561.lua


+ 0 - 0
script/libs/vl6180.lua → script/demolib/vl6180.lua


+ 0 - 0
script/libs/ze08g_ch2o.lua → script/demolib/ze08g_ch2o.lua


+ 0 - 0
script/libs/zh07.lua → script/demolib/zh07.lua