`
1、作品简介
断电了,还在挑灯阅读,太伤眼了;大半夜,灯太亮,太刺眼,影响小伙伴,那么黑,键盘看不见,怎么玩游戏,台灯那么大,太笨拙,太站地方,春节后214情人节很快到了,其实我想来个浪漫的夜色。。。
有解决之道? 呵呵,本文这个可通过USB来控制三基色RGB灯可完美地完成这个小CASE。
2、作品亮点
传统的USB LED小台灯方案,都是一个简单的方案,即把多个白色LED灯和电阻串并起来,然后直接接到USB的VBUS(+5V)电源端上,然后这样的方案,只能发出单色的光。 相比之下,本方案具有以下创新和特点:
① 发光单元采用RGB三基色LED灯,通过任意搭配理论上可发出255x255x255=16581375种颜色的灯光!
② Windows端的人机界面程序,可以及其方便地控制RGB灯的发光颜色。
③ 调整好的LED灯发光颜色,断电后可保存在单片机的EEPROM里,上电后颜色可恢复。 ④ 采用支持USB HID协议的CH9326芯片,可无需再麻烦安装驱动程序(即免驱动),而且采用 HID协议还可广泛应用于多种操作系统,如window 7, XP, Linux等等.
⑤ 板载电子芯片式保险丝BD2243G,具有uS级别的过流保护功能,相比可恢复保险丝那种数秒反应的传统方案,BD2243G具有数千倍更快的过流保护动作。而且通过外置的电阻R,可任意设置过流保护的大小。 设置好了颜色的USB LED灯,还可以这样用,直插充电宝~
3、系统构架图
4、原理图
原理图分为多个部分,下面逐一介绍:
第一部分: 系统供电和VBUS过流保护部分:
备注说明: 上图中,采用ROHM罗姆公司的DB2243G芯片,通过调节R2电阻,可以设置电流受限的大小,当电流超过改值时,Pin6 脚输出为零伏,即负载断开,同时D2这个红色的发光LED指示灯会亮起,表示过流啦!正常输出情况下,D2是熄灭的。有了这个电路,即使负载直接对地短接,都不会损坏PC机的USB端口!而且保护动作极快!不是传统可恢复保险丝那种简单的被动器件可比拟的。过流状态消除后,Pin6 脚立刻恢复正常输出状态,即输出等于5V。 第二部分:系统供电部分
备注说明: 上图中,SOT-23封装的LDO芯片PT5110的作用是把5V降压到+3.3V。如果系统(负载端)需要VCC=5V,那PT5110应该不焊接,同时在F2焊接一个零欧姆的电阻或者焊接一个可恢复保险丝即可。需要指出的是,系统中的芯片(单片机和CH9326)都是可以在5V或3.3V下工作的。区别只是IO输出的电平不同而已。
备注说明: 上图中,USB通信部分由CH9326独立完成,它可完成USB枚举、配置和收发通信任务,大大减轻和解决了单片机的USB 通信难题。CH9326可以理解成一个透明的通信装置,任何简易的单片机都可以不用考虑USB是如何实现的,只负责串口收发数据即可USB双向通信功能。在本系统总,CH9326的主要用途是将PC端发过来的RGB灯的控制数据输出到串口TxD中,同时也可以将RxD端口接收到的单片机数据回传到PC中。
需要指出的是: 如果想让CH9326工作于5V,那R14电阻需要空着。而想让CH9326工作于3.3V,那R14电阻需要焊接上0欧姆;此外,D5 LED指示灯在USB连接到PC后,如果能通信正常,那D5会亮起,反之不亮。而单片机可以通过USB-LINK-OK这根线了解到USB通信连接的状态。如果通信不正常,单片机可以通过/RESET信号对CH9326进行复位。
第四部分:单片机驱动和控制RGB灯部分
备注说明: 上图中,LED灯的主控由8位单片机 stm8s003或stm8s103完成,单片机通过三路PWM的方式分别控制RGB灯的发光颜色。P1是单片机的烧录和仿真下载端口,使用者可以用ST-LINK/V2 这个才几十元的单片机开发工具!
5、材料清单(BOM列表)
以下是这个电子制作的BOM列表,器件全部采购来自立创商城
(szlcsc.com),
PCB板的制造和SMT贴片在深圳嘉立创完成。
6、PCB实物图
7、软件部分的描述
软件分为两部分,一部分是单片机端的实现,另外一部分是PC电脑端(上位机)的控制程序。其中,单片机上电后首先初始化相关IO、按键扫描、串口波特率和串口中断。其关键部分的代码如下:
三路PWM输出控制的初始化片段:
主程序Main的重复执行部分:
while (1)
{
if(tFlag) //------- 通过状态机的方式,每隔 8ms 执行一次按键处理的其中一个步骤
{
IWDG_ReloadCounter(); //Reload IWDG counter
KeyScan();
tFlag = 0;
}
if(MyKey[0].KeyPress) //------- 如果发现按键有效被按下,重复关灯或开灯(颜色不变)
{
if(sMode==0)
{
TIM2_SetCompare1(0x00);
TIM2_SetCompare3(0x00);
}
else
{
TIM2_SetCompare2(RxBuffer[0]);
TIM2_SetCompare1(RxBuffer[1]);
TIM2_SetCompare3(RxBuffer[2]);
}
sMode = ~sMode;
MyKey[0].KeyPress = 0; //-- 完成按键按下的任务,清除按键处理标记。
}
if(RxFlag) //---- 通过串口中断的方式,接收串口数据。收到后RxFlag=1
{
//--- 收到PC端(CH9326)下传过来的RGB数据,然后输出改变RGB-LED灯的
PWM驱动信号,同时保存PWM值到单片机的EEPROM区。
sMode = 0x00;
TIM2_SetCompare2(RxBuffer[0]);
TIM2_SetCompare1(RxBuffer[1]);
TIM2_SetCompare3(RxBuffer[2]);
SaveValue(); //---- 保存PWM驱动信号,上当后将可恢复LED颜色。
UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE); //--- 再次允许串口接收
RxFlag = 0; //---- 串口接收处理完毕,清楚接收标记。
}
} //--- End of While(1)
//------------- 以下是串口中断的处理部分:通过状态机的方式,接收RGB灯的控制数据
INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
{
//=================== Receiver Processing
gTemp = UART1->SR; //--- Creal OverRUN if possible.
gTemp = UART1->DR; //--- UART1_ReceiveData8();
switch(gState)
{
case 0x00:
if(gTemp==0x1B)gState = 0x01;
else gState = 0x00;
break;
case 0x01:
if(gTemp==0xF5)
{
gState = 0x02;
gRxIndex = 0x00;
}
else gState = 0x00;
break;
case 0x02:
RxBuffer[gRxIndex++]= gTemp; //----- Following xxx Bytes...
if(gRxIndex>=3) //--- Receive Finish,OK
{
UART1_ITConfig(UART1_IT_RXNE_OR, DISABLE);
gState = 0x00;
RxFlag = 0xFF;
}
break;
default:
gState = 0x00;
break;
} //------- End of Swith(gState)
}
PC电脑端(上位机)的控制程序,其界面如下:
备注说明: 因版面有限,单片机端和PC电脑端的控制程序(VC++ 编写)的全部源码
`