你好,如下代码中,没有给出输出 的 IO 指令,是否可以补充完善?://*******product model:RGB 7 彩灯
.CHIP PMS132B ;SOP16
//.CHIP PFC154 ;SOP14
//.CHIP PMC153 ;SOP14
//{{PADAUK_CODE_OPTION
.Code_Option LVR 3.5V
.Code_Option Security Enable // Security 7/8 words Enable
.Code_Option Comparator_Edge All_Edge
.Code_Option Bootup_Time Slow
.Code_Option PWM_Source 16MHz
.Code_Option GPC_PWM Disable
.Code_Option Interrupt_Src1 PB.0
.Code_Option Interrupt_Src0 PA.0
.Code_Option PB4_PB7_Drive Strong
//}}PADAUK_CODE_OPTION
.INCLUDE "HEAD.H"
;----------- 常量定义 -----------
SYNC_MIN EQU 80 ; 同步头最小(8ms)32
SYNC_MAX EQU 140 ; 同步头最大(14ms)56
DATA_0_MIN EQU 2 ; 数据0最小(0.2ms)
DATA_0_MAX EQU 6 ; 数据0最大(0.6ms)
DATA_1_MIN EQU 8 ; 数据1最小(0.8ms)
DATA_1_MAX EQU 14 ; 数据1最大(1.4ms)
RF EQU PA.0
;RF_IN_Size => 3
;MAX_BRIGHTNESS EQU 6 ;6级亮度
;*********************************************************
.ROMADR 0X001 ;;
GOTO FPPA0
;********************************************************
.ROMADR 0X10 ;INTERR IN address
;====================== 中断服务程序 ======================
INTERRUPT:
PUSHAF ; 保存现场
T1SN INTRQ.2;T16
GOTO TM2_INT
;-------------------------------------------
TM16_INT:
SET0 INTRQ.2
SET1 TIME_T16_INT_1MS_FLAG
; 处理T16中断
INC T16_TIEMS_COUNTER_TIME_R ; 每次进入中断时,递增一个计时器变量,用于累计时间
; 检查是否达到40ms
MOV A, T16_TIEMS_COUNTER_TIME_R ; 将计时器值加载到累加器A中
CEQSN A, 40 ; 如果A等于40,则跳转到UPDATE_GRADIENT执行颜色更新逻辑
GOTO ISR_EXIT; ; 否则直接退出中断
GOTO UPDATE_GRADIENT
UPDATE_GRADIENT:
; 更新渐变步进
INC STEP_A ; 增加STEP_A,表示A路LED的色相步进
DZSN STEP_A;, RESET_STEP_A ; 如果STEP_A溢出(即超过255),则跳转到RESET_STEP_A重置为0
GOTO $+2
GOTO RESET_STEP_A
INC STEP_B ; 增加STEP_B,表示B路LED的色相步进
DZSN STEP_B;, RESET_STEP_B ; 如果STEP_B溢出(即超过255),则跳转到RESET_STEP_B重置为0
GOTO ISR_EXIT
GOTO RESET_STEP_B ; 跳回中断退出点
RESET_STEP_A:
MOV A,0
MOV STEP_A,A; 0; ; 将STEP_A重置为0,重新开始下一个颜色循环
GOTO ISR_EXIT; ; 返回中断退出点
RESET_STEP_B:
MOV A,0
MOV STEP_B,A; 0; ; 将STEP_B重置为0,重新开始下一个颜色循环
GOTO ISR_EXIT; ; 返回中断退出点
;------------------------------------------
TM2_INT:
; TM2中断处理 (250us周期)
T1SN INTRQ.TM2 ; 检测TM2中断标志
GOTO CHECK_RF ;PA0 中断检查
INC Timer_250us ; 专用TM2计数器
SET0 INTRQ.TM2 ; 清除中断标志
MOV A, 170;72;80;Timer_250us ; 加载计数器值
SUB A, Timer_250us ; 18ms超时检测
T1SN FC ; 检查是否超时
GOTO ISR_Exit ; 未超时继续
SET0 RF_Start ; 超时复位接收状态
CLEAR Timer_250us ; 重置计时器
GOTO ISR_Exit;
CHECK_RF:
T1SN INTRQ. RF ; 检测RF中断标志
GOTO ISR_Exit ;ISR_END
T1SN PA.0 ; 检测PA0当前电平(1=高电平)
GOTO RF_Clear;RF_Low ; 低电平处理分支
T1SN RF_Start ; 检查是否已经开始接收
GOTO Check_Start ; 起始码检测分支
; 数据位 ;------ 1码检测--------------------
;----- 0:----0.3ms-0.6mS H + 0.8mS-1.4ms L
;------1:----0.8-1.4ms H + 0.3-1.4ms L
;结束位:-----0.3-0.6ms H + 10-14ms L
;(Timer_250us>=3 && Timer_250us<=5) //0.75~1.25ms
INC Icnt ; 位计数器加1
MOV A, Timer_250us ; 加载计时器值
SUB A,DATA_1_MIN; 3 ; 1码检测下限(0.75ms)
T0SN FC ; 检查是否大于下限
GOTO Check_Zero ; 跳转0码检测
MOV A,DATA_1_MAX; 5 ; 1码检测上限(1.25ms)
SUB A, Timer_250us ; 计算时间差
T0SN FC ; 检查是否小于上限
GOTO Check_Zero ; 跳转0码检测
SET0 CF ; 设置进位标志为1
SLC Data_In$0 ; 数据左移并带进位
SLC Data_In$1 ; 数据左移并带进位
SLC Data_In$2 ; 数据左移并带进位
GOTO Check_Complete ; 跳转完成检测
Check_Zero:
; ------0码检测-------
;(Timer_250us>=1 && Timer_250us<=2)//0.25~0.5ms
MOV A, Timer_250us ; 加载计时器值
SUB A,DATA_0_MIN; 1 ; 0码下限(0.25ms)
T0SN FC ; 检查是否大于下限
GOTO Data_Error ; 错误处理
MOV A,DATA_0_MAX; 2 ; 0码上限(0.5ms)
SUB A, Timer_250us ; 计算时间差
T0SN FC ; 检查是否小于上限
GOTO Data_Error ; 错误处理
SET1 FC ; 设置进位标志为0
SLC Data_In$0 ; 数据左移并带进位
SLC Data_In$1 ; 数据左移并带进位
SLC Data_In$2 ; 数据左移并带进位
Check_Complete: ; 完成检测
MOV A, 24 ; 加载位计数器
XOR A, Icnt ; 检查是否满24位
T1SN FZ ; 判断是否完成
GOTO RF_Clear ; 未完成继续接收
; SET1 RF_End ; 设置接收完成标志
SET0 RF_Start ; 清除接收开始标志
; 数据存储与校验
current_RF_ID_R0 = Data_In$0; ;.0-7 ; 存储低8位
current_RF_ID_R1 = Data_In$1;
current_RF_ID_R2 = Data_In$2;
T0SN FIRST_ID_SVAE_FLAG
GOTO SVAE_ID
; DTAT_SAVE_R0=current_RF_ID_R0;
DTAT_SAVE_R1=current_RF_ID_R1;
DTAT_SAVE_R2=current_RF_ID_R2;
SET1 FIRST_ID_SVAE_FLAG
SVAE_ID:
SET1 RF_END
GOTO RF_Clear ; 跳转中断清除
Check_Start: ; 起始码检测
;----(Timer_250us>=32 && Timer_250us<=48) //用8-12ms低电平做起始码
MOV A, Timer_250us ; 加载计时器值
SUB A,SYNC_MIN; 32 ; 起始码下限(8.75ms)
T0SN FC ; 检查是否大于下限
GOTO RF_Clear ; 无效起始码
MOV A,SYNC_MAX; 56;48 ; 起始码上限(11.25ms)
SUB A, Timer_250us ; 计算时间差
T0SN FC ; 检查是否小于上限
GOTO RF_Clear ; 无效起始码
SET1 RF_Start ; 设置接收开始标志
Data_In = 0 ; ; 清空数据缓存
CLEAR Icnt ; 复位位计数器
CLEAR Timer_250us ; 重置250us计时器
GOTO RF_Clear
Data_Error: ; 错误处理
CLEAR Icnt ; 复位位计数器
SET0 RF_Start ; 清除接收开始标志
Data_In = 0 ; ; 清空数据缓存
CLEAR Timer_250us ; 重置250us计时器
RF_Clear: ; RF中断清除
SET0 INTRQ.RF ; 清除RF中断标志
CLEAR Timer_250us ; 重置250us计时器
GOTO ISR_Exit ; 跳转中断退出
TM2_Clear: ; 定时器中断清除
SET0 INTRQ.TM2 ; 清除定时器中断标志
GOTO ISR_EXIT
ISR_Exit: ; 中断退出
POPAF ; 恢复A和FLAG寄存器
RETI ; 中断返回
;--------------------------------------------
//=======================================================
FPPA0:
.ADJUST_IC SYSCLK=IHRC/4, IHRC=16MHz, VDD=5.0V;
// WatchDog Disable, RAM 0 ~ 0xF temporary be used
//You can add the follow code :
CLKMD.En_WatchDog=0; // WatchDog Enable
SP=STACK0
;//--------------CLRRAM ----------------------
Initialize:
; CALL DELAY_1SUP;
MOV A,_SYS(RAM_SIZE)-1
MOV LB@RAM_POINTER,A
CLEAR HB@RAM_POINTER
L_CLRRAMLP:
MOV A,0X00
IDXM RAM_POINTER,A
DZSN LB@RAM_POINTER
GOTO L_CLRRAMLP
;//--------------INITIAL IO----------------------
IO_Initialize:
PA = 0B_0000_0000;
PAC = 0B_0111_1000; ; //0:input;1:output;
PAPH = 0B_1111_1001; ;1=ENABLED PULL UP
PADIER=0B_1111_1111;
PB=0B_1000_0000;
PBC=0B_0111_1001; ; //0:input;1:output;
PBPH=0B_1111_1001; ;1=ENABLED PULL UP
PBDIER=0B_1111_1111;
;--------TM2 100uS -------------------
; TM2CT=0; ; 清零定时器计数器
; MOV A,9
; MOV TM2B, A ; 设置预分频值为9
; $ TM2C IHRC,Period ; 配置时钟源为内部高速RC
; $ TM2S 8BIT,/16,/25 ; 设置8位模式,16分频,25周期
;100US
tm2ct = 0;
tm2b = 4;
$ TM2C IHRC,Disable,Period;
$ TM2S 8bit,/64,/5;
SET0 INTRQ.TM2; ; 清除定时器中断标志
SET1 INTEN.TM2; ; 使能定时器中断
;-----------PA0 IN_INT ---------------------------
//设置PA0引脚输入模式,根据情况选择是否需要上拉
$ PA.0 in,pull;
$ INTEGS PA0_B; //PA0中断边缘选择,上升缘和下降缘上升缘都请求中断PA0_B,上升缘请求中断为PA0_R,下降缘请求中断为PA0_F。
SET1 INTEN.PA0; = 1; //中断允许寄存器,开PA0中断
SET0 INTRQ.PA0; = 0; //中断请求寄存器,清零INTRQ寄存器。
;-------------1MS---------------------------------------
Reload_T16 = 32768 - 16000;
stt16 Reload_T16;
$ T16M IHRC,/1,bit15;
$ INTEGS BIT_R;
INTRQ.T16 = 0;
INTEN.T16 = 1;
Engint;
;*************************************************************
START:
;PG2PWM=>PB.3 => RED_A;//A路红色,使用内部 PG2PWM资源,8位;
;PG1PWM=>,PA.4 => BLU_A;//A路蓝色,使用内部 PG1PWM资源,8位;
;PA.3 => GRE_A;//A路绿色,用IO口模拟 输出PWM
;PB.6 => RED_B;B路红色,用IO口模拟 输出PWM
;PB.5 => GRE_B;//B路绿色,用IO口模拟 输出PWM
;PB.4 => BLU_B;//B路蓝色,用IO口模拟 输出PWM
MOV A,0 ; 清除累加器 A
SET1 POWER_RUN_FALG; 设置初始状态为开启
MOV A,6
MOV CUR_MODE,A; 7 ; 设置当前模式为7
MOV A,2
MOV BRIGHT_LEVEL,A; 3 ; 设置初始亮度等级为中间值
MOV A,128
MOV HUE_A,A;A路色相值
MOV HUE_B,A;B路色相值
CLEAR T16_TIEMS_COUNTER_TIME_R; 清除计时器
Data_In = 0 ; ; 清空数据缓存
;------------PWMG1--PA4---/A路蓝色--------------------------------
START_LOOP:
$ PWMG1C Enable,PA4,IHRC; PA4 OUT PWM
$ PWMG1S /4,/1;
PWMG1DTL = 0b010_00000;
PWMG1DTH = 0b0100_0111;
PWMG1CUBL = 0b10_000000;
PWMG1CUBH = 0b1000_1110;
;------------PWMG2----A路红色---------------------------------
$ PWMG2C Enable,PB3,IHRC; PB3 OUT PWM
$ PWMG2S /4,/1;
PWMG2DTL = 0b010_00000;
PWMG2DTH = 0b0100_0111;
PWMG2CUBL = 0b10_000000;
PWMG2CUBH = 0b1000_1110;
;--------------PA3 A-----A路绿色----------------------------
T1SN TIME_T16_INT_1MS_FLAG; 1mS 中断标志
GOTO MAIN
SET0 TIME_T16_INT_1MS_FLAG
; 请补充 PA3 输出 PWM
; 初始化定时器 T16
GOTO MAIN; 跳转到主循环
;*********************************************************
;暖白-红-绿-蓝-紫-青-粉-白光-黄光
MAIN:
CALL COMPLETE_RF_ID
CALL Power_Control_ON_OFF
CALL MODE_DECIDE
NOP
GOTO MAIN
;*****************************************************************
COMPLETE_RF_ID:
T1SN RF_End ; 设置接收完成标志
RET
current_ID_COMPLETE:
MOV A,current_RF_ID_R1;
CEQSN A,DTAT_SAVE_R1
GOTO ID_EEROR
MOV A,current_RF_ID_R2
CEQSN A,DTAT_SAVE_R2
RET
SET1 ID_COMPLETE_OK_FLAG;ID 正确
SET0 RF_End ; 设置接收完成标志
current_RF_ID_R0 = Data_In$0;
RET
ID_EEROR:
SET0 ID_COMPLETE_OK_FLAG;ID 正确
SET0 RF_End ; 设置接收完成标志
RET
;****************************************************************
Power_Control_ON_OFF:
MOV A,02H ; 将按键值加载到ACC中
XOR A,current_RF_ID_R0 ; 检查是否为02H(开/关机)
T1SN FZ
RET
CLEAR current_RF_ID_R0
T0SN POWER_RUN_FALG
GOTO Power_Control_OFF;$+3
SET1 POWER_RUN_FALG
GOTO Power_Control_ON
Power_Control_ON:
CALL UPDATE_MODE ; 开机时更新模式
RET
Power_Control_OFF: ;关闭全部PWM
PWMG2C=0;
PWMG1C=0;
PA.3=0;
PA.4=0;
PB.3=0;
PB.4=0;
PB.5=0;
PB.6=0;
SET0 POWER_RUN_FALG
RET
;****************************************************************
MODE_DECIDE:
;CEQSN A, 4, INCREASE_BRIGHTNESS; 如果等于 04H,则增加亮度
T1SN POWER_RUN_FALG
RET
MOV A, 04H ; 检查是否为04H(亮度增加)
CEQSN A,current_RF_ID_R0
GOTO $+2
GOTO Brightness_Up_Handler ; 如果是04H,跳转到亮度增加处理
;CEQSN A, 10, DECREASE_BRIGHTNESS; 如果等于 0AH,则减少亮度
MOV A,0AH
CEQSN A,current_RF_ID_R0
GOTO $+2
GOTO Brightness_Down_Handler
; CEQSN A, 6, NEXT_MODE; 如果等于 06H,则进入下一个模式
MOV A,06H
CEQSN A,current_RF_ID_R0
GOTO $+2
GOTO NEXT_MODE
; CEQSN A, 12, PREV_MODE; 如果等于 0CH,则进入上一个模式
MOV A,0CH
CEQSN A,current_RF_ID_R0
GOTO $+2
GOTO PREV_MODE
; 如果没有按键操作,继续执行当前模式
GOTO UPDATE_PWM;
POWER_TOGGLE:
; 切换电源状态
T1SN POWER_RUN_FALG; POWER_ON_FLAG, 1; 反转电源标志
GOTO MAIN;_LOOP;
RET
;*****************************************
Brightness_Up_Handler:
; 增加亮度等级
INC BRIGHT_LEVEL
; DZSN BRIGHT_LEVEL, MAX_BRIGHTNESS; 如果超过最大值,回到最小值
; GOTO UPDATE_PWM;
MOV A,5
SUB A,BRIGHT_LEVEL
T1SN FC
GOTO UPDATE_PWM;
;DECREASE_BRIGHTNESS:
Brightness_Down_Handler:
; 减少亮度等级
DEC BRIGHT_LEVEL
; DZSN BRIGHT_LEVEL, MIN_BRIGHTNESS; 如果低于最小值,回到最大值
; GOTO UPDATE_PWM;
MOV A,0
CEQSN A,BRIGHT_LEVEL
GOTO UPDATE_PWM;
GOTO Brightness_Up_Handler
;--------------切换模式--------------------
NEXT_MODE:
; 切换到下一个模式
INC CUR_MODE
; DZSN CUR_MODE, MAX_MODE; 如果超过最大模式,回到第一个模式
; GOTO UPDATE_PWM;
MOV A,7
SUB A,CUR_MODE
T1SN FC
GOTO UPDATE_PWM;
GOTO PREV_MODE
PREV_MODE:
; 切换到上一个模式
; DEC CUR_MODE
; DZSN CUR_MODE, MIN_MODE; 如果低于最小模式,回到最后一个模式
; GOTO UPDATE_PWM;
DZSN CUR_MODE;, MIN_MODE; 如果低于最小模式,回到最后一个模式
GOTO UPDATE_PWM;
GOTO NEXT_MODE
;-------亮度调整-----------
;MAX_BRIGHTNESS:
; MOV BRIGHT_LEVEL, 6; 最大亮度等级
; GOTO UPDATE_PWM;
;MIN_BRIGHTNESS:
; MOV BRIGHT_LEVEL, 1; 最小亮度等级
; GOTO UPDATE_PWM;
;MAX_MODE:
; MOV CUR_MODE, 1; 最大模式
; GOTO UPDATE_PWM;
;MIN_MODE:
; MOV CUR_MODE, 7; 最小模式
; GOTO UPDATE_PWM;
;******************************************************************
UPDATE_PWM:
; 根据当前模式更新PWM占空比
MOV A,0
CEQSN A,CUR_MODE
GOTO $+2
GOTO MODE_1
MOV A,1
CEQSN A,CUR_MODE
GOTO $+2
GOTO MODE_2
MOV A,2
CEQSN A,CUR_MODE
GOTO $+2
GOTO MODE_3
MOV A,3
CEQSN A,CUR_MODE
GOTO $+2
GOTO MODE_4
MOV A,4
CEQSN A,CUR_MODE
GOTO $+2
GOTO MODE_5
MOV A,5
CEQSN A,CUR_MODE
GOTO $+2
GOTO MODE_6
MOV A,6
CEQSN A,CUR_MODE
GOTO $+2
GOTO MODE_7
RET
;******************************************************************
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
UPDATE_MODE:
; 关机时不更新模式
T1SN POWER_RUN_FALG
RET
MODE_1:
; 模式1:A路红色,B路绿色
CALL GET_BRIGHTNESS; 获取当前亮度值
MOV Duty_R_RGB_A, A; A路红色
MOV A, 0; A路绿色
MOV Duty_G_RGB_A, A
MOV A, 0; A路蓝色
MOV Duty_B_RGB_A, A
MOV A, 0; B路红色
MOV Duty_R_RGB_B, A
MOV Duty_G_RGB_B, A; B路绿色
MOV A, 0; B路蓝色
MOV Duty_B_RGB_B, A
GOTO END_UPDATE;
MODE_2:
; 模式2:A路粉色,B路黄色
CALL GET_BRIGHTNESS; 获取当前亮度值
MOV Duty_R_RGB_A, A; A路红色
MOV A, 128; A路绿色
MOV Duty_G_RGB_A, A
MOV A, 0; A路蓝色
MOV Duty_B_RGB_A, A
MOV A, 128; B路红色
MOV Duty_R_RGB_B, A
MOV Duty_G_RGB_B, A; B路绿色
MOV A, 128; B路蓝色
MOV Duty_B_RGB_B, A
GOTO END_UPDATE;
MODE_3:
; 模式3:A路绿色,B路蓝色
CALL GET_BRIGHTNESS; 获取当前亮度值
MOV A, 0; A路红色
MOV Duty_R_RGB_A, A
MOV Duty_G_RGB_A, A; A路绿色
MOV A, 0; A路蓝色
MOV Duty_B_RGB_A, A
MOV A, 0; B路红色
MOV Duty_R_RGB_B, A
MOV A, 0; B路绿色
MOV Duty_G_RGB_B, A
MOV Duty_B_RGB_B, A; B路蓝色
GOTO END_UPDATE;
MODE_4:
; 模式4:A路紫色,B路白色
CALL GET_BRIGHTNESS; 获取当前亮度值
MOV Duty_R_RGB_A, A; A路红色
MOV A, 0; A路绿色
MOV Duty_G_RGB_A, A
MOV Duty_B_RGB_A, A; A路蓝色
MOV Duty_R_RGB_B, A; B路红色
MOV Duty_G_RGB_B, A; B路绿色
MOV Duty_B_RGB_B, A; B路蓝色
GOTO END_UPDATE;
MODE_5:
; 模式5:A路蓝色,B路粉色
CALL GET_BRIGHTNESS; 获取当前亮度值
MOV A, 0; A路红色
MOV Duty_R_RGB_A, A
MOV A, 0; A路绿色
MOV Duty_G_RGB_A, A
MOV Duty_B_RGB_A, A; A路蓝色
MOV Duty_R_RGB_B, A; B路红色
MOV Duty_G_RGB_B, A; B路绿色
MOV A, 128; B路蓝色
MOV Duty_B_RGB_B, A
GOTO END_UPDATE;
MODE_6:
; 模ode6:A路蓝色,B路橙色
CALL GET_BRIGHTNESS; 获取当前亮度值
MOV A, 0; A路红色
MOV Duty_R_RGB_A, A
MOV A, 0; A路绿色
MOV Duty_G_RGB_A, A
MOV Duty_B_RGB_A, A; A路蓝色
MOV Duty_R_RGB_B, A; B路红色
MOV Duty_G_RGB_B, A; B路绿色
MOV A, 128; B路蓝色
MOV Duty_B_RGB_B, A
GOTO END_UPDATE;
;*************************************************************
END_UPDATE:
; 更新PWM占空比
MOV A,Duty_R_RGB_A; 更新A路红色PWM
MOV PWMG2DTL,A
MOV A,Duty_R_RGB_A;
MOV PWMG2DTH,A
MOV A,Duty_G_RGB_A; 更新A路绿色PWM
MOV PWMG1DTL,A
MOV A,Duty_G_RGB_A;
MOV PWMG1DTH,A
; 这里需要添加B路PWM的更新代码
MOV A,Duty_R_RGB_B; 更新A路红色PWM
MOV PWMG1DTL,A
MOV A,Duty_R_RGB_B;
MOV PWMG1DTH,A
MOV A,Duty_G_RGB_B; 更新A路绿色PWM
MOV PWMG2DTL,A
MOV A,Duty_G_RGB_B;
MOV PWMG2DTH,A
;GOTO MAIN ;_LOOP;
RET
;************************************************************
GET_BRIGHTNESS:
; 获取当前亮度值
; MOV A, BRIGHT_LEVEL
; MOV PC, BRIGHT_TABLE; 查找亮度表
; RET;
A = BRIGHT_LEVEL+1
_PCADD
{
RET 51; 20%,
RET 89; 35%,
RET 128; 50%,
RET 166; 65%,
RET 204; 80%,
RET 255; 100%,
}
;*************************************************************
MODE_7:
; 更新A路颜色
; 更新A路颜色
MOV A, HUE_A ; 将当前A路色相值加载到累加器A
CALL HSV_TO_RGB ; 调用HSV转RGB子程序,得到R、G、B三通道值(R_VAL, G_VAL, B_VAL)
CALL GET_BRIGHTNESS ; 获取当前亮度值(存入A)
; 计算红色通道 × 亮度值
MOV A, R_VAL ; 第一个乘数 → A
MOV MULOP, A ; 复制A中的值到 MULOP
MOV A, BRIGHT ; 第二个乘数 → A
MUL ; 执行乘法:R_VAL × BRIGHT
MOV Duty_R_RGB_A, A ; 存低字节到PWM寄存器
MOV A, MULRH ; 读取高字节
MOV Duty_R_RGB_H_A, A ; 存高字节备用
; 计算绿色通道 × 亮度值
MOV A, G_VAL ; 第一个乘数 → A
MOV MULOP, A ; 复制A中的值到 MULOP
MOV A, BRIGHT ; 第二个乘数 → A
MUL ; 执行乘法:G_VAL × BRIGHT
MOV Duty_G_RGB_A, A ; 存低字节到PWM寄存器
MOV A, MULRH ; 读取高字节
MOV Duty_G_RGB_H_A, A ; 存高字节备用
; 计算蓝色通道 × 亮度值
MOV A, B_VAL ; 第一个乘数 → A
MOV MULOP, A ; 复制A中的值到 MULOP
MOV A, BRIGHT ; 第二个乘数 → A
MUL ; 执行乘法:B_VAL × BRIGHT
MOV Duty_B_RGB_A, A ; 存低字节到PWM寄存器
MOV A, MULRH ; 读取高字节
MOV Duty_B_RGB_H_A, A ; 存高字节备用
;-----------------------------------------------------
; 更新B路颜色
MOV A, HUE_B ; 将当前B路色相值加载到累加器A
CALL HSV_TO_RGB ; 调用HSV转RGB子程序,得到B路的R、G、B值
CALL GET_BRIGHTNESS ; 获取当前亮度值(存入A)
; 计算B路红色通道 × 亮度值
MOV A, R_VAL ; 第一个乘数 → A
MOV MULOP, A ; 复制A中的值到 MULOP
MOV A, BRIGHT ; 第二个乘数 → A
MUL ; 执行乘法:R_VAL × BRIGHT
MOV Duty_R_RGB_B, A ; 存低字节到PWM寄存器
MOV A, MULRH ; 读取高字节
MOV Duty_R_RGB_H_B, A ; 存高字节备用
; 计算B路绿色通道 × 亮度值
MOV A, G_VAL ; 第一个乘数 → A
MOV MULOP, A ; 复制A中的值到 MULOP
MOV A, BRIGHT ; 第二个乘数 → A
MUL ; 执行乘法:G_VAL × BRIGHT
MOV Duty_G_RGB_B, A ; 存低字节到PWM寄存器
MOV A, MULRH ; 读取高字节
MOV Duty_G_RGB_H_B, A ; 存高字节备用
; 计算B路蓝色通道 × 亮度值
MOV A, B_VAL ; 第一个乘数 → A
MOV MULOP, A ; 复制A中的值到 MULOP
MOV A, BRIGHT ; 第二个乘数 → A
MUL ; 执行乘法:B_VAL × BRIGHT
MOV Duty_B_RGB_B, A ; 存低字节到PWM寄存器
MOV A, MULRH ; 读取高字节
MOV Duty_B_RGB_H_B, A ; 存高字节备用
RET
;*****************************************************
; -----------------------------
; 子程序:HSV_TO_RGB
; 功能:将HSV颜色值转换为RGB颜色值
; 输入:A = 色相值(0-255)
; 输出:R_VAL, G_VAL, B_VAL(8位RGB通道值)
; 说明:本子程序假设饱和度和亮度已为最大值(255),适用于全彩LED控制
; 特别注意:所有数据传送必须通过累加器 A 完成(无 # 符号)
; -----------------------------
HSV_TO_RGB:
; 将输入的色相值保存到 SEGMENT 寄存器中
MOV A, HUE_A ; 将当前色相值加载到 A
MOV SEGMENT, A ; 将 A 中的值复制到 SEGMENT
; 右移3位,得到色相区段编号(0~5,共6个区段)
; MOV A, SEGMENT ; 将 SEGMENT 的值加载到 A
; SR A, 3 ; 右移3位,相当于除以8,得到整数部分
SR SEGMENT
MOV SEGMENT,A
MOV SEGMENT, A ; 将结果存回 SEGMENT
; 计算色相的小数部分
; MOV A, SEGMENT ; 将整数部分加载到 A
; SL A, 3 ; 左移3位,相当于乘以8,恢复整数部分的8倍
SL SEGMENT
MOV FRACTION, A ; 将整数部分的8倍存入 FRACTION
MOV A, HUE_B ; 重新加载原始色相值到 A
SUB A, FRACTION ; 原色相值 - 整数部分的8倍 = 小数部分
MOV FRACTION, A ; 将小数部分存入 FRACTION
; 根据区段跳转到对应的RGB计算分支
; MOV A, SEGMENT ; 将区段编号加载到 A
; CEQSN A, 0, RED_SEGMENT ; 区段0 → 红色区间
MOV A,0
CEQSN A,SEGMENT
GOTO $+2
GOTO RED_SEGMENT
; CEQSN A, 1, GREEN_SEGMENT ; 区段1 → 绿色区间
MOV A,1
CEQSN A,SEGMENT
GOTO $+2
GOTO GREEN_SEGMENT
; CEQSN A, 2, BLUE_SEGMENT ; 区段2 → 蓝色区间
MOV A,2
CEQSN A,SEGMENT
GOTO $+2
GOTO BLUE_SEGMENT
; CEQSN A, 3, MAGENTA_SEGMENT ; 区段3 → 品红区间
MOV A,3
CEQSN A,SEGMENT
GOTO $+2
GOTO MAGENTA_SEGMENT
; CEQSN A, 4, CYAN_SEGMENT ; 区段4 → 青色区间
MOV A,4
CEQSN A,SEGMENT
GOTO $+2
GOTO CYAN_SEGMENT
; CEQSN A, 5, YELLOW_SEGMENT ; 区段5 → 黄色区间
MOV A,5
CEQSN A,SEGMENT
GOTO $+2
GOTO YELLOW_SEGMENT
; 区段0 - 红色区间 (Red to Yellow)
RED_SEGMENT:
MOV A, 255 ; 加载红色通道最大值 255 到 A
MOV R_VAL, A ; 将 A 中的值写入 R_VAL(红色通道满)
MOV A, FRACTION ; 将小数部分加载到 A
MOV G_VAL, A ; 将 A 中的值写入 G_VAL(绿色通道从小到大变化)
MOV A, 0 ; 加载蓝色通道最小值 0 到 A
MOV B_VAL, A ; 将 A 中的值写入 B_VAL(蓝色通道不变)
RET ; 返回主程序
; 区段1 - 绿色区间 (Green to Cyan)
GREEN_SEGMENT:
MOV A, 255 ; 加载 255 到 A
SUB A, FRACTION ; A = 255 - FRACTION(红色通道从255递减)
MOV R_VAL, A ; 将结果写入 R_VAL
MOV A, 255 ; 加载 255 到 A
MOV G_VAL, A ; 将 A 中的值写入 G_VAL(绿色通道满)
MOV A, 0 ; 加载 0 到 A
MOV B_VAL, A ; 将 A 中的值写入 B_VAL(蓝色通道不变)
RET ; 返回主程序
; 区段2 - 蓝色区间 (Blue to Magenta)
BLUE_SEGMENT:
MOV A, 0 ; 加载 0 到 A
MOV R_VAL, A ; 将 A 中的值写入 R_VAL(红色通道不变)
MOV A, 255 ; 加载 255 到 A
MOV G_VAL, A ; 将 A 中的值写入 G_VAL(绿色通道满)
MOV A, FRACTION ; 将小数部分加载到 A
MOV B_VAL, A ; 将 A 中的值写入 B_VAL(蓝色通道从小到大变化)
RET ; 返回主程序
; 区段3 - 品红区间 (Magenta to Red)
MAGENTA_SEGMENT:
MOV A, 0 ; 加载 0 到 A
MOV R_VAL, A ; 将 A 中的值写入 R_VAL(红色通道不变)
MOV A, 255 ; 加载 255 到 A
SUB A, FRACTION ; A = 255 - FRACTION(绿色通道从255递减)
MOV G_VAL, A ; 将结果写入 G_VAL
MOV A, 255 ; 加载 255 到 A
MOV B_VAL, A ; 将 A 中的值写入 B_VAL(蓝色通道满)
RET ; 返回主程序
; 区段4 - 青色区间 (Cyan to Green)
CYAN_SEGMENT:
MOV A, FRACTION ; 将小数部分加载到 A
MOV R_VAL, A ; 将 A 中的值写入 R_VAL(红色通道从小到大变化)
MOV A, 0 ; 加载 0 到 A
MOV G_VAL, A ; 将 A 中的值写入 G_VAL(绿色通道不变)
MOV A, 255 ; 加载 255 到 A
MOV B_VAL, A ; 将 A 中的值写入 B_VAL(蓝色通道满)
RET ; 返回主程序
; 区段5 - 黄色区间 (Yellow to Magenta)
YELLOW_SEGMENT:
MOV A, 255 ; 加载 255 到 A
MOV R_VAL, A ; 将 A 中的值写入 R_VAL(红色通道满)
MOV A, 0 ; 加载 0 到 A
MOV G_VAL, A ; 将 A 中的值写入 G_VAL(绿色通道不变)
MOV A, 255 ; 加载 255 到 A
SUB A, FRACTION ; A = 255 - FRACTION(蓝色通道从255递减)
MOV B_VAL, A ; 将结果写入 B_VAL
RET ; 返回主程序