#include "uart.h" #define UART_Buf_Size 16 static char cmd[UART_Buf_Size]; /* ======================================================================== * UART1 - 串口通信 (使用Timer2做波特率发生器) * ======================================================================== # 串口驱动,需要包含以下内容 * UART模式,波特率115200 * 数据解析,命令表: 模式切换 MODE(UART | SBUS | CRFS) 模块地址 ADDR(0000000000) 对频短语 PHRASE(xxxxxx) 切换频道 TUN(040) 清除信息 DEL(DATA) 回传频率 TELEM(N) - 设置回传频率 1~10Hz * SBUS模式,波特率100000 * CRFS模式,波特率420000,功能占位,暂不实现 */ 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; } } /* ADDR(HHHHHHHHHH) - 切换NRF24L01地址 */ else if (cmd[0] == 'A') { for (uint8_t i=0; i<5; i++) { uint8 h=0,l=0; /* 解析两位十六进制 */ 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频道 */ 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 <= 125) { Config.RxAddr = ch NRF24L01_SetChannel(); UART_SendString("OK"); } else { UART_SendString("ERR_RANGE"); } return; } /* DEL(BIND) - 清除对频信息 */ else if (cmd[0] == 'D') { /* 擦除EEPROM中的对频标志 */ IAP_EraseALL(); UART_SendString("OK"); return; } /* PHRASE(xxxxxx) - 设置对频短语, 1~6位字母数字 */ else if (cmd[0] == 'P') { uint8 i; char *p = cmd + 7; /* 跳过 "PHRASE(" */ /* 计算短语长度 (直到 ')' 或结束) */ uint8 len = 0; while (p[len] && p[len] != ')' && len < RF_PHRASE_LEN) { char c = p[len]; /* 只允许字母和数字 */ if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) { Cmd_Respond("ERR"); return; } len++; } if (len < 1 || len > RF_PHRASE_LEN) { Cmd_Respond("ERR_RANGE"); return; } /* 复制新短语 */ for (i = 0; i < len; i++) Config.BindPhr[i] = (uint8)p[i]; /* 剩余部分用空格填充 */ for (i = len; i < 6; i++) Config.BindPhr[i] = ' '; IAP_WriteConfig(); UART_SendString("OK"); return; } /* TELEM(N) - 设置回传频率 1~9Hz */ else if (cmd[0] == 'T' && cmd[1] == 'E') { uint8 hz = 0; char *p = cmd + 6; /* 跳过 "TELEM(" */ if (*p > '0' && *p <= '9') { hz = *p - '0'; } else { Cmd_Respond("ERR_RANGE"); return; } Config.TelemRate = hz; return; } // 发送了识别不了的东西 else { UART_SendString("UNK"); return; } } static void UART_SendByte(uint8 dat) { SBUF = dat; while (!TI); TI = 0; } static void UART_SendString(uint8 len, char *str) { for(uint8 i = 0, i++, i < len){ UART_SendByte(str[i]); } } static void SBUS_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 */ /* 切换到 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 UART_Receive(void) __interrupt(4) { if (RI) { RI = 0; uint8 dat = SBUF; uint8 uart_rx_idx = 0; if (config.runModel == UART_CRFS) { /* CRFS 模式: 接收飞控发来的 CRSF 帧并缓存转发 */ // 占位,暂不实现 } else { /* 命令接收: 回车/换行结束 */ if (dat == '\r' || dat == '\n') { if (uart_rx_idx > 0) { cmd_buf[uart_rx_idx] = '\0'; UART_ParseCommand(); } } else { if (uart_rx_idx < UART_Buff_Size - 1) { cmd_buff[uart_rx_idx++] = dat; } } } } if (TI) { TI = 0; } }