From 72393b6ef77dc6bd9784101d118fa71ff87d1b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=81=E4=B8=83?= <1415613786@qq.com> Date: Thu, 5 Nov 2026 18:16:29 +0800 Subject: [PATCH] feat: initialize mesh role and broadcast online --- STM8_app_asm/src/app_vectors.asm | 232 +++++++++++++++++++++++++++++-- tools/mesh_cli_test.py | 4 +- 2 files changed, 223 insertions(+), 13 deletions(-) diff --git a/STM8_app_asm/src/app_vectors.asm b/STM8_app_asm/src/app_vectors.asm index cedac22..7b4e109 100644 --- a/STM8_app_asm/src/app_vectors.asm +++ b/STM8_app_asm/src/app_vectors.asm @@ -61,6 +61,11 @@ _App_Reset: bset 0x5007, #5 bset 0x5008, #5 bres 0x5009, #5 + ; PB4:蓝牙初始化故障指示灯,低电平点亮;正常流程中输出高电平熄灭。 + bset 0x5005, #4 + bset 0x5007, #4 + bset 0x5008, #4 + bres 0x5009, #4 ; PA2/PWRC:低电平进入JDY-28M AT指令窗口,高电平恢复Mesh通信。 bres 0x5000, #2 bset 0x5002, #2 @@ -100,6 +105,24 @@ _App_Reset: mov 0x5235, #0x0C ; PWRC拉低后等待约10ms,给JDY-28M预留AT指令窗口建立时间。 call _App_Delay10ms + ; 上电先确认模块是否处于MESH指令模式ROLE2。 + call _App_QueryRole2 + ld a, 0x004C + jrne _App_RoleReady + ; 非ROLE2时写入ROLE2,并重新查询;最多再尝试两轮。 + call _App_SetRole2 + call _App_Delay10ms + call _App_QueryRole2 + ld a, 0x004C + jrne _App_RoleReady + call _App_SetRole2 + call _App_Delay10ms + call _App_QueryRole2 + ld a, 0x004C + jrne _App_RoleReady + jpf _App_BluetoothInitFault + +_App_RoleReady: call _App_QueryModuleAddress ; 查询结束后释放PWRC,模块恢复正常Mesh通信。 bset 0x5000, #2 @@ -114,17 +137,9 @@ _App_Reset: mov 0x0035, #0x00 mov 0x0036, #0x00 mov 0x5235, #0x2C + ; 蓝牙模式、短地址和串口业务状态均初始化完成后,广播一次上线通知。 + call _App_SendOnlineBroadcast rim - ; 发送一次固定的0x55,仅用于现场确认TX链路、波特率和串口接线。 - ; 该字节不是业务协议数据,正式联调确认TX正常后可删除这三行。 - ld a, #0x55 - ld 0x0020, a -_App_StartupTxWait: - ld a, 0x5230 - and a, #0x80 - jreq _App_StartupTxWait - ld a, 0x0020 - ld 0x5231, a _App_MainLoop: ; 主循环从环形缓冲区取出字节。UART中断只负责接收和入队, @@ -151,6 +166,203 @@ _App_MainLoop: mov 0x0036, #0x00 jra _App_MainLoop +;------------------------------------------------------------------------------- +; 蓝牙初始化故障停机点。 +; 模块未确认ROLE2时点亮PB4,释放PWRC后停留在此处,不进入Mesh业务。 +; PB5仍由TIM4驱动,便于区分蓝牙故障和MCU停机。 +;------------------------------------------------------------------------------- +_App_BluetoothInitFault: + bset 0x5000, #2 + bres 0x5005, #4 + rim +_App_BluetoothFaultLoop: + jra _App_BluetoothFaultLoop + +;------------------------------------------------------------------------------- +; 查询JDY-28M当前模式,只有收到+ROLE=2才将0x004C置1。 +; 该函数在启动阶段调用,此时UART接收中断尚未开启,因此直接轮询UART。 +;------------------------------------------------------------------------------- +_App_QueryRole2: + mov 0x004B, #0x00 + mov 0x004C, #0x00 + ; 发送AT+ROLE\r\n。 + mov 0x003E, #0x41 + call _App_SendByte + mov 0x003E, #0x54 + call _App_SendByte + mov 0x003E, #0x2B + call _App_SendByte + mov 0x003E, #0x52 + call _App_SendByte + mov 0x003E, #0x4F + call _App_SendByte + mov 0x003E, #0x4C + call _App_SendByte + mov 0x003E, #0x45 + call _App_SendByte + mov 0x003E, #0x0D + call _App_SendByte + mov 0x003E, #0x0A + call _App_SendByte + ldw x, #0xFFFF +_App_RoleWait: + ld a, 0x5230 + and a, #0x20 + jrne _App_RoleRead + decw x + jrne _App_RoleWait + ret +_App_RoleRead: + ld a, 0x5231 + ld 0x003E, a + call _App_RoleParseByte + tnz 0x004C + jrne _App_RoleDone + decw x + jrne _App_RoleWait +_App_RoleDone: + ret + +; 逐字节匹配字符串“+ROLE=2”。收到完整字符串后确认ROLE2。 +_App_RoleParseByte: + ld a, 0x003E + ld 0x003F, a + ld a, 0x004B + cp a, #0x00 + jreq _App_RolePlus + cp a, #0x01 + jreq _App_RoleR + cp a, #0x02 + jreq _App_RoleO + cp a, #0x03 + jreq _App_RoleL + cp a, #0x04 + jreq _App_RoleE + cp a, #0x05 + jreq _App_RoleEqual + ld a, 0x003F + cp a, #0x32 + jrne _App_RoleReset + mov 0x004C, #0x01 + ret +_App_RolePlus: + ld a, 0x003F + cp a, #0x2B + jreq _App_RoleNext + jra _App_RoleReset +_App_RoleR: + ld a, 0x003F + cp a, #0x52 + jreq _App_RoleNext + jra _App_RoleReset +_App_RoleO: + ld a, 0x003F + cp a, #0x4F + jreq _App_RoleNext + jra _App_RoleReset +_App_RoleL: + ld a, 0x003F + cp a, #0x4C + jreq _App_RoleNext + jra _App_RoleReset +_App_RoleE: + ld a, 0x003F + cp a, #0x45 + jreq _App_RoleNext + jra _App_RoleReset +_App_RoleEqual: + ld a, 0x003F + cp a, #0x3D + jreq _App_RoleNext + jra _App_RoleReset +_App_RoleNext: + inc 0x004B + ret +_App_RoleReset: + mov 0x004B, #0x00 + ret + +; 发送AT+ROLE2\r\n,将模块切换到MESH指令模式。 +_App_SetRole2: + mov 0x003E, #0x41 + call _App_SendByte + mov 0x003E, #0x54 + call _App_SendByte + mov 0x003E, #0x2B + call _App_SendByte + mov 0x003E, #0x52 + call _App_SendByte + mov 0x003E, #0x4F + call _App_SendByte + mov 0x003E, #0x4C + call _App_SendByte + mov 0x003E, #0x45 + call _App_SendByte + mov 0x003E, #0x32 + call _App_SendByte + mov 0x003E, #0x0D + call _App_SendByte + mov 0x003E, #0x0A + call _App_SendByte + ret + +;------------------------------------------------------------------------------- +; 发送设备上线广播。 +; +; 业务格式:CMD=07、LEN=00、CRC16_H、CRC16_L。 +; 外层目标地址固定使用FFFF,表示广播到Mesh网络内的所有设备。 +; 该函数只在本次上电初始化全部成功后调用一次,用于通知其他设备或主机: +; 本设备已经完成ROLE2确认、短地址查询,并进入可通信状态。 +; +; 发送帧格式: +; 41 54 2B AA A1 FF FF A0 07 00 CRC_H CRC_L 0D 0A +; +; 注意:函数不依赖外层接收帧中的源地址,也不把本机地址重复放入业务数据; +; 其他设备需要使用JDY-28M接收外层提供的发送方短地址识别本设备。 +;------------------------------------------------------------------------------- +_App_SendOnlineBroadcast: + ; 准备业务区并计算CMD、LEN的CRC16/MODBUS。 + mov 0x0040, #0x07 + mov 0x0041, #0x00 + call _App_CrcBusiness3 + + ; JDY-28M Mesh发送固定帧头。 + mov 0x003E, #0x41 + call _App_SendByte + mov 0x003E, #0x54 + call _App_SendByte + mov 0x003E, #0x2B + call _App_SendByte + mov 0x003E, #0xAA + call _App_SendByte + mov 0x003E, #0xA1 + call _App_SendByte + ; FFFF表示广播目标地址。 + mov 0x003E, #0xFF + call _App_SendByte + mov 0x003E, #0xFF + call _App_SendByte + ; A0表示Mesh数据通信类型。 + mov 0x003E, #0xA0 + call _App_SendByte + ; 发送业务区:07 00 CRC高字节 CRC低字节。 + mov 0x003E, #0x07 + call _App_SendByte + mov 0x003E, #0x00 + call _App_SendByte + ld a, 0x003D + ld 0x003E, a + call _App_SendByte + ld a, 0x003C + ld 0x003E, a + call _App_SendByte + ; 保留JDY-28M发送帧尾0D 0A。 + mov 0x003E, #0x0D + call _App_SendByte + mov 0x003E, #0x0A + call _App_SendByte + ret + ;------------------------------------------------------------------------------- ; 查询JDY-28M本机Mesh短地址。 ; 发送AT+MADDR\r\n,解析+MADDR=XXXX。地址保存到0x0046/0x0047, diff --git a/tools/mesh_cli_test.py b/tools/mesh_cli_test.py index 9be0b9f..c8435a0 100644 --- a/tools/mesh_cli_test.py +++ b/tools/mesh_cli_test.py @@ -385,14 +385,12 @@ def main() -> None: parser.add_argument("--port", help="直接指定电脑串口;不指定时启动后扫描并选择") parser.add_argument("--baudrate", type=int, default=9600, help="串口波特率,默认9600") parser.add_argument("--timeout", type=float, default=0.2, help="串口读取超时,默认0.2秒") - parser.add_argument("--response-timeout", type=float, default=3.0, help="设备应答等待时间,默认10秒") + parser.add_argument("--response-timeout", type=float, default=10.0, help="设备应答等待时间,默认10秒") args = parser.parse_args() selected_port = args.port or select_serial_port() with serial.Serial(selected_port, args.baudrate, timeout=args.timeout) as port: print(f"已打开串口:{selected_port},波特率:{args.baudrate}") run_menu(port, args.response_timeout) - - if __name__ == "__main__": main()