feat: complete assembly mesh relay control path
- synchronize STM8 application and external flash layout updates\n- add assembly bootloader and assembly application test projects\n- add UART1 interrupt receive ring buffer\n- parse JDY-28M Mesh outer frames and source addresses\n- add CRC-16/MODBUS validation\n- implement relay control command 0x01 and response 0x81\n- support unicast and broadcast relay control frames\n- update host protocol, OTA documents, and serial tools
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# STM8S003F3P6TR PB5独立LED测试工程。
|
||||
# 本工程不包含Bootloader;测试主程序按0x8500链接,用于和汇编Bootloader合并。
|
||||
|
||||
PROJECT := pb5_led_test
|
||||
BUILD_DIR := build
|
||||
CC := sdcc
|
||||
PACKIHX := packihx
|
||||
|
||||
CFLAGS := -mstm8 --std-c99 --opt-code-size -Iinclude
|
||||
LDFLAGS := -mstm8 --out-fmt-ihx --code-loc 0x8000
|
||||
APP_LDFLAGS := -mstm8 --out-fmt-ihx --code-loc 0x8500
|
||||
|
||||
OBJECT := $(BUILD_DIR)/main.rel
|
||||
IHX := $(BUILD_DIR)/$(PROJECT).ihx
|
||||
HEX := $(BUILD_DIR)/$(PROJECT).hex
|
||||
APP_IHX := $(BUILD_DIR)/$(PROJECT)_app.ihx
|
||||
APP_HEX := $(BUILD_DIR)/$(PROJECT)_app.hex
|
||||
|
||||
.PHONY: all app clean
|
||||
|
||||
all: app
|
||||
|
||||
# 生成供Bootloader跳转测试使用的主程序镜像,链接地址必须为0x8500。
|
||||
app: $(APP_HEX)
|
||||
|
||||
$(APP_HEX): $(APP_IHX)
|
||||
$(PACKIHX) $< > $@
|
||||
|
||||
$(APP_IHX): $(OBJECT)
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
$(CC) $(APP_LDFLAGS) -o $@ $<
|
||||
|
||||
$(HEX): $(IHX)
|
||||
$(PACKIHX) $< > $@
|
||||
|
||||
$(IHX): $(OBJECT)
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
$(CC) $(LDFLAGS) -o $@ $<
|
||||
|
||||
$(OBJECT): src/main.c
|
||||
@mkdir -p $(BUILD_DIR)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @file stm8_test_registers.h
|
||||
* @brief PB5 LED测试工程使用的最小GPIO寄存器定义。
|
||||
*/
|
||||
#ifndef STM8_TEST_REGISTERS_H
|
||||
#define STM8_TEST_REGISTERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** GPIOA输出数据寄存器地址。 */
|
||||
#define GPIOA_ODR_ADDR 0x5000u
|
||||
/** GPIOA数据方向寄存器地址。 */
|
||||
#define GPIOA_DDR_ADDR 0x5002u
|
||||
/** GPIOA控制寄存器1地址。 */
|
||||
#define GPIOA_CR1_ADDR 0x5003u
|
||||
/** GPIOA控制寄存器2地址。 */
|
||||
#define GPIOA_CR2_ADDR 0x5004u
|
||||
/** GPIOB输出数据寄存器地址。 */
|
||||
#define GPIOB_ODR_ADDR 0x5005u
|
||||
/** GPIOB数据方向寄存器地址。 */
|
||||
#define GPIOB_DDR_ADDR 0x5007u
|
||||
/** GPIOB控制寄存器1地址,置1表示推挽输出。 */
|
||||
#define GPIOB_CR1_ADDR 0x5008u
|
||||
/** GPIOB控制寄存器2地址,置0表示低速输出。 */
|
||||
#define GPIOB_CR2_ADDR 0x5009u
|
||||
/** GPIOC输出数据寄存器地址。 */
|
||||
#define GPIOC_ODR_ADDR 0x500Au
|
||||
/** GPIOC数据方向寄存器地址。 */
|
||||
#define GPIOC_DDR_ADDR 0x500Cu
|
||||
/** GPIOC控制寄存器1地址。 */
|
||||
#define GPIOC_CR1_ADDR 0x500Du
|
||||
/** GPIOC控制寄存器2地址。 */
|
||||
#define GPIOC_CR2_ADDR 0x500Eu
|
||||
/** GPIOD输出数据寄存器地址。 */
|
||||
#define GPIOD_ODR_ADDR 0x500Fu
|
||||
/** GPIOD数据方向寄存器地址。 */
|
||||
#define GPIOD_DDR_ADDR 0x5011u
|
||||
/** GPIOD控制寄存器1地址。 */
|
||||
#define GPIOD_CR1_ADDR 0x5012u
|
||||
/** GPIOD控制寄存器2地址。 */
|
||||
#define GPIOD_CR2_ADDR 0x5013u
|
||||
|
||||
/** 时钟分频寄存器地址。 */
|
||||
#define CLK_CKDIVR_ADDR 0x50C6u
|
||||
/** TIM4控制寄存器1地址。 */
|
||||
#define TIM4_CR1_ADDR 0x5340u
|
||||
/** TIM4中断使能寄存器地址。 */
|
||||
#define TIM4_IER_ADDR 0x5343u
|
||||
/** TIM4状态寄存器1地址。 */
|
||||
#define TIM4_SR1_ADDR 0x5344u
|
||||
/** TIM4预分频寄存器地址。 */
|
||||
#define TIM4_PSCR_ADDR 0x5347u
|
||||
/** TIM4自动重装载寄存器地址。 */
|
||||
#define TIM4_ARR_ADDR 0x5348u
|
||||
/** TIM4计数器地址。 */
|
||||
#define TIM4_CNTR_ADDR 0x5346u
|
||||
/** TIM4事件产生寄存器地址。 */
|
||||
#define TIM4_EGR_ADDR 0x5345u
|
||||
|
||||
/** PB5对应的位掩码。 */
|
||||
#define PB5_MASK 0x20u
|
||||
|
||||
/** 通过地址访问8位STM8外设寄存器。 */
|
||||
#define REG8(address) (*((volatile uint8_t *)(address)))
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @file main.c
|
||||
* @brief STM8S003F3P6TR PB5独立硬件测试程序。
|
||||
*
|
||||
* 本测试程序只把PB5配置为推挽输出,并使用TIM4中断以约500ms周期翻转。
|
||||
* 程序不初始化UART、SPI、ADC、蓝牙或看门狗,用于验证应用中断向量。
|
||||
*
|
||||
* 当前测试工程直接从0x8000链接,烧录后不依赖原项目的Bootloader。
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "stm8_test_registers.h"
|
||||
|
||||
/**
|
||||
* 产生约500ms的软件延时。
|
||||
*
|
||||
* 该延时用于LED肉眼观察,不作为正式产品的精确定时基准。实际周期会
|
||||
* 受到MCU主频、编译器优化和芯片时钟配置影响,但足以判断LED是否翻转。
|
||||
*/
|
||||
static volatile uint16_t tim4_count;
|
||||
|
||||
/**
|
||||
* TIM4更新中断服务函数。
|
||||
*
|
||||
* SDCC会根据IRQ23把该函数放入应用程序向量槽0x8564。每次中断先清除
|
||||
* TIM4更新标志,再累计1ms节拍;累计500次后直接翻转PB5,避免引入其他
|
||||
* 模块,从而只验证Bootloader到应用程序的TIM4中断链路。
|
||||
*/
|
||||
void Test_TIM4_ISR(void) __interrupt(23)
|
||||
{
|
||||
REG8(TIM4_SR1_ADDR) = 0x00u;
|
||||
++tim4_count;
|
||||
if (tim4_count >= 500u)
|
||||
{
|
||||
tim4_count = 0u;
|
||||
REG8(GPIOB_ODR_ADDR) ^= PB5_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化TIM4为约1ms更新事件:16MHz / 128 / 125 = 1kHz。 */
|
||||
static void Test_TIM4_Init(void)
|
||||
{
|
||||
REG8(CLK_CKDIVR_ADDR) = 0x00u;
|
||||
REG8(TIM4_CR1_ADDR) = 0x00u;
|
||||
REG8(TIM4_IER_ADDR) = 0x00u;
|
||||
REG8(TIM4_PSCR_ADDR) = 0x07u;
|
||||
REG8(TIM4_ARR_ADDR) = 124u;
|
||||
REG8(TIM4_CNTR_ADDR) = 0u;
|
||||
REG8(TIM4_EGR_ADDR) = 0x01u;
|
||||
REG8(TIM4_SR1_ADDR) = 0x00u;
|
||||
/* 配置完成后允许TIM4更新中断。 */
|
||||
REG8(TIM4_IER_ADDR) = 0x01u;
|
||||
REG8(TIM4_CR1_ADDR) = 0x01u;
|
||||
}
|
||||
|
||||
/**
|
||||
* 固件入口函数。
|
||||
*
|
||||
* PB5采用推挽输出,初始电平为低电平,TIM4中断累计500次后翻转一次。
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
/* 先写入低电平,再切换为推挽输出,减少上电瞬间的错误脉冲。 */
|
||||
REG8(GPIOB_ODR_ADDR) &= (uint8_t)~PB5_MASK;
|
||||
REG8(GPIOB_DDR_ADDR) |= PB5_MASK;
|
||||
REG8(GPIOB_CR1_ADDR) |= PB5_MASK;
|
||||
REG8(GPIOB_CR2_ADDR) &= (uint8_t)~PB5_MASK;
|
||||
|
||||
tim4_count = 0u;
|
||||
Test_TIM4_Init();
|
||||
__asm__("rim");
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* PB5翻转全部由TIM4 ISR完成,主循环保持空闲。 */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user