完整Lua源码示例以太网 CH9121 TCP Client 通信

96 篇文章 0 订阅
67 篇文章 0 订阅

本教程参考 FlexLua 官网 ShineBlink 开发板栏目,FlexLua技术可降低 IoT 硬件开发难度,零门槛开发 IoT 硬件。

一、本例程实现功能

  1. Core 初始化 CH9121 以太网模块为 TCP Client 角色, DHCP 动态 IP
  2. 和 TCP Server (IP=192.168.0.102,端口号=1001)建立通信连接
  3. 周期性(5秒间隔)采集 RS485 Modbus 温湿度传感器数据并转换成可读性更强的 Json 字符串:
  • {"Dev":"TH","Data":{"Humi":79.7,"Temp":26.8},"Err":null}
  1. 然后将该 Json 字符串发送给 TCP Server

二、 CH9121模块 (SB-C18)

eb4e21b8202b00fd0c2f379d1b8db04e.jpeg

264de5a42dc8d293aeacfcefb5c4d1ee.jpeg

三、接线图

5c3e805a739ee53d84a722ef6a8683d8.jpeg

四、材料清单

  • CH9121 以太网模块
  • RS485 模块
  • RS485温湿度传感器

五、完整代码

----------------------配置信息------------------------
--Part1: 以太网参数配置:TCP Client DHCP动态IP示例(目的IP=192.168.0.102,目的端口号=1001)
ROLE = {0x01} --0x00:TCP Server, 0x01:TCP Client, 0x02:UDP Server, 0x03:UDP Client
SRCPORT = {0x41,0x9c} --源端口号,例如40001=0x9c41
DHCP = {0x01} --0x00关闭DHCP, 0x01使能DHCP
SRCIP = {0,0,0,0} --源IP地址,DHCP=0x00时有效
GATEWAY = {0,0,0,0}--网关地址,DHCP=0x00时有效
SUBNET = {0,0,0,0} --子网掩码,DHCP=0x00时有效

DESPORT = {0xe9,0x03} --目的端口号,例如1001=0x03e9,注意:仅当ROLE设置为TCP/UDP Client时才有效
DESIP = {192,168,0,102} --目的IP地址,注意:仅当ROLE设置为TCP/UDP Client时才有效

--Part2: 系统配置
SysDevName = "TH" --该名称会体现在Json字符串中,用来标识传感器设备名称
SysSensorHeatTime = 5 --传感器上电后的预热时间,单位:秒,请查阅相应厂家的传感器说明书
SysWorkInterval = 5 --传感器采集周期,单位:秒

--外围设备GPIO分配
CH9121_RSTI = "D6"
CH9121_CFG = "D5" --DTU01电路板没有连接CFG引脚,所以不能用CFG引脚方式配置以太网模块,必须要用协商方式(该方式需要提前用Wch厂家提供的上位机开启)

-------------------全局变量(可变值)-------------------
RedLedTimeMsCnt = 0
GreenLedTimeMsCnt = 0
DelayTimeMsCnt = 0

--示例:读取某厂家的一款RS485温湿度传感器
--获取到的Json数据形如:{"Humi":79.7,"Temp":26.8}
function ModbusToJson()
--配置RS485 Modbus转Json功能,并设置将要生成的Json字符串最大长度为150字节
LIB_ModbusToJsonConfig(150)--必须小于255
--湿度值寄存器地址0x0000,类型为16bit带符号AB型,小数点个数1个,Json Key名称"Humi"
LIB_ModbusToJsonAdd(0x0000,"S_AB",1,"Humi")
--温度值寄存器地址0x0001,类型为16bit带符号AB型,小数点个数1个,Json Key名称"Temp"
LIB_ModbusToJsonAdd(0x0001,"S_AB",1,"Temp")

--参数设置(4800,无校验,1位停止位,功能码"03",从机地址0x01,应答最长等待1000ms,包与包最短间隔100ms)
--注意:应答最长等待时间取决于通信数据量以及传感器,请查阅传感器说明书,通信失败时请尝试增加该值
--注意:包与包最短间隔时间取决于传感器,请查阅传感器说明书,通信失败时请尝试增加该值
LIB_ModbusToJsonSend("BAUDRATE_4800","NoneParity","StopBit_1","03",0x01,1000,100)
end

--等待RS485通信结束,并将合成好的Json数据通过以太网ETH发送给服务器
function WaitAndEthSend(dev)
--等待RS485通信结束
while true do
--读取传感器结果和错误信息(如果没有错误Err=null)
Finish,Data,Err = LIB_ModbusToJsonFinishCheck()
if Finish == 1 then
--如果获取到了传感器的Json数据
if Data ~= "null" then
RedLedTimeMsCnt = 100 --红色LED闪烁100毫秒(0.1秒)
end
--MbToJsonStr形如:{"Dev":"TH","Data":{"Humi":79.7,"Temp":26.8},"Err":null}
MbToJsonStr = string.format("{\"Dev\":\"%s\",\"Data\":%s,\"Err\":%s}", dev, Data, Err)
--将MbToJsonStr通过Uart0串口透传发送给以太网模块
LIB_Uart0Send(LIB_StrToTab(MbToJsonStr))
break --跳出while循环
end
end
end

--CH9121以太网模块写命令和数据
function Ch9121Write(cmd, data)
LIB_GpioToggle("D11") --喂硬件看门狗
SendData = {0x57,0xab}
SendData[#SendData+1] = cmd
for i=1,#data do
SendData[#SendData+1] = data[i]
end
--发送数据包
LIB_Uart0Send(SendData)
LIB_DelayMs(100)--延时不能低于100ms,不然会有个别指令收不到回复
--查询Uart0是否收到0xaa应答
u0_flag,u0_tab = LIB_Uart0Recv()
if u0_flag == 1 and u0_tab[1] == 0xaa then
print(string.format("Ch9121 0x%02x wr ok, Send=",cmd)..LIB_HexTabToHexStr(SendData).."\r\n")
else
print(string.format("Ch9121 0x%02x wr fail, Send=",cmd)..LIB_HexTabToHexStr(SendData).."\r\n")
end
end

--CH9121以太网模块读命令和数据
function Ch9121Read(cmd)
LIB_GpioToggle("D11") --喂硬件看门狗
SendData = {0x57,0xab}
SendData[#SendData+1] = cmd
--发送数据包
LIB_Uart0Send(SendData)
LIB_DelayMs(100)--延时不能低于100ms,不然会有个别指令收不到回复
--查询Uart0是否收到应答
u0_flag,u0_tab = LIB_Uart0Recv()
if u0_flag == 1 then
print(string.format("Ch9121 0x%02x rd ok, Recv=",cmd)..LIB_HexTabToHexStr(u0_tab).."\r\n")
else
print(string.format("Ch9121 0x%02x rd fail, Send=",cmd)..LIB_HexTabToHexStr(SendData).."\r\n")
end
end

--CH9121初始化
function Ch9121Init()
LIB_GpioOutputConfig(CH9121_RSTI,"STANDARD")
LIB_GpioOutputConfig(CH9121_CFG,"STANDARD")
--CH9121复位
LIB_GpioWrite(CH9121_RSTI,0)
LIB_DelayMs(100)
LIB_GpioWrite(CH9121_RSTI,1)
LIB_DelayMs(200)--这里需要延时
LIB_GpioToggle("D11") --喂硬件看门狗
--CH9121进入配置模式(CFG引脚方式)
LIB_GpioWrite(CH9121_CFG,0)--DTU01没接CFG,此种配置方式无效!
LIB_DelayMs(100)
--CH9121进入配置模式(串口协商方式)
LIB_DelayMs(500)
SendData = {0x55,0xaa,0x5a}
LIB_Uart0Send(SendData)--发送 55 aa 5a
cnt = 0
while cnt < 500 do --500ms内等待ch9121回复a5
LIB_DelayMs(1)
LIB_GpioToggle("D11") --喂硬件看门狗
cnt = cnt + 1
u0_flag,u0_tab = LIB_Uart0Recv()
if u0_flag == 1 and u0_tab[1] == 0xa5 then
break
end
end
if cnt >= 500 then
print("Ch9121 init fail, system reset!")
LIB_GpioWrite("D3",0) --蓝灯亮3秒后重启
LIB_GpioToggle("D11") --喂硬件看门狗
LIB_DelayMs(3000)
LIB_SystemReset()
end

SendData = {0xa5}
LIB_Uart0Send(SendData)--发送 a5
cnt = 0
while cnt < 500 do --500ms内等待ch9121回复a5
LIB_DelayMs(1)
LIB_GpioToggle("D11") --喂硬件看门狗
cnt = cnt + 1
u0_flag,u0_tab = LIB_Uart0Recv()
if u0_flag == 1 and u0_tab[1] == 0xa5 then
break
end
end
if cnt >= 500 then
print("Ch9121 init fail, system reset!")
LIB_GpioWrite("D3",0) --蓝灯亮3秒后重启
LIB_GpioToggle("D11") --喂硬件看门狗
LIB_DelayMs(3000)
LIB_SystemReset()
end

LIB_DelayMs(20)

--读取芯片MAC地址
mac_ok,mac = Ch9121Read(0x81)
if mac_ok == 1 and #mac == 6 then
print("Mac:"..LIB_HexTabToHexStr(mac))
end
Ch9121Write(0x10,ROLE) --0x00:TCP Server, 0x01:TCP Client, 0x02:UDP Server, 0x03:UDP Client
--配置网络信息(目的IP和端口号配置),仅当Client时有效
if ROLE[1] == 0x01 or ROLE[1] == 0x03then
Ch9121Write(0x15,DESIP)--目的IP
Ch9121Write(0x16,DESPORT)--目的端口号
end
--配置网络信息(静态IP配置)
if DHCP[1] ~= 0x01 then
Ch9121Write(0x11,SRCIP)--源IP
Ch9121Write(0x12,SUBNET)--子网掩码
Ch9121Write(0x13,GATEWAY) --网关
end
Ch9121Write(0x14,SRCPORT)--本地源端口PORT
Ch9121Write(0x23,{0x01,0x00,0x00,0x00})--RX接收打包超时时间1*5ms
Ch9121Write(0x24,{0x00})--网线断开不断网
Ch9121Write(0x25,{0x00,0x02,0x00,0x00})--RX接收打包数据个数512字节
Ch9121Write(0x26,{0x01})--网络连接时清空串口数据
Ch9121Write(0x33,DHCP)--DHCP or Static
Ch9121Write(0x0d,{})--更新配置参数至EEPROM
Ch9121Write(0x0e,{})--执行配置,复位CH9121
LIB_GpioToggle("D11") --喂硬件看门狗
LIB_DelayMs(200)
--CH9121退出配置模式
LIB_GpioWrite(CH9121_CFG,1)--DTU01没接CFG,此种配置方式无效!
--CH9121退出配置模式(串口协商方式)
Ch9121Write(0x5e,{})
LIB_DelayMs(50)
end

--延时N秒函数
function DelayS(N)
DelayTimeMsCnt = 0
target_ms = N*1000
while DelayTimeMsCnt <= target_ms do
GC(1)
end
end

--定义10毫秒定时器的回调函数,函数名字必须是LIB_10msTimerCallback
function LIB_10msTimerCallback()
GreenLedTimeMsCnt = GreenLedTimeMsCnt + 10
DelayTimeMsCnt = DelayTimeMsCnt + 10
LIB_GpioToggle("D11") --喂硬件看门狗
--红色LED灯闪烁处理程序
if RedLedTimeMsCnt > 10 then
RedLedTimeMsCnt = RedLedTimeMsCnt - 10
LIB_GpioWrite("D0",0) --红灯亮
else
LIB_GpioWrite("D0",1) --红灯灭
end
end

--硬件初始化函数
function Init()
--使能系统日志,不用的时候关闭
--LIB_SystemLogEnable()
--配置Uart0波特率为9600,和CH9121以太网模块通信
LIB_Uart0Config("BAUDRATE_9600")
--配置D0,D1,D3为普通GPIO输出,控制LED_R,LED_G,LED_B
LIB_GpioOutputConfig("D0","STANDARD")
LIB_GpioOutputConfig("D1","STANDARD")
LIB_GpioOutputConfig("D3","STANDARD")
LIB_GpioWrite("D0",1) --红灯灭
LIB_GpioWrite("D1",1) --绿灯灭
LIB_GpioWrite("D3",1) --蓝灯灭
--配置D11为普通输出,控制看门狗
LIB_GpioOutputConfig("D11","STANDARD")
--初始化CH9121以太网模块
Ch9121Init()
--配置Uart1作为485接口,初始默认波特率4800,并且D8作为自动收发切换引脚
LIB_Uart1Rs485Config("BAUDRATE_4800","D8")
--使能系统10毫秒定时器开始工作
LIB_10msTimerConfig("ENABLE")
end

--硬件初始化
Init()
--传感器预热
DelayS(SysSensorHeatTime)
--开始大循环
while(GC(1) == true)
do
--通过RS485 Modbus读取传感器数据
ModbusToJson()
--将传感器Json数据通过以太网ETH透传发送给服务器
WaitAndEthSend(SysDevName)
--等待2秒让以太网数据发送成功
DelayS(2)
--延时SysWorkInterval秒后重新执行本循环
DelayS(SysWorkInterval)
end


如果感兴趣,上面代码中出现的LIB开头的库函数可以在 API文档 中通过Ctrl+F查询。

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值