Files
2026-06-29 19:04:09 +08:00

256 lines
8.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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 @ 40MHz1T模式
* 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. 设置PCONSMOD=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 @ 40MHz1T模式
* 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. 设置PCONSMOD=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;
}
}