之前发布过一个 UEFI Shell 版本的 PCH UART,这次发布的是 Windows 版本的。
功能和使用方法同之前的 Shell 版本没有差别。在 AmberLake-Y 下测试通过。

接收端串口设置

可执行程序下载(密码 lab-z.com):
很早之前入手过一块 FT232H 的板卡,这次进行一下 UART 最高速度的测试。测试条件是 Windows 10 操作系统,系统默认的驱动(VCP)。

FT232 上 TXD 是 Pin13 (AD0), RXD 是Pin14(AD1)


使用串口工具直接发送 HEX 55 55 55 55 55 55 55 55 55 55 值(这样从信号看起来就是不断变化的0 1 信号),示波器查看结果如下:


此外,有一些波特率是无法使用的比如:10Mhz ,测试显示无信号输出。测试板子上的晶振是 12Mhz 的,可能是因为这个原因,所有有些分频是无法出来的。从上面可以看出, FT232H UART 模式下,最高的有效传输速度可以达到 12Mhz*(8/10)=9 600 000 bits/s = 1.444Mbytes/s。
本文数据根据实验得出,有问题欢迎朋友直接指出共同探讨。
参考:
1. http://ftdichip.cn/Support/Documents/DataSheets/ICs/DS_FT232H.pdf
从 Windows8 开始,操作系统将设备的 D3 状态分为2种: D3hot 和 D3Cold。
设备可以直接从 D0 状态进入D3Hot,D3Cold 只能从 D3Hot 状态进入。 从 D0 到 D3Hot 的状态切换是通过驱动程序来完成的。进入 D3Hot 后,仍然能够在这个设备连接的总线(Bus)上看到这个设备。当这个总线上的设备进入 D3Hot 后,总线必须处于 D0 状态。进入 D3Hot 后,设备可以返回 D0 状态,或者进入 D3Cold 状态。
当设备进入 D3Cold 后,总线上无法检测到这个设备(设备完全断电)。当设备进入 D3Cold 后,它所处的总线可以进入低功耗状态。同时这个设备不会响应总线上的检测动作。进入 D3Cold 后,设备只能返回 D0 状态,不能直接切换为 D3Hot 状态。
参考:
1.https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/device-sleeping-states
2.https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/supporting-d3cold-in-a-driver
3.https://blog.csdn.net/qq_38180524/article/details/106079187
4.http://blog.chinaunix.net/uid-7374279-id-5838168.html
5: kd> vertarget Windows 10 Kernel Version 19041 MP (8 procs) Free x64 Product: WinNt, suite: TerminalServer SingleUserTS Edition build lab: 19041.1.amd64fre.vb_release.191206-1406 Machine Name: Kernel base = 0xfffff805`0da00000 PsLoadedModuleList = 0xfffff805`0e62a2b0 Debug session time: Wed Feb 10 15:55:42.009 2021 (UTC + 8:00) System Uptime: 7 days 23:02:38.960
参考:
1.https://www.cnblogs.com/yilang/p/12009225.html
春节这几天趁着有空再进一步研究了一下 ESP32 S2 的 USB 玩法。线路连接方法和之前介绍的相同【参考1】,特别注意,这次没有连接 ESP32S2 的5V和 USB 端口的5V, 这是防止 USB 端口上的5V和板子上的5V不同导致的电流倒灌。首先测试 HID的例子:

烧写代码后设备管理器中可以看到多出的 HID 设备。

我手上的开发板是ESP32-S2-Saola-1R,引脚入下图:

调试方法:

这样,可以在 Arduino 串口监视器中看到 Debug 信息,比如插入时有如下信息:

接下来研究一下 MSD (MassStorageDevice,U盘)的例子,在Example->ESP32 TinyUSB->MSC。这个例子需要使用1.5MB的 PSRAM ,对于我入手的板子来说 Flash 是4MB ,PSRAM 是2MB,完全能够满足要求。此外,需要 Enable PSRAM,否则会出现不断重启的问题:

烧写之后系统中就会出现如下的硬盘。

测试发现最新版本的 ESPTinyUSB 库似乎有问题,下面是我这边正常使用的老版本的库:
参考:
之前看到过很多人用一些词组来证明中文的简洁和高效,比如:人们看到“炮闩”,通过“闩”就能猜到它的用途。这让我想起最近网上的一个笑话:“老师在群里发消息说明天开始一元二次方程。有家长问。能不能一元三次?打个折?” 缺少必要知识,就无法理解“元”的含义。 “一元二次方程” 的英文名是“quadratic equation with one unknown”,从上面大抵能看明白这个方程中有一个未知数以及它的二次方。所以,懂和不懂是取决于知识的储备和语言文字并没有太多关系。
| 缩写 | 原始词组 | 解释 |
| ACM | Authenticated Code Module | 用于验证当前密钥之类的模块,放在 BIOS 中的,这个可以看作是 BootGuard 功能的一部分(换句话说,如果想 Enabled BootGuard 功能,除了在 FIT 中 Enable BootGuard,还要保证BIOS中有这个模块。某些情况下,IBV Enabled Debug 功能后,因为 Size 的原因会关闭 ACM ,这样做出来的Debug BIOS 无法在 Fuse 后,并且Enable BootGuard的板子上运行。现象会是:上电之后马上掉电)。 |
| BtG | BootGuard | BootGuard 在【参考1】有介绍。 |
| BUP | Bring-Up | 主板上电过程,有时候指新打出来板子然后Porting BIOS 的过程。 |
| CSE | Converged Security Engine | 系统上的 CSME 系统 |
| dTPM | Discrete TPM | 分立式TPM。对应有一颗专用芯片,通常使用 SPI 接口和PCH 相连。Intel PTT 相当于将一个 dTPM 集成到SOC 中。 |
| EK | Endorsement Key | 签署密钥,或背书密码。它是一个TPM平台的不可迁移的解密密钥,它是一个2048bit的RSA密钥对。它生成于平台的生产过程中,代表着每个平台的真实身份,每个平台都拥有唯一的一个。在确定平台所有者时,用于解密所有者的授权数据,还有解密与生成AIK相关的数据。签署密钥从不用作数据加密和签名。签署密钥的主要功能是生成身份证明密钥(AIK)和建立TPM平台的所有者,由TPM的所有者来生成存储根密钥SRK,使用SRK来加密、存储其他的密钥。【参考2】 |
| FIPS | Federal Information Processing Standard | 美国联邦信息处理标准 |
| FIT | Flash Image Tool | 有时缩写为 FITC, 是一个用于设置 IFWI 的工具,由Intel 提供,跟随 CSME 分发。 |
| FPF | Field Programmable Fuses | 可编程熔丝位。在 PCH 中有一些只能编写一次的熔丝位。可以理解成类似保险丝一样的东西,需要的时候通过编程能够将这个位置写死。比如,Enable PTT之后通过设置对应的熔丝位会使得这个功能无法再次 Disabled。 |
| fTPM | Firmware TPM | 固件模拟TPM。通过在 CPU 上运行的代码来模拟实现 TPM 的功能。为了增加安全性,相关代码是放在 Protected Execution Environment (PEE) 来执行的。 |
| IBB | Initial Boot Block | 这是 UEFI 中的概念,用于校验 BIOS 其余部分。 |
| PEE | Protected Execution Environment | 受保护运行环境,能够独立于普通CPU 运行环境来运行代码。 |
| PRTC | Protected Real Time Clock | 受保护的时钟,能够抵御 Hammering 和 Replay 攻击。对于这两种攻击介绍如下【参考4】 重放攻击(Replay Attacks)又称重播攻击、回放攻击,是指攻击者发送一个目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程,破坏认证的正确性。重放攻击可以由发起者,也可以由拦截并重发该数据的敌方进行。攻击者利用网络监听或者其他方式盗取认证凭据,之后再把它重新发给认证服务器。重放攻击在任何网络通过程中都可能发生,是计算机世界黑客常用的攻击方式之一。 重放操作 一个电子商务网站,要求客户对电子订单签名以防止非授权用户下订单。攻击者如要冒充某位客户下订单,最好可以获得他的私钥,如果不成功,攻击者可以监听这位顾客的通信,将顾客以前发送的订单记录下来,然后他就可以直接将这些订单发给网站了。因为这些订单的确是合法客户签名过的,如果网站没有一种识别重放订单的机制,它就会不加犹豫地接收这些订单。 |
| PTP | Platform TPM Profile | |
| RBE | ROM Boot Extension | |
| RNG | Random Number Generator | 随机数生成器 |
| ROT | Root of Trust | 根信任节点 |
| RPMB | Replay Protected Memory Block | 防重放攻击内存块, 将PTT数据存放在独立的 NVM 区域。 |
| RPMC | Replay Protection Monotonic Counters | 防重放攻击单调递增计数器。这个计数器只能增加不能减小,通过这样的方式来对抗重放攻击。 |
| RTC | Real Time Clock | |
| RTM | Root of Trust for Measurement | |
| RTR | Root of Trust for Reporting | |
| RTS | Root of Trust for Storage | |
| TCG | Trusted Computing Group | 可信计算组织。TCG组织制定了TPM(Trusted Platform Module)的标准,很多安全芯片都是符合这个规范的。而且由于其硬件实现安全防护,正逐渐成为PC,尤其是便携式PC的标准配置。 |
| TPM | Trusted Platform Module | 可信平台模块。 |
| VSC | Virtual Smart Cards | 虚拟智能卡。常见的公交卡就是一种智能卡。可以看到它能够实现身份验证,支付等等的功能。同样的,虚拟智能卡也能实现这样的功能。可以想象下面的应用场景:通过 TPM 实现了 Virtual Smart Cards 的功能,然后 Windows 就可以访问企业内部的敏感资源。比如,你将一份文档发送到企业内部打印机上,之前需要刷胸卡来完成打印,现在有了 VSC 可以通在打印机上刷笔记本电脑的方式完成打印。 |
可以看到,上面的很多词,如果不是专业人员,无论是英文还是中文都是需要多加解释的。再比如:“有一个机械中特别重要的装置,叫活塞,英文是piston。不过在中国,这个词最早不叫活塞,而叫“鞲鞴”。来,眼睛别晕,先扶着墙把晚饭吐出来,然后把这个字复制到word里,放大三倍字号。这个词,念“勾背”。据李文、戴吾三两位考证,是中国第一艘火轮船的制造者徐寿发明的,徐寿1871年在《汽机发轫》首次把piston翻成鞲鞴。别看这词冷僻古怪又麻烦,还真是有典故的。“鞲”字意义是革制的皮套,引申成皮制的鼓风机,也就是风箱;“鞴”字就更精妙了,它的意思是:水受压而喷涌而出。唐代皮日休的《通玄子栖宾亭记》:“源内橐籥鞴出琉璃液。”一鼓一压,正是活塞工作之象。徐寿文化水平太高,用这两个字来译piston,真是用典贴切,古今妙译里,也排得上号,就是他妈太麻烦了……所以后来大家普遍都使用“活塞”这个更浅显的词,鞲鞴则只留存在专业领域。”【参考3】
参考:
1.https://www.lab-z.com/btg/ Boot Guard 简介
2.https://www.cnblogs.com/embedded-linux/p/6716740.html TPM Key相关概念
3.https://www.zhihu.com/question/24449484/answer/27850454 作者:马伯庸
4.https://baike.baidu.com/item/%E9%87%8D%E6%94%BE%E6%94%BB%E5%87%BB 重放攻击
5.https://docs.microsoft.com/en-us/windows/security/identity-protection/virtual-smart-cards/virtual-smart-card-overview
6.https://baike.baidu.com/item/%E6%99%BA%E8%83%BD%E5%8D%A1 智能卡
智能卡(Smart Card) :内嵌有微芯片的塑料卡(通常是一张信用卡的大小)的通称。一些智能卡包含一个微电子芯片,智能卡需要通过读写器进行数据交互。智能卡配备有CPU、RAM和I/O,可自行处理数量较多的数据而不会干扰到主机CPU的工作。智能卡还可过滤错误的数据,以减轻主机CPU的负担。适应于端口数目较多且通信速度需求较快的场合。 卡内的集成电路包括中央处理器CPU、可编程只读存储器EEPROM、随机存储器RAM和固化在只读存储器ROM中的卡内操作系统COS(Chip Operating System)。卡中数据分为外部读取和内部处理部分。
智能卡(Smart Card) :内嵌有微芯片的塑料卡(通常是一张信用卡的大小)的通称。一些智能卡包含一个微电子芯片,智能卡需要通过读写器进行数据交互。智能卡配备有CPU、RAM和I/O,可自行处理数量较多的数据而不会干扰到主机CPU的工作。智能卡还可过滤错误的数据,以减轻主机CPU的负担。适应于端口数目较多且通信速度需求较快的场合。 卡内的集成电路包括中央处理器CPU、可编程只读存储器EEPROM、随机存储器RAM和固化在只读存储器ROM中的卡内操作系统COS(Chip Operating System)。卡中数据分为外部读取和内部处理部分。
某些情况下,我们需要在没有源代码的情况下需要对BIOS ROM 进行直接修改。本文就以修改 OVMF.FD 为例介绍这个过程。
首先介绍一下这次修改的目标,使用下面的命令生成 Debug Log:
qemu-system-x86_64 -bios "ovmf.fd" -debugcon file:debug.log -global isa-debugcon.iobase=0x402
其中有下面这样一个错误:
SecCoreStartupWithStack(0xFFFCC000, 0x820000)
LABZ report checksum error!
Register PPI Notify: DCD0BE23-9586-40F4-B643-06522CED4EDE
Install PPI: 8C8CE578-8A3D-4F1C-9935-896185C32DD3
Install PPI: 5473C07A-3DCB-4DCA-BD6F-1E9689E7349A
The 0th FV start address is 0x00000820000, size is 0x000E0000, handle is 0x820000
Register PPI Notify: 49EDB1C1-BF21-4761-BB12-EB0031AABB39
Register PPI Notify: EA7CA24B-DED5-4DAD-A389-BF827E8F9B38
Install PPI: B9E0ABFE-5979-4914-977F-6DEE78C278A6
我们的目标就是通过修改 OVMF.FD 来去掉这个错误。
使用 UEFITool 打开 OVMF.FD ,使用搜索功能查找错误字符串,可以看到是位于 SecMain 中。这个文件没有压缩,对于我们搜索来说会很方便。

为了研究代码,还需要使用这个工具将SecMain 释放出来:

释放出来的文件是以 “MZ”开头的:

使用 IDA 来分析解压出来的这个文件,特别注意,因为代码中含有64Bit的指令,必须使用 IDA-64 才能得到结果。


我们需要找到相关的代码,在菜单中选择 View->Open subviews->Strings

先用Ctrl+F 找到前面提到的字符串,在字符串上双击即可跳转到对应的代码:

新版本的 IDA 默认使用图形化反编译结果,看起来并不是很直接,右键切换到 Text View

这里就可以看的很清楚,比较 rax 和 rdx ,如果不相等就输出字符串,如果相等就跳过:

使用 Hex View 查看,74 0F就是 jz short loc_FFFCCE37 这个跳转语句,将这条语句修改为 jmp short loc_FFFCCE37 就不会输出错误提示了。

修改方法是:在 OVMF中搜索 FD FF FF 48 3B C2 74 0F (整个文件中只有一处),找到后将 74 修改为改成 EB (JMP)。这样修改后再次使用 QEMU 启动修改后的 OVMF.FD ,可以在 Debug.log 中看到之前的字符串已经消失。
本文使用的,修改之前的 OVMF 可以在这里下载:
这个信息是在 Omvf/Sec/SecMain.c 中加入如下代码生成的:
//
// Find PEI Core entry point
//
Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
if (EFI_ERROR (Status)) {
*PeiCoreEntryPoint = 0;
}
//LABZ_Debug_Start
if (((EFI_PHYSICAL_ADDRESS) FindImageBase -(EFI_PHYSICAL_ADDRESS) FindAndReportEntryPoints)!=0x0) {
DEBUG ((EFI_D_ERROR, "LABZ report checksum error!\n"));
}
//LABZ_Debug_End
return;
}
对于现在的电脑来说,USB是外部通讯的不二选择,通过这个接口可以引出键盘鼠标等等外部设备。这次尝试使用国产的 CH55X 系列单片机来做一个 USB 提醒器,通过这个设备能够做到LED 发光提示还有蜂鸣器声音提示。
首先介绍一下 CH55X 系列芯片是南京沁恒(WCH)出品的带有USB功能的系列单片机【参考1】,提起这家公司的名称大多数人会感到陌生,但是如果提起CH340/CH341芯片大家都会非常熟悉,这款低成本的USB串口转换芯片就是这家公司的产品。这次设计用到的 CH552 和 CH551/CH554 是同一个系列。他们主要的差别是:CH551 是最低端的,工作频率是 24Mhz,FLASH 有 10K (可以看作是单片机的 ROM),内存是 512+256字节,只能做 USB Device;CH552比前者配置稍微高了一些,FLASH空间有16K,内存有1K+256字节,只能做 USB Device;CH554比前面都高级,FLASH 和 内存和 CH552 相同,但是可以当作 USB Host 使用能够实现解析USB 键盘鼠标这样设备的工作。可以看出,相比 Atmel 的 32U4 (Arduino Leonardo),主要缺点是内存太小。但是胜在价格便宜,引脚简单(这样容易焊接)。在立创商城上面的芯片价格如下(CH552/4 不同封装引脚数量不同,所以价格是在一个范围内)
CH551G 2.475元
CH552 2.7-2.78元
Ch554 5.43-7.03元
32u4 23.51元
因此,如果CH55X 系列芯片能够满足你的需求,能够大大降低成品的成本。同时, CH55X 系列单片机对于外围元件要求极低,无须晶振,只要合适的贴片电容即可工作起来。
这次设计使用CH552G芯片是 SOP16 封装,同样的 CH554 也有SOP16封装可以直接替换(CO-Layout)

电路设计如下:

这个芯片使用C1/C2 两个 0.1uF 的电容即可工作,5V 供电,从 VCC/VDD 引脚进入。上图中 V33 经过 R1 (10K)连接到 USB+引脚上,其中的 PAD1无须上键在这里作为开关使用用于控制芯片进入 Bootloader Mode。
板子上还有一个 WS2812B MINI(3.5×3.5mm) 用于提供灯光提示,同样的这个元件无须外围配合,直接用CH55X P1.5即可控制:

外围有一个蜂鸣器,因为CH55X 引脚提供电流有限,所以使用S8050这个三极管扩流,同时外加R3用于限流,主要是避免声音太大。CH55X P3.4 Pin 用于控制蜂鸣器开关。因为该引脚是 PWM 引脚,因此这里即可以使用有源蜂鸣器和无源蜂鸣器。有源蜂鸣器的含义是“内部有震荡源”,类似于电动机,有了供电就能发声;与其相反,无源蜂鸣器含义是“内部没有震荡源”,因此需要用引脚电流变换来驱动它。对于有源蜂鸣器,P3.4 当作普通的GPIO 即可;对于无源蜂鸣器,需要设定为 PWM 然后给他设置占空比和频率(默认即可)。

PCB 设计如下:

切换为 3D 模式预览如下(这次设计的 Symbol使用的都是嘉立创的,所以自带了 3D 模型,非常直观):


拿到手的 PCB和焊接后的照片如下:

接下来就开始软件设计了。这个芯片原本设计使用 C51 来进行变成,用户可以通过 Keil 这样的集成开发环境进行编程,但是对于我们来说C51还是过于复杂。这里使用 Github上的一个开源项目:ch55xduino【参考2】,能够让我们像开发 Arduino 一样为 CH551/2/4 进行开发。
首先介绍一下项目的安装:和其他的所有的第三方板卡一样, 在 Preferences –> Additional Boards Manager URLs 中加入这个板卡的地址https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json

之后打开 Boards Manager

搜索这个项目

Install 安装之后在 Boards Manager 中能够看到这个板卡,编译时,CH551使用 CH551 Board, CH552/4 使用 CH552 Board

接下来就是如何编译一个程序,可以在 Example 中看到专用的例子,比如下面就是关于 USB 设备的例子:

打开一个例子尝试编译,完成后就需要做上传的准备工作了。刚拿到手 ,板子上没有Bootloader,需要短接板子背面 PAD 处(电路图中是0.1uF电容,实际上不上件预留为空),这样V33会通过10K 电阻后进入 D+ Pin,板子会进入 Bootloader Mode。


属性如下:

使用 Zadig 给他安装一个驱动,勾选 Edit

重命名为 USB Module

安装之后:

编译后会自动搜索名为 “USB Module”的设备并且上传

需要注意的是:如果你的代码没有实现 USB 串口,那么只能短接PAD 让板子进入 BootLoader Mode再次上传。
了解了上面的知识,即可着手设计代码实现提醒器的功能。我们设计了2种提醒方式:LED 和蜂鸣器,分别通过2个命令进行设置,形式如下:
完整代码如下:
#define BEEPERPIN 34
#define LEDPIN 15
#define TX(LedColor) {\
if (((LedColor)&0x80)==0) {\
XdigitalWriteFast(1,5,HIGH);\
(LedColor)=(LedColor)<<1;\
XdigitalWriteFast(1,5,LOW);\
XdigitalWriteFast(1,5,LOW);\
XdigitalWriteFast(1,5,LOW);\
}else{\
XdigitalWriteFast(1,5,HIGH);\
XdigitalWriteFast(1,5,HIGH);\
XdigitalWriteFast(1,5,HIGH);\
XdigitalWriteFast(1,5,HIGH);\
XdigitalWriteFast(1,5,HIGH);\
XdigitalWriteFast(1,5,HIGH);\
XdigitalWriteFast(1,5,HIGH);\
(LedColor)=(LedColor)<<1;\
XdigitalWriteFast(1,5,LOW);\
XdigitalWriteFast(1,5,LOW);\
XdigitalWriteFast(1,5,LOW);\
XdigitalWriteFast(1,5,LOW);\
XdigitalWriteFast(1,5,LOW);\
}\
}
#ifndef USER_USB_RAM
#error "This example needs to be compiled with a USER USB setting"
#endif
#include "src/userUsbCdc/USBCDC.h"
void setup() {
// 设置蜂鸣器Pin 为Low (停止发声)
pinMode(BEEPERPIN,OUTPUT);
digitalWrite(BEEPERPIN,LOW);
// 设置LED 控制Pin
pinMode(LEDPIN,OUTPUT);
digitalWrite(LEDPIN,LOW);
USBInit();
}
byte Status=0;
byte RValue,GValue,BValue;
byte THigh=0,TLow=0;
unsigned long CounterDown=0xFFFFFFFF;
void loop() {
while (USBSerial_available()) {
// 接收来自USB串口的字符
char serialChar = USBSerial_read();
if ((serialChar == '[')&&(Status==0)) { Status=1; continue;}
if ((serialChar == 'c')&&(Status==1)) {Status=2; continue;}
if (Status==2) {RValue=serialChar; Status=3; continue;}
if (Status==3) {GValue=serialChar; Status=4; continue;}
if (Status==4) {BValue=serialChar; Status=5; continue;}
if (Status==5) {
if (serialChar == ']') {Status=6;continue;}
else {Status=0; continue;}
}
if ((serialChar == 'b')&&(Status==1)) {Status=7; continue;}
if (Status==7) {THigh=serialChar; Status=8; continue;}
if (Status==8) {TLow=serialChar; Status=9; continue;}
if (Status==9) {
if (serialChar == ']') {Status=10; continue;}
else {
// 如果最后收到的字符不是 [ 那么需要重新开始
Status=0; continue;
}
}
}
// 根据收到的 cRGB 设置 LED 颜色
if (Status==6) {
USBSerial_println_s("RGB");
USBSerial_println_i(RValue);
USBSerial_println_i(GValue);
USBSerial_println_i(BValue);
USBSerial_flush();
// 设置 WS2812 颜色, 特别注意这里和时许非常相关,具体数值都是示波器测量取得
//Send Green value from Bit7 to 0
TX(GValue);TX(GValue);TX(GValue);TX(GValue);TX(GValue);TX(GValue);TX(GValue);TX(GValue);
//Send Red value from Bit7 to 0
TX(RValue);TX(RValue);TX(RValue);TX(RValue);TX(RValue);TX(RValue);TX(RValue);TX(RValue);
//Send Blue value from Bit7 to 0
TX(BValue);TX(BValue);TX(BValue);TX(BValue);TX(BValue);TX(BValue);TX(BValue);TX(BValue);
// 重新设置为状态 0
Status=0;
}
// 根据设置的延时开始倒计时
if (Status==10) {
if ((THigh==0)&&(TLow==0)) {
digitalWrite(BEEPERPIN,LOW);
}
// 设置触发时间
else CounterDown=(THigh*256+TLow)*1000UL+millis();
Status=0;
}
// 如果当前处于状态 0 并且设置的触发时间小于当前时间,那么就开始响
if ((Status==0)&&(CounterDown<millis())) {
// 对应 Pin 拉高,蜂鸣器开始发声
digitalWrite(BEEPERPIN,HIGH);
// 拉高之后会一直发声
CounterDown=0xFFFFFFFF;
}
}
特别提一句:WS2812 有很多版本,彼此之间在时序上有差别。比如,下面两种从Datasheet看就是有差别的,前者的代码(CH55xDuino)在后者(这次设计使用的)上会有问题:
| WS2812D-F8 | WS2812B-Mini | |
| T0H | 400±150ns | 300±80ns |
| T0L | 850±150ns | 790±210ns |
| T1H | 850±150ns | 790±210ns |
| T1L | 400±150ns | 300±80ns |
| RES | >50us | >280us |
所以,我在代码上重写了 WS2812 相关部分,因为对时序要求很高,所以最好使用汇编语言,但是因为我对 C51汇编很陌生,于是只能写成宏的方式。有兴趣的朋友可以尝试修改CH55xduino的库文件。
BOM 如下,不包括PCB 在10元左右,可以看到这个芯片在制作 USB 相关设备方面很有竞争力:

虽然CH55X系列芯片有诸多好处,但是还存在如下缺点:
参考:
========================================
因为 GitHub 在访问上可能存在的问题,所以我在这里放一个 json 文件,就是说你可以在 Preferences –> Additional Boards Manager URLs 中使用下面这个地址:
http://www.lab-z.com/wp-content/uploads/2021/05/package_ch55xduino_mcs51_index.json
| Req Id | Title | Location | Link for Job Description |
| NS532 | Platform Applications Engineer, Senior Staff | Shanghai | https://jobs.jobvite.com/amperecomputing/job/o9s6cfwD |
| NS627 | Platform Applications Engineer (Software), Principal | Shanghai / Shenzhen | https://jobs.jobvite.com/amperecomputing/job/oVPbefwT |
| NS660 | Platform Applications Engineer (Software), Staff | Shanghai | https://jobs.jobvite.com/amperecomputing/job/oKFvefwS |
| NS703 | Platform Applications Engineer (Hardware) Staff | Shanghai | https://jobs.jobvite.com/amperecomputing/job/othIefwq |
| NS771 | Senior Recruiter | Shanghai | https://jobs.jobvite.com/amperecomputing/job/o5g5efwo |
| NS764 | Field Marketing Manager | Shanghai | https://jobs.jobvite.com/amperecomputing/job/oCO2efwq |
| NS775 | Sales Operations, Senior Manager | Shanghai | https://jobs.jobvite.com/amperecomputing/job/oPt6efwm |
| NS687 | Field Applications Engineer, Staff | Shanghai / Beijing | https://jobs.jobvite.com/amperecomputing/job/oTVDefwp |
| NS631 | Platform Applications Engineer (Software) Staff | Beijing | https://jobs.jobvite.com/amperecomputing/job/oWheefwp |
| NS650 | Platform Applications Engineer, Senior Staff | Taipei | https://jobs.jobvite.com/amperecomputing/job/oD3sefw6 |
| NS642 | Staff ATE Hardware Engineer | Taiwan – Virtual | https://jobs.jobvite.com/amperecomputing/job/oVXqefwg |
| NS724 | Supplier Quality Engineer, Staff | Taiwan – Virtual | https://jobs.jobvite.com/amperecomputing/job/oolNefwu |
| NS725 | Document Controller / Technical Writer, Staff | Taiwan – Virtual | https://jobs.jobvite.com/amperecomputing/job/oplNefwv |
| NS726 | Customer Quality Engineer, Staff | Taiwan – Virtual | https://jobs.jobvite.com/amperecomputing/job/oqlNefww |
| NS750 | System Level Test (SLT) Engineer, Staff | Taiwan – Virtual | https://jobs.jobvite.com/amperecomputing/job/o6uXefwv |
有兴趣的朋友可以直接联系 jun.chen@amperecomputing.com