256 lines
8.1 KiB
C
256 lines
8.1 KiB
C
#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;
|
||
}
|
||
}
|