feat: add relay status query and mesh test cli

This commit is contained in:
十七
2026-11-05 17:38:29 +08:00
parent ebef6a8694
commit aedde75d65
2 changed files with 687 additions and 12 deletions
+289 -12
View File
@@ -61,6 +61,11 @@ _App_Reset:
bset 0x5007, #5
bset 0x5008, #5
bres 0x5009, #5
; PA2/PWRC:低电平进入JDY-28M AT指令窗口,高电平恢复Mesh通信。
bres 0x5000, #2
bset 0x5002, #2
bset 0x5003, #2
bres 0x5004, #2
; TIM4:16MHz/128/125,目标约1ms更新一次。
mov 0x5340, #0x00
@@ -91,6 +96,13 @@ _App_Reset:
; 防止刚开启接收中断时立即进入一次“伪接收”或把残留字节当作有效数据。
ld a, 0x5230
ld a, 0x5231
; 地址查询阶段先使用普通收发模式,避免AT响应进入Mesh环形缓冲区。
mov 0x5235, #0x0C
; PWRC拉低后等待约10ms,给JDY-28M预留AT指令窗口建立时间。
call _App_Delay10ms
call _App_QueryModuleAddress
; 查询结束后释放PWRC,模块恢复正常Mesh通信。
bset 0x5000, #2
; UART接收环形缓冲区使用RAM 0x0020~0x002F,共16字节。
; 0x0030为写索引,0x0031为读索引,0x0032为溢出计数。
mov 0x0030, #0x00
@@ -139,6 +151,157 @@ _App_MainLoop:
mov 0x0036, #0x00
jra _App_MainLoop
;-------------------------------------------------------------------------------
; 查询JDY-28M本机Mesh短地址。
; 发送AT+MADDR\r\n,解析+MADDR=XXXX。地址保存到0x0046/0x0047,
; 0x004A为有效标志。查询失败时地址标志保持0,不阻止后续Mesh运行。
;-------------------------------------------------------------------------------
_App_QueryModuleAddress:
mov 0x0048, #0x00
mov 0x0049, #0x00
mov 0x004A, #0x00
mov 0x003E, #0x41
call _App_SendByte
mov 0x003E, #0x54
call _App_SendByte
mov 0x003E, #0x2B
call _App_SendByte
mov 0x003E, #0x4D
call _App_SendByte
mov 0x003E, #0x41
call _App_SendByte
mov 0x003E, #0x44
call _App_SendByte
mov 0x003E, #0x44
call _App_SendByte
mov 0x003E, #0x52
call _App_SendByte
mov 0x003E, #0x0D
call _App_SendByte
mov 0x003E, #0x0A
call _App_SendByte
ldw x, #0xFFFF
_App_AddressWait:
ld a, 0x5230
and a, #0x20
jrne _App_AddressRead
decw x
jrne _App_AddressWait
ret
_App_AddressRead:
ld a, 0x5231
ld 0x003E, a
call _App_AddressParseByte
tnz 0x004A
jrne _App_AddressDone
decw x
jrne _App_AddressWait
ret
_App_AddressDone:
ret
; 解析单个AT响应字节,状态0~6匹配+MADDR=,状态7接收4位十六进制地址。
_App_AddressParseByte:
ld a, 0x003E
ld 0x003F, a
ld a, 0x0048
cp a, #0x00
jreq _App_AddrPlus
cp a, #0x01
jreq _App_AddrM
cp a, #0x02
jreq _App_AddrA
cp a, #0x03
jreq _App_AddrD1
cp a, #0x04
jreq _App_AddrD2
cp a, #0x05
jreq _App_AddrR
cp a, #0x06
jreq _App_AddrEqual
; 状态7:转换十六进制字符并左移累加。
call _App_HexNibble
ld 0x003E, a
sll 0x0047
rlc 0x0046
sll 0x0047
rlc 0x0046
sll 0x0047
rlc 0x0046
sll 0x0047
rlc 0x0046
ld a, 0x003E
or a, 0x0047
ld 0x0047, a
inc 0x0049
ld a, 0x0049
cp a, #0x04
jrne _App_AddrReturn
mov 0x004A, #0x01
ret
_App_AddrPlus:
ld a, 0x003F
cp a, #0x2B
jrne _App_AddrReset
inc 0x0048
ret
_App_AddrM:
ld a, 0x003F
cp a, #0x4D
jrne _App_AddrReset
inc 0x0048
ret
_App_AddrA:
ld a, 0x003F
cp a, #0x41
jrne _App_AddrReset
inc 0x0048
ret
_App_AddrD1:
ld a, 0x003F
cp a, #0x44
jrne _App_AddrReset
inc 0x0048
ret
_App_AddrD2:
ld a, 0x003F
cp a, #0x44
jrne _App_AddrReset
inc 0x0048
ret
_App_AddrR:
ld a, 0x003F
cp a, #0x52
jrne _App_AddrReset
inc 0x0048
ret
_App_AddrEqual:
ld a, 0x003F
cp a, #0x3D
jrne _App_AddrReset
mov 0x0046, #0x00
mov 0x0047, #0x00
mov 0x0049, #0x00
mov 0x0048, #0x07
ret
_App_AddrReset:
mov 0x0048, #0x00
_App_AddrReturn:
ret
; 将ASCII十六进制字符转换为0~15;非法字符返回0。
_App_HexNibble:
ld a, 0x003F
sub a, #0x30
cp a, #0x0A
jrult _App_HexReturn
ld a, 0x003F
sub a, #0x41
add a, #0x0A
ret
_App_HexReturn:
ret
;-------------------------------------------------------------------------------
; JDY-28M Mesh外层帧状态机。
;
@@ -167,7 +330,9 @@ _App_MeshParseByte:
_App_ParseWaitF1:
ld a, 0x0020
cp a, #0xF1
jrne _App_ParseReturn
jreq _App_F1OK
jpf _App_ParseReturn
_App_F1OK:
mov 0x0034, #0x01
ret
@@ -180,8 +345,15 @@ _App_ParseWaitDD:
_App_ParseWait09:
ld a, 0x0020
; 当前JDY-28M实测接收帧固定头为F1 DD 08。
cp a, #0x08
jreq _App_MeshHeaderOK
cp a, #0x09
jrne _App_ParseReset
jreq _App_MeshHeaderOK
cp a, #0x0A
jreq _App_MeshHeaderOK
jpf _App_ParseReset
_App_MeshHeaderOK:
mov 0x0034, #0x03
mov 0x0035, #0x00
ret
@@ -255,21 +427,42 @@ _App_ProcessBusiness:
; 先计算CMD、LEN、DATA的CRC,并与业务帧末尾两个字节比较;
; CRC错误时静默丢弃,绝不执行继电器动作。
call _App_CrcBusiness3
; CRC结束时0x003F保存CMD+LEN+DATA的总长度,动态定位帧尾CRC。
ld a, 0x003F
add a, #0x40
ldw x, #0x0000
ld xl, a
ld a, (x)
ld 0x003E, a
ld a, 0x003D
cp a, 0x0043
cp a, 0x003E
jreq _App_CrcHighOK
jpf _App_BusinessReturn
_App_CrcHighOK:
incw x
ld a, (x)
ld 0x003E, a
ld a, 0x003C
cp a, 0x0044
cp a, 0x003E
jreq _App_CrcLowOK
jpf _App_BusinessReturn
_App_CrcLowOK:
ld a, 0x0040
cp a, #0x05
jreq _App_AddressCommand
cp a, #0x02
jreq _App_StatusCommand
cp a, #0x01
jreq _App_CmdOK
jreq _App_ControlCommand
jpf _App_BusinessReturn
_App_CmdOK:
_App_AddressCommand:
ld a, 0x0041
cp a, #0x00
jreq _App_AddressQuery
jpf _App_BusinessReturn
_App_ControlCommand:
ld a, 0x0041
cp a, #0x01
jreq _App_LenOK
@@ -284,13 +477,72 @@ _App_LenOK:
; 只有DATA=00或01允许控制继电器。
_App_RelayOff:
mov 0x5000, #0x00
mov 0x0045, #0x81
jra _App_RelayRespond
_App_RelayOn:
mov 0x5000, #0x02
mov 0x0045, #0x81
jra _App_RelayRespond
; -----------------------------------------------------------------------------
; 函数/处理分支:_App_StatusCommand
; 功能:处理业务命令CMD=0x02,即主机查询当前继电器状态。
;
; 输入:
; 0x0041:业务LEN,必须为0,查询命令不携带DATA字段。
; 0x5000:继电器控制状态寄存器,当前设计中0x02表示吸合,0x00表示断开。
;
; 输出:
; 返回业务命令CMD=0x82;LEN=1;DATA=0x01表示吸合,0x00表示断开。
; 返回帧仍由_App_RelayRespond统一计算CRC并封装为JDY-28M发送帧。
;
; 说明:
; 这里查询的是单片机实际输出的继电器控制状态,而不是触点反馈。
; 当前硬件没有继电器触点反馈,所以该状态不能证明继电器触点一定
; 已经机械吸合;触点异常仍由ACS712电流检测和故障上报逻辑判断。
; -----------------------------------------------------------------------------
_App_StatusCommand:
ld a, 0x0041
cp a, #0x00
jreq _App_StatusQuery
jpf _App_BusinessReturn
_App_StatusQuery:
mov 0x0045, #0x82
jra _App_RelayRespond
_App_AddressQuery:
; CMD=05、LEN=00:返回CMD=85、LEN=02和本机MADDR。
ld a, 0x004A
jrne _App_AddressValid
; 上电查询可能因模块尚未进入AT窗口而失败;收到地址查询时再重试一次。
bres 0x5000, #2
call _App_Delay10ms
mov 0x5235, #0x0C
call _App_QueryModuleAddress
bset 0x5000, #2
mov 0x5235, #0x2C
ld a, 0x004A
jrne _App_AddressValid
; 地址仍未读取成功时,使用FFFF作为诊断地址继续回复;
; 主机可据此确认广播命令已经到达设备,但MADDR读取失败。
mov 0x0046, #0xFF
mov 0x0047, #0xFF
_App_AddressValid:
mov 0x0040, #0x85
mov 0x0041, #0x02
ld a, 0x0046
ld 0x0042, a
ld a, 0x0047
ld 0x0043, a
jra _App_ResponseAddressCrc
_App_RelayRespond:
; 业务区改写为CMD=81、LEN=1、DATA=当前控制状态。
mov 0x0040, #0x81
; 业务区改写为应答CMD、LEN=1、DATA=当前控制状态。
; 控制命令使用0x81,状态查询命令使用0x82;应答命令由调用分支
; 预先写入0x0045,避免复制两套完全相同的CRC和发送代码。
ld a, 0x0045
ld 0x0040, a
mov 0x0041, #0x01
ld a, 0x5000
and a, #0x02
@@ -305,7 +557,16 @@ _App_ResponseCrc:
ld 0x0043, a
ld a, 0x003C
ld 0x0044, a
jra _App_SendResponse
_App_ResponseAddressCrc:
call _App_CrcBusiness3
ld a, 0x003D
ld 0x0044, a
ld a, 0x003C
ld 0x0045, a
; JDY-28M发送格式:41 54 2B AA A1 | 目标地址 | A0 | 业务区 | 0D 0A。
; 目标地址使用外层源地址,即发起查询的主机地址。
_App_SendResponse:
mov 0x003E, #0x41
call _App_SendByte
mov 0x003E, #0x54
@@ -324,8 +585,10 @@ _App_ResponseCrc:
call _App_SendByte
mov 0x003E, #0xA0
call _App_SendByte
ld a, #0x00
ld 0x003F, a
ld a, 0x0041
add a, #0x04
ld 0x0048, a
mov 0x003F, #0x00
_App_SendResponseBusiness:
ld a, 0x003F
add a, #0x40
@@ -336,7 +599,7 @@ _App_SendResponseBusiness:
call _App_SendByte
inc 0x003F
ld a, 0x003F
cp a, #0x05
cp a, 0x0048
jrne _App_SendResponseBusiness
; 按JDY-28M Mesh发送协议保留完整帧尾0D 0A。
mov 0x003E, #0x0D
@@ -375,7 +638,10 @@ _App_CrcNoPoly:
jrne _App_CrcBit
inc 0x003F
ld a, 0x003F
cp a, #0x03
ld 0x003E, a
ld a, 0x0041
add a, #0x02
cp a, 0x003E
jrne _App_CrcByte
ret
@@ -387,6 +653,17 @@ _App_SendByte:
ld 0x5231, a
ret
;-------------------------------------------------------------------------------
; 粗略延时约10ms。
; 主频为16MHz,本延时只用于蓝牙模块PWRC窗口建立,不作为业务定时基准。
;-------------------------------------------------------------------------------
_App_Delay10ms:
ldw x, #0xFFFF
_App_Delay10msLoop:
decw x
jrne _App_Delay10msLoop
ret
;-------------------------------------------------------------------------------
; TIM4中断服务函数。
; 每500次约1ms中断翻转一次PB5,因此目标周期约500ms。计数变量放在RAM中,