修改了一些代码

This commit is contained in:
2026-06-28 23:50:53 +08:00
parent c9d25d7323
commit 8aa637be48
12 changed files with 210 additions and 1310 deletions
+147 -44
View File
@@ -23,61 +23,42 @@
#include "nrf24.h"
#include "uart.h"
void EEPROM_LoadConfig();
void Init();
void LoadConfig();
void SystemInit();
void PWMBInit();
void main(void) {
/* 系统初始化 */
System_Init();
GPIO_Init();
Timer0_Init();
UART1_Init();
ADC_Init();
IAP_Init();
SystemInit();
PWMBInit();
/* 初始化NRF24L01 */
NRF24L01_Init();
/* 初始PWM: 中位 */
PWM_SetAllFailsafe();
// 从EEPROM加载配置 */
EEPROM_LoadConfig();
// 从EEPROM加载配置并应用 */
InitSet(LoadConfig());
/* 检测NRF模块 */
if (!NRF24L01_Check()) {
/* NRF模块未检测到, 设置硬件错误标志, LED双闪 */
nrf_hw_error = 1;
SysStatus = NRF_ERROR;
while (1) LED_Update();
}
while (1) {
/* 处理串口命令 */
UART1_ProcessCmd();
if (NRF_IRQ == 1) {
// 处理NRF24L01接收数据
NRF24L01_ProcessRX();
// 更新输出数据
outputFun();
}
/* LED状态指示 */
LED_Update();
}
}
void Init() {
void SystemInit() {
// System_Init()
/* 切换到内部24MHz IRC */
P_SW2 |= EAXFR; /* 使能访问扩展SFR */
CLKDIV = 0x00; /* 主时钟不分频 */
CKSEL = 0x00; /* 选择内部高速IRC */
P_SW2 &= ~EAXFR;
// 使用stc-isp下载时, 系统时钟已设置为内部IRC 40MHz, 可省略
P_SW2 |= 0x80; // 使能访问扩展SFRXFR
// 选择内部高速IRC作为主时钟源(复位后默认即为内部IRC,可省略)
CLKSEL = 0x00; // MCKSEL[1:0]=00 选择内部IRC
// 主时钟不分频
CLKDIV = 0x00; // 系统时钟 = 主时钟 / 1 = 40MHz
/* 设置内部IRC为24MHz */
IRC24MCR = 0x80; /* 使能内部24MHz IRC */
while (!(IRC24MCR & 0x01)); /* 等待IRC稳定 */
// GPIO_Init()
/* P3.4-P3.7: 推挽输出 (PWM通道) */
P3M0 |= 0xF0;
@@ -127,14 +108,136 @@ void Init() {
// Timer_Init()
/* 16位自动重载模式, 1T */
TMOD &= ~0x0F;
TMOD |= 0x01; /* T0: 16位定时器 */
AUXR |= T0x12; /* T0: 1T模式 */
/* 4us @ 24MHz: 96 ticks */
TH0 = 0xFF;
TL0 = 0xA0; /* 65536 - 96 = 0xFFA0 */
TMOD &= 0xF0; /* 清除T0模式低4位 */
TMOD |= 0x00; /* T0: 16位定时器 */
AUXR |= 0x80; /* 不分频,T0x12=1,定时器0时钟 = SYSCLK */
/* 50us @ 40MHz */
TH0 = 0xFE;
TL0 = 0x70;
ET0 = 1; /* 使能T0中断 */
EA = 1;
TR0 = 1; /* 启动T0 */
}
// UART_Init()
/* 使用 Timer2 做波特率发生器 */
/* 115200 @ 24MHz: T2 reload = 65536 - 52 = 0xFFCC */
T2H = 0xFF;
T2L = 0xCC;
AUXR |= T2x12; /* T2: 1T模式 */
AUXR |= T2R; /* 启动T2 */
/* UART1 配置: 8位可变波特率, 模式1 */
SCON = 0x50; /* 模式1, REN=1 */
AUXR |= S1ST2; /* UART1使用T2做波特率 */
PCON &= ~SMOD0; /* SMOD0=0, 帧格式8位数据 */
/* 使能接收中断 */
ES = 1;
RI = 0;
/* SPI 初始化: 主模式, 模式0, 5MHz @ 40MHz */
// 1. 配置 SPI 时钟频率 (SPR[1:0] = 01)
// 同时设置其他控制位:
// SSIG = 1 (忽略SS引脚,由MSTR控制主从)[reference:7]
// SPEN = 1 (使能SPI)[reference:8]
// DORD = 0 (MSB先发)[reference:9]
// MSTR = 1 (主机模式)[reference:10]
// CPOL = 0 (时钟空闲时为低电平)[reference:11]
// CPHA = 0 (第一个时钟沿采样)[reference:12]
// 组合得到 SPCTL = 0b11010001 = 0xD1
SPCTL = 0xD1;
// 2. 清空中断标志
SPSTAT = 0xC0;
// 3. (可选) 使能SPI中断
// IE2 |= ESPI;
}
void PWMBInit() {
// 1. 使能访问扩展特殊功能寄存器 (XFR)
P_SW2 |= 0x80;
// 2. 配置时基:1MHz 计数时钟,20ms 周期, 基于40MHz系统
PWMB_PSCR = 39; // 预分频器
PWMB_ARR = 19999; // 自动重装载值
// 3. 配置四个通道为 PWM 模式1 (PWM1),使能预装载
PWMB_CCMR1 = 0x68; // 通道5: PWM模式1, 预装载使能
PWMB_CCMR2 = 0x68; // 通道6
PWMB_CCMR3 = 0x68; // 通道7
PWMB_CCMR4 = 0x68; // 通道8
// 4. 设置初始占空比(例如 1.5ms,对应 90°)
PWMB_CCR5 = 1500;
PWMB_CCR6 = 1500;
PWMB_CCR7 = 1500;
PWMB_CCR8 = 1500;
// 5. 配置 GPIO 为推挽输出
// P1.7
P1M0 |= 0x80; // P1M0.7 = 1
P1M1 &= ~0x80; // P1M1.7 = 0
// P5.4
P5M0 |= 0x10; // P5M0.4 = 1
P5M1 &= ~0x10; // P5M1.4 = 0
// P3.3, P3.4
P3M0 |= 0x18; // bit3 and bit4
P3M1 &= ~0x18;
// 6. 引脚功能映射 (选择第二组引脚)
PWMB_PS = PWMB_PS_VALUE; // 0x55
// 7. 使能输出
PWMB_ENO = 0x55; // bit0: ENO5P, bit2: ENO6P, bit4: ENO7P, bit6: ENO8P
PWMB_CCER1 = 0x11; // CC5E=1, CC6E=1
PWMB_CCER2 = 0x11; // CC7E=1, CC8E=1
// 8. 主输出使能
PWMB_BKR |= 0x80; // MOE=1
// 9. 启动计数器
PWMB_CR1 |= 0x01; // CEN=1
}
void LED_Update(void) {
switch (led_mode) {
case UNCONNECTED:
// 未连接状态,1Hz闪烁
if (sys_tick < 500) P32 = 1; else P32 = 0;
break;
case NRF_BINDING:
// 对频状态,2Hz闪烁
if (sys_tick % 500 < 250) P32 = 1; else P32 = 0;
break;
case NRF_ERROR:
// NRF硬件错误状态,双闪
if (sys_tick < 100) P32 = 0; /* 亮 100ms */
else if (sys_tick < 200) P32 = 1; /* 灭 100ms */
else if (sys_tick < 300) P32 = 0; /* 亮 100ms */
else P32 = 1; /* 灭 700ms */
break;
case CONNECTED:
// 已连接状态,常亮
P32 = 1;
break;
default:
P32 = 0;
break;
}
}
void Servo_SetAngle(uint16 CH_Value[4]) {
// 角度范围 0 ~ 180,对应脉宽 0.5ms ~ 2.5ms,即5002500
// CH_Value范围10002000,值为1500时中点
PWMB_CCR5 = CH_Value[0]*2-1500;
PWMB_CCR6 = CH_Value[1]*2-1500;
PWMB_CCR7 = CH_Value[2]*2-1500;
PWMB_CCR8 = CH_Value[3]*2-1500;
}
// 中断
void tm0_isr(void) __interrupt(1) {
// 40MHz系统下10us中断, 用于系统滴答
static idata uint8 sys_tick_cnt = 0;
/* 系统滴答 (1ms) */
if (sys_tick_cnt++ >= 100) {
sys_tick_cnt = 0;
if (sys_tick++ >= 1000) sys_tick = 0; // 1秒清零
}
}