- 打卡等级:初来乍到
- 打卡总天数:1
- 最近打卡:2026-07-03 23:23:23
新手上路
- 积分
- 5
|
最近想做一个音乐频谱,WS2812驱动正常了,设置ADC只要ADC一读取数值WS2812的灯光就不能正常显示,不知道是DMA冲突还是程序堵塞导致DMA不正常,程序如下:
#include "AI8051U.h"
#include <intrins.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
/************* 功能说明 **************
专为 EV1527 格式 24 位遥控器优化:
- 位0:高电平 0.4ms,低电平 1.2ms
- 位1:高电平 1.2ms,低电平 0.4ms
- 停止位:高 0.4ms,低 0.4ms
- 地址码:高 16 位(用户码),键码:低 8 位
******************************************/
/************* 常量声明 **************/
#define LED_NUM 60
#define SPI_NUM (LED_NUM*12)
#define MODE_NUM 4
#define COLOR_NUM 9
#define BRIGHTNESS_LEVEL_MAX 10
#define BRIGHTNESS_MIN 10
#define BRIGHTNESS_MAX 255
#define UART_BUF_SIZE 32
bit uart_print_enabled = 1; // 串口打印开关,默认开启
#define MAIN_Fosc 24000000UL //定义主时钟
#define BRT (65536 - MAIN_Fosc /9600/ 4)
// 遥控器地址(16 位,请根据实际遥控器修改)
#define REMOTE_ADDR 0xFFFF
// RF 解码常量(20us 中断计数,24MHz)
#define SYNC_LOW_MIN 400 // 8ms (典型同步头低电平 9ms)
#define SYNC_LOW_MAX 800 // 12ms
#define BIT1_THRESHOLD 40 // 高电平阈值 (0码~20, 1码~60, 取中间值40)
unsigned int learned_addr = REMOTE_ADDR; // 当前使用的遥控器地址(可由学习更新)
// EEPROM 地址
// 原有参数仍保存在 0x0000 扇区(0x0000~0x01FF)
#define EE_ADDR_MODE 0x0000
#define EE_ADDR_LIGHT_ON 0x0001
#define EE_ADDR_BRIGHT_LEV 0x0002
#define EE_ADDR_COLOR_IDX 0x0003
#define EE_ADDR_SPEED_LEV 0x0004
// 遥控器地址单独存放在 0x0200 扇区(0x0200~0x03FF)
#define EE_ADDR_REMOTE_H 0x0200 // 地址高字节
#define EE_ADDR_REMOTE_L 0x0201 // 地址低字节
/************* 变量声明 **************/
unsigned char xdata led_RGB[LED_NUM][3];
unsigned char xdata led_SPI[SPI_NUM];
bit B_SPI_DMA_busy;
bit light_on = 1;
unsigned char mode = 0;
unsigned char ColorIdex = 0;
unsigned char brightness_level = 10;
unsigned char speed_level = 5;
unsigned int speed_value = 32;
unsigned char global_brightness = 255;
unsigned char last_mode_before_off = 0;
bit ModeNeedSave = 0;
bit LightNeedSave = 0;
bit BrightNeedSave = 0;
bit ColorNeedSave = 0;
bit SpeedNeedSave = 0;
const unsigned char code colorTable[COLOR_NUM][3] = {
{255,0,0}, {0,255,0}, {0,0,255},
{255,255,0}, {255,0,255}, {0,255,255},
{255,255,255}, {255,165,0}, {128,0,128}
};
unsigned char uartBuf[UART_BUF_SIZE];
unsigned char uartCount = 0;
bit uartCmdReady = 0;
//端口定义
sbit ModeKey = P2^6;
sbit ColorKey = P3^4;
sbit BrightKey = P3^5;
sbit SpeedKey = P3^6;
sbit RF_IN = P3^3;
// 按键变量
bit ModeKeyPrev = 1, ColorKeyPrev = 1, BrightKeyPrev = 1, SpeedKeyPrev = 1;
unsigned long mode_press_start = 0;
bit mode_long_handled = 0;
unsigned long color_press_start = 0;
bit color_long_handled = 0;
bit learn_mode = 0;
unsigned long learn_timeout = 0;
// RF 解码变量(阈值法)
volatile unsigned long rf_code_32 = 0;
volatile bit rf_rec_ok = 0;
volatile unsigned char rf_bit_cnt = 0;
volatile bit rf_sync_detected = 0;
volatile unsigned int rf_high_cnt = 0;
volatile unsigned int rf_low_cnt = 0;
volatile bit rf_last_level = 0;
volatile unsigned long system_ticks = 0;
volatile unsigned int sync_timeout = 0;
#define SYNC_TIMEOUT_MAX 80
volatile unsigned long last_rf_time = 0;
volatile unsigned long last_rf_code = 0;
volatile unsigned long rf_mode_first_time = 0;
volatile unsigned char rf_mode_frame_cnt = 0;
volatile bit rf_mode_press_detected = 0;
volatile bit rf_mode_short_handled = 0;
volatile bit rf_mode_long_handled = 0;
volatile bit rf_mode_short_flag = 0;
volatile bit rf_mode_long_flag = 0;
volatile bit rf_sync_high_phase = 0; // 同步头高电平阶段标志
// 遥控器按键宏(根据 STC8H 定义)
#define REMOTE_KEY_POWER_ON 0x01 // 电源开关(短按开关灯)
#define REMOTE_KEY_LIGHT_MODE_UP 0x02 // 模式+
#define REMOTE_KEY_LIGHT_ON_OFF 0x03 // 点按开灯或关灯(独立开关)
#define REMOTE_KEY_LIGHT_SPEED_DOWN 0x04 // 速度-
#define REMOTE_KEY_DEMO 0x05 // 演示(恢复默认)
#define REMOTE_KEY_LIGHT_SPEED_UP 0x06 // 速度+
#define REMOTE_KEY_COLOR_UP 0x07 // 颜色+
#define REMOTE_KEY_LIGHT_MODE_DOWN 0x08 // 模式-
#define REMOTE_KEY_LIGHT_BRIGHT_UP 0x09 // 亮度+
#define REMOTE_KEY_LIGHT_COLOR_DOWN 0x0A // 颜色-
#define REMOTE_KEY_MODE_DOWN 0x0B // 模式转换(可忽略或用作频谱切换,但无频谱,可忽略)
#define REMOTE_KEY_LIGHT_BRIGHT_DOWN 0x0C // 亮度-
#define REMOTE_KEY_PRE 0x0D // 上一曲(忽略)
#define REMOTE_KEY_NEXT 0x0E // 下一曲(忽略)
#define REMOTE_KEY_PLAY 0x0F // 播放/暂停(忽略)
#define REMOTE_KEY_VOL_DOWN 0x10 // 音量减(忽略)
#define REMOTE_KEY_VOL_UP 0x11 // 音量加(忽略)
#define REMOTE_KEY_EQ 0x12 // EQ(忽略)
#define FRAME_HEADER 0xEA
#define FRAME_TYPE_BT 0x05
#define FRAME_TYPE_STATUS 0x01
#define FRAME_TYPE_LC 0x03
// 事件映射表(与 STC8H 一致)
typedef struct {
unsigned char event_id;
unsigned char cmd_byte;
} event_map_t;
static const event_map_t lc_event_map[] = {
{0x01, 0x80}, // 电源
{0x02, 0x40}, // MODE+
{0x03, 0xC0}, // 开关
{0x04, 0x20}, // SPEED-
{0x05, 0xA0}, // DEMO
{0x06, 0x60}, // SPEED+
{0x07, 0xE0}, // COLOR+
{0x08, 0x10}, // MODE-
{0x09, 0x90}, // BRIGHT+
{0x0A, 0x50}, // COLOR-
{0x0B, 0xD0}, // MODE转换
{0x0C, 0x30}, // BRIGHT-
{0x0D, 0xB0}, // 上一曲
{0x0E, 0x70}, // 下一曲
{0x0F, 0xF0}, // 播放/暂停
{0x10, 0x08}, // VOL-
{0x11, 0x88}, // VOL+
{0x12, 0x48} // EQ
};
// ---- ADC 双通道音频采样 ----
unsigned int Lamp = 0, Ramp = 0; // 左右声道峰值(平滑后)
unsigned int Lmax = 0, Lmin = 1023; // 左声道极值(用于计算幅值)
unsigned int Rmax = 0, Rmin = 1023; // 右声道极值
unsigned char adc_channel = 0; // 当前采样通道(0左,1右)
/************* 函数声明 **************/
void SPI_Config(unsigned char SPI_io, unsigned char SPI_speed);
void LoadSPI(void);
void SPI_DMA_TxTRIG(unsigned char xdata *TxBuf, unsigned int num);
void delay_ms(unsigned int ms);
void delay_us(unsigned int us);
void SetLedRGB(unsigned char i, unsigned char r, unsigned char g, unsigned char b);
void ClearAllLED(void);
void HSV_to_RGB(unsigned int hue, unsigned char sat, unsigned char val, unsigned char *rgb);
void Timer0Init(void);
void ProcessRFCommand(void);
void CheckRFTimeout(void);
void HandleRFCommands(void);
void UART_Init(void);
void UART_SendChar(unsigned char dat);
void UART_SendString(char *str);
void UART_SendNumber(unsigned char num);
void UART_SendUint16(unsigned int num);
void UART_SendHexByte(unsigned char byte);
void ChangeColor(void);
void ChangeBrightness(void);
void ChangeSpeed(void);
void ParseUartCommand(void);
void SaveAllParams(void);
void LoadAllParams(void);
void IapIdle(void);
unsigned char IapRead(unsigned int addr);
void IapProgram(unsigned int addr, unsigned char dat);
void IapErase(unsigned int addr);
void Effect_RainbowFlow(void);
void Effect_Breath(void);
void Effect_StaticColor(void);
void Key_Scan(void);
void SaveLearnedAddr(void);
void ChangeSpectrumScheme(void);
void SendEventToBluetooth(unsigned char event_id);
void SendToBluetooth(unsigned char type, unsigned char data_len, unsigned char data1, unsigned char data2);
void ProcessBluetoothCommand(unsigned char *buf, unsigned char len);
void ADC_Init(void);
void ADC_StartConversion(unsigned char channel);
bit ADC_GetResult(unsigned int *val);
void Effect_AudioSpectrum(void);
/************* 函数指针数组 **************/
void (*effect_func[])(void) = {
Effect_AudioSpectrum, // 模式 0
Effect_RainbowFlow, // 模式 1(原模式0)
Effect_Breath, // 模式 2(原模式1)
Effect_StaticColor // 模式 3(原模式2)
};
/*************** 主函数 *******************************/
void main(void) {
unsigned int i;
// ---- ADC 非阻塞状态变量 ----
static unsigned char adc_ch = 0; // 当前采样通道(0左,1右)
static unsigned char adc_busy = 0; // 是否已启动转换
static unsigned int adc_val_L = 0, adc_val_R = 0;
static unsigned int last_L = 0, last_R = 0;
static unsigned char sample_cnt = 0;
static unsigned char timeout_cnt = 0;
unsigned int val;
EAXFR = 1;
WTST = 0;
CKCON = 0;
// IO 配置
P1M0 = 0; P1M1 = 0;
P3M1 |= 0x08; P3M0 &= ~0x08; P3PU &= ~0x08; // RF 输入 P3.3
P2M1 |= 0x40; P2M0 &= ~0x40; P2PU |= 0x40; // ModeKey P2.6
P3M1 |= 0x70; P3M0 &= ~0x70; P3PU |= 0x70; // Color, Bright, Speed
SPI_Config(0, 1);
P1M1 |= 0x40; P1PD |= 0x40; // MISO 下拉
Timer0Init();
UART_Init();
LoadAllParams();
// ---- 初始化 ADC(非中断方式) ----
// ADC_Init();
// 启动第一次转换(通道0)
// ADC_StartConversion(0);
adc_busy = 1;
EA = 1;
UART_SendString("\r\n=== System Ready ===\r\n");
ClearAllLED();
LoadSPI();
SPI_DMA_TxTRIG(led_SPI, SPI_NUM);
while (1) {
// ==================== 1. 处理各种事件 ====================
ParseUartCommand();
ProcessRFCommand();
HandleRFCommands();
CheckRFTimeout();
Key_Scan();
if (learn_mode && (system_ticks > learn_timeout)) {
learn_mode = 0;
UART_SendString("Learn timeout\r\n");
}
// ==================== 2. 灯效计算 ====================
if (light_on) {
if (mode < MODE_NUM) effect_func[mode]();
else Effect_RainbowFlow();
for (i = 0; i < LED_NUM; i++) {
led_RGB[i][0] = (unsigned int)led_RGB[i][0] * global_brightness / 255;
led_RGB[i][1] = (unsigned int)led_RGB[i][1] * global_brightness / 255;
led_RGB[i][2] = (unsigned int)led_RGB[i][2] * global_brightness / 255;
}
} else {
ClearAllLED();
}
// ==================== 3. SPI-DMA 传输 ====================
LoadSPI();
SPI_DMA_TxTRIG(led_SPI, SPI_NUM); // 此函数应尽快返回,不操作 ADC
// ==================== 4. 保存参数 ====================
if (ModeNeedSave || LightNeedSave || BrightNeedSave || ColorNeedSave || SpeedNeedSave) {
SaveAllParams();
ModeNeedSave = 0;
LightNeedSave = 0;
BrightNeedSave = 0;
ColorNeedSave = 0;
SpeedNeedSave = 0;
}
// ==================== 5. 延时,等待 DMA 完成 ====================
delay_ms(20);
// ==================== 6. ADC 非阻塞采样(仅在频谱模式) ====================
if (mode == 0) {
// 每 N 个周期启动一次新转换(降低频率)
sample_cnt++;
if (sample_cnt >= 5) { // 5 个周期约 100ms
sample_cnt = 0;
// 若上次转换已完成,则启动新一次
if (!adc_busy) {
ADC_StartConversion(adc_ch);
adc_busy = 1;
}
}
// 检查是否有转换完成
if (adc_busy && ADC_GetResult(&val)) {
adc_busy = 0;
// 根据当前通道存储结果
if (adc_ch == 0) {
adc_val_L = val;
// 平滑滤波
adc_val_L = (last_L * 3 + adc_val_L) / 4;
last_L = adc_val_L;
Lamp = adc_val_L;
} else {
adc_val_R = val;
adc_val_R = (last_R * 3 + adc_val_R) / 4;
last_R = adc_val_R;
Ramp = adc_val_R;
}
// 切换通道,准备下一次启动
adc_ch ^= 1;
}
// 超时保护:如果 ADC 长时间未完成,强制重新启动
if (adc_busy) {
timeout_cnt++;
if (timeout_cnt > 10) { // 约 200ms 未完成
timeout_cnt = 0;
// 强制清除标志并重新启动
ADC_CONTR &= ~0x10; // 清除标志
ADC_StartConversion(adc_ch);
}
} else {
timeout_cnt = 0;
}
} else {
// 非频谱模式:清零变量
Lamp = 0;
Ramp = 0;
// 若 ADC 处于忙状态,可取消转换(可选)
if (adc_busy) {
adc_busy = 0;
ADC_CONTR &= ~0x10; // 清除标志
}
}
}
}
// 切换频谱模式的配色方案(仅当当前模式为频谱模式时有效)
void ChangeSpectrumScheme(void) {
}
/************* 按键扫描 **************/
void Key_Scan(void)
{
// 模式键 P2.6
if (ModeKey == 0 && ModeKeyPrev == 1) {
mode_press_start = system_ticks;
mode_long_handled = 0;
}
if (ModeKey == 0 && !mode_long_handled) {
if (system_ticks - mode_press_start > 500) {
light_on = !light_on;
LightNeedSave = 1;
if (!light_on) last_mode_before_off = mode;
UART_SendString(light_on ? "Key Light ON\r\n" : "Key Light OFF\r\n");
mode_long_handled = 1;
}
}
if (ModeKey == 1 && ModeKeyPrev == 0) {
if (!mode_long_handled) {
if (light_on) {
mode = (mode + 1) % MODE_NUM;
ModeNeedSave = 1;
UART_SendString("Mode "); UART_SendNumber(mode); UART_SendString("\r\n");
} else {
light_on = 1;
mode = last_mode_before_off;
LightNeedSave = 1;
UART_SendString("Key Light ON\r\n");
}
}
}
ModeKeyPrev = ModeKey;
// 颜色键 P3.4
if (ColorKey == 0 && ColorKeyPrev == 1) {
color_press_start = system_ticks;
color_long_handled = 0;
}
if (ColorKey == 0 && !color_long_handled) {
if (system_ticks - color_press_start > 500) {
if (!light_on && !learn_mode) {
learn_mode = 1;
learn_timeout = system_ticks + 10000UL;
UART_SendString("Learn mode, press remote...\r\n");
} else if (light_on) {
UART_SendString("Turn off light to learn\r\n");
}
color_long_handled = 1;
}
}
if (ColorKey == 1 && ColorKeyPrev == 0) {
if (!color_long_handled && light_on) {
ColorIdex = (ColorIdex + 1) % COLOR_NUM;
ColorNeedSave = 1;
UART_SendString("Color "); UART_SendNumber(ColorIdex); UART_SendString("\r\n");
}
}
ColorKeyPrev = ColorKey;
// 亮度键 P3.5
if (BrightKey == 0 && BrightKeyPrev == 1 && light_on) {
static unsigned char level = 5;
unsigned char i, b;
for (i = 1; i <= BRIGHTNESS_LEVEL_MAX; i++) {
b = BRIGHTNESS_MIN + (i-1) * (BRIGHTNESS_MAX - BRIGHTNESS_MIN) / (BRIGHTNESS_LEVEL_MAX - 1);
if (global_brightness <= b) { level = i; break; }
}
level++;
if (level > BRIGHTNESS_LEVEL_MAX) level = 1;
global_brightness = BRIGHTNESS_MIN + (level-1) * (BRIGHTNESS_MAX - BRIGHTNESS_MIN) / (BRIGHTNESS_LEVEL_MAX - 1);
brightness_level = level;
BrightNeedSave = 1;
UART_SendString("Bright "); UART_SendNumber(level); UART_SendString("/10\r\n");
}
BrightKeyPrev = BrightKey;
// 速度键 P3.6
if (SpeedKey == 0 && SpeedKeyPrev == 1 && light_on) {
speed_level = (speed_level % BRIGHTNESS_LEVEL_MAX) + 1;
speed_value = (11 - speed_level) * 3 + 8;
SpeedNeedSave = 1;
UART_SendString("Speed "); UART_SendNumber(speed_level); UART_SendString("/10\r\n");
}
SpeedKeyPrev = SpeedKey;
}
/************* 定时器0(阈值法解码,适配 EV1527) **************/
void Timer0Init(void) {
AUXR |= 0x80; // ?¨ê±?÷0éè???a1T?£ê?
TMOD &= 0xF0;
TMOD |= 0x01; // 16???¨ê±?÷£?ê??ˉ??×°
TL0 = 0x20;
TH0 = 0xFE;
TF0 = 0;
TR0 = 1;
ET0 = 1;
}
void Timer0_ISR(void) interrupt 1
{
static unsigned char tick_50 = 0;
bit current_level;
TL0 = 0x20; TH0 = 0xFE;
if (++tick_50 >= 50) { tick_50 = 0; system_ticks++; }
current_level = RF_IN;
if (current_level != rf_last_level) {
if (current_level == 1) { // 上升沿(低电平结束)
if (rf_low_cnt > SYNC_LOW_MIN && rf_low_cnt < SYNC_LOW_MAX) {
if (!rf_sync_detected || rf_bit_cnt == 0) {
rf_sync_detected = 1;
rf_bit_cnt = 0;
rf_code_32 = 0;
sync_timeout = 0;
}
} else {
// 低电平异常,但只有未采集数据时才复位
if (rf_sync_detected && rf_bit_cnt == 0) {
rf_sync_detected = 0;
}
}
rf_low_cnt = 0;
} else { // 下降沿(高电平结束)
if (rf_sync_detected && rf_bit_cnt < 24) {
if (rf_high_cnt > BIT1_THRESHOLD)
rf_code_32 = (rf_code_32 << 1) | 1;
else
rf_code_32 = (rf_code_32 << 1) | 0;
rf_bit_cnt++;
if (rf_bit_cnt == 24) {
rf_rec_ok = 1;
rf_sync_detected = 0;
sync_timeout = 0;
}
}
rf_high_cnt = 0;
}
rf_last_level = current_level;
} else {
if (current_level) rf_high_cnt++;
else rf_low_cnt++;
}
}
void ProcessRFCommand(void)
{
unsigned long cur_code, cur_time;
unsigned char key_code;
unsigned int addr;
if (!rf_rec_ok) return;
rf_rec_ok = 0;
cur_code = rf_code_32;
cur_time = system_ticks;
// 过滤全0或全1
if (cur_code == 0 || cur_code == 0xFFFFFF) {
UART_SendString("RF invalid (all zeros/ones)\r\n");
return;
}
addr = (unsigned int)(cur_code >> 8);
key_code = (unsigned char)(cur_code & 0xFF);
// ---- 学习模式 ----
if (learn_mode) {
learn_mode = 0;
learned_addr = addr;
SaveLearnedAddr();
UART_SendString("Learn success, addr: 0x");
UART_SendHexByte((unsigned char)(addr >> 8));
UART_SendHexByte((unsigned char)(addr & 0xFF));
UART_SendString("\r\n");
return;
}
// 过滤地址无效
if (addr == 0x0000 || addr == 0xFFFF) {
UART_SendString("RF invalid address\r\n");
return;
}
// 调试打印(可选)
UART_SendString("RF raw: 0x");
UART_SendHexByte((unsigned char)(cur_code >> 16));
UART_SendHexByte((unsigned char)(cur_code >> 8));
UART_SendHexByte((unsigned char)cur_code);
UART_SendString("\r\n");
// 去重
if (cur_code == last_rf_code && (cur_time - last_rf_time) < 300) {
UART_SendString("RF duplicate ignored\r\n");
return;
}
last_rf_code = cur_code;
last_rf_time = cur_time;
// 地址匹配
if (addr != learned_addr) {
UART_SendString("RF addr mismatch\r\n");
return;
}
// ---- 处理按键(直接映射) ----
UART_SendString("RF Key: 0x");
UART_SendHexByte(key_code);
UART_SendString("\r\n");
switch (key_code) {
// ---------- 灯光控制按键 ----------
case REMOTE_KEY_POWER_ON: // 0x01 电源开关
light_on = !light_on;
LightNeedSave = 1;
if (!light_on) last_mode_before_off = mode;
UART_SendString(light_on ? "RF Power ON\r\n" : "RF Power OFF\r\n");
SendEventToBluetooth(0x01); // 事件ID 0x01 -> 电源键
break;
case REMOTE_KEY_LIGHT_MODE_UP: // 0x02 模式+
if (light_on) {
mode = (mode + 1) % MODE_NUM;
ModeNeedSave = 1;
UART_SendString("RF Mode+\r\n");
SendEventToBluetooth(0x02); // 模式+
}
break;
case REMOTE_KEY_LIGHT_ON_OFF: // 0x03 开关(独立)
light_on = !light_on;
LightNeedSave = 1;
if (light_on) {
mode = last_mode_before_off;
} else {
last_mode_before_off = mode;
}
UART_SendString(light_on ? "RF Light ON (toggle)\r\n" : "RF Light OFF (toggle)\r\n");
SendEventToBluetooth(0x03); // 开关事件
break;
case REMOTE_KEY_LIGHT_SPEED_DOWN: // 0x04 速度-
if (light_on && speed_level > 1) {
speed_level--;
speed_value = (11 - speed_level) * 3 + 8;
SpeedNeedSave = 1;
UART_SendString("RF Speed-\r\n");
SendEventToBluetooth(0x04); // 速度-
}
break;
case REMOTE_KEY_DEMO: // 0x05 演示(恢复默认)
mode = 0;
brightness_level = 10;
global_brightness = 255;
ColorIdex = 0;
speed_level = 5;
speed_value = (11 - speed_level) * 3 + 8;
light_on = 1;
last_mode_before_off = 0;
ModeNeedSave = LightNeedSave = BrightNeedSave = ColorNeedSave = SpeedNeedSave = 1;
UART_SendString("RF Demo reset\r\n");
SendEventToBluetooth(0x05); // DEMO事件
break;
case REMOTE_KEY_LIGHT_SPEED_UP: // 0x06 速度+
if (light_on && speed_level < 10) {
speed_level++;
speed_value = (11 - speed_level) * 3 + 8;
SpeedNeedSave = 1;
UART_SendString("RF Speed+\r\n");
SendEventToBluetooth(0x06); // 速度+
}
break;
case REMOTE_KEY_COLOR_UP: // 0x07 颜色+
if (light_on) {
ColorIdex = (ColorIdex + 1) % COLOR_NUM;
ColorNeedSave = 1;
UART_SendString("RF Color+\r\n");
SendEventToBluetooth(0x07); // 颜色+
}
break;
case REMOTE_KEY_LIGHT_MODE_DOWN: // 0x08 模式-
if (light_on) {
mode = (mode - 1 + MODE_NUM) % MODE_NUM;
ModeNeedSave = 1;
UART_SendString("RF Mode-\r\n");
SendEventToBluetooth(0x08); // 模式-
}
break;
case REMOTE_KEY_LIGHT_BRIGHT_UP: // 0x09 亮度+
if (light_on && brightness_level < 10) {
brightness_level++;
global_brightness = BRIGHTNESS_MIN + (brightness_level - 1) * (BRIGHTNESS_MAX - BRIGHTNESS_MIN) / (BRIGHTNESS_LEVEL_MAX - 1);
BrightNeedSave = 1;
UART_SendString("RF Bright+\r\n");
SendEventToBluetooth(0x09); // 亮度+
}
break;
case REMOTE_KEY_LIGHT_COLOR_DOWN: // 0x0A 颜色-
if (light_on) {
ColorIdex = (ColorIdex - 1 + COLOR_NUM) % COLOR_NUM;
ColorNeedSave = 1;
UART_SendString("RF Color-\r\n");
SendEventToBluetooth(0x0A); // 颜色-
}
break;
case REMOTE_KEY_MODE_DOWN: // 0x0B 模式转换(原用于频谱切换)
// 当前无频谱功能,但可发送事件给蓝牙(若需要)
UART_SendString("RF Mode convert (ignored)\r\n");
SendEventToBluetooth(0x0B); // 模式转换事件(蓝牙可能无响应)
break;
case REMOTE_KEY_LIGHT_BRIGHT_DOWN: // 0x0C 亮度-
if (light_on && brightness_level > 1) {
brightness_level--;
global_brightness = BRIGHTNESS_MIN + (brightness_level - 1) * (BRIGHTNESS_MAX - BRIGHTNESS_MIN) / (BRIGHTNESS_LEVEL_MAX - 1);
BrightNeedSave = 1;
UART_SendString("RF Bright-\r\n");
SendEventToBluetooth(0x0C); // 亮度-
}
break;
// ---------- 音频控制按键(仅转发蓝牙,不控制灯光) ----------
case REMOTE_KEY_PRE: // 0x0D 上一曲
UART_SendString("RF Audio: PRE\r\n");
SendEventToBluetooth(0x0D);
break;
case REMOTE_KEY_NEXT: // 0x0E 下一曲
UART_SendString("RF Audio: NEXT\r\n");
SendEventToBluetooth(0x0E);
break;
case REMOTE_KEY_PLAY: // 0x0F 播放/暂停
UART_SendString("RF Audio: PLAY\r\n");
SendEventToBluetooth(0x0F);
break;
case REMOTE_KEY_VOL_DOWN: // 0x10 音量减
UART_SendString("RF Audio: VOL-\r\n");
SendEventToBluetooth(0x10);
break;
case REMOTE_KEY_VOL_UP: // 0x11 音量加
UART_SendString("RF Audio: VOL+\r\n");
SendEventToBluetooth(0x11);
break;
case REMOTE_KEY_EQ: // 0x12 EQ切换
UART_SendString("RF Audio: EQ\r\n");
SendEventToBluetooth(0x12);
break;
default:
UART_SendString("RF unknown key\r\n");
break;
}
}
// 长按/短按超时检测
void CheckRFTimeout(void)
{
unsigned long cur_time = system_ticks;
if (rf_mode_press_detected) {
if (!rf_mode_long_handled && rf_mode_frame_cnt >= 4) {
rf_mode_long_flag = 1;
rf_mode_long_handled = 1;
rf_mode_short_handled = 1;
}
if ((cur_time - rf_mode_first_time) > 500) {
if (!rf_mode_long_handled && !rf_mode_short_handled && rf_mode_frame_cnt >= 2) {
rf_mode_short_flag = 1;
}
rf_mode_press_detected = 0;
rf_mode_frame_cnt = 0;
rf_mode_short_handled = 0;
rf_mode_long_handled = 0;
}
}
}
// 执行RF命令
void HandleRFCommands(void)
{
if (rf_mode_long_flag) {
rf_mode_long_flag = 0;
light_on = !light_on;
LightNeedSave = 1;
if (!light_on) last_mode_before_off = mode;
UART_SendString(light_on ? "Long ON\r\n" : "Long OFF\r\n");
}
if (rf_mode_short_flag) {
rf_mode_short_flag = 0;
if (light_on) {
mode = (mode + 1) % MODE_NUM;
ModeNeedSave = 1;
UART_SendString("Mode "); UART_SendNumber(mode); UART_SendString("\r\n");
} else {
light_on = 1;
mode = last_mode_before_off;
LightNeedSave = 1;
UART_SendString("RF Light ON\r\n");
}
}
}
//================ 灯效 ==============
void Effect_RainbowFlow(void)
{
static unsigned int hue_offset = 0;
unsigned int i, hue;
unsigned char rgb[3];
hue_offset = (hue_offset + speed_level * 2) % 360;
for (i = 0; i < LED_NUM; i++) {
hue = (i * 360 / LED_NUM + hue_offset) % 360;
HSV_to_RGB(hue, 255, 255, rgb);
SetLedRGB((unsigned char)i, rgb[1], rgb[0], rgb[2]);
}
}
void Effect_Breath(void)
{
static unsigned char breath = 10;
static signed char breath_dir = 1;
static unsigned char breath_color_idx = 0;
unsigned char r, g, b;
unsigned int i;
breath += breath_dir * ((speed_level + 2) / 3);
if (breath >= 250) { breath = 250; breath_dir = -1; }
if (breath <= 0) {
breath = 0;
if (breath_dir == -1) breath_color_idx = (breath_color_idx + 1) % 7;
breath_dir = 1;
}
r = (unsigned int)colorTable[breath_color_idx][0] * breath / 255;
g = (unsigned int)colorTable[breath_color_idx][1] * breath / 255;
b = (unsigned int)colorTable[breath_color_idx][2] * breath / 255;
for (i = 0; i < LED_NUM; i++) SetLedRGB((unsigned char)i, r, g, b);
}
void Effect_StaticColor(void)
{
unsigned int i;
for (i = 0; i < LED_NUM; i++) {
SetLedRGB((unsigned char)i, colorTable[ColorIdex][0], colorTable[ColorIdex][1], colorTable[ColorIdex][2]);
}
}
//================ LED 操作 ==============
void SetLedRGB(unsigned char i, unsigned char r, unsigned char g, unsigned char b)
{
if (!light_on) { r = g = b = 0; }
led_RGB[i][0] = g;
led_RGB[i][1] = r;
led_RGB[i][2] = b;
}
void ClearAllLED(void)
{
unsigned int i;
for (i = 0; i < LED_NUM; i++) {
led_RGB[i][0] = 0;
led_RGB[i][1] = 0;
led_RGB[i][2] = 0;
}
}
//================ HSV to RGB ==============
void HSV_to_RGB(unsigned int hue, unsigned char sat, unsigned char val, unsigned char *rgb)
{
unsigned char r, g, b, region, remainder;
unsigned int p, q, t;
if (sat == 0) { r = g = b = val; }
else {
if (hue >= 360) hue %= 360;
region = hue / 60;
remainder = (hue % 60) * 255 / 60;
p = val * (255 - sat) / 255;
q = val * (255 - (sat * remainder / 255)) / 255;
t = val * (255 - (sat * (255 - remainder) / 255)) / 255;
switch (region) {
case 0: r = val; g = t; b = p; break;
case 1: r = q; g = val; b = p; break;
case 2: r = p; g = val; b = t; break;
case 3: r = p; g = q; b = val; break;
case 4: r = t; g = p; b = val; break;
default: r = val; g = p; b = q; break;
}
}
rgb[0] = g; rgb[1] = r; rgb[2] = b;
}
//================ SPI ==============
void LoadSPI(void)
{
unsigned char xdata *px;
unsigned int i, j;
unsigned char k, dat;
for (i = 0; i < SPI_NUM; i++) led_SPI[i] = 0;
px = &led_RGB[0][0];
for (i = 0, j = 0; i < (LED_NUM * 3); i++) {
dat = *px; px++;
for (k = 0; k < 4; k++) {
if (dat & 0x80) led_SPI[j] = 0xE0;
else led_SPI[j] = 0x80;
if (dat & 0x40) led_SPI[j] |= 0x0E;
else led_SPI[j] |= 0x08;
dat <<= 2;
j++;
}
}
}
void SPI_Config(unsigned char SPI_io, unsigned char SPI_speed)
{
SPCTL = (SPI_speed & 3) | (1<<6) | (1<<4); // SPEN=1, MSTR=1
P_SW1 = (P_SW1 & ~0x0c) | ((SPI_io << 2) & 0x0c);
HSCLKDIV = 1;
SPI_CLKDIV = 1;
if (SPI_io == 0) {
P1M1 &= ~0xA0;
P1M0 |= 0xA0;
P15 = 0;
}
}
void SPI_DMA_TxTRIG(unsigned char xdata *TxBuf, unsigned int num) {
unsigned int j;
// ---- DMA 传输期间关闭 ADC 电源 ----
ADC_CONTR &= ~0x80; // 关闭 ADC 电源
SPSTAT = 0xC0;
HSSPI_CFG = 3;
HSSPI_CFG2 = (1<<5) | (1<<4) | 3;
j = (unsigned int)TxBuf;
DMA_SPI_TXAH = (unsigned char)(j >> 8);
DMA_SPI_TXAL = (unsigned char)j;
DMA_SPI_AMTH = (unsigned char)((num - 1) / 256);
DMA_SPI_AMT = (unsigned char)((num - 1) % 256);
DMA_SPI_ITVH = 0;
DMA_SPI_ITVL = 0;
DMA_SPI_STA = 0x00;
DMA_SPI_CFG = (1<<7) | (1<<6) | (0<<2) | 0;
DMA_SPI_CFG2 = 0;
DMA_SPI_CR = (1<<7) | (1<<6) | 1;
B_SPI_DMA_busy = 1;
// ---- DMA 启动后恢复 ADC 电源 ----
ADC_CONTR |= 0x80; // 恢复 ADC 电源
}
void SPI_DMA_ISR(void) interrupt DMA_SPI_VECTOR {
DMA_SPI_STA = 0;
B_SPI_DMA_busy = 0;
EADC = 1; // DMA 传输完成,恢复 ADC 中断
}
//================ 串口 ==============
void UART_Init(void)
{
SCON = 0x50;
T2L = (unsigned char)(BRT & 0xFF);
T2H = (unsigned char)(BRT >> 8);
AUXR |= 0x15;
ES = 1;
}
void UART_SendChar(unsigned char dat)
{ if (!uart_print_enabled) return;
SBUF = dat;
while (!TI);
TI = 0;
}
void UART_SendString(char *str)
{ if (!uart_print_enabled) return;
while (*str)
UART_SendChar(*str++);
}
void UART_SendNumber(unsigned char num)
{ if (!uart_print_enabled) return;
if (num >= 100) { UART_SendChar(num/100 + '0'); UART_SendChar((num%100)/10 + '0'); UART_SendChar(num%10 + '0'); }
else if (num >= 10) { UART_SendChar(num/10 + '0'); UART_SendChar(num%10 + '0'); }
else UART_SendChar(num + '0');
}
void UART_SendHexByte(unsigned char byte)
{
unsigned char n;
n = (byte >> 4) & 0x0F; UART_SendChar((n < 10) ? (n + '0') : (n - 10 + 'A'));
n = byte & 0x0F; UART_SendChar((n < 10) ? (n + '0') : (n - 10 + 'A'));
}
void UART_SendUint16(unsigned int num) {
if (!uart_print_enabled) return;
if (num >= 10000) UART_SendChar(num / 10000 + '0');
if (num >= 1000) UART_SendChar((num % 10000) / 1000 + '0');
if (num >= 100) UART_SendChar((num % 1000) / 100 + '0');
if (num >= 10) UART_SendChar((num % 100) / 10 + '0');
UART_SendChar(num % 10 + '0');
}
void UART_ISR(void) interrupt 4
{
unsigned char ch;
static unsigned char bin_state = 0; // 0:等待头, 1:收到头, 2:收到长度, 3:收到数据
static unsigned char bin_buf[8];
static unsigned char bin_idx = 0;
static unsigned char bin_len = 0;
static unsigned char bin_sum = 0;
if (RI) {
RI = 0;
ch = SBUF;
// ----- 二进制帧接收状态机(优先处理) -----
switch (bin_state) {
case 0: // 等待帧头 0xEA
if (ch == FRAME_HEADER) {
bin_state = 1;
bin_idx = 0;
bin_sum = 0;
bin_buf[bin_idx++] = ch;
bin_sum += ch;
} else {
goto ascii_parse; // 不是二进制帧,交给 ASCII 处理
}
break;
case 1: // 接收长度
bin_buf[bin_idx++] = ch;
bin_sum += ch;
bin_len = ch;
if (bin_len >= 1 && bin_len <= 4) { // 数据长度 1~4 字节
bin_state = 2;
} else {
bin_state = 0; // 长度非法,复位
}
break;
case 2: // 接收数据(包括类型和参数)
bin_buf[bin_idx++] = ch;
bin_sum += ch;
if (bin_idx == bin_len + 2) { // 头+长度+数据(不含校验)
bin_state = 3;
}
break;
case 3: // 接收校验和
if (ch == bin_sum) {
// 校验通过,处理命令
ProcessBluetoothCommand(bin_buf, bin_len + 3); // 总长度 = 头+长度+数据+校验
} else {
// 校验失败,丢弃
}
bin_state = 0;
break;
}
return; // 二进制帧处理完毕,不再进入 ASCII
ascii_parse:
// ----- ASCII 命令(原有逻辑) -----
if (ch == '\r' || ch == '\n') {
if (uartCount > 0) {
uartBuf[uartCount] = '\0';
uartCmdReady = 1;
}
uartCount = 0;
} else if (uartCount < UART_BUF_SIZE - 1) {
uartBuf[uartCount++] = ch;
}
}
if (TI) {
TI = 0;
}
}
void ParseUartCommand(void)
{
unsigned char *cmd = uartBuf;
unsigned int num;
if (!uartCmdReady) return;
uartCmdReady = 0;
if (strncmp(cmd, "THRESHOLD", 9) == 0) {
// 此命令已不再需要,保留为空
}
else if (strncmp(cmd, "MODE", 4) == 0) {
num = atoi(cmd + 5);
if (num < MODE_NUM) {
mode = (unsigned char)num;
ModeNeedSave = 1;
if (!light_on) { light_on = 1; LightNeedSave = 1; }
UART_SendString("Mode "); UART_SendNumber(mode); UART_SendString("\r\n");
}
}
else if (strncmp(cmd, "SPEED", 5) == 0) {
num = atoi(cmd + 6);
if (num >= 1 && num <= 10) {
speed_level = (unsigned char)num;
speed_value = (11 - speed_level) * 3 + 8;
SpeedNeedSave = 1;
UART_SendString("Speed "); UART_SendNumber(speed_level); UART_SendString("\r\n");
}
}
else if (strncmp(cmd, "BRIGHT", 6) == 0) {
num = atoi(cmd + 7);
if (num >= 1 && num <= 10) {
brightness_level = (unsigned char)num;
global_brightness = 10 + (245 * (brightness_level - 1)) / 9;
BrightNeedSave = 1;
UART_SendString("Bright "); UART_SendNumber(brightness_level); UART_SendString("\r\n");
}
}
else if (strncmp(cmd, "COLOR", 5) == 0) {
num = atoi(cmd + 6);
if (num < COLOR_NUM) {
ColorIdex = (unsigned char)num;
ColorNeedSave = 1;
UART_SendString("Color "); UART_SendNumber(ColorIdex); UART_SendString("\r\n");
}
}
else if (strncmp(cmd, "ON", 2) == 0) {
if (!light_on) { light_on = 1; LightNeedSave = 1; UART_SendString("Light ON\r\n"); }
}
else if (strncmp(cmd, "OFF", 3) == 0) {
if (light_on) { light_on = 0; last_mode_before_off = mode; LightNeedSave = 1; ClearAllLED(); UART_SendString("Light OFF\r\n"); }
}
else if (strncmp(cmd, "STATUS", 6) == 0) {
UART_SendString("Mode:"); UART_SendNumber(mode);
UART_SendString(" Speed:"); UART_SendNumber(speed_level);
UART_SendString(" Bright:"); UART_SendNumber(brightness_level);
UART_SendString(" Color:"); UART_SendNumber(ColorIdex);
UART_SendString(" Light:"); UART_SendString(light_on ? "ON" : "OFF");
UART_SendString("\r\n");
}
else if (strncmp(cmd, "LEARN", 5) == 0) {
if (!light_on && !learn_mode) {
learn_mode = 1;
learn_timeout = system_ticks + 10000UL;
UART_SendString("Learn mode, press remote...\r\n");
} else if (light_on) {
UART_SendString("Turn off light first\r\n");
} else {
UART_SendString("Already learning\r\n");
}
}
}
//================ EEPROM ==============
void IapIdle(void) { IAP_CONTR = 0; IAP_CMD = 0; IAP_TRIG = 0; IAP_ADDRH = 0x80; IAP_ADDRL = 0; }
unsigned char IapRead(unsigned int addr)
{
unsigned char dat;
IAP_CONTR = 0x80;
IAP_TPS = (unsigned char)(MAIN_Fosc / 1000000L);
IAP_CMD = 1;
IAP_ADDRL = (unsigned char)(addr & 0xFF);
IAP_ADDRH = (unsigned char)(addr >> 8);
IAP_TRIG = 0x5A; IAP_TRIG = 0xA5;
_nop_();
dat = IAP_DATA;
IapIdle();
return dat;
}
void IapProgram(unsigned int addr, unsigned char dat)
{
IAP_CONTR = 0x80;
IAP_TPS = (unsigned char)(MAIN_Fosc / 1000000L);
IAP_CMD = 2;
IAP_ADDRL = (unsigned char)(addr & 0xFF);
IAP_ADDRH = (unsigned char)(addr >> 8);
IAP_DATA = dat;
IAP_TRIG = 0x5A; IAP_TRIG = 0xA5;
_nop_();
IapIdle();
}
void IapErase(unsigned int addr)
{
IAP_CONTR = 0x80;
IAP_TPS = (unsigned char)(MAIN_Fosc / 1000000L);
IAP_CMD = 3;
IAP_ADDRL = (unsigned char)(addr & 0xFF);
IAP_ADDRH = (unsigned char)(addr >> 8);
IAP_TRIG = 0x5A; IAP_TRIG = 0xA5;
_nop_();
IapIdle();
}
void LoadAllParams(void)
{
unsigned char val;
unsigned char h = IapRead(EE_ADDR_REMOTE_H);
unsigned char l = IapRead(EE_ADDR_REMOTE_L);
// ---- 加载常用参数(0x0000 扇区) ----
val = IapRead(EE_ADDR_MODE);
if (val < MODE_NUM) mode = val; else mode = 0;
val = IapRead(EE_ADDR_LIGHT_ON);
if (val == 0 || val == 1) light_on = val; else light_on = 1;
val = IapRead(EE_ADDR_BRIGHT_LEV);
if (val >= 1 && val <= 10) {
brightness_level = val;
global_brightness = 10 + (245 * (brightness_level - 1)) / 9;
} else {
brightness_level = 10;
global_brightness = 255;
}
val = IapRead(EE_ADDR_COLOR_IDX);
if (val < COLOR_NUM) ColorIdex = val; else ColorIdex = 0;
val = IapRead(EE_ADDR_SPEED_LEV);
if (val >= 1 && val <= 10) speed_level = val; else speed_level = 5;
speed_value = (11 - speed_level) * 3 + 8;
// ---- 加载遥控器地址(独立扇区 0x0200) ----
if (h != 0xFF || l != 0xFF) {
learned_addr = (h << 8) | l;
} else {
learned_addr = REMOTE_ADDR; // 未学习,使用默认
}
UART_SendString("EEPROM loaded\r\n");
}
void SaveAllParams(void)
{
EA = 0;
IapErase(0x0000); // 仅擦除 0x0000 扇区
IapProgram(EE_ADDR_MODE, mode);
IapProgram(EE_ADDR_LIGHT_ON, light_on ? 1 : 0);
IapProgram(EE_ADDR_BRIGHT_LEV, brightness_level);
IapProgram(EE_ADDR_COLOR_IDX, ColorIdex);
IapProgram(EE_ADDR_SPEED_LEV, speed_level);
// 注意:遥控器地址不在此保存
EA = 1;
UART_SendString("EEPROM saved\r\n");
}
void SaveLearnedAddr(void)
{
EA = 0;
IapErase(0x0200); // 擦除 0x0200 扇区(含地址位置)
IapProgram(EE_ADDR_REMOTE_H, (unsigned char)(learned_addr >> 8));
IapProgram(EE_ADDR_REMOTE_L, (unsigned char)(learned_addr & 0xFF));
EA = 1;
UART_SendString("Remote address saved\r\n");
}
void delay_ms(unsigned int ms)
{
unsigned int i;
do {
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
void delay_us(unsigned int us)
{
while (us--) {
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_();
}
}
// 修改颜色(循环切换)
void ChangeColor(void)
{
ColorIdex = (ColorIdex + 1) % COLOR_NUM;
ColorNeedSave = 1;
}
// 修改亮度(循环切换等级)
void ChangeBrightness(void)
{
brightness_level = (brightness_level % BRIGHTNESS_LEVEL_MAX) + 1;
global_brightness = BRIGHTNESS_MIN + (brightness_level - 1) * (BRIGHTNESS_MAX - BRIGHTNESS_MIN) / (BRIGHTNESS_LEVEL_MAX - 1);
BrightNeedSave = 1;
}
// 修改速度(循环切换等级)
void ChangeSpeed(void)
{
speed_level = (speed_level % BRIGHTNESS_LEVEL_MAX) + 1;
speed_value = (11 - speed_level) * 3 + 8;
SpeedNeedSave = 1;
}
// 发送给蓝牙模块的帧(通过 UART1)
void SendToBluetooth(unsigned char type, unsigned char data_len, unsigned char data1, unsigned char data2)
{
unsigned char buf[8], idx = 0, i, sum = 0;
buf[idx++] = FRAME_HEADER;
buf[idx++] = 1 + data_len;
buf[idx++] = type;
buf[idx++] = data1;
if (data_len == 2) buf[idx++] = data2;
for (i = 0; i < idx; i++) sum += buf[i];
buf[idx++] = sum;
EA = 0;
for (i = 0; i < idx; i++) {
SBUF = buf[i];
while (!TI);
TI = 0;
}
EA = 1;
}
// 发送蓝牙事件
void SendEventToBluetooth(unsigned char event_id)
{
unsigned char cmd = 0;
unsigned char i;
for (i = 0; i < sizeof(lc_event_map)/sizeof(lc_event_map[0]); i++) {
if (lc_event_map[i].event_id == event_id) {
cmd = lc_event_map[i].cmd_byte;
break;
}
}
if (cmd != 0) {
SendToBluetooth(FRAME_TYPE_LC, 1, cmd, 0xFF);
}
}
// 处理蓝牙二进制命令(帧格式:EA 03 05 11 02)
void ProcessBluetoothCommand(unsigned char *buf, unsigned char len)
{
unsigned char type = buf[2]; // 第3字节为类型
unsigned char data1 = buf[3];
unsigned char data2 = (len >= 5) ? buf[4] : 0xFF;
if (type == FRAME_TYPE_BT) {
switch (data1) {
case 0x0B: // 关灯
if (light_on) {
light_on = 0;
last_mode_before_off = mode;
LightNeedSave = 1;
ClearAllLED();
}
break;
case 0x0C: // 开灯
if (!light_on) {
light_on = 1;
mode = last_mode_before_off;
LightNeedSave = 1;
}
break;
case 0x03: // 灯光开关(单按)
light_on = !light_on;
LightNeedSave = 1;
ClearAllLED();
break;
case 0x43: // 模式+
case 0x07:
mode = (mode + 1) % MODE_NUM;
ModeNeedSave = 1;
break;
case 0x42: // 模式-
mode = (mode - 1 + MODE_NUM) % MODE_NUM;
ModeNeedSave = 1;
break;
case 0x45: // COLOR+
ChangeColor();
break;
case 0x44: // COLOR-
ColorIdex = (ColorIdex == 0) ? COLOR_NUM - 1 : ColorIdex - 1;
ColorNeedSave = 1;
break;
case 0x46: // 亮度+
ChangeBrightness();
break;
case 0x47: // 亮度-
if (brightness_level > 1) {
brightness_level--;
global_brightness = BRIGHTNESS_MIN + (brightness_level-1) * (BRIGHTNESS_MAX - BRIGHTNESS_MIN) / (BRIGHTNESS_LEVEL_MAX - 1);
BrightNeedSave = 1;
}
break;
case 0x48: // 速度+
ChangeSpeed();
break;
case 0x49: // 速度-
if (speed_level > 1) {
speed_level--;
speed_value = (11 - speed_level) * 3 + 8;
SpeedNeedSave = 1;
}
break;
case 0x00: // 恢复默认
mode = 0;
brightness_level = 10;
global_brightness = 255;
ColorIdex = 0;
speed_level = 5;
speed_value = (11 - speed_level) * 3 + 8;
light_on = 1;
last_mode_before_off = 0;
ModeNeedSave = LightNeedSave = BrightNeedSave = ColorNeedSave = SpeedNeedSave = 1;
break;
case 0x11: // 进入学习模式
if (!light_on && !learn_mode) {
learn_mode = 1;
learn_timeout = system_ticks + 10000UL;
UART_SendString("Learn mode by BT\r\n");
}
break;
case 0x16: // 白灯模式(若有)
// 可忽略或根据需要实现
break;
default:
UART_SendString("BT unknown\r\n");
break;
}
}
// 可扩展其他类型
}
// ==================== ADC 相关函数(新增/替换) ====================
// ---- ADC 初始化(官方推荐配置) ----
void ADC_Init(void) {
// 配置 P1.0 和 P1.1 为高阻输入(ADC 输入)
P1M0 &= ~0x03;
P1M1 |= 0x03;
// 设置 ADC 时序(官方推荐值)
P_SW2 |= 0x80; // 允许访问扩展寄存器
ADCTIM = 0x3F; // 采样时间最大
P_SW2 &= 0x7F;
ADCCFG = 0x2F; // 右对齐,12位,时钟分频
ADC_CONTR = 0x80; // 开启 ADC 电源
_nop_(); _nop_(); _nop_(); _nop_();
delay_ms(2); // 等待电源稳定
// 不使能 ADC 中断(使用查询方式)
EADC = 0;
// 清除可能残留的标志
ADC_CONTR &= ~0x10;
}
// ---- 非阻塞:启动一次 ADC 转换 ----
void ADC_StartConversion(unsigned char channel) {
// 确保 ADC 电源开启(如果之前未关闭)
ADC_CONTR = 0x80; // 电源开启
ADC_CONTR |= 0x40; // 启动转换
ADC_CONTR = (ADC_CONTR & 0xF0) | (channel & 0x07); // 设置通道
}
// ---- 非阻塞:检查 ADC 转换是否完成,完成则返回结果 ----
bit ADC_GetResult(unsigned int *val) {
if (ADC_CONTR & 0x10) { // 检查 ADC_FLAG
*val = ((unsigned int)(ADC_RES & 0x0F) << 8) | ADC_RESL;
ADC_CONTR &= ~0x10; // 清除标志
return 1;
}
return 0;
}
// ---- 双声道频谱灯效(模式 0) ----
void Effect_AudioSpectrum(void) {
unsigned char half = LED_NUM / 2;
unsigned char height_L, height_R;
unsigned char i, r, g, b;
unsigned int val_L, val_R;
static unsigned int last_L = 0, last_R = 0;
static unsigned char test_cnt = 0;
// 采样左声道(P1.0)
//val_L = SampleADC(0);
// 采样右声道(P1.1)
// val_R = SampleADC(1);
// ---- 测试用固定值 ----
height_L = half / 2; // 固定 50% 高度
height_R = half / 2;
// 或者使用正弦波模拟
test_cnt++;
height_L = (unsigned long)(128 + 127 * sin(test_cnt * 0.1)) * half / 255;
// 简单平滑滤波(减少跳动)
val_L = (last_L * 3 + val_L) / 4;
val_R = (last_R * 3 + val_R) / 4;
last_L = val_L;
last_R = val_R;
// 映射到灯珠高度(0 ~ half)
height_L = (unsigned long)val_L * half / 4095;
height_R = (unsigned long)val_R * half / 4095;
if (height_L > half) height_L = half;
if (height_R > half) height_R = half;
r = colorTable[ColorIdex][0];
g = colorTable[ColorIdex][1];
b = colorTable[ColorIdex][2];
// 左半部分:从左到右上升
for (i = 0; i < half; i++) {
if (i < height_L)
SetLedRGB(i, r, g, b);
else
SetLedRGB(i, 0, 0, 0);
}
// 右半部分:从中间往右上升
for (i = 0; i < half; i++) {
if (i < height_R)
SetLedRGB(half + i, r, g, b);
else
SetLedRGB(half + i, 0, 0, 0);
}
} 请问有没有大神可以指导一下!谢谢!
|
|