Quellcode durchsuchen

Merge branch 'master' of https://gitee.com/openLuat/LuatOS

alienwalker vor 4 Monaten
Ursprung
Commit
dacf0192b9
88 geänderte Dateien mit 4203 neuen und 1431 gelöschten Zeilen
  1. 0 69
      .github/workflows/air780.yml
  2. 0 29
      .github/workflows/air780ci_notify.yml
  3. 33 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/agpio_task.lua
  4. 0 38
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/agpio_test.lua
  5. 37 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_input_task.lua
  6. 0 43
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_input_test.lua
  7. 0 36
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_irq_count_test.lua
  8. 57 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_irq_task.lua
  9. 0 32
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_irq_test.lua
  10. 29 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_irqcount_task.lua
  11. 34 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_output_task.lua
  12. 0 41
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_output_test.lua
  13. 32 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_pull_task.lua
  14. 0 40
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_pullupdown_test.lua
  15. 33 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_toggle_task.lua
  16. 0 36
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_toggle_test.lua
  17. 31 30
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/main.lua
  18. 111 41
      module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/readme.md
  19. 104 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/iperf/iperf_client.lua
  20. 87 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/iperf/iperf_server.lua
  21. 67 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/iperf/main.lua
  22. 136 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/iperf/readme.md
  23. 57 112
      module/Air780EHM_Air780EHV_Air780EGH/demo/mobile/main.lua
  24. 114 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/mobile/mobile_test.lua
  25. 103 0
      module/Air780EHM_Air780EHV_Air780EGH/demo/mobile/readme.md
  26. 0 37
      module/Air780EPM/demo/gpio/AGPIO/main.lua
  27. 0 39
      module/Air780EPM/demo/gpio/GPIO上拉下拉模式/main.lua
  28. 0 27
      module/Air780EPM/demo/gpio/GPIO中断(触发)模式/main.lua
  29. 0 34
      module/Air780EPM/demo/gpio/GPIO中断(计数)模式/main.lua
  30. 0 34
      module/Air780EPM/demo/gpio/GPIO翻转测速/main.lua
  31. 0 41
      module/Air780EPM/demo/gpio/GPIO输入模式/main.lua
  32. 0 37
      module/Air780EPM/demo/gpio/GPIO输出模式/main.lua
  33. 33 0
      module/Air780EPM/demo/gpio/agpio_task.lua
  34. 41 0
      module/Air780EPM/demo/gpio/gpio_input_task.lua
  35. 57 0
      module/Air780EPM/demo/gpio/gpio_irq_task.lua
  36. 29 0
      module/Air780EPM/demo/gpio/gpio_irqcount_task.lua
  37. 35 0
      module/Air780EPM/demo/gpio/gpio_output_task.lua
  38. 32 0
      module/Air780EPM/demo/gpio/gpio_pull_task.lua
  39. 33 0
      module/Air780EPM/demo/gpio/gpio_toggle_task.lua
  40. 84 0
      module/Air780EPM/demo/gpio/main.lua
  41. 131 0
      module/Air780EPM/demo/gpio/readme.md
  42. 104 0
      module/Air780EPM/demo/iperf/iperf_client.lua
  43. 87 0
      module/Air780EPM/demo/iperf/iperf_server.lua
  44. 67 0
      module/Air780EPM/demo/iperf/main.lua
  45. 115 0
      module/Air780EPM/demo/iperf/readme.md
  46. 57 112
      module/Air780EPM/demo/mobile/main.lua
  47. 114 0
      module/Air780EPM/demo/mobile/mobile_test.lua
  48. 97 0
      module/Air780EPM/demo/mobile/readme.md
  49. 0 37
      module/Air8000/demo/gpio/AGPIO/main.lua
  50. 0 39
      module/Air8000/demo/gpio/GPIO上拉下拉模式/main.lua
  51. 0 30
      module/Air8000/demo/gpio/GPIO中断(触发)模式/main.lua
  52. 0 34
      module/Air8000/demo/gpio/GPIO中断(计数)模式/main.lua
  53. 0 34
      module/Air8000/demo/gpio/GPIO翻转测速/main.lua
  54. 0 41
      module/Air8000/demo/gpio/GPIO输入模式/main.lua
  55. 0 37
      module/Air8000/demo/gpio/GPIO输出模式/main.lua
  56. 33 0
      module/Air8000/demo/gpio/agpio_task.lua
  57. 41 0
      module/Air8000/demo/gpio/gpio_input_task.lua
  58. 57 0
      module/Air8000/demo/gpio/gpio_irq_task.lua
  59. 29 0
      module/Air8000/demo/gpio/gpio_irqcount_task.lua
  60. 35 0
      module/Air8000/demo/gpio/gpio_output_task.lua
  61. 32 0
      module/Air8000/demo/gpio/gpio_pull_task.lua
  62. 33 0
      module/Air8000/demo/gpio/gpio_toggle_task.lua
  63. 84 0
      module/Air8000/demo/gpio/main.lua
  64. 0 50
      module/Air8000/demo/gpio/power_on/main.lua
  65. 130 0
      module/Air8000/demo/gpio/readme.md
  66. 104 0
      module/Air8000/demo/iperf/iperf_client.lua
  67. 87 0
      module/Air8000/demo/iperf/iperf_server.lua
  68. 67 0
      module/Air8000/demo/iperf/main.lua
  69. 115 0
      module/Air8000/demo/iperf/readme.md
  70. 61 112
      module/Air8000/demo/mobile/main.lua
  71. 114 0
      module/Air8000/demo/mobile/mobile_test.lua
  72. 97 0
      module/Air8000/demo/mobile/readme.md
  73. 0 39
      module/Air8101/demo/gpio/GPIO中断模式/main.lua
  74. 0 35
      module/Air8101/demo/gpio/GPIO输入模式/main.lua
  75. 0 35
      module/Air8101/demo/gpio/GPIO输出模式/main.lua
  76. 37 0
      module/Air8101/demo/gpio/gpio_input_task.lua
  77. 57 0
      module/Air8101/demo/gpio/gpio_irq_task.lua
  78. 29 0
      module/Air8101/demo/gpio/gpio_irqcount_task.lua
  79. 34 0
      module/Air8101/demo/gpio/gpio_output_task.lua
  80. 32 0
      module/Air8101/demo/gpio/gpio_pull_task.lua
  81. 33 0
      module/Air8101/demo/gpio/gpio_toggle_task.lua
  82. 84 0
      module/Air8101/demo/gpio/main.lua
  83. 123 0
      module/Air8101/demo/gpio/readme.md
  84. 94 0
      module/Air8101/demo/iperf/iperf_client.lua
  85. 76 0
      module/Air8101/demo/iperf/iperf_server.lua
  86. 67 0
      module/Air8101/demo/iperf/main.lua
  87. 102 0
      module/Air8101/demo/iperf/netdrv_eth_spi.lua
  88. 135 0
      module/Air8101/demo/iperf/readme.md

+ 0 - 69
.github/workflows/air780.yml

@@ -1,69 +0,0 @@
-name: air780
-
-on:
-  push:
-    paths:
-      - '.github/workflows/air780.yml'
-      - 'lua/**'
-      - 'luat/**'
-      - 'components/**'
-      - 'bsp/air780/**'
-  workflow_dispatch:
-  repository_dispatch:
-    types:
-      - webhook-780-action
-
-jobs:
-  build:
-    runs-on: ubuntu-20.04
-    steps:
-    - uses: actions/checkout@v1
-    - name: prepare software
-      run: |
-        sudo apt-get update
-        sudo apt-get install git gcc-multilib libc6 libgcc1 libstdc++5 libstdc++6 libsdl-dev p7zip-full -y
-        sudo apt-get install libncurses5-dev -y
-        sudo add-apt-repository ppa:xmake-io/xmake -y
-        sudo apt install xmake -y
-    - name: clone 780
-      run: |
-        sudo sh -c "curl https://raw.githubusercontent.com/kadwanev/retry/master/retry -o /usr/local/bin/retry && chmod +x /usr/local/bin/retry"
-        cd ..
-        git clone https://github.com/openLuat/luatos-soc-2022.git air780
-        cd air780
-        git remote add gitee https://gitee.com/openLuat/luatos-soc-2022.git
-        retry 'git pull gitee master'
-        git checkout gitee/master
-    - name: make
-      run: |
-        cd ../air780
-        sed -i 's/os.exec(cmd)/if 1 then return end/g' xmake.lua
-        export PROJECT_NAME="luatos"
-        export LSPD_MODE=enable
-        mkdir /home/runner/toolchains
-        wget -q https://github.com/openLuat/LuatOS/releases/download/v0.0.1/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 -O /home/runner/toolchains/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
-        xmake g --pkg_searchdirs=/home/runner/toolchains
-        xmake -y
-        mkdir ../LuatOS/luatosfw
-        mv out/luatos/* ../LuatOS/luatosfw
-    - name: Upload artifact
-      uses: actions/upload-artifact@v4
-      with:
-        name: air780
-        path: luatosfw
-    - name: report if failure
-      if: always()
-      env:
-        STATUS: ${{ job.status }}
-        MQTTADDR: ${{ secrets.MQTTADDR }}
-        MQTTPORT: ${{ secrets.MQTTPORT }}
-        MQTTTOPIC: ${{ secrets.MQTTTOPIC }}
-        DD_APPKEY: ${{ secrets.DD_APPKEY }}
-        DD_APPSECRET: ${{ secrets.DD_APPSECRET }}
-        DD_NOTIFY_LIST: ${{ secrets.DD_NOTIFY_LIST }}
-        DD_API_TOKEN: ${{ secrets.DD_API_TOKEN }}
-        DD_API_SEND: ${{ secrets.DD_API_SEND }}
-      run: |
-        sudo pip3 install paho_mqtt gitpython requests
-        cd tools
-        if [ "$STATUS" = "failure" ];then python3 ciNotify.py $MQTTADDR $MQTTPORT $MQTTTOPIC "https://github.com/openLuat/LuatOS/actions/runs/$GITHUB_RUN_ID" "air780" "$DD_APPKEY" "$DD_APPSECRET" "$DD_NOTIFY_LIST" "$DD_API_TOKEN" "$DD_API_SEND"; fi

+ 0 - 29
.github/workflows/air780ci_notify.yml

@@ -1,29 +0,0 @@
-name: air780ci_notify
-
-on:
-  workflow_dispatch:
-  repository_dispatch:
-    types:
-      - webhook_air780ci_notify
-
-jobs:
-  build:
-    runs-on: ubuntu-20.04
-    steps:
-    - uses: actions/checkout@v1
-    - name: report if failure
-      if: always()
-      env:
-        STATUS: ${{ job.status }}
-        MQTTADDR: ${{ secrets.MQTTADDR }}
-        MQTTPORT: ${{ secrets.MQTTPORT }}
-        MQTTTOPIC: ${{ secrets.MQTTTOPIC }}
-        DD_APPKEY: ${{ secrets.DD_APPKEY }}
-        DD_APPSECRET: ${{ secrets.DD_APPSECRET }}
-        DD_NOTIFY_LIST: ${{ secrets.DD_NOTIFY_LIST }}
-        DD_API_TOKEN: ${{ secrets.DD_API_TOKEN }}
-        DD_API_SEND: ${{ secrets.DD_API_SEND }}
-      run: |
-        sudo pip3 install paho_mqtt gitpython requests
-        cd tools
-        python3 ciNotify.py $MQTTADDR $MQTTPORT $MQTTTOPIC "http://luat.papapoi.com:23380/openLuat/luatos-soc-2022" "Air780编译" "$DD_APPKEY" "$DD_APPSECRET" "$DD_NOTIFY_LIST" "$DD_API_TOKEN" "$DD_API_SEND"

+ 33 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/agpio_task.lua

@@ -0,0 +1,33 @@
+--[[
+@module  agpio_task
+@summary agpio功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 AGPIO 功能的代码示例,核心业务逻辑为:
+AGPIO与普通GPIO在PSM+模式下的区别演示
+1. 初始化普通GPIO和AGPIO
+   - 配置普通GPIO1为输出模式并设置为高电平
+   - 配置AGPIO26为输出模式并设置为高电平
+2. 等待一段时间让GPIO状态稳定
+3. 关闭USB电源以降低功耗
+4. 进入深度休眠模式(PSM+模式),此时RAM 掉电,唤醒后程序从初始状态运行。
+5. 观察结果:通过示波器或逻辑分析仪等设备观察进入PSM+模式后普通GPIO为掉电状态,而AGPIO保持了休眠前的电平状态
+]]
+
+local gpio_number = 1   -- 普通GPIO GPIO号为1,休眠后掉电。
+local Agpio_number = 26 -- AGPIO GPIO号为26,休眠后可保持电平。
+
+gpio.setup(gpio_number, 1)
+gpio.setup(Agpio_number, 1)
+
+local function enterlowpower()
+    sys.wait(10000)
+    -- 关闭USB电源
+    pm.power(pm.USB, false)
+    -- 进入PSM+模式
+    pm.power(pm.WORK_MODE, 3)
+end
+
+sys.taskInit(enterlowpower)

+ 0 - 38
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/agpio_test.lua

@@ -1,38 +0,0 @@
---[[
-@module  agpio_test
-@summary AGPIO测试模块
-@version 1.0
-@date    2025.07.01
-@author  Jensen
-@usage
-使用Air780EGH核心板测试对比AGPIO和普通GPIO进入休眠模式前后的区别
-本测试需测量核心板功耗,将板载USB旁边的开关拨到off一端,
-供电需通过Vbat外接合宙IOTpower或Air9000功耗分析仪的3.8V输出
-]]
-
--- 定义AGPIO端口: GPIO27
-local agpio_number = 27
--- 定义普通GPIO端口: GPIO01
-local normal_gpio_number = 1
-
-function test_agpio_func()
-
-    -- 配置AGPIO为输出模式,初始输出高电平
-    gpio.setup(agpio_number, 1)
-    -- 配置普通GPIO为输出模式,初始输出高电平
-    gpio.setup(normal_gpio_number, 1)
-    
-    sys.wait(16000)
-    -- 上电模式工作运行16s后关闭USB电源
-    pm.power(pm.USB, false)
-    -- 进入低功耗模式
-    pm.power(pm.WORK_MODE, 3)
-
-
-    -- 之后按rst键重新复位系统测试
-end
-
-
---创建并且启动一个task
---运行这个task的主函数 test_agpio_func
-sys.taskInit(test_agpio_func)

+ 37 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_input_task.lua

@@ -0,0 +1,37 @@
+--[[
+@module  gpio_input_task
+@summary GPIO输入检测与LED联动示例
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为GPIO输入检测功能的代码示例,核心业务逻辑为:
+1. 初始化GPIO24为输入模式(可用杜邦线接稳压电源,高电平接3.3V,低电平接地)
+2. 初始化GPIO26为输出模式,默认高电平(亮)
+3. 启用输入消抖,消抖时间50 ms
+4. 每500 ms读取一次GPIO24电平,并同步控制LED亮灭
+5. 高电平→LED亮,低电平→LED灭
+]]
+
+-- 配置gpio24为输入模式
+-- 配置GPIO26为输出模式
+local inputpin = 24
+local ledpin = 26
+
+local input = gpio.setup(inputpin, nil, gpio.PULLDOWN)
+local led = gpio.setup(ledpin, 1)
+
+gpio.debounce(inputpin, 50)
+--GPIO24检测到有高低电平输入后,会返回GPIO24当前获取到的电平为高还是低,高返回值为1,低返回值为0
+--将这个返回值,传给GPIO26,为0 则GPIO26输出低电平,为1则输出高电平
+local function controlgpio()
+    local level = 0
+    while true do
+        level = gpio.get(inputpin)
+        log.info("gpio","set netled level: ",level)
+        gpio.set(ledpin, level)
+        sys.wait(500)
+    end
+end
+
+sys.taskInit(controlgpio)

+ 0 - 43
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_input_test.lua

@@ -1,43 +0,0 @@
---[[
-@module  gpio_input_test
-@summary GPIO输出测试模块
-@version 1.0
-@date    2025.07.01
-@author  Jensen
-@usage
-使用Air780EGH核心板测试GPIO输入功能,主要流程为获取指定IO口的输入电平,根据高电平状态,点亮外接LED灯;根据低电平状态,熄灭外接LED灯
-]]
-
--- 配置外接LED灯的GPIO端口
-local led_io_number = 27
-
--- 配置输入检测的GPIO端口
-local input_io_numble = 24
-
-function test_gpio_input_func()
-
-    local input_level
-    -- 配置LED GPIO为推挽输出模式,第二参数1表示初始为输出高电平
-    gpio.setup(led_io_number, 1)
-    -- 配置输入检测的GPIO为输入模式, 第二参数nil表示输入模式,第三参数nil表示浮空输入(未检测到电平时 电平状态不确定)
-    gpio.setup(input_io_numble, nil, nil)
-    -- 配置输入IO防抖动参数:50ms
-    gpio.debounce(input_io_numble, 50)
-    
-    while 1 do
-        -- 获取IO电平,并打印
-        input_level = gpio.get(input_io_numble) 
-        log.info("GPIO", "input level", input_level)
-        
-        -- 根据获取的电平来设置LED
-        gpio.set(led_io_number, input_level)
-        
-        -- 延时500ms,循环上面的流程
-        sys.wait(500)
-    end
-end
-
-
---创建并且启动一个task
---运行这个task的主函数 test_gpio_input_func
-sys.taskInit(test_gpio_input_func)

+ 0 - 36
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_irq_count_test.lua

@@ -1,36 +0,0 @@
---[[
-@module  gpio_irq_test
-@summary GPIO中断计数测试模块
-@version 1.0
-@date    2025.07.01
-@author  Jensen
-@usage
-使用Air780EGH核心板测试GPIO中断计数功能,主要流程为配置指定PIN脚IO输出1KHz占空比50%的方波波形作为中断信号原,
-通过杜邦线连接到使能中断计数的IO管脚,定时统计中断触发的次数。
-]]
-
-
--- 配置GPIO中断检测端口
-local irq_io_number = 24
-
-function test_gpio_irq_count_func()
-
-    -- PIN引脚16,配置PWM4输出波形,并作为信号源将其通过杜邦线连接到PIN引脚20(GPIO24)
-    -- 第一参数表示PWM channel4,第二参数表示频率为1000Hz,第三参数表示占空比为50%
-    pwm.open(4,1000,50)
-
-    -- 配置GPIO为中断计数模式, 第二参数为gpio.count表示中断计数模式,
-    gpio.setup(irq_io_number, gpio.count)
-    
-    --每隔1S统计一次中断触发的次数
-    while true do
-        sys.wait(1000)
-        log.info("irq cnt", gpio.count(irq_io_number))
-    end
-    
-end
-
-
---创建并且启动一个task
---运行这个task的主函数 test_gpio_irq_count_func
-sys.taskInit(test_gpio_irq_count_func)

+ 57 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_irq_task.lua

@@ -0,0 +1,57 @@
+--[[
+@module  gpio_irq_task
+@summary GPIO中断功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 GPIO 按键短按和长按检测的代码示例,核心业务逻辑为:
+1. 配置GPIO24为中断模式,上升沿和下降沿均触发
+2. 实现按键短按(小于3秒)和长按(大于等于3秒)的检测功能
+3. 可连接按键或直接用杜邦线轻触GND进行测试
+4. 注意:使用杜邦线测试时,因为脉冲可能无法控制,所以不要加防抖防止程序测试异常
+]]
+
+-- 配置gpio24为中断模式,上升沿(gpio.RISING)和下降沿(gpio.FALLING)均触发(gpio.BOTH)
+local gpio_pin = 24
+-- gpio.debounce(gpio_pin, 100) -- 实际设计板子时,根据自己的需求可以更改防抖配置以及打开防抖
+
+-- 按键状态变量
+local long_press_threshold = 3000  -- 长按判断阈值,3秒
+local current_state = 1  -- 跟踪当前按键状态,1为释放,0为按下
+
+-- 定时器回调函数,处理长按事件
+local function timer_callback(gpio_id)
+    log.info("按键检测", "长按事件", gpio_id)
+end
+
+-- 定义GPIO中断处理函数
+local function gpio_irq_handler()
+    local pin_state = gpio.get(gpio_pin)  -- 获取GPIO当前状态
+    
+    -- 只有当状态发生变化时才处理
+    if pin_state ~= current_state then
+        current_state = pin_state  -- 更新当前状态
+        
+        if pin_state == 0 then
+            -- 按键按下
+            log.info("按键检测", "按键按下")
+            if not sys.timerIsActive(timer_callback, gpio_pin) then
+                -- 启动定时器,3秒后触发长按事件
+                sys.timerStart(timer_callback, long_press_threshold, gpio_pin)
+            end
+        elseif pin_state == 1 then
+            -- 按键释放
+            log.info("按键检测", "按键释放")
+            
+            -- 如果定时器还在运行,说明是短按
+            if sys.timerIsActive(timer_callback, gpio_pin) then
+                sys.timerStop(timer_callback, gpio_pin)
+                log.info("按键检测", "短按事件")
+            end
+        end
+    end
+end
+
+-- 配置GPIO中断
+gpio.setup(gpio_pin, gpio_irq_handler, gpio.PULLUP, gpio.BOTH)

+ 0 - 32
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_irq_test.lua

@@ -1,32 +0,0 @@
---[[
-@module  gpio_irq_test
-@summary GPIO中断测试模块
-@version 1.0
-@date    2025.07.01
-@author  Jensen
-@usage
-使用Air780EGH核心板测试GPIO中断功能,主要流程为配置指定IO的触发模式,IO被触发时输出调试信息
-]]
-
-
--- 配置GPIO中断检测端口
-local irq_io_number = 24
-
-function io_irq_handler(level, io_number)
-    log.info("gpio", io_number, "被触发", "level=", level)
-end
-
-function test_gpio_irq_func()
-
-    -- 配置GPIO为中断模式, 第二参数为function表示中断模式,
-    -- 第三参数表示内部上拉输入,第四参数表示下降沿触发中断
-    gpio.setup(irq_io_number, io_irq_handler, gpio.PULLUP, gpio.FALLING)
-    -- 配置输入IO防抖动参数:100ms
-    gpio.debounce(irq_io_number, 100)
-    
-end
-
-
---创建并且启动一个task
---运行这个task的主函数 test_gpio_irq_func
-sys.taskInit(test_gpio_irq_func)

+ 29 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_irqcount_task.lua

@@ -0,0 +1,29 @@
+--[[
+@module  gpio_irqcount_task
+@summary GPIO中断计数功能
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为GPIO中断计数功能的代码示例,核心业务逻辑为:
+1. 配置GPIO24为中断计数模式,用于统计外部信号触发次数
+2. 每1秒读取并打印一次中断触发次数
+3. 可用杜邦线轻触3.3V电源正极,即可观察中断触发效果。
+]]
+
+-- 配置gpio24为中断计数模式
+-- 设置好后系统会自动记录中断触发次数。
+local gpio_pin = 24
+-- gpio.setup(gpio_pin, gpio.count, gpio.PULLUP, gpio.FALLING)
+gpio.setup(gpio_pin, gpio.count)
+
+-- 每隔1S统计一次中断触发的次数
+local function countIrq()
+    while true do
+        sys.wait(1000)
+        -- 返回从上次调用该函数后到当前时刻的中断触发次数
+        log.info("irq cnt", gpio.count(gpio_pin)) -- 调用函数时会自动清空中断累计值
+    end
+end
+
+sys.taskInit(countIrq)

+ 34 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_output_task.lua

@@ -0,0 +1,34 @@
+--[[
+@module  gpio_output_task
+@summary GPIO输出功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 GPIO 输出功能的代码示例,核心业务逻辑为:
+通过GPIO26输出高低电平,可用万用表测量验证
+1. 初始化GPIO26为输出模式
+2. 在任务循环中周期性地拉高/拉低GPIO26
+3. 通过1000ms间隔切换电平,便于万用表观察
+]]
+
+local gpio_number = 26
+
+gpio.setup(gpio_number, 1) -- 设置GPIO26为输出模式
+
+local function controlgpio_task()
+    -- 开始演示GPIO输出功能
+    local count = 0
+    while 1 do
+        gpio.set(gpio_number, 1)
+        log.info("GPIO", "当前IO26电平设置为高",count)
+        sys.wait(1000)
+        gpio.set(gpio_number, 0)
+        log.info("GPIO", "当前IO26电平设置为低")
+        sys.wait(1000)
+        count = count + 1
+    end
+end
+
+-- 执行任务函数
+sys.taskInit(controlgpio_task)

+ 0 - 41
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_output_test.lua

@@ -1,41 +0,0 @@
---[[
-@module  gpio_output_test
-@summary GPIO输出测试模块
-@version 1.0
-@date    2025.07.01
-@author  Jensen
-@usage
-使用Air780EGH核心板测试GPIO输出功能,主要流程为指定IO口外接LED灯,500ms输出高电平点亮LED,500ms输出低电平熄灭LED,循环执行这个流程
-]]
-
--- 配置外接LED灯的GPIO端口
-local led_io_number = 27
-
-function test_gpio_output_func()
-    -- 定义运行计数器
-    local count = 0
-    
-    -- 配置GPIO为输出模式
-    gpio.setup(led_io_number, 1)
-    
-    while 1 do
-        -- 打印运行计数
-        log.info("GPIO", "Go Go Go", count, rtos.bsp())
-        
-        -- 点亮500ms
-        gpio.set(led_io_number, 1)
-        sys.wait(500)
-        
-        -- 熄灭500ms
-        gpio.set(led_io_number, 0)
-        sys.wait(500)
-        
-        -- 运行计数器累计加1
-        count = count + 1
-    end
-end
-
-
---创建并且启动一个task
---运行这个task的主函数 test_gpio_output_func
-sys.taskInit(test_gpio_output_func)

+ 32 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_pull_task.lua

@@ -0,0 +1,32 @@
+--[[
+@module  gpio_pull_task
+@summary GPIO上下拉功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 GPIO 上下拉功能的代码示例,核心业务逻辑为:
+1. 配置GPIO2为上拉输入模式
+2. 配置GPIO26为下拉输入模式
+3. 定时读取并打印两个GPIO的电平状态
+4. 将GPIO2和GPIO26引脚接地或接3.3V来控制GPIO2和GPIO26的电平变化,验证上拉/下拉配置是否生效
+]]
+
+local gpio_pin1 = 2
+local gpio_pin2 = 26
+-- 按键防抖函数
+gpio.debounce(gpio_pin1, 50)
+gpio.debounce(gpio_pin2, 50)
+
+-- 设置GPIO2引脚为上拉输入模式
+gpio.setup(gpio_pin1, nil, gpio.PULLUP)
+
+-- 设置GPIO26引脚为下拉输入模式
+gpio.setup(gpio_pin2, nil, gpio.PULLDOWN)
+
+local function gpiopulltask()
+    log.info("GPIO",gpio_pin1,"电平",gpio.get(gpio_pin1))
+    log.info("GPIO",gpio_pin2,"电平",gpio.get(gpio_pin2))
+end
+
+sys.timerLoopStart(gpiopulltask,1000)

+ 0 - 40
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_pullupdown_test.lua

@@ -1,40 +0,0 @@
---[[
-@module  gpio_pullupdown_test
-@summary GPIO输入的上拉下拉测试模块
-@version 1.0
-@date    2025.07.01
-@author  Jensen
-@usage
-使用Air780EGH核心板测试GPIO输入模式上拉和下拉模式的电平状态
-]]
-
--- 定义输入上拉模式的端口GPIO7
-local gpio_pullup_number = 7
--- 定义输入下拉模式的端口GPIO27
-local gpio_pulldown_number = 27
-
-function test_gpio_pullupdown_func()
-
-    -- 设置GPIO输入上拉模式
-    gpio.setup(gpio_pullup_number, nil, gpio.PULLUP)
-    -- 配置输入检测防抖50ms
-    gpio.debounce(gpio_pullup_number, 50)
-
-    -- 设置GPIO输入下拉模式
-    gpio.setup(gpio_pulldown_number, nil, gpio.PULLDOWN)
-    -- 配置输入检测防抖50ms
-    gpio.debounce(gpio_pulldown_number, 50)
-    
-    while 1 do
-        -- 打印获取端口当前的电平状态
-        log.info("GPIO",gpio_pullup_number,"电平",gpio.get(gpio_pullup_number))
-        log.info("GPIO",gpio_pulldown_number,"电平",gpio.get(gpio_pulldown_number))
-       
-        sys.wait(1000)
-    end
-end
-
-
---创建并且启动一个task
---运行这个task的主函数 test_gpio_pullupdown_func
-sys.taskInit(test_gpio_pullupdown_func)

+ 33 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_toggle_task.lua

@@ -0,0 +1,33 @@
+--[[
+@module  gpio_toggle
+@summary 波形翻转功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 GPIO 翻转(脉冲)输出的代码示例,核心业务逻辑为:
+GPIO 快速翻转测速与波形观测
+1. 配置 GPIO26 为输出模式并上拉初始化;
+2. 在任务中循环调用 gpio.pulse() 按给定模式输出脉冲序列;
+   - 演示模式为 0xA9(二进制 10101001),每次输出 8 组电平变化;
+3. 使用示波器或逻辑分析仪连接到 GPIO26,观察翻转波形与频率,翻转一次所需时间大概 50ns;
+4. 可根据需要修改 `test_gpio_number`、`0xA9`(翻转模式)和 `8`(组数),以测试不同引脚和模式;
+5. 注意:高频翻转请勿直接驱动重负载,推荐用于逻辑检测或带限流的 LED 演示。
+]]
+
+local test_gpio_number = 26
+
+gpio.setup(test_gpio_number, 0, gpio.PULLUP)
+
+local function gpiotoggletask()
+    sys.wait(100)
+    while true do
+        sys.wait(100)
+        -- 通过GPIO26脚输出输出8组电平变化
+        -- 0xA9就是输出的电平高低状态,即 10101001
+        gpio.pulse(test_gpio_number, 0xA9, 8, 0)
+        log.info("gpio----------->pulse")
+    end
+end
+
+sys.taskInit(gpiotoggletask)

+ 0 - 36
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/gpio_toggle_test.lua

@@ -1,36 +0,0 @@
---[[
-@module  gpio_toggle_test
-@summary GPIO翻转测试模块
-@version 1.0
-@date    2025.07.01
-@author  Jensen
-@usage
-使用Air780EGH核心板测试GPIO的IO翻转时间,通过gpio.pulse输出指定脉冲变化的波形,使用示波器或逻辑分析仪来测量脉冲电平翻转的时间
-]]
-
--- 配置输出pulse的GPIO端口
-local pulse_io_number = 27
-
-function test_gpio_toggle_func()
-
-    -- 配置GPIO为输出模式,初始输出低电平
-    gpio.setup(pulse_io_number, 0)
-    
-    while 1 do
-        -- 通过测试的GPIO27 输出指定的脉冲信号
-        -- 结合脉冲高低变化可以评估IO翻转时间,使用示波器或逻辑分析仪来测量电平翻转的时间
-        -- 第三参数表示输出8组电平变化,每组1或0表示高和低电平
-        -- 第二参数0xA9就是输出的电平高低状态,即 10101001
-        -- 第四参数表示每个电平的延时保持时间,0代表无延时
-        gpio.pulse(pulse_io_number, 0xA9, 8, 0)
-        
-        -- 打印运行打印信息
-        log.info("gpio----------->pulse")
-        sys.wait(100)
-    end
-end
-
-
---创建并且启动一个task
---运行这个task的主函数 test_gpio_toggle_func
-sys.taskInit(test_gpio_toggle_func)

+ 31 - 30
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/main.lua

@@ -2,12 +2,16 @@
 @module  main
 @summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
 @version 1.0
-@date    2025.07.01
-@author  Jensen
+@date    2025.10.21
+@author  拓毅恒
 @usage
-本demo演示的功能为:
-实现使用Air780EGH完成GPIO相关功能测试,包括GPIO的输入输出,中断检测/中断计数,翻转速度,上下拉测试与AGPIO测试
+本demo演示的核心功能为:
+演示GPIO的多种功能模式,包括输出模式、输入模式、上拉下拉模式、中断触发模式、中断计数模式、AGPIO低功耗模式以及GPIO翻转测速功能。
+用户可通过取消注释相应的require语句来启用不同的功能模块进行测试。
+
+更多说明参考本目录下的readme.md文件
 ]]
+
 --[[
 必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
 PROJECT:项目名,ascii string类型
@@ -17,17 +21,19 @@ VERSION:项目版本号,ascii string类型
             X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
             因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
         如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
-
-
 ]]
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "GPIO_TEST"
+PROJECT = "GPIO_testdemo"
 VERSION = "001.000.000"
 
---添加硬狗防止程序卡死
+log.info("main", "project name is ", PROJECT, "version is ", VERSION)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
 if wdt then
-    wdt.init(9000)--初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
 end
 
 -- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
@@ -38,13 +44,11 @@ end
 --     errDump.config(true, 600)
 -- end
 
-
 -- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
 -- 可以使用合宙的iot.openluat.com平台进行远程升级
 -- 也可以使用客户自己搭建的平台进行远程升级
 -- 远程升级的详细用法,可以参考fota的demo进行使用
 
-
 -- 启动一个循环定时器
 -- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
 -- 方便分析内存使用是否有异常
@@ -53,29 +57,26 @@ end
 --     log.info("mem.sys", rtos.meminfo("sys"))
 -- end, 3000)
 
+-- 加载 gpio 输出功能模块
+require "gpio_output_task"
 
--- 以下GPIO测试模块,测试时一次加载一个测试模块
-
---GPIO输出测试
-require "gpio_output_test"
-
---GPIO输入测试
---require "gpio_input_test"
+-- 加载 gpio  输入功能模块
+-- require "gpio_input_task"
 
---GPIO中断输入测试
---require "gpio_irq_test"
+-- 加载 gpio 上下拉功能模块
+-- require "gpio_pull_task"
 
---GPIO中断计数测试
---require "gpio_irq_count_test"
+-- 加载 gpio 中断功能模块
+-- require "gpio_irq_task"
 
---GPIO翻转速度测试
---require "gpio_toggle_test"
+-- 加载 gpio 中断计数功能模块
+-- require "gpio_irqcount_task"
 
---GPIO上拉下拉测试
---require "gpio_pullupdown_test"
+-- 加载 agpio 功能模块
+-- require "agpio_task"
 
---AGPIO测试
---require "agpio_test"
+-- 加载 gpio 翻转功能模块
+-- require "gpio_toggle_task"
 
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句

+ 111 - 41
module/Air780EHM_Air780EHV_Air780EGH/demo/gpio/readme.md

@@ -1,67 +1,137 @@
+## 功能模块介绍
 
-## 演示功能概述
+1、main.lua:主程序入口,负责初始化系统并启动各个GPIO功能任务;
 
-本demo使用Air780EGH核心板,演示GPIO接口功能测试,包括GPIO的输入输出,中断检测/中断计数,翻转速度,上下拉测试与AGPIO测试
+2、gpio_output_task.lua:GPIO输出模式功能模块,演示GPIO输出控制方法;
 
-## 演示硬件环境
+3、gpio_input_task.lua:GPIO输入模式功能模块,演示GPIO输入读取方法;
 
-1、Air780EHM核心板一块,TYPE-C USB数据线一根
+4、gpio_pull_task.lua:GPIO上拉下拉模式功能模块,演示GPIO上拉下拉配置;
 
-2、LED模块一个,独立按键模块一个,杜邦线若干
+5、gpio_irq_task.lua:GPIO中断(触发)模式功能模块,演示GPIO中断触发、回调处理及按键短按长按检测;
 
-3、合宙IOTpower 或 Air9000功耗分析仪 一台
+6、gpio_irqcount_task.lua:GPIO中断(计数)模式功能模块,演示GPIO中断计数功能;
 
-4、逻辑分析仪 或 示波器 一台
+7、agpio_task.lua:AGPIO功能模块,演示低功耗GPIO在休眠模式下的特性;
 
-5、万用表一台
+8、gpio_toggle_task.lua:GPIO翻转测速功能模块,演示GPIO脉冲输出功能;
 
-4、不同测试的引脚硬件连接介绍
 
-1)GPIO输出测试(gpio_output_test):(PIN16)GPIO27 外接LED模块
 
-2)GPIO输入测试(gpio_input_test): (PIN16)GPIO27 外接LED模块, (PIN20)GPIO24 杜邦线连接电源3.3V或GND
+## 演示功能概述
 
-3)GPIO中断输入测试(gpio_irq_test): (PIN20)GPIO24 杜邦线连接电源3.3V或GND
+1、gpio_output_task:GPIO输出模式功能演示
+- 配置GPIO26为输出模式,通过GPIO26输出高低电平
+- 可使用万用表测量验证GPIO26的电平变化
+- 以1000ms间隔切换电平状态,便于观察
+- 演示gpio.setup的输出模式配置和状态控制方法
+
+2、gpio_input_task:GPIO输入模式功能演示
+- 配置GPIO24为输入模式,配置GPIO26为输出模式
+- 实现输入信号读取,并将读取到的电平状态同步控制GPIO26
+- 演示gpio.debounce防抖功能的使用
+- 展示如何通过输入GPIO的状态控制输出GPIO
+
+3、gpio_pull_task:GPIO上拉下拉模式功能演示
+- 配置GPIO2为上拉输入模式,GPIO26为下拉输入模式
+- 演示gpio.debounce防抖功能在不同上下拉模式下的应用
+- 通过定时任务周期性读取并打印GPIO的当前电平状态
+- 展示如何使用gpio.get函数获取GPIO的实时状态
+
+4、gpio_irq_task:GPIO中断(触发)模式功能演示
+- 配置GPIO24为中断模式,支持上升沿和下降沿触发(双边沿触发)
+- 实现中断触发时的回调函数,打印触发信息
+- 演示gpio.debounce防抖功能在中断模式下的应用
+- 实现按键短按(小于3秒)和长按(大于等于3秒)的检测功能
+- 可连接按键或直接用杜邦线轻触GND进行测试
+
+5、gpio_irqcount_task:GPIO中断(计数)模式功能演示
+- 配置GPIO24为中断计数模式,用于统计信号触发次数
+- 配置PWM4输出1kHz、占空比50%的方波作为计数信号源
+- 实现周期性(1秒)统计和打印中断触发次数
+- 展示gpio.count函数在计数模式下的使用方法
+
+6、agpio_task:AGPIO功能演示
+- 演示普通GPIO和AGPIO在进入休眠模式前后的区别
+- 普通GPIO(GPIO1)在休眠后会掉电,而AGPIO(GPIO26)可保持电平状态
+- 演示如何通过pm.power控制系统进入低功耗模式
+- 展示休眠前后GPIO电平状态的变化情况
+
+7、gpio_toggle_task:GPIO翻转测速功能演示
+- 配置GPIO26为输出模式,初始电平为低电平
+- 演示gpio.pulse函数生成指定模式的电平变化序列
+- 输出8组电平变化(0xA9,即二进制10101001)
+- 展示如何通过快速电平翻转实现特定信号模式的输出
 
-4)GPIO中断计数测试(gpio_irq_count_test): (PIN16)PWM4 通过杜邦线与(PIN20)GPIO24相连接
+## 演示硬件环境
 
-5)GPIO翻转速度测试(gpio_toggle_test): (PIN16)GPIO27 连接示波器或逻辑分析仪
+1、Air780EHM/Air780EHV/Air780EGH核心板一块:
+- 确保核心板正常供电
 
-6)GPIO上拉下拉测试(gpio_pullupdown_test): (PIN56)GPIO07用于上拉输入,(PIN16)GPIO27用于下拉输入
+2、TYPE-C USB数据线一根,Air780EHM/Air780EHV/Air780EGH核心板和数据线的硬件接线方式为:
+- Air780EHM/Air780EHV/Air780EGH核心板通过TYPE-C USB口供电;
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
 
-7)AGPIO测试(apio_test):  (PIN22)GPIO01, (PIN16)GPIO27 测试时分别连接示波器,核心板USB旁边的开关拨到off一端, Vbat连接合宙IOTpower或Air9000的"+", GND连接合宙IOTpower或Air9000的"-",合宙IOTpower或Air9000设置3.8V供电打开
+3、可选硬件(根据需要):
+- 外部按键或信号源:用于GPIO输入模式和中断模式的信号输入测试
+- 面包板、杜邦线:用于连接外部信号源和核心板GPIO
 
 ## 演示软件环境
 
 1、Luatools下载调试工具
 
-2、[Air780EHM V2007版本固件](https://docs.openluat.com/air780egh/luatos/firmware/version/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录V2007固件对比验证)
-
-## 演示核心步骤
-
-1、搭建好硬件环境
+2、固件获取地址:
 
-2、通过Luatools将demo与固件烧录到核心板中
+[Air780EHM 固件](https://docs.openluat.com/air780epm/luatos/firmware/version/#air780ehmluatos)
 
-3、烧录好后,不同测试结果描述如下,具体详见相关文档 [Air780EGH GPIO](https://docs.openluat.com/air780egh/luatos/app/driver/gpio/)
+[Air780EHV 固件](https://docs.openluat.com/air780ehv/luatos/firmware/version/)
 
-1)GPIO输出测试(gpio_output_test):LED模块500ms输出高电平点亮LED,500ms输出低电平熄灭LED,循环执行这个流程
+[Air780EGH 固件](https://docs.openluat.com/air780egh/luatos/firmware/version/)
 
-2)GPIO输入测试(gpio_input_test): 获取GPIO24电平状态,为高则LED点亮,为低则LED熄灭
-
-3)GPIO中断输入测试(gpio_irq_test): GPIO24杜邦线连接电源3.3V或GND,luatools中都会打印 "被触发" 的字段
-
-4)GPIO中断计数测试(gpio_irq_count_test): luatools中会打印测试结果
-
-> I/user irq count 2000  
-> I/user irq count 1999  
-> I/user irq count 2001  
-
-5)GPIO翻转速度测试(gpio_toggle_test): 逻辑分析仪或示波器测量(PIN16)GPIO27的IO高低电平变化 40-50ns左右
-
-6)GPIO上拉下拉测试(gpio_pullupdown_test): luatools中会打印测试结果
-
-> I/user GPIO  7 电平 1  
-> I/user GPIO  27 电平 0  
+## 演示核心步骤
 
-7)AGPIO测试(apio_test):  正常工作模式,万用表测量(PIN22)GPIO01、(PIN16)GPIO27电平都为3.0V,进入低功耗模式时万用表测量(PIN22)GPIO01为0V, (PIN16)GPIO27保持3.0V不变
+在main.lua中,可以根据需要启用或禁用特定的GPIO功能任务:
+- 通过注释或取消注释相应的require语句来控制功能模块的加载
+- 每个功能模块作为独立的任务运行,可以单独测试或组合测试
+
+### 1、GPIO输出模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_output_task"`这一行
+3. 将代码下载到核心板并运行
+4. **演示效果**:GPIO26将按照设定的时间间隔交替输出高电平和低电平,可使用万用表测量验证
+
+### 2、GPIO输入模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_input_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:当GPIO24输入为高电平时,GPIO26会输出高电平;当GPIO24输入为低电平时,GPIO26会输出低电平
+
+### 3、GPIO上拉下拉模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保只保留`require "gpio_pull_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:串口日志中会周期性显示GPIO2(上拉输入)和GPIO26(下拉输入)的当前电平状态
+
+### 4、GPIO中断(触发)模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_irq_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:当GPIO24的电平发生变化时,会触发中断并检测按键动作,在串口日志中打印短按(小于3秒)或长按(大于等于3秒)事件
+
+### 5、GPIO中断(计数)模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_irqcount_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:PWM4输出方波信号到GPIO24,串口日志中每秒显示一次中断触发的计数值
+
+### 6、AGPIO功能
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "agpio_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:系统进入低功耗模式后,普通GPIO(GPIO1)电平会掉电,而AGPIO(GPIO26)可以保持其电平状态,通过示波器或逻辑分析仪等工具可以查看示例效果展示
+
+### 7、GPIO翻转测速
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_toggle_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:GPIO26会根据gpio.pulse函数的配置快速输出特定模式的电平变化序列(二进制10101001),通过示波器或逻辑分析仪等工具可以查看示例效果展示

+ 104 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/iperf/iperf_client.lua

@@ -0,0 +1,104 @@
+--[[
+@module  iperf_client
+@summary iperf客户端模式测试模块
+@version 1.0
+@date    2025.10.29
+@author  拓毅恒
+@usage
+本模块演示如何初始化CH390以太网并启动iperf客户端模式进行测试。
+适用于路由器连接场景,设备通过DHCP从路由器获取IP地址。
+1、初始化SPI接口连接CH390
+2、设置CH390驱动和网络参数
+3、配置从路由器获取IP地址
+4、连接到指定的iperf服务器并进行测试
+
+本文件没有对外接口,直接在 main.lua 中 require "iperf_client" 即可加载运行。
+]]
+
+-- 引入必要的模块
+local exnetif = require "exnetif"
+
+-- 配置服务器IP地址(需要根据实际服务器IP进行修改)
+local SERVER_IP = "192.168.1.3"  -- 这里需要修改为实际的服务器IP地址
+
+-- iperf测试报告处理函数
+local function iperf_report_handler(bytes, ms_duration, bandwidth)
+    -- 转换为Mbps显示
+    local bandwidth_mbps = bandwidth / 1024 / 1024 * 8
+    log.info("iperf报告", string.format("数据量: %d bytes, 持续时间: %d ms, 带宽: %.2f Mbps", bytes, ms_duration, bandwidth_mbps))
+end
+
+-- iperf客户端任务
+local function iperf_client_task()
+    log.info("iperf测试", "开始初始化网络...")
+    -- 使用exnetif配置SPI外接以太网芯片CH390H
+    exnetif.set_priority_order({
+        {
+            ETHERNET = {
+                pwrpin = 20, 
+                tp = netdrv.CH390,
+                opts = {spi = 0, cs = 8}
+            }
+        }
+    })
+    -- 等待IP地址获取成功
+    log.info("iperf测试", "等待获取IP地址...")
+    -- 设置IP获取超时
+    local ip_wait_count = 60
+    while true do
+        local ipv4 = socket.localIP(socket.LWIP_ETH)
+        if ipv4 and ipv4 ~= "0.0.0.0" then
+            log.info("iperf测试", "IP获取成功:", ipv4)
+            break
+        end
+        
+        -- 超时检查
+        if ip_wait_count <= 0 then
+            log.error("iperf测试", "获取IP地址超时")
+            return
+        end
+        ip_wait_count = ip_wait_count - 1
+        sys.wait(1000)
+    end
+    
+    -- 等待以太网连接
+    while not socket.adapter(socket.LWIP_ETH) do
+        sys.wait(100)
+    end
+    log.info("iperf测试", "以太网连接状态: 已连接")
+
+    -- 启动客户端模式,连接到指定服务器
+    log.info("iperf测试", "启动客户端模式")
+    log.info("iperf测试", "连接到服务器IP:", SERVER_IP, "端口: 5001")
+    
+    -- 连接服务器
+    iperf.client(socket.LWIP_ETH, SERVER_IP, 5001)
+    
+    -- 订阅iperf测试报告事件
+    sys.subscribe("IPERF_REPORT", iperf_report_handler)
+    
+    log.info("iperf测试", "测试开始")
+    
+        -- 设置测试循环次数,共测试2分钟
+    local test_count = 24
+    while test_count > 0 do
+        -- 等待IPERF_REPORT事件,超时时间5秒
+        local report_received = sys.waitUntil("IPERF_REPORT", 5000)
+        if report_received then
+            -- 如果收到报告事件,退出循环
+            log.info("iperf测试", "收到报告,结束测试")
+            break
+        else
+            -- 如果超时,继续测试
+            test_count = test_count - 1
+            log.info("iperf测试", "测试进行中...")
+        end
+    end
+    
+    -- 测试结束
+    log.info("iperf测试", "测试结束,关闭客户端")
+    iperf.abort()
+end
+
+-- 执行iperf客户端模式测试
+sys.taskInit(iperf_client_task)

+ 87 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/iperf/iperf_server.lua

@@ -0,0 +1,87 @@
+--[[
+@module  iperf_server
+@summary iperf服务器模式测试模块
+@version 1.0
+@date    2025.10.29
+@author  拓毅恒
+@usage
+本模块演示如何初始化CH390以太网并启动iperf服务器模式进行测试。
+适用于路由器连接场景,设备通过DHCP从路由器获取IP地址。
+使用步骤:
+1、初始化SPI接口连接CH390
+2、设置CH390驱动和网络参数
+3、配置从路由器获取IP地址
+4、启动iperf服务器并处理测试结果
+
+本文件没有对外接口,直接在 main.lua 中 require "iperf_server" 即可加载运行。
+]]
+
+-- 引入必要的模块
+local exnetif = require "exnetif"
+
+-- 记录服务器IP
+local server_ip = "0.0.0.0"
+
+-- iperf测试报告处理函数
+local function iperf_report_handler(bytes, ms_duration, bandwidth)
+    -- 转换为Mbps显示
+    local bandwidth_mbps = bandwidth / 1024 / 1024 * 8
+    log.info("iperf报告", string.format("数据量: %d bytes, 持续时间: %d ms, 带宽: %.2f Mbps", bytes, ms_duration, bandwidth_mbps))
+end
+
+-- iperf服务器任务
+local function iperf_server_task()
+    log.info("iperf测试", "开始初始化网络...")
+    -- 使用exnetif配置SPI外接以太网芯片CH390H
+    exnetif.set_priority_order({
+        {
+            ETHERNET = {
+                pwrpin = 20, 
+                tp = netdrv.CH390,
+                opts = {spi = 0, cs = 8}
+            }
+        }
+    })
+    -- 等待IP地址获取成功
+    log.info("iperf测试", "等待获取IP地址...")
+    local ip_wait_count = 60
+    while true do
+        local ipv4 = socket.localIP(socket.LWIP_ETH)
+        if ipv4 and ipv4 ~= "0.0.0.0" then
+            log.info("iperf测试", "IP获取成功:", ipv4)
+            server_ip = ipv4
+            break
+        end
+        
+        -- 超时检查
+        if ip_wait_count <= 0 then
+            log.error("iperf测试", "获取IP地址超时")
+            return
+        end
+        
+        ip_wait_count = ip_wait_count - 1
+        sys.wait(1000)
+    end
+    -- 等待以太网连接
+    while not socket.adapter(socket.LWIP_ETH) do
+        sys.wait(100)
+    end
+    log.info("iperf测试", "以太网连接状态: 已连接")
+    
+    -- 连接到路由器场景,不需要配置DHCP服务器
+    log.info("iperf测试", "网络配置完成")
+    
+    -- 订阅iperf测试报告事件
+    sys.subscribe("IPERF_REPORT", iperf_report_handler)
+    
+    -- 启动iperf服务器
+    log.info("iperf测试", "启动服务器模式")
+    log.info("iperf测试", "服务器IP地址:", server_ip, "端口: 5001")
+    iperf.server(socket.LWIP_ETH)
+    sys.wait(2000)
+    log.info("iperf测试", "服务器已启动,等待客户端连接")
+    log.info("iperf测试", "请在客户端设备上设置服务器IP地址为:", server_ip)
+end
+
+-- 执行iperf服务器模式测试
+sys.taskInit(iperf_server_task)

+ 67 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/iperf/main.lua

@@ -0,0 +1,67 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.28
+@author  拓毅恒
+@usage
+演示功能概述
+本demo演示如何使用LuatOS的iperf模块进行网络吞吐量测试。
+iperf是一种网络性能测试工具,支持服务器模式和客户端模式,可以测试网络的带宽和稳定性。
+本demo提供了两个独立的测试用例:
+1、iperf服务器模式 - 设备作为服务器等待客户端连接
+2、iperf客户端模式 - 设备作为客户端主动连接服务器
+
+更多说明参考本目录下的readme.md文件
+]]
+PROJECT = "IPERF_DEMO"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
+log.info("main", PROJECT, VERSION)
+
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 iperf 服务器测试模块
+require "iperf_server"
+
+-- 加载 iperf 客户端测试模块
+-- require "iperf_client"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 136 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/iperf/readme.md

@@ -0,0 +1,136 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,用于选择加载服务器或客户端模块;
+
+2、iperf_server.lua:iperf服务器模块,用于初始化网络并启动iperf服务器;
+
+3、iperf_client.lua:iperf客户端模块,用于初始化网络并连接到服务器进行测试;
+
+## 演示功能概述
+
+本项目演示如何使用Air780EHM/Air780EHV/Air780EGH核心板进行网络性能测试。通过修改后的代码,可以实现两台Air780EHM/Air780EHV/Air780EGH核心板通过路由器连接,进行网络吞吐量测试。
+
+1、支持以下功能特性:
+
+- 支持DHCP客户端模式,自动从路由器获取IP地址
+- 服务器模式和客户端模式分离,可在不同设备上运行
+- 增强的错误处理和超时机制
+- 清晰的日志输出,便于调试和监控
+- 带宽自动计算并以Mbps显示
+
+## 演示硬件环境
+
+![](https://docs.openluat.com/air780ehv/luatos/common/hwenv/image/Air780EHV.png)
+
+1、两台Air780EHM/Air780EHV/Air780EGH核心板
+
+2、一台路由器(支持DHCP功能)
+
+3、网线两根
+
+4、Air780EHM/Air780EHV/Air780EGH核心板和数据线的硬件接线方式为
+
+- Air780EHM/Air780EHV/Air780EGH核心板通过TYPE-C USB口供电;
+
+- 如果测试发现软件频繁重启,重启原因值为:poweron reason 0,可能是供电不足,此时再通过直流稳压电源对核心板的vbat管脚进行4V供电,或者5V管脚进行5V供电;
+
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+5、AirETH_1000配件板一块,Air780EHM/Air780EHV/Air780EGH核心板和AirETH_1000配件板的硬件接线方式为:
+
+| Air780EHM/Air780EHV/Air780EGH核心板  |  AirETH_1000配件板 |
+| --------------- | ----------------- |
+| 3V3             | 3.3v              |
+| gnd             | gnd               |
+| 86/SPI0CLK      | SCK               |
+| 83/SPI0CS       | CSS               |
+| 84/SPI0MISO     | SDO               |
+| 85/SPI0MOSI     | SDI               |
+| 107/GPIO21      | INT               |
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、固件获取地址:
+
+[Air780EHM 固件](https://docs.openluat.com/air780epm/luatos/firmware/version/#air780ehmluatos)
+
+[Air780EHV 固件](https://docs.openluat.com/air780ehv/luatos/firmware/version/)
+
+[Air780EGH 固件](https://docs.openluat.com/air780egh/luatos/firmware/version/)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、配置服务器端(一台核心板+AirETH_1000配件板)
+
+   a. 确保`main.lua`中已启用服务器模块,禁用客户端模块:
+   ```lua
+   -- 加载 iperf 服务器测试模块
+   require "iperf_server"
+
+   -- 加载 iperf 客户端测试模块
+   -- require "iperf_client"
+   ```
+
+   b. 烧录到一台Air780EHM/Air780EHV/Air780EGH核心板
+
+   c. 连接AirETH_1000配件板到路由器的LAN口
+
+   d. 启动核心板,它将自动从路由器获取IP地址并启动iperf服务器
+
+3、配置客户端(另一台核心板+AirETH_1000配件板)
+
+   a. 修改`iperf_client.lua`文件中的服务器IP地址为服务器核心板的实际IP地址:
+
+   ```lua
+   -- 配置服务器IP地址(需要根据实际服务器IP进行修改)
+   local SERVER_IP = "192.168.1.3"  -- 这里需要修改为实际的服务器IP地址
+   ```
+
+   b. 确保`main.lua`中已启用客户端模块,禁用服务器模块:
+
+   ```lua
+   -- 加载 iperf 服务器测试模块
+   -- require "iperf_server"
+
+   -- 加载 iperf 客户端测试模块
+   require "iperf_client"
+   ```
+
+   c. 烧录到另一台Air780EHM/Air780EHV/Air780EGH核心板
+
+   d. 连接AirETH_1000配件板到路由器的LAN口
+
+   e. 启动核心板,它将自动从路由器获取IP地址并尝试连接到服务器
+
+## 查看测试结果
+
+测试启动后,可以通过Luatools工具查看测试日志。客户端将显示实时的测试报告,包括数据量、持续时间和带宽(以Mbps为单位)。
+
+```lua
+2025-11-06 17:02:24.658][000000013.298] I/user.iperf测试 测试进行中...
+[2025-11-06 17:02:24.675][000000013.314] D/iperf iperf正常结束, type 1
+[2025-11-06 17:02:24.677][000000013.314] D/lwiperf iperf_free 88 c1d553c
+[2025-11-06 17:02:24.678][000000013.316] D/iperf report bytes 5989824 ms_duration 10002 bandwidth 4784 kbps
+[2025-11-06 17:02:24.680][000000013.317] I/user.iperf报告 数据量: 5989824 bytes, 持续时间: 10002 ms, 带宽: 0.04 Mbps
+```
+
+## 注意事项
+
+1、确保两台核心板和电脑都连接到同一个路由器,并且路由器已启用DHCP功能
+
+2、服务器的IP地址需要在客户端配置文件中正确设置,否则客户端将无法连接
+
+3、默认情况下,服务器在端口5001上监听连接请求
+
+4、测试默认持续2分钟后自动结束
+
+## 常见问题排查
+
+1、无法连接到服务器
+   - 确认服务器IP地址是否正确
+   - 检查两台设备是否在同一网段
+   - 检查网线连接是否牢固

+ 57 - 112
module/Air780EHM_Air780EHV_Air780EGH/demo/mobile/main.lua

@@ -1,122 +1,67 @@
-
--- LuaTools需要PROJECT和VERSION这两个信息
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.23
+@author  拓毅恒
+@usage
+本demo演示的核心功能为:
+移动网络功能测试,包括SIM卡管理、基站数据查询、频段(Band)测试和修改、移动网络信息获取(IMEI/IMSI/信号强度等)以及SIM卡状态监控。
+通过加载mobile_test模块来运行相关测试功能。
+
+更多说明参考本目录下的readme.md文件
+]]
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
 PROJECT = "mobiledemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
+VERSION = "001.000.000"
 
+log.info("main", "project name is ", PROJECT, "version is ", VERSION)
 
--- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
-if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
-    pm.power(pm.PWK_MODE, false)
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
 end
 
-
--- 对于双卡的设备, 可以设置为自动选sim卡
--- 但是, 这样SIM1所在管脚就强制复用为SIM功能, 不可以再复用为GPIO
--- mobile.simid(2)
-mobile.simid(2,true)--优先用SIM0
-
-
-sys.taskInit(function()
-
-	log.info("status", mobile.status())
-    local band = zbuff.create(40)
-    local band1 = zbuff.create(40)
-    mobile.getBand(band)
-    log.info("当前使用的band:")
-    for i=0,band:used()-1 do
-        log.info("band", band[i])
-    end
-    band1[0] = 38
-    band1[1] = 39
-    band1[2] = 40
-    mobile.setBand(band1, 3)    --改成使用38,39,40
-    band1:clear()
-    mobile.getBand(band1)
-    log.info("修改后使用的band:")
-    for i=0,band1:used()-1 do
-        log.info("band", band1[i])
-    end
-    mobile.setBand(band, band:used())    --改回原先使用的band,也可以下载的时候选择清除fs
-
-    mobile.getBand(band1)
-    log.info("修改回默认使用的band:")
-    for i=0,band1:used()-1 do
-        log.info("band", band1[i])
-    end
-	-- mobile.vsimInit()
-	-- mobile.flymode(nil,true)
-	-- mobile.vsimOnOff(true)
-	-- mobile.flymode(nil,false)
-    -- mobile.apn(0,2,"") -- 使用默认APN激活CID2
-    -- mobile.rtime(3) -- 在无数据交互时,RRC 3秒后自动释放
-    -- 下面是配置自动搜索小区间隔,和轮询搜索冲突,开启1个就可以了
-    -- mobile.setAuto(10000,30000, 5) -- SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
-	log.info("status", mobile.status())
-    sys.wait(2000)
-    while 1 do
-        log.info("imei", mobile.imei())
-        log.info("imsi", mobile.imsi())
-        local sn = mobile.sn()
-        if sn then
-            log.info("sn",   sn:toHex())
-        end
-		log.info("status", mobile.status())
-        
-
-        log.info("iccid", mobile.iccid())
-        log.info("csq", mobile.csq()) -- 4G模块的CSQ并不能完全代表强度
-        log.info("rssi", mobile.rssi()) -- 需要综合rssi/rsrq/rsrp/snr一起判断
-        log.info("rsrq", mobile.rsrq())
-        log.info("rsrp", mobile.rsrp())
-        log.info("snr", mobile.snr())
-        log.info("simid", mobile.simid()) -- 这里是获取当前SIM卡槽
-        log.info("apn", mobile.apn(0,1))
-        log.info("ip", socket.localIP())
-		log.info("lua", rtos.meminfo())
-        -- sys内存
-        log.info("sys", rtos.meminfo("sys"))
-        sys.wait(15000)
-    end
-end)
-
--- 基站数据的查询
-
--- 订阅式, 模块本身会周期性查询基站信息,但通常不包含临近小区
-sys.subscribe("CELL_INFO_UPDATE", function()
-    log.info("cell", json.encode(mobile.getCellInfo()))
-end)
-
--- 轮询式, 包含临近小区信息,这是手动搜索,和上面的自动搜索冲突,开启一个就行
-sys.taskInit(function()
-    sys.wait(5000)
-	mobile.config(mobile.CONF_SIM_WC_MODE, 2)
-    while 1 do
-        mobile.reqCellInfo(10)
-        sys.wait(11000)
-        log.info("cell", json.encode(mobile.getCellInfo()))
-		mobile.config(mobile.CONF_SIM_WC_MODE, 2)
-    end
-end)
-
--- 获取sim卡的状态
-
-sys.subscribe("SIM_IND", function(status, value)
-    log.info("sim status", status)
-    if status == 'GET_NUMBER' then
-        log.info("number", mobile.number(0))
-    end
-	if status == "SIM_WC" then
-        log.info("sim", "write counter", value)
-    end
-end)
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 mobile_test 功能模块
+require "mobile_test"
 
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()
 -- sys.run()之后后面不要加任何语句!!!!!
+

+ 114 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/mobile/mobile_test.lua

@@ -0,0 +1,114 @@
+--[[
+@module  mobile_test
+@summary Air780Exx mobile功能测试模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 Air780Exx 核心板演示移动网络功能的代码示例,核心业务逻辑包括:
+1. SIM卡管理和选择(自动选卡功能)
+2. 基站数据查询(订阅式和轮询式两种方式)
+3. 频段(Band)测试和修改
+4. 移动网络信息获取(IMEI、IMSI、信号强度等)
+5. SIM卡状态监控
+]]
+
+-- 对于双卡的设备, 可以设置为自动选sim卡
+-- 但是SIM1所在管脚就强制复用为SIM功能, 占用4个IO口(gpio4/5/6/23),不可以再复用为GPIO
+-- mobile.simid(2)
+mobile.simid(2,true)--优先用SIM0
+
+-- 基站数据的查询
+-- 订阅式, 模块本身会周期性查询基站信息,但通常不包含临近小区
+local function sub_cell_info_task()
+    log.info("cell", json.encode(mobile.getCellInfo()))
+end
+
+sys.subscribe("CELL_INFO_UPDATE", sub_cell_info_task)
+
+-- 轮询式, 包含临近小区信息,这是手动搜索,和上面的自动搜索冲突,开启一个就行
+local function get_cell_info_task()
+    sys.wait(5000)
+	mobile.config(mobile.CONF_SIM_WC_MODE, 2)
+    while 1 do
+        mobile.reqCellInfo(10)
+        sys.wait(11000)
+        log.info("cell", json.encode(mobile.getCellInfo()))
+		mobile.config(mobile.CONF_SIM_WC_MODE, 2)
+    end
+end
+
+-- 获取sim卡的状态
+local function get_sim_status_task(status, value)
+    log.info("sim status", status)
+    if status == 'GET_NUMBER' then
+        log.info("number", mobile.number(0))
+    end
+	if status == "SIM_WC" then
+        log.info("sim", "write counter", value)
+    end
+end
+
+sys.subscribe("SIM_IND", get_sim_status_task)
+
+-- 定义测试band和移动网络信息的函数
+local function mobileinfo_task()
+    -- 设置默认APN 
+    -- 注意:在国内公网卡基本上都不需要设置APN, 专网卡才需要设置
+    mobile.apn(0,1,"cmiot","","",nil,0)
+    -- 开启SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
+    mobile.setAuto(10000,30000, 5) -- 此函数仅需要配置一次
+    
+    log.info("************开始测试band************")
+    local band = zbuff.create(40)
+    local band1 = zbuff.create(40)
+    mobile.getBand(band)
+    log.info("当前使用的band:")
+    for i=0,band:used()-1 do
+        log.info("band", band[i])
+    end
+    band1[0] = 38
+    band1[1] = 39
+    band1[2] = 40
+    mobile.setBand(band1, 3)    --改成使用38,39,40
+    band1:clear()
+    mobile.getBand(band1)
+    log.info("修改后使用的band:")
+    for i=0,band1:used()-1 do
+        log.info("band", band1[i])
+    end
+    mobile.setBand(band, band:used())    --改回原先使用的band,也可以下载的时候选择清除fs
+
+    mobile.getBand(band1)
+    log.info("修改回默认使用的band:")
+    for i=0,band1:used()-1 do
+        log.info("band", band1[i])
+    end
+    log.info("************band测试完毕************")
+
+	log.info("status", mobile.status())
+    sys.wait(2000)
+    while 1 do
+        log.info("imei", mobile.imei())
+        log.info("imsi", mobile.imsi())
+        log.info("apn", mobile.apn()) -- 获取当前APN
+        log.info("status", mobile.status())
+        log.info("iccid", mobile.iccid())
+        log.info("csq", mobile.csq()) -- 4G模块的CSQ并不能完全代表强度
+        log.info("rssi", mobile.rssi()) -- 需要综合rssi/rsrq/rsrp/snr一起判断
+        log.info("rsrq", mobile.rsrq())
+        log.info("rsrp", mobile.rsrp())
+        log.info("snr", mobile.snr())
+        log.info("simid", mobile.simid()) -- 这里是获取当前SIM卡槽
+        log.info("apn", mobile.apn(0,1))
+        -- sys内存
+        log.info("lua", rtos.meminfo())
+        log.info("sys", rtos.meminfo("sys"))
+        sys.wait(15000)
+    end
+end
+
+-- 轮询式查找小区, 包含临近小区信息,与上面订阅式搜索冲突,开启一个就行
+-- sys.taskInit(get_cell_info_task)
+-- 启动测试任务
+sys.taskInit(mobileinfo_task)

+ 103 - 0
module/Air780EHM_Air780EHV_Air780EGH/demo/mobile/readme.md

@@ -0,0 +1,103 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,负责初始化系统环境和加载移动网络测试模块;
+
+2、mobile_test.lua:移动网络功能测试模块,演示Air780EHM/Air780EHV/Air780EGH的移动网络相关功能;
+
+## 演示功能概述
+
+1、mobile_test:演示以下几种应用场景的使用方式
+
+- SIM卡配置和管理功能演示;
+- 基站数据查询(订阅式和轮询式)功能演示;
+- SIM卡状态订阅功能演示;
+- 频段(Band)测试和修改功能演示;
+- 移动网络信息获取(IMEI/IMSI/信号强度等)功能演示;
+
+## 演示硬件环境
+
+1、Air780EHM/Air780EHV/Air780EGH核心板一块 + 可上网的SIM卡一张 + 4G天线一根:
+
+- SIM卡插入核心板的SIM卡槽
+- 天线装到核心板上
+
+2、TYPE-C USB数据线一根 + USB转串口数据线一根,Air780EHM/Air780EHV/Air780EGH核心板和数据线的硬件接线方式为:
+
+- Air780EHM/Air780EHV/Air780EGH核心板通过TYPE-C USB口供电;(外部供电/USB供电 拨动开关 拨到 USB供电一端)
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、固件获取地址:
+
+[Air780EHM 固件](https://docs.openluat.com/air780epm/luatos/firmware/version/#air780ehmluatos)
+
+[Air780EHV 固件](https://docs.openluat.com/air780ehv/luatos/firmware/version/)
+
+[Air780EGH 固件](https://docs.openluat.com/air780egh/luatos/firmware/version/)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、确保SIM卡已正确插入核心板
+
+3、Luatools烧录内核固件和demo脚本代码
+
+4、烧录成功后,自动开机运行,通过串口日志可以观察到以下信息:
+
+- SIM卡状态监控信息
+- 基站数据查询结果
+- 移动网络信息(IMEI/IMSI/信号强度等)
+- 频段测试和修改结果
+
+``` lua
+[2025-10-23 15:58:31.141][000000000.361] I/user.main project name is  mobiledemo version is  001.000.000
+[2025-10-23 15:58:31.142][000000000.370] I/mobile sim set to 2 , ret 0
+[2025-10-23 15:58:31.144][000000000.373] I/user.************开始测试band************
+[2025-10-23 15:58:31.161][000000001.774] I/user.当前使用的band:
+[2025-10-23 15:58:31.163][000000001.775] I/user.band 1
+[2025-10-23 15:58:31.165][000000001.775] I/user.band 3
+[2025-10-23 15:58:31.167][000000001.775] I/user.band 5
+[2025-10-23 15:58:31.169][000000001.776] I/user.band 8
+[2025-10-23 15:58:31.170][000000001.776] I/user.band 34
+[2025-10-23 15:58:31.172][000000001.776] I/user.band 38
+[2025-10-23 15:58:31.173][000000001.776] I/user.band 39
+[2025-10-23 15:58:31.175][000000001.777] I/user.band 40
+[2025-10-23 15:58:31.176][000000001.777] I/user.band 41
+[2025-10-23 15:58:31.178][000000001.791] I/user.修改后使用的band:
+[2025-10-23 15:58:31.179][000000001.792] I/user.band 38
+[2025-10-23 15:58:31.180][000000001.792] I/user.band 39
+[2025-10-23 15:58:31.182][000000001.793] I/user.band 40
+[2025-10-23 15:58:31.183][000000001.799] I/user.修改回默认使用的band:
+[2025-10-23 15:58:31.184][000000001.800] I/user.band 1
+[2025-10-23 15:58:31.186][000000001.800] I/user.band 3
+[2025-10-23 15:58:31.187][000000001.800] I/user.band 5
+[2025-10-23 15:58:31.189][000000001.800] I/user.band 8
+[2025-10-23 15:58:31.190][000000001.801] I/user.band 34
+[2025-10-23 15:58:31.191][000000001.801] I/user.band 38
+[2025-10-23 15:58:31.193][000000001.801] I/user.band 39
+[2025-10-23 15:58:31.195][000000001.802] I/user.band 40
+[2025-10-23 15:58:31.196][000000001.802] I/user.band 41
+[2025-10-23 15:58:31.198][000000001.802] I/user.************band测试完毕************
+[2025-10-23 15:58:48.147][000000018.809] I/user.imei 864793080175404
+[2025-10-23 15:58:48.149][000000018.809] I/user.imsi 460240452233401
+[2025-10-23 15:58:48.151][000000018.810] I/user.status 1
+[2025-10-23 15:58:48.153][000000018.810] I/user.iccid 89860855102480513401
+[2025-10-23 15:58:48.155][000000018.810] I/user.csq 27
+[2025-10-23 15:58:48.157][000000018.811] I/user.rssi -58
+[2025-10-23 15:58:48.158][000000018.811] I/user.rsrq -9
+[2025-10-23 15:58:48.160][000000018.811] I/user.rsrp -87
+[2025-10-23 15:58:48.161][000000018.812] I/user.snr 16
+[2025-10-23 15:58:48.163][000000018.812] I/user.simid 0
+[2025-10-23 15:58:48.169][000000018.812] I/user.apn cmiot.MNC024.MCC460.GPRS
+[2025-10-23 15:58:48.171][000000018.813] I/user.lua 4194296 56552 56552
+[2025-10-23 15:58:48.172][000000018.813] I/user.sys 3202992 355468 360724
+[2025-10-23 15:58:56.722][000000027.379] I/user.cell [{"mnc":0,"dlbandwidth":5,"tdd":0,"earfcn":1300,"ulbandwidth":5,"band":3,"mcc":460,"pci":219,"rsrp":-86,"tac":18511,"rssi":-57,"rsrq":-9,"snr":16,"cid":190213964},{"mnc":15,"earfcn":1300,"pci":219,"rsrp":-86,"tac":18511,"mcc":460,"rsrq":-9,"snr":16,"cid":190213964},{"mnc":0,"earfcn":40936,"pci":368,"rsrp":-103,"tac":18511,"mcc":460,"rsrq":-7,"snr":0,"cid":192844432}]
+[2025-10-23 15:58:56.726][000000027.382] I/user.sim status SIM_WC
+[2025-10-23 15:58:56.728][000000027.383] I/user.sim write counter 2
+```
+
+5、日志中会实时显示移动网络相关信息的变化,可通过观察日志来验证功能是否正常工作

+ 0 - 37
module/Air780EPM/demo/gpio/AGPIO/main.lua

@@ -1,37 +0,0 @@
--- 本示例对比了普通GPIO和AGPIO的进入休眠模式前后的区别。
--- Luatools需要PROJECT和VERSION这两个信息
-PROJECT = "AGPIO_GPIO_testdemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
-local gpio_number = 1   -- 普通GPIO GPIO号为1,休眠后掉电。
-local Agpio_number = 27 -- AGPIO GPIO号为27,休眠后可保持电平。
-
-gpio.setup(gpio_number, 1)
-gpio.setup(Agpio_number, 1)
-
-sys.taskInit(function()
-    sys.wait(16000)
-    -- 关闭USB电源
-    pm.power(pm.USB, false)
-    -- 进入低功耗模式
-    pm.power(pm.WORK_MODE, 3)
-    sys.wait(10000)
-    pm.power(pm.USB, true)
-    pm.power(pm.WORK_MODE, 0)
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 39
module/Air780EPM/demo/gpio/GPIO上拉下拉模式/main.lua

@@ -1,39 +0,0 @@
--- Luatools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio2demo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000)--初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
-end
-
---配置gpio7为中断上拉模式
---配置gpio27为中断下拉模式
---请根据实际需求更改gpio编号和上下拉
-local gpio_pin1 = 7
-local gpio_pin2 = 27
--- 按键防抖函数
-gpio.debounce(gpio_pin1, 50)
-gpio.debounce(gpio_pin2, 50)
-
--- 设置GPIO7引脚为上拉输入模式
-gpio.setup(gpio_pin1, nil, gpio.PULLUP)
-
--- 设置GPIO27引脚为下拉输入模式
-gpio.setup(gpio_pin2, nil, gpio.PULLDOWN)
-
-
-sys.timerLoopStart(function ()
-    log.info("GPIO",gpio_pin1,"电平",gpio.get(gpio_pin1))
-    log.info("GPIO",gpio_pin2,"电平",gpio.get(gpio_pin2))
-end,1000)
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 27
module/Air780EPM/demo/gpio/GPIO中断(触发)模式/main.lua

@@ -1,27 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio_irq"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
--- 配置gpio24为中断模式,上升沿(gpio.RISING)和下降沿(gpio.FALLING)均触发(gpio.BOTH)
--- 请根据实际需求更改gpio编号和触发模式
-local gpio_pin = 24
-gpio.debounce(gpio_pin, 100)
-gpio.setup(gpio_pin, function()
-    log.info("gpio", gpio_pin, "被触发")
-end, gpio.PULLUP, gpio.BOTH)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 34
module/Air780EPM/demo/gpio/GPIO中断(计数)模式/main.lua

@@ -1,34 +0,0 @@
--- Luatools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio_irq"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000)--初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
-end
-
---配置gpio24为中断计数模式
---请根据实际需求更改gpio编号和上下拉
-local gpio_pin = 24
--- gpio.setup(gpio_pin, gpio.count, gpio.PULLUP, gpio.FALLING)
-gpio.setup(gpio_pin, gpio.count)
-
---配置PWM4输出 1kHZ 占空比50%的方波作为信号源
-pwm.open(4,1000,50)
-
---每隔1S统计一次中断触发的次数
-sys.taskInit(function()
-    while true do
-        sys.wait(1000)
-        log.info("irq cnt", gpio.count(gpio_pin))
-    end
-end)
-
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 34
module/Air780EPM/demo/gpio/GPIO翻转测速/main.lua

@@ -1,34 +0,0 @@
--- Luatools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio2demo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
-local test_gpio_number = 27
-
-gpio.setup(test_gpio_number, 0, gpio.PULLUP)
-
-sys.taskInit(function()
-    sys.wait(100)
-    while true do
-        sys.wait(100)
-        -- 通过GPIO27脚输出输出8组电平变化
-        -- 0xA9就是输出的电平高低状态,即 10101001
-        gpio.pulse(test_gpio_number, 0xA9, 8, 0)
-        log.info("gpio----------->pulse2")
-    end
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 41
module/Air780EPM/demo/gpio/GPIO输入模式/main.lua

@@ -1,41 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio_irq"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
--- 配置gpio24为输入模式
--- 配置GPIO27(即开发板上LED灯)为输出模式
-
--- 请根据实际需求更改gpio编号和上下拉
-
-local inputpin = 24
-local ledpin = 27
-
-local input = gpio.setup(inputpin,nil)
-local led = gpio.setup(ledpin, 1)
-
-gpio.debounce(inputpin, 50)
---GPIO24检测到有高低电平输入后,会返回GPIO24当前获取到的电平为高还是低,高返回值为1,低返回值为0
---将这个返回值,传给GPIO27(LED),为0 则GPIO27输出低电平(LED灯灭),为1则输出高电平(LED灯亮)
-sys.taskInit(function ()
-    while true do
-        led(input())
-        sys.wait(500)
-    end
-end)
-
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 37
module/Air780EPM/demo/gpio/GPIO输出模式/main.lua

@@ -1,37 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "gpiodemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
-local gpio_number = 27 -- Air780EPM开发板上的网络指示灯(蓝灯)与GPIO27相连
-
-LED = gpio.setup(gpio_number, 1) -- 设置GPIO27为输出模式
-
-sys.taskInit(function()
-    -- 开始呼吸灯
-    local count = 0
-    while 1 do
-        -- 呼吸灯程序
-        LED(1)
-        log.info("GPIO", "Go Go Go", count, rtos.bsp())
-        sys.wait(500)--点亮时间 500ms
-        LED(0)
-        sys.wait(500)--熄灭时间 500ms
-        count = count + 1
-    end
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 33 - 0
module/Air780EPM/demo/gpio/agpio_task.lua

@@ -0,0 +1,33 @@
+--[[
+@module  agpio_task
+@summary Air780EPM演示agpio功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air780EPM开发板演示 AGPIO 功能的代码示例,核心业务逻辑为:
+AGPIO与普通GPIO在PSM+模式下的区别演示
+1. 初始化普通GPIO和AGPIO
+   - 配置普通GPIO1为输出模式并设置为高电平
+   - 配置AGPIO27为输出模式并设置为高电平
+2. 等待一段时间让GPIO状态稳定
+3. 关闭USB电源以降低功耗
+4. 进入深度休眠模式(PSM+模式),此时RAM 掉电,唤醒后程序从初始状态运行。
+5. 观察结果:通过示波器或逻辑分析仪等设备观察进入PSM+模式后普通GPIO为掉电状态,而AGPIO保持了休眠前的电平状态
+]]
+
+local gpio_number = 1   -- 普通GPIO GPIO号为1,休眠后掉电。
+local Agpio_number = 27 -- AGPIO GPIO号为27,休眠后可保持电平。
+
+gpio.setup(gpio_number, 1)
+gpio.setup(Agpio_number, 1)
+
+local function enterlowpower()
+    sys.wait(10000)
+    -- 关闭USB电源
+    pm.power(pm.USB, false)
+    -- 进入PSM+模式
+    pm.power(pm.WORK_MODE, 3)
+end
+
+sys.taskInit(enterlowpower)

+ 41 - 0
module/Air780EPM/demo/gpio/gpio_input_task.lua

@@ -0,0 +1,41 @@
+--[[
+@module  gpio_input_task
+@summary Air780EPM演示GPIO输入检测与LED联动示例
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air780EPM开发板演示GPIO输入检测功能的代码示例,核心业务逻辑为:
+1. 初始化GPIO24为输入模式(可用杜邦线接稳压电源,高电平接3.3V,低电平接地)
+2. 初始化GPIO27(板载LED)为输出模式,默认高电平(亮)
+3. 启用输入消抖,消抖时间50 ms
+4. 每500 ms读取一次GPIO24电平,并同步控制LED亮灭
+5. 高电平→LED亮,低电平→LED灭
+]]
+
+-- 配置gpio24为输入模式
+-- 配置GPIO27(即开发板上LED灯)为输出模式
+
+-- 请根据实际需求更改gpio编号和上下拉
+
+local inputpin = 24
+local ledpin = 27
+
+local input = gpio.setup(inputpin, nil, gpio.PULLDOWN)
+local led = gpio.setup(ledpin, 1)
+
+gpio.debounce(inputpin, 50)
+--GPIO24检测到有高低电平输入后,会返回GPIO24当前获取到的电平为高还是低,高返回值为1,低返回值为0
+--将这个返回值,传给GPIO27(LED),为0 则GPIO27输出低电平(LED灯灭),为1则输出高电平(LED灯亮)
+-- 定义一个函数用于循环读取输入引脚电平并控制LED灯
+local function controlLed()
+    local level = 0
+    while true do
+        level = gpio.get(inputpin)
+        log.info("gpio","set netled level: ",level)
+        gpio.set(ledpin, level)
+        sys.wait(500)
+    end
+end
+
+sys.taskInit(controlLed)

+ 57 - 0
module/Air780EPM/demo/gpio/gpio_irq_task.lua

@@ -0,0 +1,57 @@
+--[[
+@module  gpio_irq_task
+@summary Air780EPM演示GPIO中断功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air780EPM开发板演示 GPIO 按键短按和长按检测的代码示例,核心业务逻辑为:
+1. 配置GPIO24为中断模式,上升沿和下降沿均触发
+2. 实现按键短按(小于3秒)和长按(大于等于3秒)的检测功能
+3. 可连接按键或直接用杜邦线轻触GND进行测试
+4. 注意:使用杜邦线测试时,因为脉冲可能无法控制,所以不要加防抖防止程序测试异常
+]]
+
+-- 配置gpio24为中断模式,上升沿(gpio.RISING)和下降沿(gpio.FALLING)均触发(gpio.BOTH)
+local gpio_pin = 24
+-- gpio.debounce(gpio_pin, 100) -- 实际设计板子时,根据自己的需求可以更改防抖配置以及打开防抖
+
+-- 按键状态变量
+local long_press_threshold = 3000  -- 长按判断阈值,3秒
+local current_state = 1  -- 跟踪当前按键状态,1为释放,0为按下
+
+-- 定时器回调函数,处理长按事件
+local function timer_callback(gpio_id)
+    log.info("按键检测", "长按事件", gpio_id)
+end
+
+-- 定义GPIO中断处理函数
+local function gpio_irq_handler()
+    local pin_state = gpio.get(gpio_pin)  -- 获取GPIO当前状态
+    
+    -- 只有当状态发生变化时才处理
+    if pin_state ~= current_state then
+        current_state = pin_state  -- 更新当前状态
+        
+        if pin_state == 0 then
+            -- 按键按下
+            log.info("按键检测", "按键按下")
+            if not sys.timerIsActive(timer_callback, gpio_pin) then
+                -- 启动定时器,3秒后触发长按事件
+                sys.timerStart(timer_callback, long_press_threshold, gpio_pin)
+            end
+        elseif pin_state == 1 then
+            -- 按键释放
+            log.info("按键检测", "按键释放")
+            
+            -- 如果定时器还在运行,说明是短按
+            if sys.timerIsActive(timer_callback, gpio_pin) then
+                sys.timerStop(timer_callback, gpio_pin)
+                log.info("按键检测", "短按事件")
+            end
+        end
+    end
+end
+
+-- 配置GPIO中断
+gpio.setup(gpio_pin, gpio_irq_handler, gpio.PULLUP, gpio.BOTH)

+ 29 - 0
module/Air780EPM/demo/gpio/gpio_irqcount_task.lua

@@ -0,0 +1,29 @@
+--[[
+@module  gpio_irqcount_task
+@summary Air780EPM演示GPIO中断计数功能
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air780EPM开发板演示GPIO中断计数功能的代码示例,核心业务逻辑为:
+1. 配置GPIO24为中断计数模式,用于统计外部信号触发次数
+2. 每1秒读取并打印一次中断触发次数
+3. 可用杜邦线轻触3.3V电源正极,即可观察中断触发效果。
+]]
+
+-- 配置gpio24为中断计数模式
+-- 设置好后系统会自动记录中断触发次数。
+local gpio_pin = 24
+-- gpio.setup(gpio_pin, gpio.count, gpio.PULLUP, gpio.FALLING)
+gpio.setup(gpio_pin, gpio.count)
+
+-- 每隔1S统计一次中断触发的次数
+local function countIrq()
+    while true do
+        sys.wait(1000)
+        -- 返回从上次调用该函数后到当前时刻的中断触发次数
+        log.info("irq cnt", gpio.count(gpio_pin)) -- 调用函数时会自动清空中断累计值
+    end
+end
+
+sys.taskInit(countIrq)

+ 35 - 0
module/Air780EPM/demo/gpio/gpio_output_task.lua

@@ -0,0 +1,35 @@
+--[[
+@module  gpio_output_task
+@summary Air780EPM演示GPIO输出功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air780EPM开发板演示 GPIO 输出功能的代码示例,核心业务逻辑为:
+通过GPIO27控制开发板载网络指示灯(蓝灯)实现闪烁效果
+1. 初始化GPIO27为输出模式
+2. 在任务循环中周期性地拉高/拉低GPIO27
+3. 通过500ms亮灭间隔实现简单的闪烁效果
+]]
+
+local gpio_number = 27 -- Air780EPM开发板上的网络指示灯(蓝灯)与GPIO27相连
+
+gpio.setup(gpio_number, 1) -- 设置GPIO27为输出模式
+
+-- 定义任务函数
+local function ledlight_task()
+    local count = 0
+    while 1 do
+        -- 闪烁灯程序
+        gpio.set(gpio_number, 1)
+        log.info("GPIO", "点亮 LED")
+        sys.wait(500)--点亮时间 500ms
+        gpio.set(gpio_number, 0)
+        log.info("GPIO", "熄灭 LED")
+        sys.wait(500)--熄灭时间 500ms
+        count = count + 1
+    end
+end
+
+-- 执行闪烁灯任务函数
+sys.taskInit(ledlight_task)

+ 32 - 0
module/Air780EPM/demo/gpio/gpio_pull_task.lua

@@ -0,0 +1,32 @@
+--[[
+@module  gpio_pull_task
+@summary Air780EPM演示GPIO上下拉功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air780EPM开发板演示 GPIO 上下拉功能的代码示例,核心业务逻辑为:
+1. 配置GPIO7为上拉输入模式
+2. 配置GPIO27为下拉输入模式
+3. 定时读取并打印两个GPIO的电平状态
+4. 将GPIO7和GPIO27引脚接地或接3.3V来控制GPIO7和GPIO27的电平变化,验证上拉/下拉配置是否生效
+]]
+
+local gpio_pin1 = 7
+local gpio_pin2 = 27
+-- 按键防抖函数
+gpio.debounce(gpio_pin1, 50)
+gpio.debounce(gpio_pin2, 50)
+
+-- 设置GPIO7引脚为上拉输入模式
+gpio.setup(gpio_pin1, nil, gpio.PULLUP)
+
+-- 设置GPIO27引脚为下拉输入模式
+gpio.setup(gpio_pin2, nil, gpio.PULLDOWN)
+
+local function gpiopulltask()
+    log.info("GPIO",gpio_pin1,"电平",gpio.get(gpio_pin1))
+    log.info("GPIO",gpio_pin2,"电平",gpio.get(gpio_pin2))
+end
+
+sys.timerLoopStart(gpiopulltask,1000)

+ 33 - 0
module/Air780EPM/demo/gpio/gpio_toggle_task.lua

@@ -0,0 +1,33 @@
+--[[
+@module  gpio_toggle
+@summary Air780EPM演示波形翻转功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 Air780EPM 开发板演示 GPIO 翻转(脉冲)输出的代码示例,核心业务逻辑为:
+GPIO 快速翻转测速与波形观测
+1. 配置 GPIO27 为输出模式并上拉初始化;
+2. 在任务中循环调用 gpio.pulse() 按给定模式输出脉冲序列;
+   - 演示模式为 0xA9(二进制 10101001),每次输出 8 组电平变化;
+3. 使用示波器或逻辑分析仪连接到 GPIO27,观察翻转波形与频率,翻转一次所需时间大概 50ns;
+4. 可根据需要修改 `test_gpio_number`、`0xA9`(翻转模式)和 `8`(组数),以测试不同引脚和模式;
+5. 注意:高频翻转请勿直接驱动重负载,推荐用于逻辑检测或带限流的 LED 演示。
+]]
+
+local test_gpio_number = 27
+
+gpio.setup(test_gpio_number, 0, gpio.PULLUP)
+
+local function gpiotoggletask()
+    sys.wait(100)
+    while true do
+        sys.wait(100)
+        -- 通过GPIO27脚输出输出8组电平变化
+        -- 0xA9就是输出的电平高低状态,即 10101001
+        gpio.pulse(test_gpio_number, 0xA9, 8, 0)
+        log.info("gpio----------->pulse")
+    end
+end
+
+sys.taskInit(gpiotoggletask)

+ 84 - 0
module/Air780EPM/demo/gpio/main.lua

@@ -0,0 +1,84 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本demo演示的核心功能为:
+演示GPIO的多种功能模式,包括输出模式、输入模式、上拉下拉模式、中断触发模式、中断计数模式、AGPIO低功耗模式以及GPIO翻转测速功能。
+用户可通过取消注释相应的require语句来启用不同的功能模块进行测试。
+
+更多说明参考本目录下的readme.md文件
+]]
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "GPIO_testdemo"
+VERSION = "001.000.000"
+
+log.info("main", "project name is ", PROJECT, "version is ", VERSION)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 gpio 输出功能模块
+require "gpio_output_task"
+
+-- 加载 gpio  输入功能模块
+-- require "gpio_input_task"
+
+-- 加载 gpio 上下拉功能模块
+-- require "gpio_pull_task"
+
+-- 加载 gpio 中断功能模块
+-- require "gpio_irq_task"
+
+-- 加载 gpio 中断计数功能模块
+-- require "gpio_irqcount_task"
+
+-- 加载 agpio 功能模块
+-- require "agpio_task"
+
+-- 加载 gpio 翻转功能模块
+-- require "gpio_toggle_task"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 131 - 0
module/Air780EPM/demo/gpio/readme.md

@@ -0,0 +1,131 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,负责初始化系统并启动各个GPIO功能任务;
+
+2、gpio_output_task.lua:GPIO输出模式功能模块,演示GPIO输出控制方法;
+
+3、gpio_input_task.lua:GPIO输入模式功能模块,演示GPIO输入读取方法;
+
+4、gpio_pull_task.lua:GPIO上拉下拉模式功能模块,演示GPIO上拉下拉配置;
+
+5、gpio_irq_task.lua:GPIO中断(触发)模式功能模块,演示GPIO中断触发、回调处理及按键短按长按检测;
+
+6、gpio_irqcount_task.lua:GPIO中断(计数)模式功能模块,演示GPIO中断计数功能;
+
+7、agpio_task.lua:AGPIO功能模块,演示低功耗GPIO在休眠模式下的特性;
+
+8、gpio_toggle_task.lua:GPIO翻转测速功能模块,演示GPIO脉冲输出功能;
+
+
+
+## 演示功能概述
+
+1、gpio_output_task:GPIO输出模式功能演示
+- 配置GPIO27为输出模式,控制开发板上的网络指示灯(蓝灯)
+- 实现简单的灯闪烁效果,LED灯交替点亮和熄灭
+- 演示gpio.setup的输出模式配置和状态控制方法
+
+2、gpio_input_task:GPIO输入模式功能演示
+- 配置GPIO24为输入模式,配置GPIO27为输出模式
+- 实现输入信号读取,并将读取到的电平状态实时反映到LED灯上
+- 演示gpio.debounce防抖功能的使用
+- 展示如何通过输入GPIO的状态控制输出GPIO
+
+3、gpio_pull_task:GPIO上拉下拉模式功能演示
+- 配置GPIO7为上拉输入模式,GPIO27为下拉输入模式
+- 演示gpio.debounce防抖功能在不同上下拉模式下的应用
+- 展示如何通过输入GPIO的状态控制输出GPIO
+
+4、gpio_irq_task:GPIO中断(触发)模式功能演示
+- 配置GPIO24为中断模式,支持上升沿和下降沿触发(双边沿触发)
+- 实现中断触发时的回调函数,打印触发信息
+- 演示gpio.debounce防抖功能在中断模式下的应用
+- 实现按键短按(小于3秒)和长按(大于等于3秒)的检测功能
+- 可连接按键或直接用杜邦线轻触GND进行测试
+
+5、gpio_irqcount_task:GPIO中断(计数)模式功能演示
+- 配置GPIO24为中断计数模式,用于统计信号触发次数
+- 配置PWM4输出1kHz、占空比50%的方波作为计数信号源
+- 实现周期性(1秒)统计和打印中断触发次数
+- 展示gpio.count函数在计数模式下的使用方法
+
+6、agpio_task:AGPIO功能演示
+- 演示普通GPIO和AGPIO在进入休眠模式前后的区别
+- 普通GPIO(GPIO1)在休眠后会掉电,而AGPIO(GPIO27)可保持电平状态
+- 演示如何通过pm.power控制系统进入低功耗模式
+- 展示休眠前后GPIO电平状态的变化情况
+
+7、gpio_toggle_task:GPIO翻转测速功能演示
+- 配置GPIO27为输出模式,初始电平为低电平
+- 演示gpio.pulse函数生成指定模式的电平变化序列
+- 输出8组电平变化(0xA9,即二进制10101001)
+- 展示如何通过快速电平翻转实现特定信号模式的输出
+
+## 演示硬件环境
+
+1、Air780EPM V1.3版本开发板一块:
+- 确保开发板正常供电
+- 开发板上的网络指示灯(蓝灯)与GPIO27相连
+- GPIO24可用于输入信号检测或中断触发测试
+
+2、TYPE-C USB数据线一根,Air780EPM V1.3版本开发板和数据线的硬件接线方式为:
+- Air780EPM V1.3版本开发板通过TYPE-C USB口供电;(外部供电/USB供电 拨动开关 拨到 USB供电一端)
+- TYPE-C USB数据线直接插到开发板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+3、可选硬件(根据需要):
+- 外部按键或信号源:用于GPIO输入模式和中断模式的信号输入测试
+- 面包板、杜邦线:用于连接外部信号源和开发板GPIO
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air780EPM 版本固件](https://docs.openluat.com/air780epm/luatos/firmware/version/)
+
+## 演示核心步骤
+
+在main.lua中,可以根据需要启用或禁用特定的GPIO功能任务:
+- 通过注释或取消注释相应的require语句来控制功能模块的加载
+- 每个功能模块作为独立的任务运行,可以单独测试或组合测试
+
+### 1、GPIO输出模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_output_task"`这一行
+3. 将代码下载到开发板并运行
+4. **演示效果**:开发板上的蓝色网络指示灯(GPIO27)将按照设定的时间间隔交替点亮和熄灭,实现呼吸灯效果
+
+### 2、GPIO输入模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_input_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:当GPIO24输入为高电平时,GPIO27上的蓝色LED灯会点亮;当GPIO24输入为低电平时,蓝色LED灯会熄灭
+
+### 3、GPIO上拉下拉模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保只保留`require "gpio_pull_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:串口日志中会周期性显示GPIO7(上拉输入)和GPIO27(下拉输入)的当前电平状态
+
+### 4、GPIO中断(触发)模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_irq_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:当GPIO24的电平发生变化时,会触发中断并检测按键动作,在串口日志中打印短按(小于3秒)或长按(大于等于3秒)事件
+
+### 5、GPIO中断(计数)模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_irqcount_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:PWM4输出方波信号到GPIO24,串口日志中每秒显示一次中断触发的计数值
+
+### 6、AGPIO功能
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "agpio_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:系统进入低功耗模式后,普通GPIO(GPIO1)电平会掉电,而AGPIO(GPIO27)可以保持其电平状态,通过示波器或逻辑分析仪等工具可以查看示例效果展示
+
+### 7、GPIO翻转测速
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_toggle_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:GPIO27会根据gpio.pulse函数的配置快速输出特定模式的电平变化序列(二进制10101001),通过示波器或逻辑分析仪等工具可以查看示例效果展示

+ 104 - 0
module/Air780EPM/demo/iperf/iperf_client.lua

@@ -0,0 +1,104 @@
+--[[
+@module  iperf_client
+@summary iperf客户端模式测试模块
+@version 1.0
+@date    2025.10.29
+@author  拓毅恒
+@usage
+本模块演示如何初始化CH390以太网并启动iperf客户端模式进行测试。
+适用于路由器连接场景,设备通过DHCP从路由器获取IP地址。
+1、初始化SPI接口连接CH390
+2、设置CH390驱动和网络参数
+3、配置从路由器获取IP地址
+4、连接到指定的iperf服务器并进行测试
+
+本文件没有对外接口,直接在 main.lua 中 require "iperf_client" 即可加载运行。
+]]
+
+-- 引入必要的模块
+local exnetif = require "exnetif"
+
+-- 配置服务器IP地址(需要根据实际服务器IP进行修改)
+local SERVER_IP = "192.168.1.3"  -- 这里需要修改为实际的服务器IP地址
+
+-- iperf测试报告处理函数
+local function iperf_report_handler(bytes, ms_duration, bandwidth)
+    -- 转换为Mbps显示
+    local bandwidth_mbps = bandwidth / 1024 / 1024 * 8
+    log.info("iperf报告", string.format("数据量: %d bytes, 持续时间: %d ms, 带宽: %.2f Mbps", bytes, ms_duration, bandwidth_mbps))
+end
+
+-- iperf客户端任务
+local function iperf_client_task()
+    log.info("iperf测试", "开始初始化网络...")
+    -- 使用exnetif配置SPI外接以太网芯片CH390H
+    exnetif.set_priority_order({
+        {
+            ETHERNET = {
+                pwrpin = 20, 
+                tp = netdrv.CH390,
+                opts = {spi = 0, cs = 8}
+            }
+        }
+    })
+    -- 等待IP地址获取成功
+    log.info("iperf测试", "等待获取IP地址...")
+    -- 设置IP获取超时
+    local ip_wait_count = 60
+    while true do
+        local ipv4 = socket.localIP(socket.LWIP_ETH)
+        if ipv4 and ipv4 ~= "0.0.0.0" then
+            log.info("iperf测试", "IP获取成功:", ipv4)
+            break
+        end
+        
+        -- 超时检查
+        if ip_wait_count <= 0 then
+            log.error("iperf测试", "获取IP地址超时")
+            return
+        end
+        ip_wait_count = ip_wait_count - 1
+        sys.wait(1000)
+    end
+    
+    -- 等待以太网连接
+    while not socket.adapter(socket.LWIP_ETH) do
+        sys.wait(100)
+    end
+    log.info("iperf测试", "以太网连接状态: 已连接")
+
+    -- 启动客户端模式,连接到指定服务器
+    log.info("iperf测试", "启动客户端模式")
+    log.info("iperf测试", "连接到服务器IP:", SERVER_IP, "端口: 5001")
+    
+    -- 连接服务器
+    iperf.client(socket.LWIP_ETH, SERVER_IP, 5001)
+    
+    -- 订阅iperf测试报告事件
+    sys.subscribe("IPERF_REPORT", iperf_report_handler)
+    
+    log.info("iperf测试", "测试开始")
+    
+        -- 设置测试循环次数,共测试2分钟
+    local test_count = 24
+    while test_count > 0 do
+        -- 等待IPERF_REPORT事件,超时时间5秒
+        local report_received = sys.waitUntil("IPERF_REPORT", 5000)
+        if report_received then
+            -- 如果收到报告事件,退出循环
+            log.info("iperf测试", "收到报告,结束测试")
+            break
+        else
+            -- 如果超时,继续测试
+            test_count = test_count - 1
+            log.info("iperf测试", "测试进行中...")
+        end
+    end
+    
+    -- 测试结束
+    log.info("iperf测试", "测试结束,关闭客户端")
+    iperf.abort()
+end
+
+-- 执行iperf客户端模式测试
+sys.taskInit(iperf_client_task)

+ 87 - 0
module/Air780EPM/demo/iperf/iperf_server.lua

@@ -0,0 +1,87 @@
+--[[
+@module  iperf_server
+@summary iperf服务器模式测试模块
+@version 1.0
+@date    2025.10.29
+@author  拓毅恒
+@usage
+本模块演示如何初始化CH390以太网并启动iperf服务器模式进行测试。
+适用于路由器连接场景,设备通过DHCP从路由器获取IP地址。
+使用步骤:
+1、初始化SPI接口连接CH390
+2、设置CH390驱动和网络参数
+3、配置从路由器获取IP地址
+4、启动iperf服务器并处理测试结果
+
+本文件没有对外接口,直接在 main.lua 中 require "iperf_server" 即可加载运行。
+]]
+
+-- 引入必要的模块
+local exnetif = require "exnetif"
+
+-- 记录服务器IP
+local server_ip = "0.0.0.0"
+
+-- iperf测试报告处理函数
+local function iperf_report_handler(bytes, ms_duration, bandwidth)
+    -- 转换为Mbps显示
+    local bandwidth_mbps = bandwidth / 1024 / 1024 * 8
+    log.info("iperf报告", string.format("数据量: %d bytes, 持续时间: %d ms, 带宽: %.2f Mbps", bytes, ms_duration, bandwidth_mbps))
+end
+
+-- iperf服务器任务
+local function iperf_server_task()
+    log.info("iperf测试", "开始初始化网络...")
+    -- 使用exnetif配置SPI外接以太网芯片CH390H
+    exnetif.set_priority_order({
+        {
+            ETHERNET = {
+                pwrpin = 20, 
+                tp = netdrv.CH390,
+                opts = {spi = 0, cs = 8}
+            }
+        }
+    })
+    -- 等待IP地址获取成功
+    log.info("iperf测试", "等待获取IP地址...")
+    local ip_wait_count = 60
+    while true do
+        local ipv4 = socket.localIP(socket.LWIP_ETH)
+        if ipv4 and ipv4 ~= "0.0.0.0" then
+            log.info("iperf测试", "IP获取成功:", ipv4)
+            server_ip = ipv4
+            break
+        end
+        
+        -- 超时检查
+        if ip_wait_count <= 0 then
+            log.error("iperf测试", "获取IP地址超时")
+            return
+        end
+        
+        ip_wait_count = ip_wait_count - 1
+        sys.wait(1000)
+    end
+    -- 等待以太网连接
+    while not socket.adapter(socket.LWIP_ETH) do
+        sys.wait(100)
+    end
+    log.info("iperf测试", "以太网连接状态: 已连接")
+    
+    -- 连接到路由器场景,不需要配置DHCP服务器
+    log.info("iperf测试", "网络配置完成")
+    
+    -- 订阅iperf测试报告事件
+    sys.subscribe("IPERF_REPORT", iperf_report_handler)
+    
+    -- 启动iperf服务器
+    log.info("iperf测试", "启动服务器模式")
+    log.info("iperf测试", "服务器IP地址:", server_ip, "端口: 5001")
+    iperf.server(socket.LWIP_ETH)
+    sys.wait(2000)
+    log.info("iperf测试", "服务器已启动,等待客户端连接")
+    log.info("iperf测试", "请在客户端设备上设置服务器IP地址为:", server_ip)
+end
+
+-- 执行iperf服务器模式测试
+sys.taskInit(iperf_server_task)

+ 67 - 0
module/Air780EPM/demo/iperf/main.lua

@@ -0,0 +1,67 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.28
+@author  拓毅恒
+@usage
+演示功能概述
+本demo演示如何使用LuatOS的iperf模块进行网络吞吐量测试。
+iperf是一种网络性能测试工具,支持服务器模式和客户端模式,可以测试网络的带宽和稳定性。
+本demo提供了两个独立的测试用例:
+1、iperf服务器模式 - 设备作为服务器等待客户端连接
+2、iperf客户端模式 - 设备作为客户端主动连接服务器
+
+更多说明参考本目录下的readme.md文件
+]]
+PROJECT = "IPERF_DEMO"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
+log.info("main", PROJECT, VERSION)
+
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 iperf 服务器测试模块
+require "iperf_server"
+
+-- 加载 iperf 客户端测试模块
+-- require "iperf_client"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 115 - 0
module/Air780EPM/demo/iperf/readme.md

@@ -0,0 +1,115 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,用于选择加载服务器或客户端模块;
+
+2、iperf_server.lua:iperf服务器模块,用于初始化网络并启动iperf服务器;
+
+3、iperf_client.lua:iperf客户端模块,用于初始化网络并连接到服务器进行测试;
+
+## 演示功能概述
+
+本项目演示如何使用Air780EPM开发板进行网络性能测试。通过修改后的代码,可以实现两台Air780EPM开发板通过路由器连接,进行网络吞吐量测试。
+
+1、支持以下功能特性:
+
+- 支持DHCP客户端模式,自动从路由器获取IP地址
+- 服务器模式和客户端模式分离,可在不同设备上运行
+- 增强的错误处理和超时机制
+- 清晰的日志输出,便于调试和监控
+- 带宽自动计算并以Mbps显示
+
+## 演示硬件环境
+
+1、两台Air780EPM开发板
+
+2、一台路由器(支持DHCP功能)
+
+3、一台电脑(用于查看日志和监控)
+
+4、网线两根
+
+5、TYPE-C USB数据线两根
+
+   - Air780EPM开发板通过TYPE-C USB口供电;(外部供电/USB供电 拨动开关 拨到 USB供电一端)
+   - TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air780EPM 固件](https://docs.openluat.com/air780epm/luatos/firmware/version/)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、配置服务器端(一台开发板)
+
+   a. 确保`main.lua`中已启用服务器模块,禁用客户端模块:
+   ```lua
+   -- 加载 iperf 服务器测试模块
+   require "iperf_server"
+
+   -- 加载 iperf 客户端测试模块
+   -- require "iperf_client"
+   ```
+
+   b. 烧录到一台Air780EPM开发板
+
+   c. 连接开发板到路由器的LAN口
+
+   d. 启动开发板,它将自动从路由器获取IP地址并启动iperf服务器
+
+3、配置客户端(另一台开发板)
+
+   a. 修改`iperf_client.lua`文件中的服务器IP地址为服务器开发板的实际IP地址:
+
+   ```lua
+   -- 配置服务器IP地址(需要根据实际服务器IP进行修改)
+   local SERVER_IP = "192.168.1.3"  -- 这里需要修改为实际的服务器IP地址
+   ```
+
+   b. 确保`main.lua`中已启用客户端模块,禁用服务器模块:
+
+   ```lua
+   -- 加载 iperf 服务器测试模块
+   -- require "iperf_server"
+
+   -- 加载 iperf 客户端测试模块
+   require "iperf_client"
+   ```
+
+   c. 烧录到另一台Air780EPM开发板
+
+   d. 连接开发板到路由器的LAN口
+
+   e. 启动开发板,它将自动从路由器获取IP地址并尝试连接到服务器
+
+## 查看测试结果
+
+测试启动后,可以通过Luatools工具查看测试日志。客户端将显示实时的测试报告,包括数据量、持续时间和带宽(以Mbps为单位)。
+
+```lua
+2025-11-06 17:02:24.658][000000013.298] I/user.iperf测试 测试进行中...
+[2025-11-06 17:02:24.675][000000013.314] D/iperf iperf正常结束, type 1
+[2025-11-06 17:02:24.677][000000013.314] D/lwiperf iperf_free 88 c1d553c
+[2025-11-06 17:02:24.678][000000013.316] D/iperf report bytes 5989824 ms_duration 10002 bandwidth 4784 kbps
+[2025-11-06 17:02:24.680][000000013.317] I/user.iperf报告 数据量: 5989824 bytes, 持续时间: 10002 ms, 带宽: 0.04 Mbps
+```
+
+## 注意事项
+
+1、确保两台开发板和电脑都连接到同一个路由器,并且路由器已启用DHCP功能
+
+2、服务器的IP地址需要在客户端配置文件中正确设置,否则客户端将无法连接
+
+3、默认情况下,服务器在端口5001上监听连接请求
+
+4、测试默认持续2分钟后自动结束
+
+## 常见问题排查
+
+1、无法连接到服务器
+   - 确认服务器IP地址是否正确
+   - 检查两台设备是否在同一网段
+   - 检查网线连接是否牢固

+ 57 - 112
module/Air780EPM/demo/mobile/main.lua

@@ -1,122 +1,67 @@
-
--- LuaTools需要PROJECT和VERSION这两个信息
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.23
+@author  拓毅恒
+@usage
+本demo演示的核心功能为:
+移动网络功能测试,包括SIM卡管理、基站数据查询、频段(Band)测试和修改、移动网络信息获取(IMEI/IMSI/信号强度等)以及SIM卡状态监控。
+通过加载mobile_test模块来运行相关测试功能。
+
+更多说明参考本目录下的readme.md文件
+]]
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
 PROJECT = "mobiledemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
+VERSION = "001.000.000"
 
+log.info("main", "project name is ", PROJECT, "version is ", VERSION)
 
--- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
-if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
-    pm.power(pm.PWK_MODE, false)
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
 end
 
-
--- 对于双卡的设备, 可以设置为自动选sim卡
--- 但是, 这样SIM1所在管脚就强制复用为SIM功能, 不可以再复用为GPIO
--- mobile.simid(2)
-mobile.simid(2,true)--优先用SIM0
-
-
-sys.taskInit(function()
-
-	log.info("status", mobile.status())
-    local band = zbuff.create(40)
-    local band1 = zbuff.create(40)
-    mobile.getBand(band)
-    log.info("当前使用的band:")
-    for i=0,band:used()-1 do
-        log.info("band", band[i])
-    end
-    band1[0] = 38
-    band1[1] = 39
-    band1[2] = 40
-    mobile.setBand(band1, 3)    --改成使用38,39,40
-    band1:clear()
-    mobile.getBand(band1)
-    log.info("修改后使用的band:")
-    for i=0,band1:used()-1 do
-        log.info("band", band1[i])
-    end
-    mobile.setBand(band, band:used())    --改回原先使用的band,也可以下载的时候选择清除fs
-
-    mobile.getBand(band1)
-    log.info("修改回默认使用的band:")
-    for i=0,band1:used()-1 do
-        log.info("band", band1[i])
-    end
-	-- mobile.vsimInit()
-	-- mobile.flymode(nil,true)
-	-- mobile.vsimOnOff(true)
-	-- mobile.flymode(nil,false)
-    -- mobile.apn(0,2,"") -- 使用默认APN激活CID2
-    -- mobile.rtime(3) -- 在无数据交互时,RRC 3秒后自动释放
-    -- 下面是配置自动搜索小区间隔,和轮询搜索冲突,开启1个就可以了
-    -- mobile.setAuto(10000,30000, 5) -- SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
-	log.info("status", mobile.status())
-    sys.wait(2000)
-    while 1 do
-        log.info("imei", mobile.imei())
-        log.info("imsi", mobile.imsi())
-        local sn = mobile.sn()
-        if sn then
-            log.info("sn",   sn:toHex())
-        end
-		log.info("status", mobile.status())
-        
-
-        log.info("iccid", mobile.iccid())
-        log.info("csq", mobile.csq()) -- 4G模块的CSQ并不能完全代表强度
-        log.info("rssi", mobile.rssi()) -- 需要综合rssi/rsrq/rsrp/snr一起判断
-        log.info("rsrq", mobile.rsrq())
-        log.info("rsrp", mobile.rsrp())
-        log.info("snr", mobile.snr())
-        log.info("simid", mobile.simid()) -- 这里是获取当前SIM卡槽
-        log.info("apn", mobile.apn(0,1))
-        log.info("ip", socket.localIP())
-		log.info("lua", rtos.meminfo())
-        -- sys内存
-        log.info("sys", rtos.meminfo("sys"))
-        sys.wait(15000)
-    end
-end)
-
--- 基站数据的查询
-
--- 订阅式, 模块本身会周期性查询基站信息,但通常不包含临近小区
-sys.subscribe("CELL_INFO_UPDATE", function()
-    log.info("cell", json.encode(mobile.getCellInfo()))
-end)
-
--- 轮询式, 包含临近小区信息,这是手动搜索,和上面的自动搜索冲突,开启一个就行
-sys.taskInit(function()
-    sys.wait(5000)
-	mobile.config(mobile.CONF_SIM_WC_MODE, 2)
-    while 1 do
-        mobile.reqCellInfo(10)
-        sys.wait(11000)
-        log.info("cell", json.encode(mobile.getCellInfo()))
-		mobile.config(mobile.CONF_SIM_WC_MODE, 2)
-    end
-end)
-
--- 获取sim卡的状态
-
-sys.subscribe("SIM_IND", function(status, value)
-    log.info("sim status", status)
-    if status == 'GET_NUMBER' then
-        log.info("number", mobile.number(0))
-    end
-	if status == "SIM_WC" then
-        log.info("sim", "write counter", value)
-    end
-end)
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 mobile_test 功能模块
+require "mobile_test"
 
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()
 -- sys.run()之后后面不要加任何语句!!!!!
+

+ 114 - 0
module/Air780EPM/demo/mobile/mobile_test.lua

@@ -0,0 +1,114 @@
+--[[
+@module  mobile_test
+@summary Air780EPM mobile功能测试模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 Air780EPM 开发板演示移动网络功能的代码示例,核心业务逻辑包括:
+1. SIM卡管理和选择(自动选卡功能)
+2. 基站数据查询(订阅式和轮询式两种方式)
+3. 频段(Band)测试和修改
+4. 移动网络信息获取(IMEI、IMSI、信号强度等)
+5. SIM卡状态监控
+]]
+
+-- 对于双卡的设备, 可以设置为自动选sim卡
+-- 但是SIM1所在管脚就强制复用为SIM功能, 占用4个IO口(gpio4/5/6/23),不可以再复用为GPIO
+-- mobile.simid(2)
+mobile.simid(2,true)--优先用SIM0
+
+-- 基站数据的查询
+-- 订阅式, 模块本身会周期性查询基站信息,但通常不包含临近小区
+local function sub_cell_info_task()
+    log.info("cell", json.encode(mobile.getCellInfo()))
+end
+
+sys.subscribe("CELL_INFO_UPDATE", sub_cell_info_task)
+
+-- 轮询式, 包含临近小区信息,这是手动搜索,和上面的自动搜索冲突,开启一个就行
+local function get_cell_info_task()
+    sys.wait(5000)
+	mobile.config(mobile.CONF_SIM_WC_MODE, 2)
+    while 1 do
+        mobile.reqCellInfo(10)
+        sys.wait(11000)
+        log.info("cell", json.encode(mobile.getCellInfo()))
+		mobile.config(mobile.CONF_SIM_WC_MODE, 2)
+    end
+end
+
+-- 获取sim卡的状态
+local function get_sim_status_task(status, value)
+    log.info("sim status", status)
+    if status == 'GET_NUMBER' then
+        log.info("number", mobile.number(0))
+    end
+	if status == "SIM_WC" then
+        log.info("sim", "write counter", value)
+    end
+end
+
+sys.subscribe("SIM_IND", get_sim_status_task)
+
+-- 定义测试band和移动网络信息的函数
+local function mobileinfo_task()
+    -- 设置默认APN 
+    -- 注意:在国内公网卡基本上都不需要设置APN, 专网卡才需要设置
+    mobile.apn(0,1,"cmiot","","",nil,0)
+    -- 开启SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
+    mobile.setAuto(10000,30000, 5) -- 此函数仅需要配置一次
+    
+    log.info("************开始测试band************")
+    local band = zbuff.create(40)
+    local band1 = zbuff.create(40)
+    mobile.getBand(band)
+    log.info("当前使用的band:")
+    for i=0,band:used()-1 do
+        log.info("band", band[i])
+    end
+    band1[0] = 38
+    band1[1] = 39
+    band1[2] = 40
+    mobile.setBand(band1, 3)    --改成使用38,39,40
+    band1:clear()
+    mobile.getBand(band1)
+    log.info("修改后使用的band:")
+    for i=0,band1:used()-1 do
+        log.info("band", band1[i])
+    end
+    mobile.setBand(band, band:used())    --改回原先使用的band,也可以下载的时候选择清除fs
+
+    mobile.getBand(band1)
+    log.info("修改回默认使用的band:")
+    for i=0,band1:used()-1 do
+        log.info("band", band1[i])
+    end
+    log.info("************band测试完毕************")
+
+	log.info("status", mobile.status())
+    sys.wait(2000)
+    while 1 do
+        log.info("imei", mobile.imei())
+        log.info("imsi", mobile.imsi())
+        log.info("apn", mobile.apn()) -- 获取当前APN
+        log.info("status", mobile.status())
+        log.info("iccid", mobile.iccid())
+        log.info("csq", mobile.csq()) -- 4G模块的CSQ并不能完全代表强度
+        log.info("rssi", mobile.rssi()) -- 需要综合rssi/rsrq/rsrp/snr一起判断
+        log.info("rsrq", mobile.rsrq())
+        log.info("rsrp", mobile.rsrp())
+        log.info("snr", mobile.snr())
+        log.info("simid", mobile.simid()) -- 这里是获取当前SIM卡槽
+        log.info("apn", mobile.apn(0,1))
+        -- sys内存
+        log.info("lua", rtos.meminfo())
+        log.info("sys", rtos.meminfo("sys"))
+        sys.wait(15000)
+    end
+end
+
+-- 轮询式查找小区, 包含临近小区信息,与上面订阅式搜索冲突,开启一个就行
+-- sys.taskInit(get_cell_info_task)
+-- 启动测试任务
+sys.taskInit(mobileinfo_task)

+ 97 - 0
module/Air780EPM/demo/mobile/readme.md

@@ -0,0 +1,97 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,负责初始化系统环境和加载移动网络测试模块;
+
+2、mobile_test.lua:移动网络功能测试模块,演示Air780EPM的移动网络相关功能;
+
+## 演示功能概述
+
+1、mobile_test:演示以下几种应用场景的使用方式
+
+- SIM卡配置和管理功能演示;
+- 基站数据查询(订阅式和轮询式)功能演示;
+- SIM卡状态订阅功能演示;
+- 频段(Band)测试和修改功能演示;
+- 移动网络信息获取(IMEI/IMSI/信号强度等)功能演示;
+
+## 演示硬件环境
+
+1、Air780EPM开发板一块 + 可上网的SIM卡一张 + 4G天线一根:
+
+- SIM卡插入开发板的SIM卡槽
+- 天线装到开发板上
+
+2、TYPE-C USB数据线一根 + USB转串口数据线一根,Air780EPM开发板和数据线的硬件接线方式为:
+
+- Air780EPM开发板通过TYPE-C USB口供电;(外部供电/USB供电 拨动开关 拨到 USB供电一端)
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、Air780EPM 版本固件:[Air780EPM 版本固件](https://docs.openluat.com/air780epm/luatos/firmware/version/)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、确保SIM卡已正确插入开发板
+
+3、Luatools烧录内核固件和demo脚本代码
+
+4、烧录成功后,自动开机运行,通过串口日志可以观察到以下信息:
+
+- SIM卡状态监控信息
+- 基站数据查询结果
+- 移动网络信息(IMEI/IMSI/信号强度等)
+- 频段测试和修改结果
+
+``` lua
+[2025-10-23 15:58:31.141][000000000.361] I/user.main project name is  mobiledemo version is  001.000.000
+[2025-10-23 15:58:31.142][000000000.370] I/mobile sim set to 2 , ret 0
+[2025-10-23 15:58:31.144][000000000.373] I/user.************开始测试band************
+[2025-10-23 15:58:31.161][000000001.774] I/user.当前使用的band:
+[2025-10-23 15:58:31.163][000000001.775] I/user.band 1
+[2025-10-23 15:58:31.165][000000001.775] I/user.band 3
+[2025-10-23 15:58:31.167][000000001.775] I/user.band 5
+[2025-10-23 15:58:31.169][000000001.776] I/user.band 8
+[2025-10-23 15:58:31.170][000000001.776] I/user.band 34
+[2025-10-23 15:58:31.172][000000001.776] I/user.band 38
+[2025-10-23 15:58:31.173][000000001.776] I/user.band 39
+[2025-10-23 15:58:31.175][000000001.777] I/user.band 40
+[2025-10-23 15:58:31.176][000000001.777] I/user.band 41
+[2025-10-23 15:58:31.178][000000001.791] I/user.修改后使用的band:
+[2025-10-23 15:58:31.179][000000001.792] I/user.band 38
+[2025-10-23 15:58:31.180][000000001.792] I/user.band 39
+[2025-10-23 15:58:31.182][000000001.793] I/user.band 40
+[2025-10-23 15:58:31.183][000000001.799] I/user.修改回默认使用的band:
+[2025-10-23 15:58:31.184][000000001.800] I/user.band 1
+[2025-10-23 15:58:31.186][000000001.800] I/user.band 3
+[2025-10-23 15:58:31.187][000000001.800] I/user.band 5
+[2025-10-23 15:58:31.189][000000001.800] I/user.band 8
+[2025-10-23 15:58:31.190][000000001.801] I/user.band 34
+[2025-10-23 15:58:31.191][000000001.801] I/user.band 38
+[2025-10-23 15:58:31.193][000000001.801] I/user.band 39
+[2025-10-23 15:58:31.195][000000001.802] I/user.band 40
+[2025-10-23 15:58:31.196][000000001.802] I/user.band 41
+[2025-10-23 15:58:31.198][000000001.802] I/user.************band测试完毕************
+[2025-10-23 15:58:48.147][000000018.809] I/user.imei 864793080175404
+[2025-10-23 15:58:48.149][000000018.809] I/user.imsi 460240452233401
+[2025-10-23 15:58:48.151][000000018.810] I/user.status 1
+[2025-10-23 15:58:48.153][000000018.810] I/user.iccid 89860855102480513401
+[2025-10-23 15:58:48.155][000000018.810] I/user.csq 27
+[2025-10-23 15:58:48.157][000000018.811] I/user.rssi -58
+[2025-10-23 15:58:48.158][000000018.811] I/user.rsrq -9
+[2025-10-23 15:58:48.160][000000018.811] I/user.rsrp -87
+[2025-10-23 15:58:48.161][000000018.812] I/user.snr 16
+[2025-10-23 15:58:48.163][000000018.812] I/user.simid 0
+[2025-10-23 15:58:48.169][000000018.812] I/user.apn cmiot.MNC024.MCC460.GPRS
+[2025-10-23 15:58:48.171][000000018.813] I/user.lua 4194296 56552 56552
+[2025-10-23 15:58:48.172][000000018.813] I/user.sys 3202992 355468 360724
+[2025-10-23 15:58:56.722][000000027.379] I/user.cell [{"mnc":0,"dlbandwidth":5,"tdd":0,"earfcn":1300,"ulbandwidth":5,"band":3,"mcc":460,"pci":219,"rsrp":-86,"tac":18511,"rssi":-57,"rsrq":-9,"snr":16,"cid":190213964},{"mnc":15,"earfcn":1300,"pci":219,"rsrp":-86,"tac":18511,"mcc":460,"rsrq":-9,"snr":16,"cid":190213964},{"mnc":0,"earfcn":40936,"pci":368,"rsrp":-103,"tac":18511,"mcc":460,"rsrq":-7,"snr":0,"cid":192844432}]
+[2025-10-23 15:58:56.726][000000027.382] I/user.sim status SIM_WC
+[2025-10-23 15:58:56.728][000000027.383] I/user.sim write counter 2
+```
+
+5、日志中会实时显示移动网络相关信息的变化,可通过观察日志来验证功能是否正常工作

+ 0 - 37
module/Air8000/demo/gpio/AGPIO/main.lua

@@ -1,37 +0,0 @@
--- 本示例对比了普通GPIO和AGPIO的进入休眠模式前后的区别。
--- Luatools需要PROJECT和VERSION这两个信息
-PROJECT = "AGPIO_GPIO_testdemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
-local gpio_number = 1   -- 普通GPIO GPIO号为1,休眠后掉电。
-local Agpio_number = 27 -- AGPIO GPIO号为27(模块上35管脚),休眠后可保持电平。
-
-gpio.setup(gpio_number, 1)
-gpio.setup(Agpio_number, 1)
-
-sys.taskInit(function()
-    sys.wait(16000)
-    -- 关闭USB电源
-    pm.power(pm.USB, false)
-    -- 进入低功耗模式
-    pm.power(pm.WORK_MODE, 3)
-    sys.wait(10000)
-    pm.power(pm.USB, true)
-    pm.power(pm.WORK_MODE, 0)
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 39
module/Air8000/demo/gpio/GPIO上拉下拉模式/main.lua

@@ -1,39 +0,0 @@
--- Luatools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio2demo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000)--初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
-end
-
---配置gpio2为中断下拉模式,模块上30 管脚
---配置gpio27为中断下拉模式,模块上35 管脚
---请根据实际需求更改gpio编号和上下拉
-local gpio_pin1 = 2      
-local gpio_pin2 = 27
--- 按键防抖函数
-gpio.debounce(gpio_pin1, 50)
-gpio.debounce(gpio_pin2, 50)
-
--- 设置GPIO7引脚为上拉输入模式
-gpio.setup(gpio_pin1, nil, gpio.PULLUP)
-
--- 设置GPIO27引脚为下拉输入模式
-gpio.setup(gpio_pin2, nil, gpio.PULLDOWN)
-
-
-sys.timerLoopStart(function ()
-    log.info("GPIO",gpio_pin1,"电平",gpio.get(gpio_pin1))
-    log.info("GPIO",gpio_pin2,"电平",gpio.get(gpio_pin2))
-end,1000)
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 30
module/Air8000/demo/gpio/GPIO中断(触发)模式/main.lua

@@ -1,30 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio_irq"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
--- 配置gpio27为中断模式,上升沿(gpio.RISING)和下降沿(gpio.FALLING)均触发(gpio.BOTH)
--- 请根据实际需求更改gpio编号和触发模式
-local gpio_pin = 153
-gpio.debounce(gpio_pin, 100)
-gpio.setup(gpio_pin, function()
-    log.info("gpio", gpio_pin, "被触发")
-end, gpio.PULLUP, gpio.BOTH)
--- 使用wakeup 获取中断
-gpio.setup(gpio.WAKEUP0, function()
-    log.info("WAKEUP0", gpio_pin, "被触发")
-end, gpio.PULLUP, gpio.BOTH)
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 34
module/Air8000/demo/gpio/GPIO中断(计数)模式/main.lua

@@ -1,34 +0,0 @@
--- Luatools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio_irq"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    --添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000)--初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
-end
-
---配置gpio27为中断计数模式
---请根据实际需求更改gpio编号和上下拉
-local gpio_pin = 27
--- gpio.setup(gpio_pin, gpio.count, gpio.PULLUP, gpio.FALLING)
-gpio.setup(gpio_pin, gpio.count)
-
---配置PWM4输出 1kHZ 占空比50%的方波作为信号源
-pwm.open(4,1000,50)
-
---每隔1S统计一次中断触发的次数
-sys.taskInit(function()
-    while true do
-        sys.wait(1000)
-        log.info("irq cnt", gpio.count(gpio_pin))
-    end
-end)
-
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 34
module/Air8000/demo/gpio/GPIO翻转测速/main.lua

@@ -1,34 +0,0 @@
--- Luatools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio2demo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
-local test_gpio_number = 27    ---模块上35管脚
-
-gpio.setup(test_gpio_number, 0, gpio.PULLUP)
-
-sys.taskInit(function()
-    sys.wait(100)
-    while true do
-        sys.wait(100)
-        -- 通过GPIO27脚输出输出8组电平变化
-        -- 0xA9就是输出的电平高低状态,即 10101001
-        gpio.pulse(test_gpio_number, 0xA9, 8, 0)
-        log.info("gpio----------->pulse2")
-    end
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 41
module/Air8000/demo/gpio/GPIO输入模式/main.lua

@@ -1,41 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio_irq"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
--- 配置gpio27为输入模式
--- 配置GPIO20(即开发板上LED灯)为输出模式
-
--- 请根据实际需求更改gpio编号和上下拉
-
-local inputpin = 27
-local ledpin = 20
-
-local input = gpio.setup(inputpin,nil)
-local led = gpio.setup(ledpin, 1)
-
-gpio.debounce(inputpin, 50)
---GPIO27检测到有高低电平输入后,会返回GPIO27当前获取到的电平为高还是低,高返回值为1,低返回值为0
---将这个返回值,传给GPIO20(LED),为0 则GPIO20输出低电平(LED灯灭),为1则输出高电平(LED灯亮)
-sys.taskInit(function ()
-    while true do
-        led(input())
-        sys.wait(500)
-    end
-end)
-
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 37
module/Air8000/demo/gpio/GPIO输出模式/main.lua

@@ -1,37 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "gpiodemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
-local gpio_number = 20 -- air8000 核心板上的23 管脚
-
-LED = gpio.setup(gpio_number, 1) -- 设置GPIO20为输出模式
-
-sys.taskInit(function()
-    -- 开始呼吸灯
-    local count = 0
-    while 1 do
-        -- 呼吸灯程序
-        LED(1)
-        log.info("GPIO", "Go Go Go", count, rtos.bsp())
-        sys.wait(500)--点亮时间 500ms
-        LED(0)
-        sys.wait(500)--熄灭时间 500ms
-        count = count + 1
-    end
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 33 - 0
module/Air8000/demo/gpio/agpio_task.lua

@@ -0,0 +1,33 @@
+--[[
+@module  agpio_task
+@summary Air8000演示agpio功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air8000开发板演示 AGPIO 功能的代码示例,核心业务逻辑为:
+AGPIO与普通GPIO在PSM+模式下的区别演示
+1. 初始化普通GPIO和AGPIO
+   - 配置普通GPIO1为输出模式并设置为高电平
+   - 配置AGPIO21为输出模式并设置为高电平
+2. 等待一段时间让GPIO状态稳定
+3. 关闭USB电源以降低功耗
+4. 进入深度休眠模式(PSM+模式),此时RAM 掉电,唤醒后程序从初始状态运行。
+5. 观察结果:通过示波器或逻辑分析仪等设备观察进入PSM+模式后普通GPIO为掉电状态,而AGPIO保持了休眠前的电平状态
+]]
+
+local gpio_number = 1   -- 普通GPIO GPIO号为1,休眠后掉电。
+local Agpio_number = 21 -- AGPIO GPIO号为21,休眠后可保持电平。
+
+gpio.setup(gpio_number, 1)
+gpio.setup(Agpio_number, 1)
+
+local function enterlowpower()
+    sys.wait(10000)
+    -- 关闭USB电源
+    pm.power(pm.USB, false)
+    -- 进入PSM+模式
+    pm.power(pm.WORK_MODE, 3)
+end
+
+sys.taskInit(enterlowpower)

+ 41 - 0
module/Air8000/demo/gpio/gpio_input_task.lua

@@ -0,0 +1,41 @@
+--[[
+@module  gpio_input_task
+@summary Air8000演示GPIO输入检测与LED联动示例
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air8000开发板演示GPIO输入检测功能的代码示例,核心业务逻辑为:
+1. 初始化GPIO1为输入模式(可用杜邦线接稳压电源,高电平接3.3V,低电平接地)
+2. 初始化GPIO146(板载LED)为输出模式,默认高电平(亮)
+3. 启用输入消抖,消抖时间50 ms
+4. 每500 ms读取一次GPIO1电平,并同步控制LED亮灭
+5. 高电平→LED亮,低电平→LED灭
+]]
+
+-- 配置gpio1为输入模式
+-- 配置GPIO146(即开发板上LED灯)为输出模式
+
+-- 请根据实际需求更改gpio编号和上下拉
+
+local inputpin = 1
+local ledpin = 146
+
+local input = gpio.setup(inputpin, nil, gpio.PULLDOWN)
+local led = gpio.setup(ledpin, 1)
+
+gpio.debounce(inputpin, 50)
+--GPIO1检测到有高低电平输入后,会返回GPIO1当前获取到的电平为高还是低,高返回值为1,低返回值为0
+--将这个返回值,传给GPIO146(LED),为0 则GPIO146输出低电平(LED灯灭),为1则输出高电平(LED灯亮)
+-- 定义一个函数用于循环读取输入引脚电平并控制LED灯
+local function controlLed()
+    local level = 0
+    while true do
+        level = gpio.get(inputpin)
+        log.info("gpio","set netled level: ",level)
+        gpio.set(ledpin, level)
+        sys.wait(500)
+    end
+end
+
+sys.taskInit(controlLed)

+ 57 - 0
module/Air8000/demo/gpio/gpio_irq_task.lua

@@ -0,0 +1,57 @@
+--[[
+@module  gpio_irq_task
+@summary Air8000演示GPIO中断功能模块
+@version 1.0
+@date    2025.11.5
+@author  拓毅恒
+@usage
+本文件为Air8000开发板演示GPIO按键短按和长按检测的代码示例,核心业务逻辑为:
+1. 配置GPIO20为中断模式,上升沿和下降沿均触发
+2. 实现按键短按(小于3秒)和长按(大于等于3秒)的检测功能
+3. 可连接按键或直接用杜邦线轻触GND进行测试
+4. 注意:使用杜邦线测试时,因为脉冲可能无法控制,所以不要加防抖防止程序测试异常
+]]
+
+-- 配置gpio20为中断模式,上升沿(gpio.RISING)和下降沿(gpio.FALLING)均触发(gpio.BOTH)
+local gpio_pin = 20
+-- gpio.debounce(gpio_pin, 100) -- 实际设计板子时,根据自己的需求可以更改防抖配置以及打开防抖
+
+-- 按键状态变量
+local long_press_threshold = 3000  -- 长按判断阈值,3秒
+local current_state = 1  -- 跟踪当前按键状态,1为释放,0为按下
+
+-- 定时器回调函数,处理长按事件
+local function timer_callback(gpio_id)
+    log.info("按键检测", "长按事件", gpio_id)
+end
+
+-- 定义GPIO中断处理函数
+local function gpio_irq_handler()
+    local pin_state = gpio.get(gpio_pin)  -- 获取GPIO当前状态
+    
+    -- 只有当状态发生变化时才处理
+    if pin_state ~= current_state then
+        current_state = pin_state  -- 更新当前状态
+        
+        if pin_state == 0 then
+            -- 按键按下
+            log.info("按键检测", "按键按下")
+            if not sys.timerIsActive(timer_callback, gpio_pin) then
+                -- 启动定时器,3秒后触发长按事件
+                sys.timerStart(timer_callback, long_press_threshold, gpio_pin)
+            end
+        elseif pin_state == 1 then
+            -- 按键释放
+            log.info("按键检测", "按键释放")
+            
+            -- 如果定时器还在运行,说明是短按
+            if sys.timerIsActive(timer_callback, gpio_pin) then
+                sys.timerStop(timer_callback, gpio_pin)
+                log.info("按键检测", "短按事件")
+            end
+        end
+    end
+end
+
+-- 配置GPIO中断
+gpio.setup(gpio_pin, gpio_irq_handler, gpio.PULLUP, gpio.BOTH)

+ 29 - 0
module/Air8000/demo/gpio/gpio_irqcount_task.lua

@@ -0,0 +1,29 @@
+--[[
+@module  gpio_irqcount_task
+@summary Air8000演示GPIO中断计数功能
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为Air8000开发板演示GPIO中断计数功能的代码示例,核心业务逻辑为:
+1. 配置GPIO21为中断计数模式,用于统计外部信号触发次数
+2. 每1秒读取并打印一次中断触发次数
+3. 可用杜邦线轻触3.3V电源正极,即可观察中断触发效果。
+]]
+
+-- 配置gpio21为中断计数模式
+-- 设置好后系统会自动记录中断触发次数。
+local gpio_pin = 21
+-- gpio.setup(gpio_pin, gpio.count, gpio.PULLUP, gpio.FALLING)
+gpio.setup(gpio_pin, gpio.count)
+
+-- 每隔1S统计一次中断触发的次数
+local function countIrq()
+    while true do
+        sys.wait(1000)
+        -- 返回从上次调用该函数后到当前时刻的中断触发次数
+        log.info("irq cnt", gpio.count(gpio_pin)) -- 调用函数时会自动清空中断累计值
+    end
+end
+
+sys.taskInit(countIrq)

+ 35 - 0
module/Air8000/demo/gpio/gpio_output_task.lua

@@ -0,0 +1,35 @@
+--[[
+@module  gpio_output_task
+@summary Air8000 演示GPIO输出功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 Air8000 开发板演示 GPIO 输出功能的代码示例,核心业务逻辑为:
+通过GPIO146控制开发板载网络指示灯(绿灯)实现闪烁效果
+1. 初始化GPIO146为输出模式
+2. 在任务循环中周期性地拉高/拉低GPIO146
+3. 通过500ms亮灭间隔实现简单的闪烁效果
+]]
+
+local gpio_number = 146 -- Air8000 开发板上的网络指示灯(绿灯)与GPIO146相连
+
+gpio.setup(gpio_number, 1) -- 设置GPIO146为输出模式
+
+-- 定义任务函数
+local function ledlight_task()
+    local count = 0
+    while 1 do
+        -- 闪烁灯程序
+        gpio.set(gpio_number, 1)
+        log.info("GPIO", "点亮 LED")
+        sys.wait(500)--点亮时间 500ms
+        gpio.set(gpio_number, 0)
+        log.info("GPIO", "熄灭 LED")
+        sys.wait(500)--熄灭时间 500ms
+        count = count + 1
+    end
+end
+
+-- 执行闪烁灯任务函数
+sys.taskInit(ledlight_task)

+ 32 - 0
module/Air8000/demo/gpio/gpio_pull_task.lua

@@ -0,0 +1,32 @@
+--[[
+@module  gpio_pull_task
+@summary Air8000演示GPIO上下拉功能模块
+@version 1.0
+@date    2025.10.2
+@author  拓毅恒
+@usage
+本文件为Air8000开发板演示 GPIO 上下拉功能的代码示例,核心业务逻辑为:
+1. 配置GPIO1为上拉输入模式
+2. 配置GPIO2为下拉输入模式
+3. 定时读取并打印两个GPIO的电平状态
+4. 将GPIO1和GPIO2引脚接地或接3.3V来控制GPIO1和GPIO2的电平变化,验证上拉/下拉配置是否生效
+]]
+
+local gpio_pin1 = 1
+local gpio_pin2 = 2
+-- 按键防抖函数
+gpio.debounce(gpio_pin1, 50)
+gpio.debounce(gpio_pin2, 50)
+
+-- 设置GPIO1引脚为上拉输入模式
+gpio.setup(gpio_pin1, nil, gpio.PULLUP)
+
+-- 设置GPIO2引脚为下拉输入模式
+gpio.setup(gpio_pin2, nil, gpio.PULLDOWN)
+
+local function gpiopulltask()
+    log.info("GPIO",gpio_pin1,"电平",gpio.get(gpio_pin1))
+    log.info("GPIO",gpio_pin2,"电平",gpio.get(gpio_pin2))
+end
+
+sys.timerLoopStart(gpiopulltask,1000)

+ 33 - 0
module/Air8000/demo/gpio/gpio_toggle_task.lua

@@ -0,0 +1,33 @@
+--[[
+@module  gpio_toggle
+@summary Air8000演示波形翻转功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 Air8000 开发板演示 GPIO 翻转(脉冲)输出的代码示例,核心业务逻辑为:
+GPIO 快速翻转测速与波形观测
+1. 配置 GPIO2 为输出模式并上拉初始化;
+2. 在任务中循环调用 gpio.pulse() 按给定模式输出脉冲序列;
+   - 演示模式为 0xA9(二进制 10101001),每次输出 8 组电平变化;
+3. 使用示波器或逻辑分析仪连接到 GPIO2,观察翻转波形与频率,翻转一次所需时间大概 50ns;
+4. 可根据需要修改 `test_gpio_number`、`0xA9`(翻转模式)和 `8`(组数),以测试不同引脚和模式;
+5. 注意:高频翻转请勿直接驱动重负载,推荐用于逻辑检测或带限流的 LED 演示。
+]]
+
+local test_gpio_number = 2
+
+gpio.setup(test_gpio_number, 0, gpio.PULLUP)
+
+local function gpiotoggletask()
+    sys.wait(100)
+    while true do
+        sys.wait(100)
+        -- 通过GPIO2脚输出输出8组电平变化
+        -- 0xA9就是输出的电平高低状态,即 10101001
+        gpio.pulse(test_gpio_number, 0xA9, 8, 0)
+        log.info("gpio----------->pulse")
+    end
+end
+
+sys.taskInit(gpiotoggletask)

+ 84 - 0
module/Air8000/demo/gpio/main.lua

@@ -0,0 +1,84 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本demo演示的核心功能为:
+演示GPIO的多种功能模式,包括输出模式、输入模式、上拉下拉模式、中断触发模式、中断计数模式、AGPIO低功耗模式以及GPIO翻转测速功能。
+用户可通过取消注释相应的require语句来启用不同的功能模块进行测试。
+
+更多说明参考本目录下的readme.md文件
+]]
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "GPIO_testdemo"
+VERSION = "001.000.000"
+
+log.info("main", "project name is ", PROJECT, "version is ", VERSION)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 gpio 输出功能模块
+-- require "gpio_output_task"
+
+-- 加载 gpio  输入功能模块
+-- require "gpio_input_task"
+
+-- 加载 gpio 上下拉功能模块
+-- require "gpio_pull_task"
+
+-- 加载 gpio 中断功能模块
+require "gpio_irq_task"
+
+-- 加载 gpio 中断计数功能模块
+-- require "gpio_irqcount_task"
+
+-- 加载 agpio 功能模块
+-- require "agpio_task"
+
+-- 加载 gpio 翻转功能模块
+-- require "gpio_toggle_task"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 50
module/Air8000/demo/gpio/power_on/main.lua

@@ -1,50 +0,0 @@
-
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "power_on_demo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-local powerkey_pin = 46    -- 赋值powerkey引脚编号
-
--- local count=0    -- 五秒内短按三次关机
--- local function pwrkeycb() 
---     log.info("pwrkey", gpio.get(powerkey_pin))
---     if gpio.get(powerkey_pin) == 0 then
---         count=count+1
---         sys.timerStart(function()
---             log.info("计数归零")
---             count=0
---         end, 5000)
---         if count>=3 then
---             pm.shutdown() 
---         end
---     end
--- end
-
-function pwroff()
-    log.info("power off!!")
-    pm.shutdown() 
-end
-
-local function pwrkeycb()    --长按五秒关机
-    log.info("pwrkey", gpio.get(powerkey_pin))
-    if gpio.get(powerkey_pin) == 1 then
-        sys.timerStop(pwroff)
-    else
-        sys.timerStart(pwroff, 5000)
-    end
-end
-
-if powerkey_pin ~= 255 then
-    gpio.setup(powerkey_pin, pwrkeycb, gpio.PULLUP,gpio.BOTH)
-else
-    log.info("bsp not support")
-end
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 130 - 0
module/Air8000/demo/gpio/readme.md

@@ -0,0 +1,130 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,负责初始化系统并启动各个GPIO功能任务;
+
+2、gpio_output_task.lua:GPIO输出模式功能模块,演示GPIO输出控制方法;
+
+3、gpio_input_task.lua:GPIO输入模式功能模块,演示GPIO输入读取方法;
+
+4、gpio_pull_task.lua:GPIO上拉下拉模式功能模块,演示GPIO上拉下拉配置;
+
+5、gpio_irq_task.lua:GPIO中断(触发)模式功能模块,演示GPIO中断触发、回调处理及按键短按长按检测;
+
+6、gpio_irqcount_task.lua:GPIO中断(计数)模式功能模块,演示GPIO中断计数功能;
+
+7、agpio_task.lua:AGPIO功能模块,演示低功耗GPIO在休眠模式下的特性;
+
+8、gpio_toggle_task.lua:GPIO翻转测速功能模块,演示GPIO脉冲输出功能;
+
+## 演示功能概述
+
+1、gpio_output_task:GPIO输出模式功能演示
+- 配置GPIO146为输出模式,控制开发板上的网络指示灯(绿灯)
+- 实现简单的灯闪烁效果,LED灯交替点亮和熄灭
+- 演示gpio.setup的输出模式配置和状态控制方法
+
+2、gpio_input_task:GPIO输入模式功能演示
+- 配置GPIO24为输入模式,配置GPIO146为输出模式
+- 实现输入信号读取,并将读取到的电平状态实时反映到LED灯上
+- 演示gpio.debounce防抖功能的使用
+- 展示如何通过输入GPIO的状态控制输出GPIO
+
+3、gpio_pull_task:GPIO上拉下拉模式功能演示
+- 配置GPIO1为上拉输入模式,GPIO2为下拉输入模式
+- 演示gpio.debounce防抖功能在不同上下拉模式下的应用
+- 通过定时任务周期性读取并打印GPIO的当前电平状态
+- 展示如何使用gpio.get函数获取GPIO的实时状态
+
+4、gpio_irq_task:GPIO中断(触发)模式功能演示
+- 配置GPIO20为中断模式,支持上升沿和下降沿触发(双边沿触发)
+- 实现中断触发时的回调函数,打印触发信息
+- 演示gpio.debounce防抖功能在中断模式下的应用
+- 实现按键短按(小于3秒)和长按(大于等于3秒)的检测功能
+- 可连接按键或直接用杜邦线轻触GND进行测试
+
+5、gpio_irqcount_task:GPIO中断(计数)模式功能演示
+- 配置GPIO21为中断计数模式,用于统计信号触发次数
+- 配置PWM4输出1kHz、占空比50%的方波作为计数信号源
+- 实现周期性(1秒)统计和打印中断触发次数
+- 展示gpio.count函数在计数模式下的使用方法
+
+6、agpio_task:AGPIO功能演示
+- 演示普通GPIO和AGPIO在进入休眠模式前后的区别
+- 普通GPIO(GPIO1)在休眠后会掉电,而AGPIO(GPIO21)可保持电平状态
+- 演示如何通过pm.power控制系统进入低功耗模式
+- 展示休眠前后GPIO电平状态的变化情况
+
+7、gpio_toggle_task:GPIO翻转测速功能演示
+- 配置GPIO2为输出模式,初始电平为低电平
+- 演示gpio.pulse函数生成指定模式的电平变化序列
+- 输出8组电平变化(0xA9,即二进制10101001)
+- 展示如何通过快速电平翻转实现特定信号模式的输出
+
+## 演示硬件环境
+
+1、Air8000 开发板一块:
+- 确保开发板正常供电
+- 开发板上的网络指示灯(绿灯)与GPIO146相连
+- GPIO21可用于中断触发测试,GPIO24可用于输入信号检测
+
+2、TYPE-C USB数据线一根,Air8000 开发板和数据线的硬件接线方式为:
+- Air8000 开发板通过TYPE-C USB口供电;(外部供电/USB供电 拨动开关 拨到 USB供电一端)
+- TYPE-C USB数据线直接插到开发板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+3、可选硬件(根据需要):
+- 外部按键或信号源:用于GPIO输入模式和中断模式的信号输入测试
+- 面包板、杜邦线:用于连接外部信号源和开发板GPIO
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air8000 版本固件](https://docs.openluat.com/air8000/luatos/firmware/)
+
+## 演示核心步骤
+
+在main.lua中,可以根据需要启用或禁用特定的GPIO功能任务:
+- 通过注释或取消注释相应的require语句来控制功能模块的加载
+- 每个功能模块作为独立的任务运行,可以单独测试或组合测试
+
+### 1、GPIO输出模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_output_task"`这一行
+3. 将代码下载到开发板并运行
+4. **演示效果**:开发板上的绿色网络指示灯(GPIO146)将按照设定的时间间隔交替点亮和熄灭,实现灯闪烁效果
+
+### 2、GPIO输入模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_input_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:当GPIO24输入为高电平时,GPIO146上的绿色LED灯会点亮;当GPIO24输入为低电平时,绿色LED灯会熄灭
+
+### 3、GPIO上拉下拉模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保只保留`require "gpio_pull_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:串口日志中会周期性显示GPIO1(上拉输入)和GPIO2(下拉输入)的当前电平状态
+
+### 4、GPIO中断(触发)模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_irq_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:当GPIO20的电平发生变化时,会触发中断并检测按键动作,在串口日志中打印短按(小于3秒)或长按(大于等于3秒)事件
+
+### 5、GPIO中断(计数)模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_irqcount_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:PWM4输出方波信号到GPIO21,串口日志中每秒显示一次中断触发的计数值
+
+### 6、AGPIO功能
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "agpio_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:系统进入低功耗模式后,普通GPIO(GPIO1)电平会掉电,而AGPIO(GPIO21)可以保持其电平状态,通过示波器或逻辑分析仪等工具可以查看示例效果展示
+
+### 7、GPIO翻转测速
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_toggle_task"`这一行语句
+3. 将代码下载到开发板并运行
+4. **演示效果**:GPIO2会根据gpio.pulse函数的配置快速输出特定模式的电平变化序列(二进制10101001),通过示波器或逻辑分析仪等工具可以查看示例效果展示

+ 104 - 0
module/Air8000/demo/iperf/iperf_client.lua

@@ -0,0 +1,104 @@
+--[[
+@module  iperf_client
+@summary iperf客户端模式测试模块
+@version 1.0
+@date    2025.10.29
+@author  拓毅恒
+@usage
+本模块演示如何初始化CH390以太网并启动iperf客户端模式进行测试。
+适用于路由器连接场景,设备通过DHCP从路由器获取IP地址。
+1、初始化SPI接口连接CH390
+2、设置CH390驱动和网络参数
+3、配置从路由器获取IP地址
+4、连接到指定的iperf服务器并进行测试
+
+本文件没有对外接口,直接在 main.lua 中 require "iperf_client" 即可加载运行。
+]]
+
+-- 引入必要的模块
+local exnetif = require "exnetif"
+
+-- 配置服务器IP地址(需要根据实际服务器IP进行修改)
+local SERVER_IP = "192.168.1.3"  -- 这里需要修改为实际的服务器IP地址
+
+-- iperf测试报告处理函数
+local function iperf_report_handler(bytes, ms_duration, bandwidth)
+    -- 转换为Mbps显示
+    local bandwidth_mbps = bandwidth / 1024 / 1024 * 8
+    log.info("iperf报告", string.format("数据量: %d bytes, 持续时间: %d ms, 带宽: %.2f Mbps", bytes, ms_duration, bandwidth_mbps))
+end
+
+-- iperf客户端任务
+local function iperf_client_task()
+    log.info("iperf测试", "开始初始化网络...")
+    -- 使用exnetif配置SPI外接以太网芯片CH390H
+    exnetif.set_priority_order({
+        {
+            ETHERNET = {
+                pwrpin = 140, 
+                tp = netdrv.CH390,
+                opts = {spi = 1, cs = 12}
+            }
+        }
+    })
+    -- 等待IP地址获取成功
+    log.info("iperf测试", "等待获取IP地址...")
+    -- 设置IP获取超时
+    local ip_wait_count = 60
+    while true do
+        local ipv4 = socket.localIP(socket.LWIP_ETH)
+        if ipv4 and ipv4 ~= "0.0.0.0" then
+            log.info("iperf测试", "IP获取成功:", ipv4)
+            break
+        end
+        
+        -- 超时检查
+        if ip_wait_count <= 0 then
+            log.error("iperf测试", "获取IP地址超时")
+            return
+        end
+        ip_wait_count = ip_wait_count - 1
+        sys.wait(1000)
+    end
+    
+    -- 等待以太网连接
+    while not socket.adapter(socket.LWIP_ETH) do
+        sys.wait(100)
+    end
+    log.info("iperf测试", "以太网连接状态: 已连接")
+
+    -- 启动客户端模式,连接到指定服务器
+    log.info("iperf测试", "启动客户端模式")
+    log.info("iperf测试", "连接到服务器IP:", SERVER_IP, "端口: 5001")
+    
+    -- 连接服务器
+    iperf.client(socket.LWIP_ETH, SERVER_IP, 5001)
+    
+    -- 订阅iperf测试报告事件
+    sys.subscribe("IPERF_REPORT", iperf_report_handler)
+    
+    log.info("iperf测试", "测试开始")
+    
+    -- 设置测试循环次数,共测试2分钟
+    local test_count = 24
+    while test_count > 0 do
+        -- 等待IPERF_REPORT事件,超时时间5秒
+        local report_received = sys.waitUntil("IPERF_REPORT", 5000)
+        if report_received then
+            -- 如果收到报告事件,退出循环
+            log.info("iperf测试", "收到报告,结束测试")
+            break
+        else
+            -- 如果超时,继续测试
+            test_count = test_count - 1
+            log.info("iperf测试", "测试进行中...")
+        end
+    end
+    
+    -- 测试结束
+    log.info("iperf测试", "测试结束,关闭客户端")
+    iperf.abort()
+end
+
+-- 执行iperf客户端模式测试
+sys.taskInit(iperf_client_task)

+ 87 - 0
module/Air8000/demo/iperf/iperf_server.lua

@@ -0,0 +1,87 @@
+--[[
+@module  iperf_server
+@summary iperf服务器模式测试模块
+@version 1.0
+@date    2025.10.29
+@author  拓毅恒
+@usage
+本模块演示如何初始化CH390以太网并启动iperf服务器模式进行测试。
+适用于路由器连接场景,设备通过DHCP从路由器获取IP地址。
+使用步骤:
+1、初始化SPI接口连接CH390
+2、设置CH390驱动和网络参数
+3、配置从路由器获取IP地址
+4、启动iperf服务器并处理测试结果
+
+本文件没有对外接口,直接在 main.lua 中 require "iperf_server" 即可加载运行。
+]]
+
+-- 引入必要的模块
+local exnetif = require "exnetif"
+
+-- 记录服务器IP
+local server_ip = "0.0.0.0"
+
+-- iperf测试报告处理函数
+local function iperf_report_handler(bytes, ms_duration, bandwidth)
+    -- 转换为Mbps显示
+    local bandwidth_mbps = bandwidth / 1024 / 1024 * 8
+    log.info("iperf报告", string.format("数据量: %d bytes, 持续时间: %d ms, 带宽: %.2f Mbps", bytes, ms_duration, bandwidth_mbps))
+end
+
+-- iperf服务器任务
+local function iperf_server_task()
+    log.info("iperf测试", "开始初始化网络...")
+    -- 使用exnetif配置SPI外接以太网芯片CH390H
+    exnetif.set_priority_order({
+        {
+            ETHERNET = {
+                pwrpin = 140, 
+                tp = netdrv.CH390,
+                opts = {spi = 1, cs = 12}
+            }
+        }
+    })
+    -- 等待IP地址获取成功
+    log.info("iperf测试", "等待获取IP地址...")
+    local ip_wait_count = 60
+    while true do
+        local ipv4 = socket.localIP(socket.LWIP_ETH)
+        if ipv4 and ipv4 ~= "0.0.0.0" then
+            log.info("iperf测试", "IP获取成功:", ipv4)
+            server_ip = ipv4
+            break
+        end
+        
+        -- 超时检查
+        if ip_wait_count <= 0 then
+            log.error("iperf测试", "获取IP地址超时")
+            return
+        end
+        
+        ip_wait_count = ip_wait_count - 1
+        sys.wait(1000)
+    end
+    -- 等待以太网连接
+    while not socket.adapter(socket.LWIP_ETH) do
+        sys.wait(100)
+    end
+    log.info("iperf测试", "以太网连接状态: 已连接")
+    
+    -- 连接到路由器场景,不需要配置DHCP服务器
+    log.info("iperf测试", "网络配置完成")
+    
+    -- 订阅iperf测试报告事件
+    sys.subscribe("IPERF_REPORT", iperf_report_handler)
+    
+    -- 启动iperf服务器
+    log.info("iperf测试", "启动服务器模式")
+    log.info("iperf测试", "服务器IP地址:", server_ip, "端口: 5001")
+    iperf.server(socket.LWIP_ETH)
+    sys.wait(2000)
+    log.info("iperf测试", "服务器已启动,等待客户端连接")
+    log.info("iperf测试", "请在客户端设备上设置服务器IP地址为:", server_ip)
+end
+
+-- 执行iperf服务器模式测试
+sys.taskInit(iperf_server_task)

+ 67 - 0
module/Air8000/demo/iperf/main.lua

@@ -0,0 +1,67 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.28
+@author  拓毅恒
+@usage
+演示功能概述
+本demo演示如何使用LuatOS的iperf模块进行网络吞吐量测试。
+iperf是一种网络性能测试工具,支持服务器模式和客户端模式,可以测试网络的带宽和稳定性。
+本demo提供了两个独立的测试用例:
+1、iperf服务器模式 - 设备作为服务器等待客户端连接
+2、iperf客户端模式 - 设备作为客户端主动连接服务器
+
+更多说明参考本目录下的readme.md文件
+]]
+PROJECT = "IPERF_DEMO"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
+log.info("main", PROJECT, VERSION)
+
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 iperf 服务器测试模块
+require "iperf_server"
+
+-- 加载 iperf 客户端测试模块
+-- require "iperf_client"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 115 - 0
module/Air8000/demo/iperf/readme.md

@@ -0,0 +1,115 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,用于选择加载服务器或客户端模块;
+
+2、iperf_server.lua:iperf服务器模块,用于初始化网络并启动iperf服务器;
+
+3、iperf_client.lua:iperf客户端模块,用于初始化网络并连接到服务器进行测试;
+
+## 演示功能概述
+
+本项目演示如何使用Air8000开发板进行网络性能测试。通过修改后的代码,可以实现两台Air8000开发板通过路由器连接,进行网络吞吐量测试。
+
+1、支持以下功能特性:
+
+- 支持DHCP客户端模式,自动从路由器获取IP地址
+- 服务器模式和客户端模式分离,可在不同设备上运行
+- 增强的错误处理和超时机制
+- 清晰的日志输出,便于调试和监控
+- 带宽自动计算并以Mbps显示
+
+## 演示硬件环境
+
+1、两台Air8000开发板
+
+2、一台路由器(支持DHCP功能)
+
+3、一台电脑(用于查看日志和监控)
+
+4、网线两根
+
+5、TYPE-C USB数据线两根
+
+   - Air8000开发板通过TYPE-C USB口供电;(外部供电/USB供电 拨动开关 拨到 USB供电一端)
+   - TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air8000 固件](https://docs.openluat.com/air8000/luatos/firmware/)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、配置服务器端(一台开发板)
+
+   a. 确保`main.lua`中已启用服务器模块,禁用客户端模块:
+   ```lua
+   -- 加载 iperf 服务器测试模块
+   require "iperf_server"
+
+   -- 加载 iperf 客户端测试模块
+   -- require "iperf_client"
+   ```
+
+   b. 烧录到一台Air8000开发板
+
+   c. 连接开发板到路由器的LAN口
+
+   d. 启动开发板,它将自动从路由器获取IP地址并启动iperf服务器
+
+3、配置客户端(另一台开发板)
+
+   a. 修改`iperf_client.lua`文件中的服务器IP地址为服务器开发板的实际IP地址:
+
+   ```lua
+   -- 配置服务器IP地址(需要根据实际服务器IP进行修改)
+   local SERVER_IP = "192.168.1.3"  -- 这里需要修改为实际的服务器IP地址
+   ```
+
+   b. 确保`main.lua`中已启用客户端模块,禁用服务器模块:
+
+   ```lua
+   -- 加载 iperf 服务器测试模块
+   -- require "iperf_server"
+
+   -- 加载 iperf 客户端测试模块
+   require "iperf_client"
+   ```
+
+   c. 烧录到另一台Air8000开发板
+
+   d. 连接开发板到路由器的LAN口
+
+   e. 启动开发板,它将自动从路由器获取IP地址并尝试连接到服务器
+
+## 查看测试结果
+
+测试启动后,可以通过Luatools工具查看测试日志。客户端将显示实时的测试报告,包括数据量、持续时间和带宽(以Mbps为单位)。
+
+```lua
+2025-11-06 17:02:24.658][000000013.298] I/user.iperf测试 测试进行中...
+[2025-11-06 17:02:24.675][000000013.314] D/iperf iperf正常结束, type 1
+[2025-11-06 17:02:24.677][000000013.314] D/lwiperf iperf_free 88 c1d553c
+[2025-11-06 17:02:24.678][000000013.316] D/iperf report bytes 5989824 ms_duration 10002 bandwidth 4784 kbps
+[2025-11-06 17:02:24.680][000000013.317] I/user.iperf报告 数据量: 5989824 bytes, 持续时间: 10002 ms, 带宽: 0.04 Mbps
+```
+
+## 注意事项
+
+1、确保两台开发板和电脑都连接到同一个路由器,并且路由器已启用DHCP功能
+
+2、服务器的IP地址需要在客户端配置文件中正确设置,否则客户端将无法连接
+
+3、默认情况下,服务器在端口5001上监听连接请求
+
+4、测试默认持续2分钟后自动结束
+
+## 常见问题排查
+
+1、无法连接到服务器
+   - 确认服务器IP地址是否正确
+   - 检查两台设备是否在同一网段
+   - 检查网线连接是否牢固

+ 61 - 112
module/Air8000/demo/mobile/main.lua

@@ -1,118 +1,67 @@
-
--- LuaTools需要PROJECT和VERSION这两个信息
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.23
+@author  拓毅恒
+@usage
+本demo演示的核心功能为:
+移动网络功能测试,包括SIM卡管理、基站数据查询、频段(Band)测试和修改、移动网络信息获取(IMEI/IMSI/信号强度等)以及SIM卡状态监控。
+通过加载mobile_test模块来运行相关测试功能。
+
+更多说明参考本目录下的readme.md文件
+]]
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
 PROJECT = "mobiledemo"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
--- sys库是标配
-_G.sys = require("sys")
-
-
-
-
-
--- 对于双卡的设备, 可以设置为自动选sim卡
--- 但是, 这样SIM1所在管脚就强制复用为SIM功能, 不可以再复用为GPIO
--- mobile.simid(2)
-mobile.simid(2,true)--优先用SIM0
-
-
-sys.taskInit(function()
-
-	log.info("status", mobile.status())
-    local band = zbuff.create(40)
-    local band1 = zbuff.create(40)
-    mobile.getBand(band)
-    log.info("当前使用的band:")
-    for i=0,band:used()-1 do
-        log.info("band", band[i])
-    end
-    band1[0] = 38
-    band1[1] = 39
-    band1[2] = 40
-    mobile.setBand(band1, 3)    --改成使用38,39,40
-    band1:clear()
-    mobile.getBand(band1)
-    log.info("修改后使用的band:")
-    for i=0,band1:used()-1 do
-        log.info("band", band1[i])
-    end
-    mobile.setBand(band, band:used())    --改回原先使用的band,也可以下载的时候选择清除fs
-
-    mobile.getBand(band1)
-    log.info("修改回默认使用的band:")
-    for i=0,band1:used()-1 do
-        log.info("band", band1[i])
-    end
-	-- mobile.vsimInit()
-	-- mobile.flymode(nil,true)
-	-- mobile.vsimOnOff(true)
-	-- mobile.flymode(nil,false)
-    -- mobile.apn(0,2,"") -- 使用默认APN激活CID2
-    -- mobile.rtime(3) -- 在无数据交互时,RRC 3秒后自动释放
-    -- 下面是配置自动搜索小区间隔,和轮询搜索冲突,开启1个就可以了
-    -- mobile.setAuto(10000,30000, 5) -- SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
-	log.info("status", mobile.status())
-    sys.wait(2000)
-    while 1 do
-        log.info("imei", mobile.imei())
-        log.info("imsi", mobile.imsi())
-        local sn = mobile.sn()
-        if sn then
-            log.info("sn",   sn:toHex())
-        end
-		log.info("status", mobile.status())
-        
-
-        log.info("iccid", mobile.iccid())
-        log.info("csq", mobile.csq()) -- 4G模块的CSQ并不能完全代表强度
-        log.info("rssi", mobile.rssi()) -- 需要综合rssi/rsrq/rsrp/snr一起判断
-        log.info("rsrq", mobile.rsrq())
-        log.info("rsrp", mobile.rsrp())
-        log.info("snr", mobile.snr())
-        log.info("simid", mobile.simid()) -- 这里是获取当前SIM卡槽
-        log.info("apn", mobile.apn(0,1))
-        log.info("ip", socket.localIP())
-		log.info("lua", rtos.meminfo())
-        -- sys内存
-        log.info("sys", rtos.meminfo("sys"))
-        sys.wait(15000)
-    end
-end)
-
--- 基站数据的查询
-
--- 订阅式, 模块本身会周期性查询基站信息,但通常不包含临近小区
-sys.subscribe("CELL_INFO_UPDATE", function()
-    log.info("cell", json.encode(mobile.getCellInfo()))
-end)
-
--- 轮询式, 包含临近小区信息,这是手动搜索,和上面的自动搜索冲突,开启一个就行
-sys.taskInit(function()
-    sys.wait(5000)
-	mobile.config(mobile.CONF_SIM_WC_MODE, 2)
-    while 1 do
-        mobile.reqCellInfo(10)
-        sys.wait(11000)
-        log.info("cell", json.encode(mobile.getCellInfo()))
-		mobile.config(mobile.CONF_SIM_WC_MODE, 2)
-    end
-end)
-
--- 获取sim卡的状态
-
-sys.subscribe("SIM_IND", function(status, value)
-    log.info("sim status", status)
-    if status == 'GET_NUMBER' then
-        log.info("number", mobile.number(0))
-    end
-	if status == "SIM_WC" then
-        log.info("sim", "write counter", value)
-    end
-end)
+VERSION = "001.000.000"
+
+log.info("main", "project name is ", PROJECT, "version is ", VERSION)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 mobile_test 功能模块
+require "mobile_test"
 
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()
 -- sys.run()之后后面不要加任何语句!!!!!
+

+ 114 - 0
module/Air8000/demo/mobile/mobile_test.lua

@@ -0,0 +1,114 @@
+--[[
+@module  mobile_test
+@summary Air8000 mobile功能测试模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 Air8000 开发板演示移动网络功能的代码示例,核心业务逻辑包括:
+1. SIM卡管理和选择(自动选卡功能)
+2. 基站数据查询(订阅式和轮询式两种方式)
+3. 频段(Band)测试和修改
+4. 移动网络信息获取(IMEI、IMSI、信号强度等)
+5. SIM卡状态监控
+]]
+
+-- 对于双卡的设备, 可以设置为自动选sim卡
+-- 但是SIM1所在管脚就强制复用为SIM功能, 占用4个IO口(gpio4/5/6/23),不可以再复用为GPIO
+-- mobile.simid(2)
+mobile.simid(2,true)--优先用SIM0
+
+-- 基站数据的查询
+-- 订阅式, 模块本身会周期性查询基站信息,但通常不包含临近小区
+local function sub_cell_info_task()
+    log.info("cell", json.encode(mobile.getCellInfo()))
+end
+
+sys.subscribe("CELL_INFO_UPDATE", sub_cell_info_task)
+
+-- 轮询式, 包含临近小区信息,这是手动搜索,和上面的自动搜索冲突,开启一个就行
+local function get_cell_info_task()
+    sys.wait(5000)
+	mobile.config(mobile.CONF_SIM_WC_MODE, 2)
+    while 1 do
+        mobile.reqCellInfo(10)
+        sys.wait(11000)
+        log.info("cell", json.encode(mobile.getCellInfo()))
+		mobile.config(mobile.CONF_SIM_WC_MODE, 2)
+    end
+end
+
+-- 获取sim卡的状态
+local function get_sim_status_task(status, value)
+    log.info("sim status", status)
+    if status == 'GET_NUMBER' then
+        log.info("number", mobile.number(0))
+    end
+	if status == "SIM_WC" then
+        log.info("sim", "write counter", value)
+    end
+end
+
+sys.subscribe("SIM_IND", get_sim_status_task)
+
+-- 定义测试band和移动网络信息的函数
+local function mobileinfo_task()
+    -- 设置默认APN 
+    -- 注意:在国内公网卡基本上都不需要设置APN, 专网卡才需要设置
+    mobile.apn(0,1,"cmiot","","",nil,0)
+    -- 开启SIM暂时脱离后自动恢复,30秒搜索一次周围小区信息
+    mobile.setAuto(10000,30000, 5) -- 此函数仅需要配置一次
+    
+    log.info("************开始测试band************")
+    local band = zbuff.create(40)
+    local band1 = zbuff.create(40)
+    mobile.getBand(band)
+    log.info("当前使用的band:")
+    for i=0,band:used()-1 do
+        log.info("band", band[i])
+    end
+    band1[0] = 38
+    band1[1] = 39
+    band1[2] = 40
+    mobile.setBand(band1, 3)    --改成使用38,39,40
+    band1:clear()
+    mobile.getBand(band1)
+    log.info("修改后使用的band:")
+    for i=0,band1:used()-1 do
+        log.info("band", band1[i])
+    end
+    mobile.setBand(band, band:used())    --改回原先使用的band,也可以下载的时候选择清除fs
+
+    mobile.getBand(band1)
+    log.info("修改回默认使用的band:")
+    for i=0,band1:used()-1 do
+        log.info("band", band1[i])
+    end
+    log.info("************band测试完毕************")
+
+	log.info("status", mobile.status())
+    sys.wait(2000)
+    while 1 do
+        log.info("imei", mobile.imei())
+        log.info("imsi", mobile.imsi())
+        log.info("apn", mobile.apn()) -- 获取当前APN
+        log.info("status", mobile.status())
+        log.info("iccid", mobile.iccid())
+        log.info("csq", mobile.csq()) -- 4G模块的CSQ并不能完全代表强度
+        log.info("rssi", mobile.rssi()) -- 需要综合rssi/rsrq/rsrp/snr一起判断
+        log.info("rsrq", mobile.rsrq())
+        log.info("rsrp", mobile.rsrp())
+        log.info("snr", mobile.snr())
+        log.info("simid", mobile.simid()) -- 这里是获取当前SIM卡槽
+        log.info("apn", mobile.apn(0,1))
+        -- sys内存
+        log.info("lua", rtos.meminfo())
+        log.info("sys", rtos.meminfo("sys"))
+        sys.wait(15000)
+    end
+end
+
+-- 轮询式查找小区, 包含临近小区信息,与上面订阅式搜索冲突,开启一个就行
+-- sys.taskInit(get_cell_info_task)
+-- 启动测试任务
+sys.taskInit(mobileinfo_task)

+ 97 - 0
module/Air8000/demo/mobile/readme.md

@@ -0,0 +1,97 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,负责初始化系统环境和加载移动网络测试模块;
+
+2、mobile_test.lua:移动网络功能测试模块,演示Air8000的移动网络相关功能;
+
+## 演示功能概述
+
+1、mobile_test:演示以下几种应用场景的使用方式
+
+- SIM卡配置和管理功能演示;
+- 基站数据查询(订阅式和轮询式)功能演示;
+- SIM卡状态订阅功能演示;
+- 频段(Band)测试和修改功能演示;
+- 移动网络信息获取(IMEI/IMSI/信号强度等)功能演示;
+
+## 演示硬件环境
+
+1、Air8000开发板一块 + 可上网的SIM卡一张 + 4G天线一根:
+
+- SIM卡插入开发板的SIM卡槽
+- 天线装到开发板上
+
+2、TYPE-C USB数据线一根 + USB转串口数据线一根,Air8000开发板和数据线的硬件接线方式为:
+
+- Air8000开发板通过TYPE-C USB口供电;(外部供电/USB供电 拨动开关 拨到 USB供电一端)
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、Air8000 版本固件:[Air8000 版本固件](https://docs.openluat.com/air8000/luatos/firmware/)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、确保SIM卡已正确插入开发板
+
+3、Luatools烧录内核固件和demo脚本代码
+
+4、烧录成功后,自动开机运行,通过串口日志可以观察到以下信息:
+
+- SIM卡状态监控信息
+- 基站数据查询结果
+- 移动网络信息(IMEI/IMSI/信号强度等)
+- 频段测试和修改结果
+
+``` lua
+[2025-10-23 15:58:31.141][000000000.361] I/user.main project name is  mobiledemo version is  001.000.000
+[2025-10-23 15:58:31.142][000000000.370] I/mobile sim set to 2 , ret 0
+[2025-10-23 15:58:31.144][000000000.373] I/user.************开始测试band************
+[2025-10-23 15:58:31.161][000000001.774] I/user.当前使用的band:
+[2025-10-23 15:58:31.163][000000001.775] I/user.band 1
+[2025-10-23 15:58:31.165][000000001.775] I/user.band 3
+[2025-10-23 15:58:31.167][000000001.775] I/user.band 5
+[2025-10-23 15:58:31.169][000000001.776] I/user.band 8
+[2025-10-23 15:58:31.170][000000001.776] I/user.band 34
+[2025-10-23 15:58:31.172][000000001.776] I/user.band 38
+[2025-10-23 15:58:31.173][000000001.776] I/user.band 39
+[2025-10-23 15:58:31.175][000000001.777] I/user.band 40
+[2025-10-23 15:58:31.176][000000001.777] I/user.band 41
+[2025-10-23 15:58:31.178][000000001.791] I/user.修改后使用的band:
+[2025-10-23 15:58:31.179][000000001.792] I/user.band 38
+[2025-10-23 15:58:31.180][000000001.792] I/user.band 39
+[2025-10-23 15:58:31.182][000000001.793] I/user.band 40
+[2025-10-23 15:58:31.183][000000001.799] I/user.修改回默认使用的band:
+[2025-10-23 15:58:31.184][000000001.800] I/user.band 1
+[2025-10-23 15:58:31.186][000000001.800] I/user.band 3
+[2025-10-23 15:58:31.187][000000001.800] I/user.band 5
+[2025-10-23 15:58:31.189][000000001.800] I/user.band 8
+[2025-10-23 15:58:31.190][000000001.801] I/user.band 34
+[2025-10-23 15:58:31.191][000000001.801] I/user.band 38
+[2025-10-23 15:58:31.193][000000001.801] I/user.band 39
+[2025-10-23 15:58:31.195][000000001.802] I/user.band 40
+[2025-10-23 15:58:31.196][000000001.802] I/user.band 41
+[2025-10-23 15:58:31.198][000000001.802] I/user.************band测试完毕************
+[2025-10-23 15:58:48.147][000000018.809] I/user.imei 864793080175404
+[2025-10-23 15:58:48.149][000000018.809] I/user.imsi 460240452233401
+[2025-10-23 15:58:48.151][000000018.810] I/user.status 1
+[2025-10-23 15:58:48.153][000000018.810] I/user.iccid 89860855102480513401
+[2025-10-23 15:58:48.155][000000018.810] I/user.csq 27
+[2025-10-23 15:58:48.157][000000018.811] I/user.rssi -58
+[2025-10-23 15:58:48.158][000000018.811] I/user.rsrq -9
+[2025-10-23 15:58:48.160][000000018.811] I/user.rsrp -87
+[2025-10-23 15:58:48.161][000000018.812] I/user.snr 16
+[2025-10-23 15:58:48.163][000000018.812] I/user.simid 0
+[2025-10-23 15:58:48.169][000000018.812] I/user.apn cmiot.MNC024.MCC460.GPRS
+[2025-10-23 15:58:48.171][000000018.813] I/user.lua 4194296 56552 56552
+[2025-10-23 15:58:48.172][000000018.813] I/user.sys 3202992 355468 360724
+[2025-10-23 15:58:56.722][000000027.379] I/user.cell [{"mnc":0,"dlbandwidth":5,"tdd":0,"earfcn":1300,"ulbandwidth":5,"band":3,"mcc":460,"pci":219,"rsrp":-86,"tac":18511,"rssi":-57,"rsrq":-9,"snr":16,"cid":190213964},{"mnc":15,"earfcn":1300,"pci":219,"rsrp":-86,"tac":18511,"mcc":460,"rsrq":-9,"snr":16,"cid":190213964},{"mnc":0,"earfcn":40936,"pci":368,"rsrp":-103,"tac":18511,"mcc":460,"rsrq":-7,"snr":0,"cid":192844432}]
+[2025-10-23 15:58:56.726][000000027.382] I/user.sim status SIM_WC
+[2025-10-23 15:58:56.728][000000027.383] I/user.sim write counter 2
+```
+
+5、日志中会实时显示移动网络相关信息的变化,可通过观察日志来验证功能是否正常工作

+ 0 - 39
module/Air8101/demo/gpio/GPIO中断模式/main.lua

@@ -1,39 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "GPIO_irq"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
--- 配置GPIO为中断模式,上升沿(GPIO.RISING)和下降沿(GPIO.FALLING),需要注意的是air8101只能支持单边沿中断
--- 请根据实际需求更改GPIO编号和触发模式
-local GPIO_pin = 1
-gpio.debounce(GPIO_pin, 100)
-gpio.setup(GPIO_pin, function()
-    log.info("GPIO", GPIO_pin, "被触发")
-end,gpio.PULLDOWN,gpio.RISING)
-
--- 在测试中,我们初始化GPIO0为输出模式,每隔一秒翻转一次输出电平,然后将此管脚与中断管脚相连
-local gpio_number = 0
-gpio_out = gpio.setup(gpio_number, 1)
-sys.taskInit(function()
-    while 1 do
-        gpio_out(1)
-        log.info("GPIO0 高")
-        sys.wait(1000)
-        gpio_out(0)
-        log.info("GPIO0 低")
-        sys.wait(1000)
-    end
-end)
-
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 35
module/Air8101/demo/gpio/GPIO输入模式/main.lua

@@ -1,35 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "GPIO_int"
-VERSION = "1.0.0"
-
-log.info("main", PROJECT, VERSION)
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
--- 请根据实际需求更改GPIO编号和上下拉
-local inputpin = 0
-
---设置GPIO为输入模式
-local input = gpio.setup(inputpin,nil)
--- 设置GPIO为上拉输入模式
---GPIO.setup(inputpin, nil, GPIO.PULLUP)
--- 设置GPIO为下拉输入模式
---GPIO.setup(inputpin, nil, GPIO.PULLDOWN)
-
-
---循环打印GPIO当前输入状态,为1是高电平,为0是低电平
-sys.taskInit(function ()
-    while true do
-        log.info("GPIO_int 电平输入状态",input())
-        sys.wait(999)
-    end
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 0 - 35
module/Air8101/demo/gpio/GPIO输出模式/main.lua

@@ -1,35 +0,0 @@
--- LuaTools需要PROJECT和VERSION这两个信息
-PROJECT = "gpio_out"
-VERSION = "1.0.1"
-
-log.info("main", PROJECT, VERSION)
-
-if wdt then
-    -- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
-    wdt.init(9000) -- 初始化watchdog设置为9s
-    sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
-end
-
-
-local gpio_number = 0
-
-LED = gpio.setup(gpio_number, 1)
-
-sys.taskInit(function()
-    -- 开始呼吸灯
-    local count = 0
-    while 1 do
-        -- 呼吸灯程序
-        LED(1)
-        log.info("GPIO", "Go Go Go", count, rtos.bsp())
-        sys.wait(500)--点亮时间 500ms
-        LED(0)
-        sys.wait(500)--熄灭时间 500ms
-        count = count + 1
-    end
-end)
-
--- 用户代码已结束---------------------------------------------
--- 结尾总是这一句
-sys.run()
--- sys.run()之后后面不要加任何语句!!!!!

+ 37 - 0
module/Air8101/demo/gpio/gpio_input_task.lua

@@ -0,0 +1,37 @@
+--[[
+@module  gpio_input_task
+@summary GPIO输入检测与LED联动示例
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为GPIO输入检测功能的代码示例,核心业务逻辑为:
+1. 初始化GPIO7为输入模式(可用杜邦线接稳压电源,高电平接3.3V,低电平接地)
+2. 初始化GPIO5为输出模式,默认高电平(亮)
+3. 启用输入消抖,消抖时间50 ms
+4. 每500 ms读取一次GPIO7电平,并同步控制LED亮灭
+5. 高电平→LED亮,低电平→LED灭
+]]
+
+-- 配置gpio7为输入模式
+-- 配置GPIO5为输出模式
+local inputpin = 7
+local ledpin = 5
+
+local input = gpio.setup(inputpin, nil, gpio.PULLDOWN)
+local led = gpio.setup(ledpin, 1)
+
+gpio.debounce(inputpin, 50)
+--GPIO7检测到有高低电平输入后,会返回GPIO7当前获取到的电平为高还是低,高返回值为1,低返回值为0
+--将这个返回值,传给GPIO5,为0 则GPIO5输出低电平,为1则输出高电平
+local function controlgpio()
+    local level = 0
+    while true do
+        level = gpio.get(inputpin)
+        log.info("gpio","set netled level: ",level)
+        gpio.set(ledpin, level)
+        sys.wait(500)
+    end
+end
+
+sys.taskInit(controlgpio)

+ 57 - 0
module/Air8101/demo/gpio/gpio_irq_task.lua

@@ -0,0 +1,57 @@
+--[[
+@module  gpio_irq_task
+@summary GPIO中断功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 GPIO 按键短按和长按检测的代码示例,核心业务逻辑为:
+1. 配置GPIO5为中断模式,上升沿和下降沿均触发
+2. 实现按键短按(小于3秒)和长按(大于等于3秒)的检测功能
+3. 可连接按键或直接用杜邦线轻触GND进行测试
+4. 注意:使用杜邦线测试时,因为脉冲可能无法控制,所以不要加防抖防止程序测试异常
+]]
+
+-- 配置gpio5为中断模式,上升沿(gpio.RISING)和下降沿(gpio.FALLING)均触发(gpio.BOTH)
+local gpio_pin = 5
+-- gpio.debounce(gpio_pin, 100) -- 实际设计板子时,根据自己的需求可以更改防抖配置以及打开防抖
+
+-- 按键状态变量
+local long_press_threshold = 3000  -- 长按判断阈值,3秒
+local current_state = 1  -- 跟踪当前按键状态,1为释放,0为按下
+
+-- 定时器回调函数,处理长按事件
+local function timer_callback(gpio_id)
+    log.info("按键检测", "长按事件", gpio_id)
+end
+
+-- 定义GPIO中断处理函数
+local function gpio_irq_handler()
+    local pin_state = gpio.get(gpio_pin)  -- 获取GPIO当前状态
+    
+    -- 只有当状态发生变化时才处理
+    if pin_state ~= current_state then
+        current_state = pin_state  -- 更新当前状态
+        
+        if pin_state == 0 then
+            -- 按键按下
+            log.info("按键检测", "按键按下")
+            if not sys.timerIsActive(timer_callback, gpio_pin) then
+                -- 启动定时器,3秒后触发长按事件
+                sys.timerStart(timer_callback, long_press_threshold, gpio_pin)
+            end
+        elseif pin_state == 1 then
+            -- 按键释放
+            log.info("按键检测", "按键释放")
+            
+            -- 如果定时器还在运行,说明是短按
+            if sys.timerIsActive(timer_callback, gpio_pin) then
+                sys.timerStop(timer_callback, gpio_pin)
+                log.info("按键检测", "短按事件")
+            end
+        end
+    end
+end
+
+-- 配置GPIO中断
+gpio.setup(gpio_pin, gpio_irq_handler, gpio.PULLUP, gpio.BOTH)

+ 29 - 0
module/Air8101/demo/gpio/gpio_irqcount_task.lua

@@ -0,0 +1,29 @@
+--[[
+@module  gpio_irqcount_task
+@summary GPIO中断计数功能
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为GPIO中断计数功能的代码示例,核心业务逻辑为:
+1. 配置GPIO5为中断计数模式,用于统计外部信号触发次数
+2. 每1秒读取并打印一次中断触发次数
+3. 可用杜邦线轻触3.3V电源正极,即可观察中断触发效果。
+]]
+
+-- 配置gpio5为中断计数模式
+-- 设置好后系统会自动记录中断触发次数。
+local gpio_pin = 5
+-- gpio.setup(gpio_pin, gpio.count, gpio.PULLUP, gpio.FALLING)
+gpio.setup(gpio_pin, gpio.count)
+
+-- 每隔1S统计一次中断触发的次数
+local function countIrq()
+    while true do
+        sys.wait(1000)
+        -- 返回从上次调用该函数后到当前时刻的中断触发次数
+        log.info("irq cnt", gpio.count(gpio_pin)) -- 调用函数时会自动清空中断累计值
+    end
+end
+
+sys.taskInit(countIrq)

+ 34 - 0
module/Air8101/demo/gpio/gpio_output_task.lua

@@ -0,0 +1,34 @@
+--[[
+@module  gpio_output_task
+@summary GPIO输出功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 GPIO 输出功能的代码示例,核心业务逻辑为:
+通过GPIO5输出高低电平,可用万用表测量验证
+1. 初始化GPIO5为输出模式
+2. 在任务循环中周期性地拉高/拉低GPIO5
+3. 通过1000ms间隔切换电平,便于万用表观察
+]]
+
+local gpio_number = 5
+
+gpio.setup(gpio_number, 1) -- 设置GPIO5为输出模式
+
+local function controlgpio_task()
+    -- 开始演示GPIO输出功能
+    local count = 0
+    while 1 do
+        gpio.set(gpio_number, 1)
+        log.info("GPIO", "当前IO5电平设置为高",count)
+        sys.wait(1000)
+        gpio.set(gpio_number, 0)
+        log.info("GPIO", "当前IO5电平设置为低")
+        sys.wait(1000)
+        count = count + 1
+    end
+end
+
+-- 执行任务函数
+sys.taskInit(controlgpio_task)

+ 32 - 0
module/Air8101/demo/gpio/gpio_pull_task.lua

@@ -0,0 +1,32 @@
+--[[
+@module  gpio_pull_task
+@summary GPIO上下拉功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 GPIO 上下拉功能的代码示例,核心业务逻辑为:
+1. 配置GPIO5为上拉输入模式
+2. 配置GPIO6为下拉输入模式
+3. 定时读取并打印两个GPIO的电平状态
+4. 将GPIO5和GPIO6引脚接地或接3.3V来控制GPIO5和GPIO6的电平变化,验证上拉/下拉配置是否生效
+]]
+
+local gpio_pin1 = 5
+local gpio_pin2 = 6
+-- 按键防抖函数
+gpio.debounce(gpio_pin1, 50)
+gpio.debounce(gpio_pin2, 50)
+
+-- 设置GPIO2引脚为上拉输入模式
+gpio.setup(gpio_pin1, nil, gpio.PULLUP)
+
+-- 设置GPIO5引脚为下拉输入模式
+gpio.setup(gpio_pin2, nil, gpio.PULLDOWN)
+
+local function gpiopulltask()
+    log.info("GPIO",gpio_pin1,"电平",gpio.get(gpio_pin1))
+    log.info("GPIO",gpio_pin2,"电平",gpio.get(gpio_pin2))
+end
+
+sys.timerLoopStart(gpiopulltask,1000)

+ 33 - 0
module/Air8101/demo/gpio/gpio_toggle_task.lua

@@ -0,0 +1,33 @@
+--[[
+@module  gpio_toggle
+@summary 波形翻转功能模块
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本文件为 GPIO 翻转(脉冲)输出的代码示例,核心业务逻辑为:
+GPIO 快速翻转测速与波形观测
+1. 配置 GPIO5 为输出模式并上拉初始化;
+2. 在任务中循环调用 gpio.pulse() 按给定模式输出脉冲序列;
+   - 演示模式为 0xA9(二进制 10101001),每次输出 8 组电平变化;
+3. 使用示波器或逻辑分析仪连接到 GPIO5,观察翻转波形与频率,翻转一次所需时间大概 50ns;
+4. 可根据需要修改 `test_gpio_number`、`0xA9`(翻转模式)和 `8`(组数),以测试不同引脚和模式;
+5. 注意:高频翻转请勿直接驱动重负载,推荐用于逻辑检测或带限流的 LED 演示。
+]]
+
+local test_gpio_number = 5
+
+gpio.setup(test_gpio_number, 0, gpio.PULLUP)
+
+local function gpiotoggletask()
+    sys.wait(100)
+    while true do
+        sys.wait(100)
+        -- 通过GPIO5脚输出输出8组电平变化
+        -- 0xA9就是输出的电平高低状态,即 10101001
+        gpio.pulse(test_gpio_number, 0xA9, 8, 0)
+        log.info("gpio----------->pulse")
+    end
+end
+
+sys.taskInit(gpiotoggletask)

+ 84 - 0
module/Air8101/demo/gpio/main.lua

@@ -0,0 +1,84 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.21
+@author  拓毅恒
+@usage
+本demo演示的核心功能为:
+演示GPIO的多种功能模式,包括输出模式、输入模式、上拉下拉模式、中断触发模式、中断计数模式、AGPIO低功耗模式以及GPIO翻转测速功能。
+用户可通过取消注释相应的require语句来启用不同的功能模块进行测试。
+
+更多说明参考本目录下的readme.md文件
+]]
+
+--[[
+必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
+PROJECT:项目名,ascii string类型
+        可以随便定义,只要不使用,就行
+VERSION:项目版本号,ascii string类型
+        如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
+            X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
+            因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为000
+        如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
+]]
+PROJECT = "GPIO_testdemo"
+VERSION = "001.000.000"
+
+log.info("main", "project name is ", PROJECT, "version is ", VERSION)
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 gpio 输出功能模块
+require "gpio_output_task"
+
+-- 加载 gpio  输入功能模块
+-- require "gpio_input_task"
+
+-- 加载 gpio 上下拉功能模块
+-- require "gpio_pull_task"
+
+-- 加载 gpio 中断功能模块
+-- require "gpio_irq_task"
+
+-- 加载 gpio 中断计数功能模块
+-- require "gpio_irqcount_task"
+
+-- 加载 agpio 功能模块
+-- require "agpio_task"
+
+-- 加载 gpio 翻转功能模块
+-- require "gpio_toggle_task"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 123 - 0
module/Air8101/demo/gpio/readme.md

@@ -0,0 +1,123 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,负责初始化系统并启动各个GPIO功能任务;
+
+2、gpio_output_task.lua:GPIO输出模式功能模块,演示GPIO输出控制方法;
+
+3、gpio_input_task.lua:GPIO输入模式功能模块,演示GPIO输入读取方法;
+
+4、gpio_pull_task.lua:GPIO上拉下拉模式功能模块,演示GPIO上拉下拉配置;
+
+5、gpio_irq_task.lua:GPIO中断(触发)模式功能模块,演示GPIO中断触发、回调处理及按键短按长按检测;
+
+6、gpio_irqcount_task.lua:GPIO中断(计数)模式功能模块,演示GPIO中断计数功能;
+
+7、agpio_task.lua:AGPIO功能模块,演示低功耗GPIO在休眠模式下的特性;
+
+8、gpio_toggle_task.lua:GPIO翻转测速功能模块,演示GPIO脉冲输出功能;
+
+
+
+## 演示功能概述
+
+1、gpio_output_task:GPIO输出模式功能演示
+- 配置GPIO5为输出模式,通过GPIO5输出高低电平
+- 可使用万用表测量验证GPIO5的电平变化
+- 以1000ms间隔切换电平状态,便于观察
+- 演示gpio.setup的输出模式配置和状态控制方法
+
+2、gpio_input_task:GPIO输入模式功能演示
+- 配置GPIO7为输入模式,配置GPIO5为输出模式
+- 实现输入信号读取,并将读取到的电平状态同步控制GPIO5
+- 演示gpio.debounce防抖功能的使用
+- 展示如何通过输入GPIO的状态控制输出GPIO
+
+3、gpio_pull_task:GPIO上拉下拉模式功能演示
+- 配置GPIO5为上拉输入模式,GPIO6为下拉输入模式
+- 演示gpio.debounce防抖功能在不同上下拉模式下的应用
+- 通过定时任务周期性读取并打印GPIO的当前电平状态
+- 展示如何使用gpio.get函数获取GPIO的实时状态
+
+4、gpio_irq_task:GPIO中断(触发)模式功能演示
+- 配置GPIO5为中断模式,支持上升沿和下降沿触发(双边沿触发)
+- 实现中断触发时的回调函数,打印触发信息
+- 演示gpio.debounce防抖功能在中断模式下的应用
+- 实现按键短按(小于3秒)和长按(大于等于3秒)的检测功能
+- 可连接按键或直接用杜邦线轻触GND进行测试
+
+5、gpio_irqcount_task:GPIO中断(计数)模式功能演示
+- 配置GPIO5为中断计数模式,用于统计信号触发次数
+- 配置PWM4输出1kHz、占空比50%的方波作为计数信号源
+- 实现周期性(1秒)统计和打印中断触发次数
+- 展示gpio.count函数在计数模式下的使用方法
+
+6、该模块暂不包含AGPIO功能演示
+
+7、gpio_toggle_task:GPIO翻转测速功能演示
+- 配置GPIO5为输出模式,初始电平为低电平
+- 演示gpio.pulse函数生成指定模式的电平变化序列
+- 输出8组电平变化(0xA9,即二进制10101001)
+- 展示如何通过快速电平翻转实现特定信号模式的输出
+
+## 演示硬件环境
+
+1、Air8101核心板一块:
+- 确保核心板正常供电
+
+2、USB数据线一根,Air8101核心板和数据线的硬件接线方式为:
+- Air8101核心板通过USB口供电;
+- USB数据线直接插到核心板的USB座子,另外一端连接电脑USB口;
+
+3、可选硬件(根据需要):
+- 外部按键或信号源:用于GPIO输入模式和中断模式的信号输入测试
+- 面包板、杜邦线:用于连接外部信号源和核心板GPIO
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air8101 版本固件](https://docs.openluat.com/air8101/luatos/firmware/)
+
+## 演示核心步骤
+
+在main.lua中,可以根据需要启用或禁用特定的GPIO功能任务:
+- 通过注释或取消注释相应的require语句来控制功能模块的加载
+- 每个功能模块作为独立的任务运行,可以单独测试或组合测试
+
+### 1、GPIO输出模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_output_task"`这一行
+3. 将代码下载到核心板并运行
+4. **演示效果**:GPIO5将按照设定的时间间隔交替输出高电平和低电平,可使用万用表测量验证
+
+### 2、GPIO输入模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_input_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:当GPIO7输入为高电平时,GPIO5会输出高电平;当GPIO7输入为低电平时,GPIO5会输出低电平
+
+### 3、GPIO上拉下拉模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保只保留`require "gpio_pull_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:串口日志中会周期性显示GPIO5(上拉输入)和GPIO6(下拉输入)的当前电平状态
+
+### 4、GPIO中断(触发)模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_irq_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:当GPIO5的电平发生变化时,会触发中断并检测按键动作,在串口日志中打印短按(小于3秒)或长按(大于等于3秒)事件
+
+### 5、GPIO中断(计数)模式
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_irqcount_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:PWM4输出方波信号到GPIO5,串口日志中每秒显示一次中断触发的计数值
+
+### 6、该模块暂不包含AGPIO功能演示
+
+### 7、GPIO翻转测速
+1. 搭建好硬件环境
+2. 打开main.lua,确保保留`require "gpio_toggle_task"`这一行语句
+3. 将代码下载到核心板并运行
+4. **演示效果**:GPIO5会根据gpio.pulse函数的配置快速输出特定模式的电平变化序列(二进制10101001),通过示波器或逻辑分析仪等工具可以查看示例效果展示

+ 94 - 0
module/Air8101/demo/iperf/iperf_client.lua

@@ -0,0 +1,94 @@
+--[[
+@module  iperf_client
+@summary iperf客户端模式测试模块
+@version 1.0
+@date    2025.10.29
+@author  拓毅恒
+@usage
+本模块演示如何初始化CH390以太网并启动iperf客户端模式进行测试。
+适用于路由器连接场景,设备通过DHCP从路由器获取IP地址。
+1、初始化SPI接口连接CH390
+2、设置CH390驱动和网络参数
+3、配置从路由器获取IP地址
+4、连接到指定的iperf服务器并进行测试
+
+本文件没有对外接口,直接在 main.lua 中 require "iperf_client" 即可加载运行。
+]]
+
+-- 引入必要的模块
+local netdrv_eth_spi = require "netdrv_eth_spi"
+
+-- 配置服务器IP地址(需要根据实际服务器IP进行修改)
+local SERVER_IP = "192.168.1.3"  -- 这里需要修改为实际的服务器IP地址
+
+-- iperf测试报告处理函数
+local function iperf_report_handler(bytes, ms_duration, bandwidth)
+    -- 转换为Mbps显示
+    local bandwidth_mbps = bandwidth / 1024 / 1024 * 8
+    log.info("iperf报告", string.format("数据量: %d bytes, 持续时间: %d ms, 带宽: %.2f Mbps", bytes, ms_duration, bandwidth_mbps))
+end
+
+-- iperf客户端任务
+local function iperf_client_task()
+    log.info("iperf测试", "等待网络初始化完成...")
+    -- 等待IP地址获取成功
+    log.info("iperf测试", "等待获取IP地址...")
+    -- 设置IP获取超时
+    local ip_wait_count = 60
+    while true do
+        local ipv4 = socket.localIP(socket.LWIP_USER1)
+        if ipv4 and ipv4 ~= "0.0.0.0" then
+            log.info("iperf测试", "IP获取成功:", ipv4)
+            break
+        end
+        
+        -- 超时检查
+        if ip_wait_count <= 0 then
+            log.error("iperf测试", "获取IP地址超时")
+            return
+        end
+        ip_wait_count = ip_wait_count - 1
+        sys.wait(1000)
+    end
+    
+    -- 等待以太网连接
+    while not socket.adapter(socket.LWIP_USER1) do
+        sys.wait(100)
+    end
+    log.info("iperf测试", "以太网连接状态: 已连接")
+
+    -- 启动客户端模式,连接到指定服务器
+    log.info("iperf测试", "启动客户端模式")
+    log.info("iperf测试", "连接到服务器IP:", SERVER_IP, "端口: 5001")
+    
+    -- 连接服务器
+    iperf.client(socket.LWIP_USER1, SERVER_IP, 5001)
+    
+    -- 订阅iperf测试报告事件
+    sys.subscribe("IPERF_REPORT", iperf_report_handler)
+    
+    log.info("iperf测试", "测试开始")
+    
+        -- 设置测试循环次数,共测试2分钟
+    local test_count = 24
+    while test_count > 0 do
+        -- 等待IPERF_REPORT事件,超时时间5秒
+        local report_received = sys.waitUntil("IPERF_REPORT", 5000)
+        if report_received then
+            -- 如果收到报告事件,退出循环
+            log.info("iperf测试", "收到报告,结束测试")
+            break
+        else
+            -- 如果超时,继续测试
+            test_count = test_count - 1
+            log.info("iperf测试", "测试进行中...")
+        end
+    end
+    
+    -- 测试结束
+    log.info("iperf测试", "测试结束,关闭客户端")
+    iperf.abort()
+end
+
+-- 执行iperf客户端模式测试
+sys.taskInit(iperf_client_task)

+ 76 - 0
module/Air8101/demo/iperf/iperf_server.lua

@@ -0,0 +1,76 @@
+--[[
+@module  iperf_server
+@summary iperf服务器模式测试模块
+@version 1.0
+@date    2025.10.29
+@author  拓毅恒
+@usage
+本模块演示如何初始化CH390以太网并启动iperf服务器模式进行测试。
+适用于路由器连接场景,设备通过DHCP从路由器获取IP地址。
+使用步骤:
+1、初始化SPI接口连接CH390
+2、设置CH390驱动和网络参数
+3、配置从路由器获取IP地址
+4、启动iperf服务器并处理测试结果
+
+本文件没有对外接口,直接在 main.lua 中 require "iperf_server" 即可加载运行。
+]]
+
+-- 引入必要的模块
+local netdrv_eth_spi = require "netdrv_eth_spi"
+
+-- 记录服务器IP
+local server_ip = "0.0.0.0"
+
+-- iperf测试报告处理函数
+local function iperf_report_handler(bytes, ms_duration, bandwidth)
+    -- 转换为Mbps显示
+    local bandwidth_mbps = bandwidth / 1024 / 1024 * 8
+    log.info("iperf报告", string.format("数据量: %d bytes, 持续时间: %d ms, 带宽: %.2f Mbps", bytes, ms_duration, bandwidth_mbps))
+end
+
+-- iperf服务器任务
+local function iperf_server_task()
+    log.info("iperf测试", "等待网络初始化完成...")
+    -- 等待IP地址获取成功
+    log.info("iperf测试", "等待获取IP地址...")
+    local ip_wait_count = 60
+    while true do
+        local ipv4 = socket.localIP(socket.LWIP_USER1)
+        if ipv4 and ipv4 ~= "0.0.0.0" then
+            log.info("iperf测试", "IP获取成功:", ipv4)
+            server_ip = ipv4
+            break
+        end
+        
+        -- 超时检查
+        if ip_wait_count <= 0 then
+            log.error("iperf测试", "获取IP地址超时")
+            return
+        end
+        
+        ip_wait_count = ip_wait_count - 1
+        sys.wait(1000)
+    end
+    -- 等待以太网连接
+    while not socket.adapter(socket.LWIP_USER1) do
+        sys.wait(100)
+    end
+    log.info("iperf测试", "以太网连接状态: 已连接")
+    
+    log.info("iperf测试", "网络配置完成")
+    
+    -- 订阅iperf测试报告事件
+    sys.subscribe("IPERF_REPORT", iperf_report_handler)
+    
+    -- 启动iperf服务器
+    log.info("iperf测试", "启动服务器模式")
+    log.info("iperf测试", "服务器IP地址:", server_ip, "端口: 5001")
+    iperf.server(socket.LWIP_USER1)
+    sys.wait(2000)
+    log.info("iperf测试", "服务器已启动,等待客户端连接")
+    log.info("iperf测试", "请在客户端设备上设置服务器IP地址为:", server_ip)
+end
+
+-- 执行iperf服务器模式测试
+sys.taskInit(iperf_server_task)

+ 67 - 0
module/Air8101/demo/iperf/main.lua

@@ -0,0 +1,67 @@
+--[[
+@module  main
+@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
+@version 1.0
+@date    2025.10.28
+@author  拓毅恒
+@usage
+演示功能概述
+本demo演示如何使用LuatOS的iperf模块进行网络吞吐量测试。
+iperf是一种网络性能测试工具,支持服务器模式和客户端模式,可以测试网络的带宽和稳定性。
+本demo提供了两个独立的测试用例:
+1、iperf服务器模式 - 设备作为服务器等待客户端连接
+2、iperf客户端模式 - 设备作为客户端主动连接服务器
+
+更多说明参考本目录下的readme.md文件
+]]
+PROJECT = "IPERF_DEMO"
+VERSION = "001.000.000"
+
+
+-- 在日志中打印项目名和项目版本号
+log.info("main", PROJECT, VERSION)
+
+
+-- 如果内核固件支持wdt看门狗功能,此处对看门狗进行初始化和定时喂狗处理
+-- 如果脚本程序死循环卡死,就会无法及时喂狗,最终会自动重启
+if wdt then
+    --配置喂狗超时时间为9秒钟
+    wdt.init(9000)
+    --启动一个循环定时器,每隔3秒钟喂一次狗
+    sys.timerLoopStart(wdt.feed, 3000)
+end
+
+
+-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
+-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
+-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
+-- 启动errDump日志存储并且上传功能,600秒上传一次
+-- if errDump then
+--     errDump.config(true, 600)
+-- end
+
+
+-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
+-- 可以使用合宙的iot.openluat.com平台进行远程升级
+-- 也可以使用客户自己搭建的平台进行远程升级
+-- 远程升级的详细用法,可以参考fota的demo进行使用
+
+
+-- 启动一个循环定时器
+-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
+-- 方便分析内存使用是否有异常
+-- sys.timerLoopStart(function()
+--     log.info("mem.lua", rtos.meminfo())
+--     log.info("mem.sys", rtos.meminfo("sys"))
+-- end, 3000)
+
+-- 加载 iperf 服务器测试模块
+require "iperf_server"
+
+-- 加载 iperf 客户端测试模块
+-- require "iperf_client"
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 102 - 0
module/Air8101/demo/iperf/netdrv_eth_spi.lua

@@ -0,0 +1,102 @@
+--[[
+@module  netdrv_eth_spi
+@summary "通过SPI外挂CH390H芯片的以太网卡"驱动模块
+@version 1.0
+@date    2025.07.24
+@author  马梦阳
+@usage
+本文件为"通过SPI外挂CH390H芯片的以太网卡"驱动模块 ,核心业务逻辑为:
+1、打开AirETH_1000配件板供电开关;
+2、初始化spi0,初始化以太网卡,并且在以太网卡上开启DHCP(动态主机配置协议);
+3、以太网卡的连接状态发生变化时,在日志中进行打印;
+
+Air8101核心板和AirETH_1000配件板的硬件接线方式为:
+Air8101核心板通过TYPE-C USB口供电(核心板背面的功耗测试开关拨到OFF一端);
+如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的VIN管脚进行5V供电;
+| Air8101核心板    | AirETH_1000配件板  |
+| --------------- | ----------------- |
+| 59/3V3          | 3.3v              |
+| gnd             | gnd               |
+| 28/DCLK         | SCK               |
+| 54/DISP         | CSS               |
+| 55/HSYN         | SDO               |
+| 57/DE           | SDI               |
+| 14/GPIO8        | INT               |
+
+本文件没有对外接口,直接在其他功能模块中require "netdrv_eth_spi"就可以加载运行;
+]]
+
+local function ip_ready_func(ip, adapter)
+    if adapter == socket.LWIP_USER1 then
+        log.info("netdrv_eth_spi.ip_ready_func", "IP_READY", socket.localIP(socket.LWIP_USER1))
+    end
+end
+
+local function ip_lose_func(adapter)
+    if adapter == socket.LWIP_USER1 then
+        log.warn("netdrv_eth_spi.ip_lose_func", "IP_LOSE")
+    end
+end
+
+
+-- 此处订阅"IP_READY"和"IP_LOSE"两种消息
+-- 在消息的处理函数中,仅仅打印了一些信息,便于实时观察"通过SPI外挂CH390H芯片的以太网卡"的连接状态
+-- 也可以根据自己的项目需求,在消息处理函数中增加自己的业务逻辑控制,例如可以在连网状态发生改变时更新网络图标
+sys.subscribe("IP_READY", ip_ready_func)
+sys.subscribe("IP_LOSE", ip_lose_func)
+
+
+-- 设置默认网卡为socket.LWIP_USER1
+socket.dft(socket.LWIP_USER1)
+
+
+-- 本demo测试使用的是核心板的VDD 3V3引脚对AirETH_1000配件板进行供电
+-- VDD 3V3引脚是Air8101内部的LDO输出引脚,最大输出电流300mA
+-- GPIO13在Air8101内部使能控制这个LDO的输出
+-- 所以在此处GPIO13输出高电平打开这个LDO
+gpio.setup(13, 1, gpio.PULLUP)
+
+
+-- 这个task的核心业务逻辑是:初始化SPI,初始化以太网卡,并在以太网卡上开启动态主机配置协议
+local function netdrv_eth_spi_task_func()
+    -- 初始化SPI0
+    local result = spi.setup(
+        0,--spi_id
+        nil,
+        0,--CPHA
+        0,--CPOL
+        8,--数据宽度
+        25600000--,--频率
+        -- spi.MSB,--高低位顺序    可选,默认高位在前
+        -- spi.master,--主模式     可选,默认主
+        -- spi.full--全双工       可选,默认全双工
+    )
+    log.info("netdrv_eth_spi", "spi open result", result)
+    -- 返回值为0,表示打开成功
+    if result ~= 0 then
+        log.error("netdrv_eth_spi", "spi open error",result)
+        return
+    end
+
+    -- 初始化以太网卡
+
+    -- 以太网联网成功(成功连接路由器,并且获取到了IP地址)后,内核固件会产生一个"IP_READY"消息
+    -- 各个功能模块可以订阅"IP_READY"消息实时处理以太网联网成功的事件
+    -- 也可以在任何时刻调用socket.adapter(socket.LWIP_USER1)来获取以太网是否连接成功
+
+    -- 以太网断网后,内核固件会产生一个"IP_LOSE"消息
+    -- 各个功能模块可以订阅"IP_LOSE"消息实时处理以太网断网的事件
+    -- 也可以在任何时刻调用socket.adapter(socket.LWIP_USER1)来获取以太网是否连接成功
+
+    -- socket.LWIP_USER1 指定网络适配器编号
+    -- netdrv.CH390外挂CH390
+    -- SPI ID 0, 片选 GPIO15
+    netdrv.setup(socket.LWIP_USER1, netdrv.CH390, {spi=0, cs=15})
+
+    -- 在以太上开启动态主机配置协议
+    netdrv.dhcp(socket.LWIP_USER1, true)
+end
+
+-- 创建并且启动一个task
+-- task的处理函数为netdrv_eth_spi_task_func
+sys.taskInit(netdrv_eth_spi_task_func)

+ 135 - 0
module/Air8101/demo/iperf/readme.md

@@ -0,0 +1,135 @@
+## 功能模块介绍
+
+1、main.lua:主程序入口,用于选择加载服务器或客户端模块;
+
+2、iperf_server.lua:iperf服务器模块,引用网络初始化模块并启动iperf服务器;
+
+3、iperf_client.lua:iperf客户端模块,引用网络初始化模块并连接到服务器进行测试;
+
+4、netdrv_eth_spi.lua:网络初始化模块,负责CH390网卡的初始化、SPI配置和DHCP获取;
+
+## 演示功能概述
+
+本项目演示如何使用Air8101核心板进行网络性能测试。通过修改后的代码,可以实现两台Air8101核心板通过路由器连接,进行网络吞吐量测试。
+
+1、支持以下功能特性:
+
+- 支持DHCP客户端模式,自动从路由器获取IP地址
+- 服务器模式和客户端模式分离,可在不同设备上运行
+- 增强的错误处理和超时机制
+- 清晰的日志输出,便于调试和监控
+- 带宽自动计算并以Mbps显示
+
+## 演示硬件环境
+
+![](https://docs.openluat.com/air8101/luatos/app/image/netdrv_multi.jpg)
+
+1、两台Air8101核心板
+
+2、一台路由器(支持DHCP功能)
+
+3、网线两根
+
+4、Air8101核心板和数据线的硬件接线方式为
+
+- Air8101核心板通过TYPE-C USB口供电;
+
+- 如果测试发现软件频繁重启,重启原因值为:poweron reason 0,可能是供电不足,此时再通过直流稳压电源对核心板的vbat管脚进行4V供电,或者5V管脚进行5V供电;
+
+- TYPE-C USB数据线直接插到核心板的TYPE-C USB座子,另外一端连接电脑USB口;
+
+5、AirETH_1000配件板一块,Air8101核心板和AirETH_1000配件板的硬件接线方式为:
+
+Air8101核心板通过TYPE-C USB口供电(核心板背面的功耗测试开关拨到OFF一端);
+如果测试发现软件重启,并且日志中出现  poweron reason 0,表示供电不足,此时再通过直流稳压电源对核心板的VIN管脚进行5V供电;
+
+| Air8101核心板    | AirETH_1000配件板  |
+| --------------- | ----------------- |
+| 59/3V3          | 3.3v              |
+| gnd             | gnd               |
+| 28/DCLK         | SCK               |
+| 54/DISP         | CSS               |
+| 55/HSYN         | SDO               |
+| 57/DE           | SDI               |
+| 14/GPIO8        | INT               |
+
+## 演示软件环境
+
+1、Luatools下载调试工具
+
+2、[Air8101 固件](https://docs.openluat.com/air8101/luatos/firmware/)
+
+## 演示核心步骤
+
+1、搭建好硬件环境
+
+2、配置服务器端(一台核心板+AirETH_1000配件板)
+
+   a. 确保`main.lua`中已启用服务器模块,禁用客户端模块:
+   ```lua
+   -- 加载 iperf 服务器测试模块
+   require "iperf_server"
+
+   -- 加载 iperf 客户端测试模块
+   -- require "iperf_client"
+   ```
+
+   b. 烧录到一台Air8101核心板
+
+   c. 连接AirETH_1000配件板到路由器的LAN口
+
+   d. 启动核心板,系统会自动加载netdrv_eth_spi模块进行网络初始化,获取IP地址并启动iperf服务器
+
+3、配置客户端(另一台核心板+AirETH_1000配件板)
+
+   a. 修改`iperf_client.lua`文件中的服务器IP地址为服务器核心板的实际IP地址:
+
+   ```lua
+   -- 配置服务器IP地址(需要根据实际服务器IP进行修改)
+   local SERVER_IP = "192.168.1.3"  -- 这里需要修改为实际的服务器IP地址
+   ```
+
+   b. 确保`main.lua`中已启用客户端模块,禁用服务器模块:
+
+   ```lua
+   -- 加载 iperf 服务器测试模块
+   -- require "iperf_server"
+
+   -- 加载 iperf 客户端测试模块
+   require "iperf_client"
+   ```
+
+   c. 烧录到另一台Air8101核心板
+
+   d. 连接AirETH_1000配件板到路由器的LAN口
+
+   e. 启动核心板,系统会自动加载netdrv_eth_spi模块进行网络初始化,获取IP地址并尝试连接到服务器
+
+## 查看测试结果
+
+测试启动后,可以通过Luatools工具查看测试日志。客户端将显示实时的测试报告,包括数据量、持续时间和带宽(以Mbps为单位)。
+
+```lua
+2025-11-06 17:02:24.658][000000013.298] I/user.iperf测试 测试进行中...
+[2025-11-06 17:02:24.675][000000013.314] D/iperf iperf正常结束, type 1
+[2025-11-06 17:02:24.677][000000013.314] D/lwiperf iperf_free 88 c1d553c
+[2025-11-06 17:02:24.678][000000013.316] D/iperf report bytes 5989824 ms_duration 10002 bandwidth 4784 kbps
+[2025-11-06 17:02:24.680][000000013.317] I/user.iperf报告 数据量: 5989824 bytes, 持续时间: 10002 ms, 带宽: 0.04 Mbps
+```
+
+## 注意事项
+
+1、确保两台核心板和电脑都连接到同一个路由器,并且路由器已启用DHCP功能
+
+2、服务器的IP地址需要在客户端配置文件中正确设置,否则客户端将无法连接
+
+3、默认情况下,服务器在端口5001上监听连接请求
+
+4、测试默认持续2分钟后自动结束
+
+## 常见问题排查
+
+1、无法连接到服务器
+   - 确认服务器IP地址是否正确
+   - 检查两台设备是否在同一网段
+   - 检查网线连接是否牢固