diff --git a/rx/config.h b/rx/config.h index 35fcc82..48e426d 100644 --- a/rx/config.h +++ b/rx/config.h @@ -28,11 +28,10 @@ #define NRF_BINDING 1 /* 3Hz - 对频中 */ #define CONNECTED 2 /* 常亮 - 已连接 */ #define NRF_ERROR 4 /* 双闪 - NRF硬件错误 */ - /* UART运行模式 */ -#define UART_UART 0 +#define UART_CMD 0 #define UART_SBUS 1 -#define UART_CRFS 2 +#define UART_CRSF 2 /* ======================================================================== * 全局变量 @@ -42,18 +41,20 @@ struct CONFIG { // 运行模式 - uint8 runModel; + uint8 RunMode; // nrf24使用的通道 - uint8 nrf_ch; + uint8 NrfCH; // nrf24使用的对频短语 - uint8 nrf_bindphr[6]; + uint8 BindPhr[6]; // nrf24地址,40位 - uint8 nrf_addr[5]; + uint8 RxAddr[5]; // 对频标志 - uint8 tx_magic; + uint8 BindMagic; // 记录的发射机地址 - uint8 tx_addr[5]; -} config; + uint8 TxAddr[5]; + // 回传频率 + uint8 TelemRate; +} Config; // nrf24l01接收的数据 struct RFDATA diff --git a/rx/main.c b/rx/main.c index b6235a3..b04578b 100644 --- a/rx/main.c +++ b/rx/main.c @@ -23,11 +23,17 @@ #include "nrf24.h" #include "uart.h" -void LoadConfig(); -void SystemInit(); -void PWMBInit(); +// EEPROM操作 +static CONFIG IAP_Read(); +static void IAP_Write(uint8 addr, CONFIG dat); +static void IAP_Erase(uint8 addr); -void main(void) { +static void LoadConfig(); +static void SystemInit(); +static void PWMBInit(); +static void UpdatePWMB(); + +static void main(void) { /* 系统初始化 */ SystemInit(); PWMBInit(); @@ -236,7 +242,6 @@ void Servo_SetAngle(uint16 CH_Value[4]) { PWMB_CCR7 = CH_Value[2]*2-1500; PWMB_CCR8 = CH_Value[3]*2-1500; } - // 中断 void tm0_isr(void) __interrupt(1) { // 40MHz系统下10us中断, 用于系统滴答 @@ -247,3 +252,11 @@ void tm0_isr(void) __interrupt(1) { if (sys_tick++ >= 1000) sys_tick = 0; // 1秒清零 } } + +static CONFIG IAP_Read(){ + static __xdata CONFIG dat; + + return dat; +} +static void IAP_Write(uint8 addr, CONFIG dat); +static void IAP_Erase(uint8 addr); \ No newline at end of file diff --git a/rx/uart.c b/rx/uart.c index 5bbdf8c..1b25277 100644 --- a/rx/uart.c +++ b/rx/uart.c @@ -1,5 +1,8 @@ #include "uart.h" +#define UART_Buf_Size 16 + +static char cmd[UART_Buf_Size]; /* ======================================================================== * UART1 - 串口通信 (使用Timer2做波特率发生器) * ======================================================================== @@ -7,127 +10,96 @@ # 串口驱动,需要包含以下内容 * UART模式,波特率115200 * 数据解析,命令表: - 模式切换 MODEL(UART | SBUS | CRFS) - 模块地址 ADDR(0x00 00 00 00 00) + 模式切换 MODE(UART | SBUS | CRFS) + 模块地址 ADDR(0000000000) 对频短语 PHRASE(xxxxxx) - 切换频道 TUN(40) + 切换频道 TUN(040) 清除信息 DEL(DATA) + 回传频率 TELEM(N) - 设置回传频率 1~10Hz * SBUS模式,波特率100000 * CRFS模式,波特率420000,功能占位,暂不实现 */ - -static void Cmd_Parse(void) { - if (!uart_cmd_ready) return; - uart_cmd_ready = 0; - - char *cmd = (char *)uart_rx_buf; - - /* MODEL(SBUS) - 切换到SBUS模式 */ - if (strcmp(cmd, "MODEL(SBUS)") == 0) { - out_mode = OUT_MODE_SBUS; - SBUS_Init(); - Cmd_Respond("OK"); - return; +static void UART_ParseCommand(void) { + // 解析运行模式 + if (cmd[0] == 'M') { + if (cmd_buf[5] == 'S'){ + Config.RunMode = UART_SBUS; + SBUS_Init(); + UART_SendString(2, "OK"); + return; + } else if (cmd_buf[5] == 'U') { + Config.RunMode = UART_CMD; + CMD_Init(); + UART_SendString(2, "OK"); + return; + } else if (cmd_buf[5] == 'C') { + CRFS_Init(); + Config.RunMode = UART_CRSF; + UART_SendString(2, "OK"); + return; + } } - - /* MODEL(PWM) - 切换到PWM模式 */ - if (strcmp(cmd, "MODEL(PWM)") == 0) { - out_mode = OUT_MODE_PWM; - /* 重新初始化UART1为115200 */ - UART1_Init(); - Cmd_Respond("OK"); - return; - } - - /* MODEL(UART) - 切换到UART模式 (占位) */ - if (strcmp(cmd, "MODEL(UART)") == 0) { - out_mode = OUT_MODE_UART; - UART1_Init(); - Cmd_Respond("OK"); - return; - } - - /* MODEL(CRFS) - 切换到CRFS/CRSF输出模式 */ - if (strcmp(cmd, "MODEL(CRFS)") == 0) { - out_mode = OUT_MODE_CRFS; - CRFS_Init(); - Cmd_Respond("OK"); - return; - } - - /* ADDR(0xHH HH HH HH HH) - 切换NRF24L01地址 */ - if (cmd[0] == 'A' && cmd[1] == 'D' && cmd[2] == 'D' && cmd[3] == 'R') { - /* 解析: ADDR(0xHH HH HH HH HH) */ - static uint8_t __xdata new_addr[NRF_ADDR_WIDTH]; - uint8_t ok = 1; - char *p = cmd + 5; /* 跳过 "ADDR(" */ - for (uint8_t i = 0; i < NRF_ADDR_WIDTH; i++) { - /* 跳过 "0x" */ - if (*p == '0' && (*(p+1) == 'x' || *(p+1) == 'X')) p += 2; - /* 跳过空格 */ - while (*p == ' ') p++; + /* ADDR(HHHHHHHHHH) - 切换NRF24L01地址 */ + else if (cmd[0] == 'A') { + for (uint8_t i=0; i<5; i++) { + uint8 h=0,l=0; /* 解析两位十六进制 */ - uint8_t hi = 0, lo = 0; - if (*p >= '0' && *p <= '9') hi = *p - '0'; - else if (*p >= 'A' && *p <= 'F') hi = *p - 'A' + 10; - else if (*p >= 'a' && *p <= 'f') hi = *p - 'a' + 10; - else { ok = 0; break; } - p++; - if (*p >= '0' && *p <= '9') lo = *p - '0'; - else if (*p >= 'A' && *p <= 'F') lo = *p - 'A' + 10; - else if (*p >= 'a' && *p <= 'f') lo = *p - 'a' + 10; - else { ok = 0; break; } - p++; - new_addr[i] = (hi << 4) | lo; - } - if (ok) { - for (uint8_t i = 0; i < NRF_ADDR_WIDTH; i++) - tx_addr[i] = new_addr[i]; - NRF24L01_WriteBuf(NRF_TX_ADDR, tx_addr, NRF_ADDR_WIDTH); - NRF24L01_WriteBuf(NRF_RX_ADDR_P0, tx_addr, NRF_ADDR_WIDTH); - Cmd_Respond("OK"); - } else { - Cmd_Respond("ERR_ADDR"); + if (cmd_buf[6+i*2] >= '0' && cmd_buf[6+i*2] <= '9') + h=cmd_buf[6+i*2]-'0'; + else if (cmd_buf[6+i*2] >= 'A' && cmd_buf[6+i*2] <= 'F') + h=cmd_buf[6+i*2]-'A'; + else { + UART_SendString(8, "ERR_ADDR"); + return; + } + + if (cmd_buf[7+i*2] >= '0' && cmd_buf[7+i*2] <= '9') + h=cmd_buf[7+i*2]-'0'; + else if (cmd_buf[7+i*2] >= 'A' && cmd_buf[7+i*2] <= 'F') + h=cmd_buf[7+i*2]-'A'; + else { + UART_SendString(8, "ERR_ADDR"); + return; + } + + Config.RxAddr[i] = h | l; } + // 应用 + WriteConfig(); + NRF24_SetAddr(); return; } - /* TUN(N) - 切换RF频道 */ - if (cmd[0] == 'T' && cmd[1] == 'U' && cmd[2] == 'N') { + else if (cmd[0] == 'T' && cmd[1] == 'U') { uint8_t ch = 0; char *p = cmd + 4; /* 跳过 "TUN(" */ while (*p >= '0' && *p <= '9') { ch = ch * 10 + (*p - '0'); p++; } - if (ch <= NRF_MAX_CHANNEL) { - NRF24L01_SetChannel(ch); - Cmd_Respond("OK"); + if (ch <= 125) { + Config.RxAddr = ch + NRF24L01_SetChannel(); + UART_SendString("OK"); } else { - Cmd_Respond("ERR_RANGE"); + UART_SendString("ERR_RANGE"); } return; } - /* DEL(BIND) - 清除对频信息 */ - if (strcmp(cmd, "DEL(BIND)") == 0) { + else if (cmd[0] == 'D') { /* 擦除EEPROM中的对频标志 */ - IAP_EraseSector(0x0000); - IAP_WriteByte(EEPROM_ADDR_BIND_FLAG, 0x00); - rx_state = RX_STATE_BINDING; - NRF_EnterBindMode(); - Cmd_Respond("OK"); + IAP_EraseALL(); + UART_SendString("OK"); return; } - /* PHRASE(xxxxxx) - 设置对频短语, 1~6位字母数字 */ - if (cmd[0] == 'P' && cmd[1] == 'H' && cmd[2] == 'R' && cmd[3] == 'A' - && cmd[4] == 'S' && cmd[5] == 'E') { - uint8_t i; + else if (cmd[0] == 'P') { + uint8 i; char *p = cmd + 7; /* 跳过 "PHRASE(" */ /* 计算短语长度 (直到 ')' 或结束) */ - uint8_t len = 0; + uint8 len = 0; while (p[len] && p[len] != ')' && len < RF_PHRASE_LEN) { char c = p[len]; /* 只允许字母和数字 */ @@ -145,87 +117,121 @@ static void Cmd_Parse(void) { } /* 复制新短语 */ for (i = 0; i < len; i++) - bind_phrase[i] = (uint8_t)p[i]; + Config.BindPhr[i] = (uint8)p[i]; /* 剩余部分用空格填充 */ - for (i = len; i < RF_PHRASE_LEN; i++) - bind_phrase[i] = ' '; - /* 保存到EEPROM */ - IAP_EraseSector(0x0000); - IAP_WriteByte(EEPROM_ADDR_BIND_FLAG, EEPROM_BIND_MAGIC); - for (i = 0; i < NRF_ADDR_WIDTH; i++) - IAP_WriteByte(EEPROM_ADDR_TX_ADDR + i, tx_addr[i]); - IAP_WriteByte(EEPROM_ADDR_RF_CH, rf_channel); - for (i = 0; i < RF_PHRASE_LEN; i++) - IAP_WriteByte(EEPROM_ADDR_BIND_PHRASE + i, bind_phrase[i]); - /* 重新初始化NRF以使用新短语 */ - NRF24L01_Init(); - NRF24L01_RXMode(); - Cmd_Respond("OK"); + for (i = len; i < 6; i++) + Config.BindPhr[i] = ' '; + + IAP_WriteConfig(); + UART_SendString("OK"); return; } - - /* TELEM(N) - 设置回传频率 1~10Hz */ - if (cmd[0] == 'T' && cmd[1] == 'E' && cmd[2] == 'L' && cmd[3] == 'E' - && cmd[4] == 'M') { - uint8_t hz = 0; + /* TELEM(N) - 设置回传频率 1~9Hz */ + else if (cmd[0] == 'T' && cmd[1] == 'E') { + uint8 hz = 0; char *p = cmd + 6; /* 跳过 "TELEM(" */ - while (*p >= '0' && *p <= '9') { - hz = hz * 10 + (*p - '0'); - p++; - } - if (hz >= 1 && hz <= 10) { - telem_rate_hz = hz; - Cmd_Respond("OK"); + if (*p > '0' && *p <= '9') { + hz = *p - '0'; } else { Cmd_Respond("ERR_RANGE"); + return; } + Config.TelemRate = hz; + return; + } + // 发送了识别不了的东西 + else { + UART_SendString("UNK"); return; } - - /* 未知命令 */ - Cmd_Respond("UNK"); } - -static void UART1_SendByte(uint8_t dat) { +static void UART_SendByte(uint8 dat) { SBUF = dat; while (!TI); TI = 0; } -static void UART1_SendString(const char *s) { - while (*s) { - UART1_SendByte((uint8_t)(*s++)); - } -} - -static void UART1_SendStringLen(const char *s, uint8_t len) { - for (uint8_t i = 0; i < len; i++) { - UART1_SendByte((uint8_t)s[i]); +static void UART_SendString(uint8 len, char *str) { + for(uint8 i = 0, i++, i < len){ + UART_SendByte(str[i]); } } static void SBUS_Init(void) { - /* 切换到 SBUS 波特率 100kbps */ - /* 100000 @ 24MHz: T2 reload = 65536 - 60 = 0xFFC4 */ - T2H = 0xFF; - T2L = 0xC4; - AUXR |= T2x12; - AUXR |= T2R; + P_SW2 |= 0x80; /* 使能访问扩展SFR(若需访问T2相关XFR) */ + /* 1. 选择定时器2作为串口1的波特率发生器 */ + AUXR &= ~0x01; /* 先清除S1ST2,再置1 */ + AUXR |= 0x01; /* S1ST2 = 1 */ + /* 2. 定时器2配置为1T模式,启动 */ + AUXR |= (1 << 2); /* T2x12 = 1,不分频 */ + AUXR |= (1 << 4); /* T2R = 1,启动定时器2 */ - /* 8E2: 8数据位, 偶校验, 2停止位 */ - PCON |= SMOD0; /* SMOD0=1, 帧格式由SM2控制 */ - SCON &= ~0x0E; /* 清除SM2, TB8 */ - /* 注意: 对于SBUS, 标准是8E2, 但这里通过三极管反相, - * 所以实际发送的是反相SBUS信号 */ + /* 切换到 SBUS 波特率 100kbps */ + /* 3. 计算重载值:100kbps @ 40MHz,1T模式 + * Baud = SYSCLK / (4 * (65536 - reload)) + * reload = 65536 - SYSCLK / (4 * Baud) + * = 65536 - 40000000 / (4 * 100000) + * = 65536 - 100 = 65436 = 0xFF9C + */ + T2H = 0xFF; + T2L = 0x9C; + + /* 4. 串口模式:模式3(9位可变波特率),使能接收,REN=1 */ + SCON = 0xD0; /* SM0=1, SM1=1, SM2=0, REN=1, TB8=0 */ + + /* 5. 设置PCON:SMOD=0(无波特率加倍),SMOD0=1(启用帧错误检测,可选) */ + PCON &= ~0x80; /* SMOD = 0 */ + PCON |= 0x40; /* SMOD0 = 1 */ + + /* 6. 使能串口中断(根据需要) */ + ES = 1; /* 允许串口中断 */ +} + +static void UART_Init(void) { + P_SW2 |= 0x80; /* 使能访问扩展SFR(若需访问T2相关XFR) */ + + /* 1. 选择定时器2作为串口1的波特率发生器 */ + AUXR &= ~0x01; /* 先清除S1ST2,再置1 */ + AUXR |= 0x01; /* S1ST2 = 1 */ + + /* 2. 定时器2配置为1T模式,启动 */ + AUXR |= (1 << 2); /* T2x12 = 1,不分频 */ + AUXR |= (1 << 4); /* T2R = 1,启动定时器2 */ + + /* 3. 计算重载值:115200bps @ 40MHz,1T模式 + * Baud = SYSCLK / (4 * (65536 - reload)) + * reload = 65536 - SYSCLK / (4 * Baud) + * = 65536 - 40000000 / (4 * 115200) + * = 65536 - 86.805... ≈ 65536 - 87 = 65449 = 0xFFA9 + */ + T2H = 0xFF; + T2L = 0xA9; + + /* 4. 串口模式:模式3(9位可变波特率),使能接收,REN=1 */ + SCON = 0xD0; /* SM0=1, SM1=1, SM2=0, REN=1, TB8=0 */ + + /* 5. 设置PCON:SMOD=0(无波特率加倍),SMOD0=1(启用帧错误检测) */ + PCON &= ~0x80; /* SMOD = 0 */ + PCON |= 0x40; /* SMOD0 = 1 */ + + /* 6. 使能串口中断(根据需要) */ + ES = 1; /* 允许串口中断 */ /* 允许串口中断 */ +} + +void SBUS_Update(RFDATA dat){ + uint8 *p = &dat; + for(i=0, i++, i<25){ + UART_SendByte(*p++); + } } /* UART1 中断服务 */ -void UART1_Interrupt(void) __interrupt(4) { +void UART_Receive(void) __interrupt(4) { if (RI) { RI = 0; - uint8_t dat = SBUF; - + uint8 dat = SBUF; + uint8 uart_rx_idx = 0; if (config.runModel == UART_CRFS) { /* CRFS 模式: 接收飞控发来的 CRSF 帧并缓存转发 */ // 占位,暂不实现 @@ -233,13 +239,12 @@ void UART1_Interrupt(void) __interrupt(4) { /* 命令接收: 回车/换行结束 */ if (dat == '\r' || dat == '\n') { if (uart_rx_idx > 0) { - uart_rx_buf[uart_rx_idx] = '\0'; - uart_cmd_ready = 1; + cmd_buf[uart_rx_idx] = '\0'; + UART_ParseCommand(); } - uart_rx_idx = 0; } else { - if (uart_rx_idx < UART_BUF_SIZE - 1) { - uart_rx_buf[uart_rx_idx++] = dat; + if (uart_rx_idx < UART_Buff_Size - 1) { + cmd_buff[uart_rx_idx++] = dat; } } } diff --git a/rx/uart.h b/rx/uart.h index 0df54c8..4d8fdf3 100644 --- a/rx/uart.h +++ b/rx/uart.h @@ -5,63 +5,22 @@ /* UART 接收缓冲 (放在 xdata) */ static uint8 __xdata uart_rx_buf[UART_BUF_SIZE]; -static uint8 uart_rx_idx = 0; -static bool uart_cmd_ready = 0; +void UART_Init(void); +void SBUS_Init(void); +void CRFS_Init(void); -/* -uart初始化, -uart发送, -uart接收, -uart命令解析, -uart命令响应, -uart接收缓冲区, -uart发送缓冲区, -uart接收索引, -uart命令就绪标志, -uart中断服务程序, -uart波特率设置 +void UART_Receive(void) __interrupt(4); + +void UART_SendByte(uint8 dat); +void UART_SendString(uint8 size, char *str); +void UART_ParseCommand(void); + +/* 转换数据为sbus信号输出 + * sbus为25字节固定信号,数据结构如下: + * Byte 1 | 帧头(固定为0x0F) + * Byte 2-23 | 数据通道(16个11位数据) + * Byte 24 | 标志位(包含帧丢失、故障保护等) + * Byte 25 | 帧尾(固定为0x00) */ -void UART1_Init(void); - -void UART1_Interrupt(void) __interrupt(4); - -void UART1_Send(void); -void UART1_Receive(void); -void UART1_ParseCommand(void); -void UART1_Response(void); -void UART1_SetBaudRate(void); - - 0x00, 0xD5, 0x7F, 0xAA, 0xFE, 0x2B, 0x81, 0x54, - 0x29, 0xFC, 0x56, 0x83, 0xD7, 0x02, 0xA8, 0x7D, - 0x52, 0x87, 0x2D, 0xF8, 0xAC, 0x79, 0xD3, 0x06, - 0x7B, 0xAE, 0x04, 0xD1, 0x85, 0x50, 0xFA, 0x2F, - 0xA4, 0x71, 0xDB, 0x0E, 0x5A, 0x8F, 0x25, 0xF0, - 0x8D, 0x58, 0xF2, 0x27, 0x73, 0xA6, 0x0C, 0xD9, - 0xF6, 0x23, 0x89, 0x5C, 0x08, 0xDD, 0x77, 0xA2, - 0xDF, 0x0A, 0xA0, 0x75, 0x21, 0xF4, 0x5E, 0x8B, - 0x9D, 0x48, 0xE2, 0x37, 0x63, 0xB6, 0x1C, 0xC9, - 0xB4, 0x61, 0xCB, 0x1E, 0x4A, 0x9F, 0x35, 0xE0, - 0xCF, 0x1A, 0xB0, 0x65, 0x31, 0xE4, 0x4E, 0x9B, - 0xE6, 0x33, 0x99, 0x4C, 0x18, 0xCD, 0x67, 0xB2, - 0x39, 0xEC, 0x46, 0x93, 0xC7, 0x12, 0xB8, 0x6D, - 0x10, 0xC5, 0x6F, 0xBA, 0xEE, 0x3B, 0x91, 0x44, - 0x6B, 0xBE, 0x14, 0xC1, 0x95, 0x40, 0xEA, 0x3F, - 0x42, 0x97, 0x3D, 0xE8, 0xBC, 0x69, 0xC3, 0x16, - 0xEF, 0x3A, 0x90, 0x45, 0x11, 0xC4, 0x6E, 0xBB, - 0xC6, 0x13, 0xB9, 0x6C, 0x38, 0xED, 0x47, 0x92, - 0xBD, 0x68, 0xC2, 0x17, 0x43, 0x96, 0x3C, 0xE9, - 0x94, 0x41, 0xEB, 0x3E, 0x6A, 0xBF, 0x15, 0xC0, - 0x4B, 0x9E, 0x34, 0xE1, 0xB5, 0x60, 0xCA, 0x1F, - 0x62, 0xB7, 0x1D, 0xC8, 0x9C, 0x49, 0xE3, 0x36, - 0x19, 0xCC, 0x66, 0xB3, 0xE7, 0x32, 0x98, 0x4D, - 0x30, 0xE5, 0x4F, 0x9A, 0xCE, 0x1B, 0xB1, 0x64, - 0x72, 0xA7, 0x0D, 0xD8, 0x8C, 0x59, 0xF3, 0x26, - 0x5B, 0x8E, 0x24, 0xF1, 0xA5, 0x70, 0xDA, 0x0F, - 0x20, 0xF5, 0x5F, 0x8A, 0xDE, 0x0B, 0xA1, 0x74, - 0x09, 0xDC, 0x76, 0xA3, 0xF7, 0x22, 0x88, 0x5D, - 0xD6, 0x03, 0xA9, 0x7C, 0x28, 0xFD, 0x57, 0x82, - 0xFF, 0x2A, 0x80, 0x55, 0x01, 0xD4, 0x7E, 0xAB, - 0x84, 0x51, 0xFB, 0x2E, 0x7A, 0xAF, 0x05, 0xD0, - 0xAD, 0x78, 0xD2, 0x07, 0x53, 0x86, 0x2C, 0xF9 -}; \ No newline at end of file +void SBUS_Update(RFDATA dat); \ No newline at end of file