251 lines
7.5 KiB
C
251 lines
7.5 KiB
C
#include "uart.h"
|
|
|
|
/* ========================================================================
|
|
* UART1 - 串口通信 (使用Timer2做波特率发生器)
|
|
* ========================================================================
|
|
|
|
# 串口驱动,需要包含以下内容
|
|
* UART模式,波特率115200
|
|
* 数据解析,命令表:
|
|
模式切换 MODEL(UART | SBUS | CRFS)
|
|
模块地址 ADDR(0x00 00 00 00 00)
|
|
对频短语 PHRASE(xxxxxx)
|
|
切换频道 TUN(40)
|
|
清除信息 DEL(DATA)
|
|
* 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;
|
|
}
|
|
|
|
/* 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++;
|
|
/* 解析两位十六进制 */
|
|
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");
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* TUN(N) - 切换RF频道 */
|
|
if (cmd[0] == 'T' && cmd[1] == 'U' && cmd[2] == 'N') {
|
|
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");
|
|
} else {
|
|
Cmd_Respond("ERR_RANGE");
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* DEL(BIND) - 清除对频信息 */
|
|
if (strcmp(cmd, "DEL(BIND)") == 0) {
|
|
/* 擦除EEPROM中的对频标志 */
|
|
IAP_EraseSector(0x0000);
|
|
IAP_WriteByte(EEPROM_ADDR_BIND_FLAG, 0x00);
|
|
rx_state = RX_STATE_BINDING;
|
|
NRF_EnterBindMode();
|
|
Cmd_Respond("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;
|
|
char *p = cmd + 7; /* 跳过 "PHRASE(" */
|
|
/* 计算短语长度 (直到 ')' 或结束) */
|
|
uint8_t 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++)
|
|
bind_phrase[i] = (uint8_t)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");
|
|
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;
|
|
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");
|
|
} else {
|
|
Cmd_Respond("ERR_RANGE");
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* 未知命令 */
|
|
Cmd_Respond("UNK");
|
|
}
|
|
|
|
|
|
static void UART1_SendByte(uint8_t 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 SBUS_Init(void) {
|
|
/* 切换到 SBUS 波特率 100kbps */
|
|
/* 100000 @ 24MHz: T2 reload = 65536 - 60 = 0xFFC4 */
|
|
T2H = 0xFF;
|
|
T2L = 0xC4;
|
|
AUXR |= T2x12;
|
|
AUXR |= T2R;
|
|
|
|
/* 8E2: 8数据位, 偶校验, 2停止位 */
|
|
PCON |= SMOD0; /* SMOD0=1, 帧格式由SM2控制 */
|
|
SCON &= ~0x0E; /* 清除SM2, TB8 */
|
|
/* 注意: 对于SBUS, 标准是8E2, 但这里通过三极管反相,
|
|
* 所以实际发送的是反相SBUS信号 */
|
|
}
|
|
|
|
/* UART1 中断服务 */
|
|
void UART1_Interrupt(void) __interrupt(4) {
|
|
if (RI) {
|
|
RI = 0;
|
|
uint8_t dat = SBUF;
|
|
|
|
if (config.runModel == UART_CRFS) {
|
|
/* CRFS 模式: 接收飞控发来的 CRSF 帧并缓存转发 */
|
|
// 占位,暂不实现
|
|
} else {
|
|
/* 命令接收: 回车/换行结束 */
|
|
if (dat == '\r' || dat == '\n') {
|
|
if (uart_rx_idx > 0) {
|
|
uart_rx_buf[uart_rx_idx] = '\0';
|
|
uart_cmd_ready = 1;
|
|
}
|
|
uart_rx_idx = 0;
|
|
} else {
|
|
if (uart_rx_idx < UART_BUF_SIZE - 1) {
|
|
uart_rx_buf[uart_rx_idx++] = dat;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (TI) {
|
|
TI = 0;
|
|
}
|
|
}
|