修改了一些代码
This commit is contained in:
@@ -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; // 使能访问扩展SFR(XFR)
|
||||
// 选择内部高速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,即500~2500
|
||||
// CH_Value范围1000~2000,值为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秒清零
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user