2024年2月更新,Step to UEFI 文章索引:
故乡的水塔
前一段看新闻,忽然意识到现在生活的城市已经很少见到这样的庞然巨物了。
我是出生和成长在黑龙江大庆市的。“大庆”这个城市名称始终和“工业学大庆”这个口号联系在一起的,同时和“大油田”深深的绑定。小时候有一段时间,我非常反感有文章用“小油苗”来称呼本地的少年儿童。甚至深深的怀疑第一个编造出这个称呼的人是没有见过“原油”的。那是一种黏糊糊散发着异常味道的物质,稍微有一些化学知识的人都会了解其中含有大量的“苯”“烃””烯“致癌成分,更不会有人产生可爱的联想。
长大之后,我去成都求学,在那里也曾经看到过很多水塔,通常都是下面飞盘造型,蓝白相间的颜色在阴郁的天空下会显得无比深沉。
大庆的水塔没有如此的艺术感,完全像一个木柄手榴弹,外立面不会有任何的装饰,赤裸着红砖努力展现着质朴和实用的主题。估计建设之初一定是本着“又不是不能用”的原则。
这样的水塔下方通常都是机房,靠近能听到其中机器的嘶吼,电力驱动的泵机将水送到顶层,用于维持这一片区供水压力。小时候站在下面,仰望水塔,会有一阵阵的眩晕感,高大的水塔仿佛随时会扑下来的巨人一般。
很长一段时间,大庆的居民楼,甚至是学校都是统一造型的。比如,下面这种样式就是典型的居民楼。从飞机上看下去都是类似的火柴盒。若干年后,我大约知道这种楼被称作“赫鲁晓夫楼”,是一种风格统一的工业化设计,能够在短期内满足改善当地人居住条件的建筑。
更早期大庆的典型住宅是被称作“干打垒”的房子。在东北,保暖性能是第一需要考虑的问题,冬季最冷的时候会达到零下三四十度。只有足够厚度的墙体才能抵御外部的寒冷。干打垒有很大一部分处于地以下,这样能够显著的节省建筑材料。也是因为这样的原因,听说早年间遇到特别大的雪天,早晨门会被积雪掩盖,通常需要从窗口跳出去,铲开门口的雪才能打开房门。
所有的学校也是相同的造型【参考1】。这是我初中的学校,之前原名是大庆市第二十四中学,原来自己独占一个大院的,后来挤进来五十六中学,再后来二者合并改名为“三十六中学”。
参考:
自制Windows 11精简版
先说最后制作出来的结果:镜像文件2.78GB.虚拟机中安装后内存占用1.6GB,硬盘占用 10GB
接下来介绍制作方法:
- 项目是来自https://github.com/ntdevlabs/tiny11builder , 项目通过运行脚本文件来提供Windows 11安装镜像中的文件再重新生成一个安装 ISO
- 运行方法是首先挂载一个 Windows 11安装镜像,比如,这里我挂接到 f:
- 以管理员权限打开Windows Power Shell 首先运行如下命令
Set-ExecutionPolicy unrestricted
4.运行 tiny11Coremaker.ps1,这个过程中会要求你选择制作的类型,推荐选择 Windows 11 pro
5.接下来等待即可,结束之后会有提示
原来的项目中会需要联网下载 oscdimg.exe 文件的,这里我直接都打包在一起,可以离线使用。
Windows Service 服务框架例子
这里提供一个Service 的例子,实现对c:\log.txt 每隔一段写入当前时间。
// MyService.cpp : 定义控制台应用程序的入口点。
//
#include <Windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
/*
BOOL IsInstalled();
BOOL Install();
BOOL Uninstall();
void LogEvent(LPCTSTR pszFormat, ...);
void WINAPI ServiceMain();
void WINAPI ServiceStrl(DWORD dwOpcode);
TCHAR szServiceName[] = _T("MyService");
BOOL bInstall;
SERVICE_STATUS_HANDLE hServiceStatus;
SERVICE_STATUS status;
DWORD dwThreadID;
SC_HANDLE hSCM;
SC_HANDLE hService;
*/
/*
OpenSCManager 用于打开服务控制管理器;
CreateService 用于创建服务;
OpenService用于打开已有的服务,返回该服务的句柄;
ControlService则用于控制已打开的服务状态,这里是让服务停止后才删除;
DeleteService 用于删除指定服务。
RegisterServiceCtrlHandler 注册服务控制
*/
//定义全局函数变量
void Init();
BOOL IsInstalled();
BOOL Install();
BOOL Uninstall();
void LogEvent(LPCTSTR pszFormat, ...);
void WINAPI ServiceMain();
void WINAPI ServiceStrl(DWORD dwOpcode);
TCHAR szServiceName[] = _T("MyService");
BOOL bInstall;
SERVICE_STATUS_HANDLE hServiceStatus;
SERVICE_STATUS status;
DWORD dwThreadID;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
Init();
dwThreadID = ::GetCurrentThreadId();
SERVICE_TABLE_ENTRY st[] =
{
{ szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ NULL, NULL }
};
if (_tcscmp(lpCmdLine, _T("/install")) == 0)
{
Install();
}
else if (_tcscmp(lpCmdLine, _T("/uninstall")) == 0)
{
Uninstall();
}
else
{
if (!::StartServiceCtrlDispatcher(st))
{
LogEvent(_T("Register Service Main Function Error!"));
}
}
return 0;
}
//初始化
void Init()
{
hServiceStatus = NULL;
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
status.dwCurrentState = SERVICE_START_PENDING;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
status.dwWin32ExitCode = 0;
status.dwServiceSpecificExitCode = 0;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
}
//服务主函数,这在里进行控制对服务控制的注册
void WINAPI ServiceMain()
{
status.dwCurrentState = SERVICE_START_PENDING;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
//注册服务控制
hServiceStatus = RegisterServiceCtrlHandler(szServiceName, ServiceStrl);
if (hServiceStatus == NULL)
{
LogEvent(_T("Handler not installed"));
return;
}
SetServiceStatus(hServiceStatus, &status);
status.dwWin32ExitCode = S_OK;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hServiceStatus, &status);
//模拟服务的运行。应用时将主要任务放于此即可
//可在此写上服务需要执行的代码,一般为死循环
while (1)
{
FILE* p=NULL;
errno_t err =_tfopen_s(&p,_T("c:\\log.txt"), _T("ab+"));
if (err != 0) {
TCHAR errMsg[256];
_wcserror_s(errMsg, 256, err);
_tprintf(_T("err! %s"), errMsg);
return ;
}
SYSTEMTIME st;
GetSystemTime(&st);
TCHAR time[100] = { 0 };
_stprintf_s(time, 100, _T("%4d-%02d-%02d %02d:%02d:%02d\r\n"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
if (p == NULL) {
return;
}
fwrite(time, sizeof(TCHAR), _tcsclen(time), p);
fclose(p);
Sleep(5000);
}
status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hServiceStatus, &status);
}
//Description: 服务控制主函数,这里实现对服务的控制,
// 当在服务管理器上停止或其它操作时,将会运行此处代码
void WINAPI ServiceStrl(DWORD dwOpcode)
{
switch (dwOpcode)
{
case SERVICE_CONTROL_STOP:
status.dwCheckPoint = 1;
status.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(hServiceStatus, &status);
Sleep(500);
status.dwCheckPoint = 0;
status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hServiceStatus, &status);
PostThreadMessage(dwThreadID, WM_CLOSE, 0, 0);
break;
case SERVICE_CONTROL_PAUSE:
break;
case SERVICE_CONTROL_CONTINUE:
break;
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
exit(0);
break;
default:
LogEvent(_T("Bad service request"));
}
}
//判断服务是否已经被安装
BOOL IsInstalled()
{
BOOL bResult = FALSE;
//打开服务控制管理器
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM != NULL)
{
//打开服务
SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_QUERY_CONFIG);
if (hService != NULL)
{
bResult = TRUE;
::CloseServiceHandle(hService);
}
::CloseServiceHandle(hSCM);
}
return bResult;
}
//安装服务函数
BOOL Install()
{
//检测是否安装过
if (IsInstalled())
return TRUE;
//打开服务控制管理器
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);
return FALSE;
}
//获取程序目录
TCHAR szFilePath[MAX_PATH];
::GetModuleFileName(NULL, szFilePath, MAX_PATH);
//创建服务
SC_HANDLE hService = ::CreateService(hSCM, szServiceName, szServiceName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
szFilePath, NULL, NULL, _T(""), NULL, NULL);
//检测创建是否成功
if (hService == NULL)
{
::CloseServiceHandle(hSCM);
MessageBox(NULL, _T("Couldn't create service"), szServiceName, MB_OK);
return FALSE;
}
//释放资源
::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);
return TRUE;
}
//删除服务函数
BOOL Uninstall()
{
//检测是否安装过
if (!IsInstalled())
return TRUE;
//打开服务控制管理器
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL)
{
MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);
return FALSE;
}
//打开具体服务
SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);
if (hService == NULL)
{
::CloseServiceHandle(hSCM);
MessageBox(NULL, _T("Couldn't open service"), szServiceName, MB_OK);
return FALSE;
}
//先停止服务
SERVICE_STATUS status;
::ControlService(hService, SERVICE_CONTROL_STOP, &status);
//删除服务
BOOL bDelete = ::DeleteService(hService);
::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);
if (bDelete) return TRUE;
LogEvent(_T("Service could not be deleted"));
return FALSE;
}
//记录服务事件
void LogEvent(LPCTSTR pFormat, ...)
{
TCHAR chMsg[256];
HANDLE hEventSource;
LPTSTR lpszStrings[1];
va_list pArg;
va_start(pArg, pFormat);
_vsntprintf_s(chMsg, sizeof(chMsg),_TRUNCATE,pFormat, pArg);
va_end(pArg);
lpszStrings[0] = chMsg;
hEventSource = RegisterEventSource(NULL, szServiceName);
if (hEventSource != NULL)
{
ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*)&lpszStrings[0], NULL);
DeregisterEventSource(hEventSource);
}
}
完整代码:
参考:
1.https://cloud.tencent.com/developer/article/1857390
2https://learn.microsoft.com/zh-cn/windows/win32/services/writing-a-service-program-s-main-function
3.https://blog.csdn.net/hsy12342611/article/details/133557759
招商价值成长混合C 投资盘点
2021 年8月买了招商价值成长混合C (012004) 8万元,2024年10月抛了,剩下 52000,亏了35%。
好奇心驱使下,查了一下资料:https://finance.sina.com.cn/fund/quotes/012004/bc.shtml,这个基金几乎从开始就一直在亏损:
基金经理是 郭锐,盈利能力 74% 的意思是超过 74% 的基金经理。
关于他的公开信息在 https://stock.finance.sina.com.cn/manager/view/mInfo.php?mid=30176884,看历史业绩(不知道为什么没有列出来我买的这支),2020年之后的基本上都在亏钱。
结论:基金有风险,投资需谨慎。投资之前最好看看以往业绩。
PVD:Battery 虚拟电池
前面的 PVD(Physical Virtual Device)设计过普通鼠标,绝对值鼠标, 这次带来的是一个虚拟电池的设计。在进行功耗和性能测试的时候,电池状态(AC/DC)对于Windows性能释放有着很大的影响。因此需要有手段来虚拟电池,之前我设计过2款虚拟电池软件的,但是这种软件是通过驱动来实现的,在具体使用时会有很大局限性。
这次带来的是使用 CH554模拟的USB HID 设备,它将自身报告为一个 UPS 设备,然后通过 USB 接口将当前电池信息报告给 Windows。代码是 Arduino 写成的,通俗易懂,只需要有 USB 知识就可以掌握。整体框架来自另外一个基于 Leonardo 的Arduino 项目。
硬件部分非常简单,就是一个 CH554e的最小系统(MSOP10)封装,非常适于制作小型设备。
#ifndef USER_USB_RAM
#error "This example needs to be compiled with a USER USB setting"
#endif
#include <WS2812.h>
#include "src/CdcHidCombo/USBCDC.h"
#include "src/CdcHidCombo/USBHIDKeyboardMouse.h"
#include "src/CdcHidCombo/PowerDevice.h"
#include "src/CdcHidCombo/USBconstant.h"
#define NUM_LEDS 1
#define COLOR_PER_LEDS 3
#define NUM_BYTES (NUM_LEDS*COLOR_PER_LEDS)
__xdata uint8_t ledData[NUM_BYTES];
#define MINUPDATEINTERVAL 26000UL
#define OnBoardLED 0x03
const byte bDeviceChemistry = IDEVICECHEMISTRY;
const byte bOEMVendor = IOEMVENDOR;
uint16_t iPresentStatus = 0, iPreviousStatus = 0;
byte bRechargable = 1;
byte bCapacityMode = 0; // units are in mWh
// Physical parameters
const uint16_t iConfigVoltage = 1380;
uint16_t iVoltage = 1300, iPrevVoltage = 0;
uint16_t iRunTimeToEmpty = 0, iPrevRunTimeToEmpty = 0;
uint16_t iAvgTimeToFull = 7200;
uint16_t iAvgTimeToEmpty = 7200;
uint16_t iRemainTimeLimit = 600;
int16_t iDelayBe4Reboot = -1;
int16_t iDelayBe4ShutDown = -1;
byte iAudibleAlarmCtrl = 2; // 1 - Disabled, 2 - Enabled, 3 - Muted
// Parameters for ACPI compliancy
uint8_t iDesignCapacity = 0xFF;
byte iWarnCapacityLimit = 10; // warning at 10%
byte iRemnCapacityLimit = 5; // low at 5%
const byte bCapacityGranularity1 = 1;
const byte bCapacityGranularity2 = 1;
uint8_t iFullChargeCapacity = 0xFF;
uint8_t iRemaining = 0xFF, iPrevRemaining = 0;
int iRes = 0;
unsigned long iIntTimer=0;
// Data format
// Keyboard(Total 9 bytes): 01(ReportID 01) + Keyboard data (8 Bytes)
// Mouse(Total 5 bytes): 02(ReportID 02) + Mouse Data (4 Bytes)
uint8_t recvStr[9];
uint8_t recvStrPtr = 0;
unsigned long Elsp;
uint8_t FeatureBuffer[256];
FeatureType FeatureList[32];
uint8_t FeatureRecord = 0;
uint16_t iManufacturerDate = 0,bCycles=20;
void setFeature(uint8_t id, uint8_t* Data, int Len)
{
/*
Serial0_print("ID:");
Serial0_print(id);
Serial0_print_c(' ');
Serial0_print(Data[0]);
Serial0_print_c(' ');
if (Len>1) {
Serial0_print(Data[1]);
Serial0_print_c(' ');
}
Serial0_print(Len);
Serial0_println_c(' ');
*/
FeatureList[id].Index = FeatureRecord;
FeatureList[id].Size = Len;
for (uint8_t i = 0; i < Len; i++) {
FeatureBuffer[FeatureRecord] = Data[i];
FeatureRecord++;
}
}
void setup() {
Serial0_begin(500000);
delay(1000);
Serial0_println("st");
uint8_t strIndex;
strIndex = 5;
setFeature(HID_PD_IPRODUCT, &strIndex, sizeof(strIndex));
strIndex = 6;
setFeature(HID_PD_MANUFACTURER, &strIndex, sizeof(strIndex));
strIndex = 7;
setFeature(HID_PD_SERIAL, &strIndex, sizeof(strIndex));
strIndex = 8;
setFeature(HID_PD_IDEVICECHEMISTRY, &strIndex, sizeof(strIndex));
setFeature(HID_PD_PRESENTSTATUS, &iPresentStatus, sizeof(iPresentStatus));
setFeature(HID_PD_RUNTIMETOEMPTY, &iRunTimeToEmpty, sizeof(iRunTimeToEmpty));
setFeature(HID_PD_AVERAGETIME2FULL, &iAvgTimeToFull, sizeof(iAvgTimeToFull));
setFeature(HID_PD_AVERAGETIME2EMPTY, &iAvgTimeToEmpty, sizeof(iAvgTimeToEmpty));
setFeature(HID_PD_REMAINTIMELIMIT, &iRemainTimeLimit, sizeof(iRemainTimeLimit));
setFeature(HID_PD_DELAYBE4REBOOT, &iDelayBe4Reboot, sizeof(iDelayBe4Reboot));
setFeature(HID_PD_DELAYBE4SHUTDOWN, &iDelayBe4ShutDown, sizeof(iDelayBe4ShutDown));
setFeature(HID_PD_RECHARGEABLE, &bRechargable, sizeof(bRechargable));
setFeature(HID_PD_CAPACITYMODE, &bCapacityMode, sizeof(bCapacityMode));
setFeature(HID_PD_CONFIGVOLTAGE, &iConfigVoltage, sizeof(iConfigVoltage));
setFeature(HID_PD_VOLTAGE, &iVoltage, sizeof(iVoltage));
setFeature(HID_PD_IOEMINFORMATION, &bOEMVendor, sizeof(bOEMVendor));
setFeature(HID_PD_AUDIBLEALARMCTRL, &iAudibleAlarmCtrl, sizeof(iAudibleAlarmCtrl));
setFeature(HID_PD_DESIGNCAPACITY, &iDesignCapacity, sizeof(iDesignCapacity));
setFeature(HID_PD_FULLCHRGECAPACITY, &iFullChargeCapacity, sizeof(iFullChargeCapacity));
setFeature(HID_PD_REMAININGCAPACITY, &iRemaining, sizeof(iRemaining));
setFeature(HID_PD_WARNCAPACITYLIMIT, &iWarnCapacityLimit, sizeof(iWarnCapacityLimit));
setFeature(HID_PD_REMNCAPACITYLIMIT, &iRemnCapacityLimit, sizeof(iRemnCapacityLimit));
setFeature(HID_PD_CPCTYGRANULARITY1, &bCapacityGranularity1, sizeof(bCapacityGranularity1));
setFeature(HID_PD_CPCTYGRANULARITY2, &bCapacityGranularity2, sizeof(bCapacityGranularity2));
setFeature(HID_PD_CYCLECOUNT,&bCycles,sizeof(bCycles));
setFeature(HID_PD_CONFIGVOLTAGE, &iConfigVoltage, sizeof(iConfigVoltage));
iManufacturerDate = (2025 - 1980) * 512 + 1 * 32 + 1;
setFeature(HID_PD_MANUFACTUREDATE, &iManufacturerDate, sizeof(iManufacturerDate));
/*
for (uint8_t i=0;i<32;i++) {
FeatureList[i].Index=i;
FeatureList[i].Size=1;
FeatureBuffer[i]=i;
}
for (uint8_t i=0;i<32;i++) {
Serial0_print(i);
Serial0_print_c(' ');
Serial0_print(FeatureList[i].Index);
Serial0_print_c(' ');
Serial0_print(FeatureList[i].Size);
Serial0_println_c(' ');
}
for (uint8_t i=0;i<FeatureRecord;i++) {
Serial0_print(FeatureBuffer[i]); Serial0_print_c(' ');
}
*/
USBInit();
bitSet(iPresentStatus, PRESENTSTATUS_CHARGING);
bitSet(iPresentStatus, PRESENTSTATUS_ACPRESENT);
bitSet(iPresentStatus , PRESENTSTATUS_BATTPRESENT);
bitSet(iPresentStatus , PRESENTSTATUS_PRIMARYBATTERY);
recvStr[0] = HID_PD_PRESENTSTATUS;
recvStr[1] = iPresentStatus & 0xFF;
recvStr[2] = (iPresentStatus >> 8) & 0xFF;;
USB_EP3_send(recvStr, 3);
setFeature(HID_PD_PRESENTSTATUS, &iPresentStatus, sizeof(iPresentStatus));
/*
iRemaining = 40;
recvStr[0] = HID_PD_REMAININGCAPACITY;
recvStr[1] = iRemaining & 0xFF;
USB_EP3_send(recvStr, 2);
setFeature(HID_PD_REMAININGCAPACITY, &iRemaining, sizeof(iRemaining));
*/
}
void loop() {
while (USBSerial_available()) {
uint8_t serialChar = USBSerial_read();
recvStr[recvStrPtr++] = serialChar;
if (recvStrPtr == 4) {
/*
for (uint8_t i = 0; i < 9; i++) {
Serial0_write(recvStr[i]);
}
*/
if (recvStr[0] == HID_PD_PRESENTSTATUS) {
//USB_EP3_send(recvStr, 3);
iPresentStatus=recvStr[1]+(recvStr[2]<<8);
Serial0_print("ps:");
Serial0_println(iPresentStatus);
}
if (recvStr[0] == HID_PD_REMAININGCAPACITY) {
iRemaining=recvStr[1];
Serial0_print("rm:");
Serial0_println(iRemaining);
}
if (recvStr[0] == OnBoardLED) {
set_pixel_for_GRB_LED(ledData, 0, recvStr[1], recvStr[2], recvStr[3]);
neopixel_show_P1_5(ledData, NUM_BYTES);
}
recvStrPtr = 0;
}
Elsp = millis();
}
// If there is no data in 100ms, clear the receive buffer
if (millis() - Elsp > 100) {
recvStrPtr = 0;
Elsp = millis();
}
if((iPresentStatus != iPreviousStatus) || (iRemaining!=iPrevRemaining) || (millis()-iIntTimer>MINUPDATEINTERVAL) ) {
recvStr[0]=HID_PD_REMAININGCAPACITY;
recvStr[1]=iRemaining;
USB_EP3_send(recvStr, 2);
setFeature(HID_PD_REMAININGCAPACITY, &iRemaining, sizeof(iRemaining));
recvStr[0]=HID_PD_PRESENTSTATUS;
recvStr[1]=iPresentStatus&0xFF;
recvStr[2]=(iPresentStatus>>8)&0xFF;
USB_EP3_send(recvStr, 3);
setFeature(HID_PD_PRESENTSTATUS, &iPresentStatus, sizeof(iPresentStatus));
Serial0_println("a:");
iPreviousStatus=iPresentStatus;
iPrevRemaining=iRemaining;
iIntTimer=millis();
}
}
简单的说,开始之后,通过 HID Descriptor 报告当前设备属性,其中有很多 Feature项目。之后 Arduino 代码通过下面这种将描述符中的 Report ID 和 数值关联起来。后面,当Ch554收到 Feature Request 之后就根据前面的注册信息返回对应值。
setFeature(HID_PD_DESIGNCAPACITY, &iDesignCapacity, sizeof(iDesignCapacity));
除了USB HID 设备,Ch554还实现了一个 USB CDC 设备,在 loop 中我们接收来自USB 串口的数据,如果是以HID_PD_PRESENTSTATUS 开头的,或者HID_PD_REMAININGCAPACITY开头的,那么直接更改状态,然后从HID 对应的 EndPoint中发送出去,这样 Windows 接收到后会更新电池状态。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
string targetVid = "VID_1209";
string targetPid = "PID_C55C";
string portName = FindUsbDevicePort(targetVid, targetPid);
if (!string.IsNullOrEmpty(portName))
{
Console.WriteLine($"Found device on port: {portName}");
}
else
{
Console.WriteLine("Device not found.");
}
Console.ReadKey();
}
static string FindUsbDevicePort(string vid, string pid)
{
string query = "SELECT * FROM Win32_PnPEntity WHERE DeviceID LIKE '%" + vid + "&" + pid + "%'";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
{
foreach (ManagementObject device in searcher.Get())
{
string deviceId = device["DeviceID"]?.ToString();
if (deviceId != null && deviceId.Contains(vid) && deviceId.Contains(pid))
{
string caption = device["Caption"]?.ToString();
if (caption != null && caption.Contains("(COM"))
{
int startIndex = caption.IndexOf("(COM") + 1;
int endIndex = caption.IndexOf(")", startIndex);
return caption.Substring(startIndex, endIndex - startIndex);
}
}
}
}
return null;
}
}
}
完整的 Arduino 代码:
完整的 C#代码:
网站故障说明
2015年1月8日早晨,我和平时一样打开浏览器,准备登录网站查看留言,结果发现无法登录。开始想着是偶尔的维护,过一会又试验了一下发现仍然没有恢复。只好登录辰讯云(https://www.chenxunyun.com/)联系客服,随后得知了一个消息:服务器硬盘损坏,数据正在恢复中。大约到了中午,再次询问的时候,得到的消息是完全损坏,全部丢失。
不幸中的万幸是每个月我都会手工备份,上一次的备份时2024年12月中旬,于是等到再次上线只好重装系统和一干软件,重新搭建服务器所需内容。盘点下来网站内容丢失不多。
如果你在使用中遇到网站任何问题,欢迎在本文留言。
ASCII 一览表
工作需要经常查看 ASCII 数值,索性弄了一个列表和在线查询的功能:
这是在线查询的功能,使用 JavaScript 实现,有兴趣的朋友也可以直接保存到本地使用:
ASCII control characters (character code 0-31)
The first 32 characters in the ASCII-table are unprintable control codes and are used to control peripherals such as printers.
DEC | OCT | HEX | BIN | Symbol | HTML Number | HTML Name | Description |
---|---|---|---|---|---|---|---|
0 | 000 | 00 | 00000000 | NUL | � | Null character | |
1 | 001 | 01 | 00000001 | SOH |  | Start of Heading | |
2 | 002 | 02 | 00000010 | STX |  | Start of Text | |
3 | 003 | 03 | 00000011 | ETX |  | End of Text | |
4 | 004 | 04 | 00000100 | EOT |  | End of Transmission | |
5 | 005 | 05 | 00000101 | ENQ |  | Enquiry | |
6 | 006 | 06 | 00000110 | ACK |  | Acknowledge | |
7 | 007 | 07 | 00000111 | BEL |  | Bell, Alert | |
8 | 010 | 08 | 00001000 | BS |  | Backspace | |
9 | 011 | 09 | 00001001 | HT | 	 | Horizontal Tab | |
10 | 012 | 0A | 00001010 | LF | | Line Feed | |
11 | 013 | 0B | 00001011 | VT |  | Vertical Tabulation | |
12 | 014 | 0C | 00001100 | FF |  | Form Feed | |
13 | 015 | 0D | 00001101 | CR | | Carriage Return | |
14 | 016 | 0E | 00001110 | SO |  | Shift Out | |
15 | 017 | 0F | 00001111 | SI |  | Shift In | |
16 | 020 | 10 | 00010000 | DLE |  | Data Link Escape | |
17 | 021 | 11 | 00010001 | DC1 |  | Device Control One (XON) | |
18 | 022 | 12 | 00010010 | DC2 |  | Device Control Two | |
19 | 023 | 13 | 00010011 | DC3 |  | Device Control Three (XOFF) | |
20 | 024 | 14 | 00010100 | DC4 |  | Device Control Four | |
21 | 025 | 15 | 00010101 | NAK |  | Negative Acknowledge | |
22 | 026 | 16 | 00010110 | SYN |  | Synchronous Idle | |
23 | 027 | 17 | 00010111 | ETB |  | End of Transmission Block | |
24 | 030 | 18 | 00011000 | CAN |  | Cancel | |
25 | 031 | 19 | 00011001 | EM |  | End of medium | |
26 | 032 | 1A | 00011010 | SUB |  | Substitute | |
27 | 033 | 1B | 00011011 | ESC |  | Escape | |
28 | 034 | 1C | 00011100 | FS |  | File Separator | |
29 | 035 | 1D | 00011101 | GS |  | Group Separator | |
30 | 036 | 1E | 00011110 | RS |  | Record Separator | |
31 | 037 | 1F | 00011111 | US |  | Unit Separator |
ASCII printable characters (character code 32-127)
Codes 32-127 are common for all the different variations of the ASCII table, they are called printable characters, represent letters, digits, punctuation marks, and a few miscellaneous symbols. You will find almost every character on your keyboard. Character 127 represents the command DEL.
DEC | OCT | HEX | BIN | Symbol | HTML Number | HTML Name | Description |
---|---|---|---|---|---|---|---|
32 | 040 | 20 | 00100000 | SP |   | Space | |
33 | 041 | 21 | 00100001 | ! | ! | ! | Exclamation mark |
34 | 042 | 22 | 00100010 | “ | " | " | Double quotes (or speech marks) |
35 | 043 | 23 | 00100011 | # | # | # | Number sign |
36 | 044 | 24 | 00100100 | $ | $ | $ | Dollar |
37 | 045 | 25 | 00100101 | % | % | % | Per cent sign |
38 | 046 | 26 | 00100110 | & | & | & | Ampersand |
39 | 047 | 27 | 00100111 | ‘ | ' | ' | Single quote |
40 | 050 | 28 | 00101000 | ( | ( | &lparen; | Open parenthesis (or open bracket) |
41 | 051 | 29 | 00101001 | ) | ) | &rparen; | Close parenthesis (or close bracket) |
42 | 052 | 2A | 00101010 | * | * | * | Asterisk |
43 | 053 | 2B | 00101011 | + | + | + | Plus |
44 | 054 | 2C | 00101100 | , | , | , | Comma |
45 | 055 | 2D | 00101101 | – | - | Hyphen-minus | |
46 | 056 | 2E | 00101110 | . | . | . | Period, dot or full stop |
47 | 057 | 2F | 00101111 | / | / | / | Slash or divide |
48 | 060 | 30 | 00110000 | 0 | 0 | Zero | |
49 | 061 | 31 | 00110001 | 1 | 1 | One | |
50 | 062 | 32 | 00110010 | 2 | 2 | Two | |
51 | 063 | 33 | 00110011 | 3 | 3 | Three | |
52 | 064 | 34 | 00110100 | 4 | 4 | Four | |
53 | 065 | 35 | 00110101 | 5 | 5 | Five | |
54 | 066 | 36 | 00110110 | 6 | 6 | Six | |
55 | 067 | 37 | 00110111 | 7 | 7 | Seven | |
56 | 070 | 38 | 00111000 | 8 | 8 | Eight | |
57 | 071 | 39 | 00111001 | 9 | 9 | Nine | |
58 | 072 | 3A | 00111010 | : | : | : | Colon |
59 | 073 | 3B | 00111011 | ; | ; | ; | Semicolon |
60 | 074 | 3C | 00111100 | < | < | < | Less than (or open angled bracket) |
61 | 075 | 3D | 00111101 | = | = | = | Equals |
62 | 076 | 3E | 00111110 | > | > | > | Greater than (or close angled bracket) |
63 | 077 | 3F | 00111111 | ? | ? | ? | Question mark |
64 | 100 | 40 | 01000000 | @ | @ | @ | At sign |
65 | 101 | 41 | 01000001 | A | A | Uppercase A | |
66 | 102 | 42 | 01000010 | B | B | Uppercase B | |
67 | 103 | 43 | 01000011 | C | C | Uppercase C | |
68 | 104 | 44 | 01000100 | D | D | Uppercase D | |
69 | 105 | 45 | 01000101 | E | E | Uppercase E | |
70 | 106 | 46 | 01000110 | F | F | Uppercase F | |
71 | 107 | 47 | 01000111 | G | G | Uppercase G | |
72 | 110 | 48 | 01001000 | H | H | Uppercase H | |
73 | 111 | 49 | 01001001 | I | I | Uppercase I | |
74 | 112 | 4A | 01001010 | J | J | Uppercase J | |
75 | 113 | 4B | 01001011 | K | K | Uppercase K | |
76 | 114 | 4C | 01001100 | L | L | Uppercase L | |
77 | 115 | 4D | 01001101 | M | M | Uppercase M | |
78 | 116 | 4E | 01001110 | N | N | Uppercase N | |
79 | 117 | 4F | 01001111 | O | O | Uppercase O | |
80 | 120 | 50 | 01010000 | P | P | Uppercase P | |
81 | 121 | 51 | 01010001 | Q | Q | Uppercase Q | |
82 | 122 | 52 | 01010010 | R | R | Uppercase R | |
83 | 123 | 53 | 01010011 | S | S | Uppercase S | |
84 | 124 | 54 | 01010100 | T | T | Uppercase T | |
85 | 125 | 55 | 01010101 | U | U | Uppercase U | |
86 | 126 | 56 | 01010110 | V | V | Uppercase V | |
87 | 127 | 57 | 01010111 | W | W | Uppercase W | |
88 | 130 | 58 | 01011000 | X | X | Uppercase X | |
89 | 131 | 59 | 01011001 | Y | Y | Uppercase Y | |
90 | 132 | 5A | 01011010 | Z | Z | Uppercase Z | |
91 | 133 | 5B | 01011011 | [ | [ | [ | Opening bracket |
92 | 134 | 5C | 01011100 | \ | \ | \ | Backslash |
93 | 135 | 5D | 01011101 | ] | ] | ] | Closing bracket |
94 | 136 | 5E | 01011110 | ^ | ^ | ^ | Caret – circumflex |
95 | 137 | 5F | 01011111 | _ | _ | _ | Underscore |
96 | 140 | 60 | 01100000 | ` | ` | ` | Grave accent |
97 | 141 | 61 | 01100001 | a | a | Lowercase a | |
98 | 142 | 62 | 01100010 | b | b | Lowercase b | |
99 | 143 | 63 | 01100011 | c | c | Lowercase c | |
100 | 144 | 64 | 01100100 | d | d | Lowercase d | |
101 | 145 | 65 | 01100101 | e | e | Lowercase e | |
102 | 146 | 66 | 01100110 | f | f | Lowercase f | |
103 | 147 | 67 | 01100111 | g | g | Lowercase g | |
104 | 150 | 68 | 01101000 | h | h | Lowercase h | |
105 | 151 | 69 | 01101001 | i | i | Lowercase i | |
106 | 152 | 6A | 01101010 | j | j | Lowercase j | |
107 | 153 | 6B | 01101011 | k | k | Lowercase k | |
108 | 154 | 6C | 01101100 | l | l | Lowercase l | |
109 | 155 | 6D | 01101101 | m | m | Lowercase m | |
110 | 156 | 6E | 01101110 | n | n | Lowercase n | |
111 | 157 | 6F | 01101111 | o | o | Lowercase o | |
112 | 160 | 70 | 01110000 | p | p | Lowercase p | |
113 | 161 | 71 | 01110001 | q | q | Lowercase q | |
114 | 162 | 72 | 01110010 | r | r | Lowercase r | |
115 | 163 | 73 | 01110011 | s | s | Lowercase s | |
116 | 164 | 74 | 01110100 | t | t | Lowercase t | |
117 | 165 | 75 | 01110101 | u | u | Lowercase u | |
118 | 166 | 76 | 01110110 | v | v | Lowercase v | |
119 | 167 | 77 | 01110111 | w | w | Lowercase w | |
120 | 170 | 78 | 01111000 | x | x | Lowercase x | |
121 | 171 | 79 | 01111001 | y | y | Lowercase y | |
122 | 172 | 7A | 01111010 | z | z | Lowercase z | |
123 | 173 | 7B | 01111011 | { | { | { | Opening brace |
124 | 174 | 7C | 01111100 | | | | | | | Vertical bar |
125 | 175 | 7D | 01111101 | } | } | } | Closing brace |
126 | 176 | 7E | 01111110 | ~ | ~ | ˜ | Equivalency sign – tilde |
127 | 177 | 7F | 01111111 | DEL |  | Delete |
The extended ASCII codes (character code 128-255)
There are several different variations of the 8-bit ASCII table. The table below is according to Windows-1252 (CP-1252) which is a superset of ISO 8859-1, also called ISO Latin-1, in terms of printable characters, but differs from the IANA’s ISO-8859-1 by using displayable characters rather than control characters in the 128 to 159 range. Characters that differ from ISO-8859-1 is marked by light blue color.
DEC | OCT | HEX | BIN | Symbol | HTML Number | HTML Name | Description |
---|---|---|---|---|---|---|---|
128 | 200 | 80 | 10000000 | € | € | € | Euro sign |
129 | 201 | 81 | 10000001 | Unused | |||
130 | 202 | 82 | 10000010 | ‚ | ‚ | ‚ | Single low-9 quotation mark |
131 | 203 | 83 | 10000011 | ƒ | ƒ | ƒ | Latin small letter f with hook |
132 | 204 | 84 | 10000100 | „ | „ | „ | Double low-9 quotation mark |
133 | 205 | 85 | 10000101 | … | … | … | Horizontal ellipsis |
134 | 206 | 86 | 10000110 | † | † | † | Dagger |
135 | 207 | 87 | 10000111 | ‡ | ‡ | ‡ | Double dagger |
136 | 210 | 88 | 10001000 | ˆ | ˆ | ˆ | Modifier letter circumflex accent |
137 | 211 | 89 | 10001001 | ‰ | ‰ | ‰ | Per mille sign |
138 | 212 | 8A | 10001010 | Š | Š | Š | Latin capital letter S with caron |
139 | 213 | 8B | 10001011 | ‹ | ‹ | ‹ | Single left-pointing angle quotation |
140 | 214 | 8C | 10001100 | Œ | Œ | Œ | Latin capital ligature OE |
141 | 215 | 8D | 10001101 | Unused | |||
142 | 216 | 8E | 10001110 | Ž | Ž | Ž | Latin capital letter Z with caron |
143 | 217 | 8F | 10001111 | Unused | |||
144 | 220 | 90 | 10010000 | Unused | |||
145 | 221 | 91 | 10010001 | ‘ | ‘ | ‘ | Left single quotation mark |
146 | 222 | 92 | 10010010 | ’ | ’ | ’ | Right single quotation mark |
147 | 223 | 93 | 10010011 | “ | “ | “ | Left double quotation mark |
148 | 224 | 94 | 10010100 | ” | ” | ” | Right double quotation mark |
149 | 225 | 95 | 10010101 | • | • | • | Bullet |
150 | 226 | 96 | 10010110 | – | – | – | En dash |
151 | 227 | 97 | 10010111 | — | — | — | Em dash |
152 | 230 | 98 | 10011000 | ˜ | ˜ | ˜ | Small tilde |
153 | 231 | 99 | 10011001 | ™ | ™ | ™ | Trade mark sign |
154 | 232 | 9A | 10011010 | š | š | š | Latin small letter S with caron |
155 | 233 | 9B | 10011011 | › | › | › | Single right-pointing angle quotation mark |
156 | 234 | 9C | 10011100 | œ | œ | œ | Latin small ligature oe |
157 | 235 | 9D | 10011101 | Unused | |||
158 | 236 | 9E | 10011110 | ž | ž | ž | Latin small letter z with caron |
159 | 237 | 9F | 10011111 | Ÿ | Ÿ | Ÿ | Latin capital letter Y with diaeresis |
160 | 240 | A0 | 10100000 | NBSP |   | | Non-breaking space |
161 | 241 | A1 | 10100001 | ¡ | ¡ | ¡ | Inverted exclamation mark |
162 | 242 | A2 | 10100010 | ¢ | ¢ | ¢ | Cent sign |
163 | 243 | A3 | 10100011 | £ | £ | £ | Pound sign |
164 | 244 | A4 | 10100100 | ¤ | ¤ | ¤ | Currency sign |
165 | 245 | A5 | 10100101 | ¥ | ¥ | ¥ | Yen sign |
166 | 246 | A6 | 10100110 | ¦ | ¦ | ¦ | Pipe, broken vertical bar |
167 | 247 | A7 | 10100111 | § | § | § | Section sign |
168 | 250 | A8 | 10101000 | ¨ | ¨ | ¨ | Spacing diaeresis – umlaut |
169 | 251 | A9 | 10101001 | © | © | © | Copyright sign |
170 | 252 | AA | 10101010 | ª | ª | ª | Feminine ordinal indicator |
171 | 253 | AB | 10101011 | « | « | « | Left double angle quotes |
172 | 254 | AC | 10101100 | ¬ | ¬ | ¬ | Negation |
173 | 255 | AD | 10101101 | SHY | ­ | ­ | Soft hyphen |
174 | 256 | AE | 10101110 | ® | ® | ® | Registered trade mark sign |
175 | 257 | AF | 10101111 | ¯ | ¯ | ¯ | Spacing macron – overline |
176 | 260 | B0 | 10110000 | ° | ° | ° | Degree sign |
177 | 261 | B1 | 10110001 | ± | ± | ± | Plus-or-minus sign |
178 | 262 | B2 | 10110010 | ² | ² | ² | Superscript two – squared |
179 | 263 | B3 | 10110011 | ³ | ³ | ³ | Superscript three – cubed |
180 | 264 | B4 | 10110100 | ´ | ´ | ´ | Acute accent – spacing acute |
181 | 265 | B5 | 10110101 | µ | µ | µ | Micro sign |
182 | 266 | B6 | 10110110 | ¶ | ¶ | ¶ | Pilcrow sign – paragraph sign |
183 | 267 | B7 | 10110111 | · | · | · | Middle dot – Georgian comma |
184 | 270 | B8 | 10111000 | ¸ | ¸ | ¸ | Spacing cedilla |
185 | 271 | B9 | 10111001 | ¹ | ¹ | ¹ | Superscript one |
186 | 272 | BA | 10111010 | º | º | º | Masculine ordinal indicator |
187 | 273 | BB | 10111011 | » | » | » | Right double angle quotes |
188 | 274 | BC | 10111100 | ¼ | ¼ | ¼ | Fraction one quarter |
189 | 275 | BD | 10111101 | ½ | ½ | ½ | Fraction one half |
190 | 276 | BE | 10111110 | ¾ | ¾ | ¾ | Fraction three quarters |
191 | 277 | BF | 10111111 | ¿ | ¿ | ¿ | Inverted question mark |
192 | 300 | C0 | 11000000 | À | À | À | Latin capital letter A with grave |
193 | 301 | C1 | 11000001 | Á | Á | Á | Latin capital letter A with acute |
194 | 302 | C2 | 11000010 | Â | Â | Â | Latin capital letter A with circumflex |
195 | 303 | C3 | 11000011 | Ã | Ã | Ã | Latin capital letter A with tilde |
196 | 304 | C4 | 11000100 | Ä | Ä | Ä | Latin capital letter A with diaeresis |
197 | 305 | C5 | 11000101 | Å | Å | Å | Latin capital letter A with ring above |
198 | 306 | C6 | 11000110 | Æ | Æ | Æ | Latin capital letter AE |
199 | 307 | C7 | 11000111 | Ç | Ç | Ç | Latin capital letter C with cedilla |
200 | 310 | C8 | 11001000 | È | È | È | Latin capital letter E with grave |
201 | 311 | C9 | 11001001 | É | É | É | Latin capital letter E with acute |
202 | 312 | CA | 11001010 | Ê | Ê | Ê | Latin capital letter E with circumflex |
203 | 313 | CB | 11001011 | Ë | Ë | Ë | Latin capital letter E with diaeresis |
204 | 314 | CC | 11001100 | Ì | Ì | Ì | Latin capital letter I with grave |
205 | 315 | CD | 11001101 | Í | Í | Í | Latin capital letter I with acute |
206 | 316 | CE | 11001110 | Î | Î | Î | Latin capital letter I with circumflex |
207 | 317 | CF | 11001111 | Ï | Ï | Ï | Latin capital letter I with diaeresis |
208 | 320 | D0 | 11010000 | Ð | Ð | Ð | Latin capital letter ETH |
209 | 321 | D1 | 11010001 | Ñ | Ñ | Ñ | Latin capital letter N with tilde |
210 | 322 | D2 | 11010010 | Ò | Ò | Ò | Latin capital letter O with grave |
211 | 323 | D3 | 11010011 | Ó | Ó | Ó | Latin capital letter O with acute |
212 | 324 | D4 | 11010100 | Ô | Ô | Ô | Latin capital letter O with circumflex |
213 | 325 | D5 | 11010101 | Õ | Õ | Õ | Latin capital letter O with tilde |
214 | 326 | D6 | 11010110 | Ö | Ö | Ö | Latin capital letter O with diaeresis |
215 | 327 | D7 | 11010111 | × | × | × | Multiplication sign |
216 | 330 | D8 | 11011000 | Ø | Ø | Ø | Latin capital letter O with slash |
217 | 331 | D9 | 11011001 | Ù | Ù | Ù | Latin capital letter U with grave |
218 | 332 | DA | 11011010 | Ú | Ú | Ú | Latin capital letter U with acute |
219 | 333 | DB | 11011011 | Û | Û | Û | Latin capital letter U with circumflex |
220 | 334 | DC | 11011100 | Ü | Ü | Ü | Latin capital letter U with diaeresis |
221 | 335 | DD | 11011101 | Ý | Ý | Ý | Latin capital letter Y with acute |
222 | 336 | DE | 11011110 | Þ | Þ | Þ | Latin capital letter THORN |
223 | 337 | DF | 11011111 | ß | ß | ß | Latin small letter sharp s – ess-zed |
224 | 340 | E0 | 11100000 | à | à | à | Latin small letter a with grave |
225 | 341 | E1 | 11100001 | á | á | á | Latin small letter a with acute |
226 | 342 | E2 | 11100010 | â | â | â | Latin small letter a with circumflex |
227 | 343 | E3 | 11100011 | ã | ã | ã | Latin small letter a with tilde |
228 | 344 | E4 | 11100100 | ä | ä | ä | Latin small letter a with diaeresis |
229 | 345 | E5 | 11100101 | å | å | å | Latin small letter a with ring above |
230 | 346 | E6 | 11100110 | æ | æ | æ | Latin small letter ae |
231 | 347 | E7 | 11100111 | ç | ç | ç | Latin small letter c with cedilla |
232 | 350 | E8 | 11101000 | è | è | è | Latin small letter e with grave |
233 | 351 | E9 | 11101001 | é | é | é | Latin small letter e with acute |
234 | 352 | EA | 11101010 | ê | ê | ê | Latin small letter e with circumflex |
235 | 353 | EB | 11101011 | ë | ë | ë | Latin small letter e with diaeresis |
236 | 354 | EC | 11101100 | ì | ì | ì | Latin small letter i with grave |
237 | 355 | ED | 11101101 | í | í | í | Latin small letter i with acute |
238 | 356 | EE | 11101110 | î | î | î | Latin small letter i with circumflex |
239 | 357 | EF | 11101111 | ï | ï | ï | Latin small letter i with diaeresis |
240 | 360 | F0 | 11110000 | ð | ð | ð | Latin small letter eth |
241 | 361 | F1 | 11110001 | ñ | ñ | ñ | Latin small letter n with tilde |
242 | 362 | F2 | 11110010 | ò | ò | ò | Latin small letter o with grave |
243 | 363 | F3 | 11110011 | ó | ó | ó | Latin small letter o with acute |
244 | 364 | F4 | 11110100 | ô | ô | ô | Latin small letter o with circumflex |
245 | 365 | F5 | 11110101 | õ | õ | õ | Latin small letter o with tilde |
246 | 366 | F6 | 11110110 | ö | ö | ö | Latin small letter o with diaeresis |
247 | 367 | F7 | 11110111 | ÷ | ÷ | ÷ | Division sign |
248 | 370 | F8 | 11111000 | ø | ø | ø | Latin small letter o with slash |
249 | 371 | F9 | 11111001 | ù | ù | ù | Latin small letter u with grave |
250 | 372 | FA | 11111010 | ú | ú | ú | Latin small letter u with acute |
251 | 373 | FB | 11111011 | û | û | û | Latin small letter u with circumflex |
252 | 374 | FC | 11111100 | ü | ü | ü | Latin small letter u with diaeresis |
253 | 375 | FD | 11111101 | ý | ý | ý | Latin small letter y with acute |
254 | 376 | FE | 11111110 | þ | þ | þ | Latin small letter thorn |
255 | 377 | FF | 11111111 | ÿ | ÿ | ÿ | Latin small letter y with diaeresis |
上述来自: https://www.ascii-code.com/
一个简单的计数批处理文件
@echo off
setlocal enabledelayedexpansion
:: 定义计数文件
set counter_file=counter.txt
:: 检查计数文件是否存在
if not exist %counter_file% (
echo 0 > %counter_file%
)
:: 从文件中读取当前计数值
set /p counter=<%counter_file%
:: 显示当前计数值
echo Current counter value: %counter%
:: 将计数值加1
set /a counter+=1
:: 将新的计数值写入文件
echo %counter% > %counter_file%
:: 显示新的计数值
echo New counter value: %counter%
::为了看的清楚,这里加入一个 Pause
pause
endlocal
MAX98357 I2S功放模块测试
之前购买了一个MAX98357 I2S功放模块,这次编写简单的代码进行测试。
硬件连接如下:
MAX98357 | ESP32S3 | 用途 |
SPK+/- 连接喇叭 | 连接喇叭正负极,喇叭输出 | |
DIN | 48 | 从 ESP32S3 发送的 I2S数据 |
BCLK | 45 | 从 ESP32S3 发送的 I2S Clock |
LRC | 35 | 从 ESP32S3 发送的 I2S 左右声道选择信号 |
GND | GND | 地 |
VCC | 5V | 供电 |
按照上述方案连接好后,烧录如下代码:
#include <I2S.h>
const int frequency = 440; // frequency of square wave in Hz
const int amplitude = 32000; // amplitude of square wave
const int sampleRate = 8000; // sample rate in Hz
const int bps = 16;
const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave
short sample = amplitude; // current sample value
int count = 0;
i2s_mode_t mode = I2S_PHILIPS_MODE; // I2S decoder is needed
// i2s_mode_t mode = ADC_DAC_MODE; // Audio amplifier is needed
// Mono channel input
// This is ESP specific implementation -
// samples will be automatically copied to both channels inside I2S driver
// If you want to have true mono output use I2S_PHILIPS_MODE and interlay
// second channel with 0-value samples.
// The order of channels is RIGH followed by LEFT
//i2s_mode_t mode = I2S_RIGHT_JUSTIFIED_MODE; // I2S decoder is needed
void setup() {
Serial.begin(115200);
Serial.println("I2S simple tone");
delay(5000);
//setAllPins(int sckPin, int fsPin, int sdPin, int outSdPin, int inSdPin);
I2S.setAllPins(45 , 35 , 48 , 48 , -1);
// start I2S at the sample rate with 16-bits per sample
if (!I2S.begin(mode, sampleRate, bps)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
}
void loop() {
while (Serial.available()) {
char c = Serial.read();
if (c == '3') {
ESP.restart();
}
// 主机端发送 l, 回复 z 用于识别串口
if (c == '1') {
Serial.print('z');
}
// 主机端发送 l, 回复 z 用于识别串口
if (c == '2') {
Serial.printf("getSckPin:%d getFsPin:%d getDataPin:%d",
I2S.getSckPin(),
I2S.getFsPin(),
I2S.getDataPin());
}
}
if (count % halfWavelength == 0 ) {
// invert the sample every half wavelength count multiple to generate square wave
sample = -1 * sample;
}
if(mode == I2S_PHILIPS_MODE || mode == ADC_DAC_MODE){ // write the same sample twice, once for Right and once for Left channel
I2S.write(sample); // Right channel
I2S.write(sample); // Left channel
}else if(mode == I2S_RIGHT_JUSTIFIED_MODE || mode == I2S_LEFT_JUSTIFIED_MODE){
// write the same only once - it will be automatically copied to the other channel
I2S.write(sample);
}
// increment the counter for the next sample
count++;
}
测试的视频在下面可以看到:
WinPE下面制造一个蓝屏
正常的 Windows下面蓝屏很常见,实际上 WinPE 下面也是可以出现蓝屏的。这次介绍通过修改 WinPE 的注册表,实现USB键盘上按下右 Ctrl+快速按下Scroll键即可触发蓝屏 【参考1】。
最关键的步骤是修改 WinPE的注册表,打开这个触发蓝屏的功能。
1.将 Windows安装盘中的 Boot 解压,放在 c:\labz 目录下,然后运行如下命令解包之:
dism /mount-wim /wimfile:c:\labz\boot.wim /index:1 /mountdir:c:\m1
2.打开本机的注册表工具,先选中 HKEY_USERS,然后在菜单上选择 Load Hive
3.在对话框上选择 c:\m1\windows\system32\config\system 文件
4.设置一个加载点
这样操作之后可以看到挂载到如下位置了
5.我们在LABZ\ControlSet001\Services\kbhid\Parameters 下面创建 CrashOnCtrlScroll 并且赋值为1
6.选中注册表上的 “LABZ”,然后菜单选择 Unload Hive,这样就从注册表中卸载了WinPE的注册表
7.之后 关闭注册表编辑器,然后使用如下命令写入 WIM(特别注意,实践中发现有时候无法正常写入,错误信息是 Windows有占用目录下的文件,这种情况下重启操作系统再运行一次即可)
dism /unmount-wim /MountDir:c:\m1 /Commit
8.接下来再次解包 Boot.WIM (原因和之前” 制作全自动安装的 Windows 11 ISO”文章提到的一样,BOOT.WIM 中有2个WindowPE环境)
dism /mount-wim /wimfile:c:\labz\boot.wim /index:2 /mountdir:c:\m1
之后同样执行2-7步骤,最终我们就得到了一个修改后的 BOOT.WIM
使用,ISO 编辑工具将BOOT.WIM 写入 ISO 之后,我们就得到了一个测试 Windows安装镜像文件。在安装过程中使用 USB 键盘,按下右侧Ctrl然后快速按下2测 Scoll 键就能够触发蓝屏了。
可以看到蓝屏发生后,显示一段之后会自动重启。
最后讲个有意思的事情。很多年前,我碰到过一个奇怪的问题:工厂那边反映我们 Release 的BIOS有问题,会导致生产过程中重启。负责这个事情的BIOS工程师是一个妹子,被这个问题折磨很久。问题发生之后,她不修改任何代码,只是重新编译一次BIOS,发给产线使用问题就会消失。但是后面不知道什么时候问题又会出来。出于好奇后来我接手这个问题进行研究。所有的整机无论是笔记本还是台式机,在生产的过程中都会有灌装系统运行产测软件的步骤。在这个过程中,会检查一些基本的功能,比如:是否会有声音,屏幕键盘鼠标能否工作正常等等。这个测试通常需要一气呵成完成的,每个测试都会收集测试结果,然后上报到服务器中的,因此如果发生意外重启会打断整个流程。测试结束后,会重新安装一个新的操作系统然后再交给客户。作为BIOS工程师,我是不太相信BIOS会导致这样的问题。因此,我和工厂要了一下他们的产测软件在实验室进行研究。产线使用 WinPE环境,我手上没有,只能在普通 Windows上试验。试验几次之后,我发现其中的测试软件会出现Windows的报错对话框。于是,将关注点放在了这个软件上。咨询产线得知这个软件的作用是在0xF0000 中搜索一个字符串。听到这里我心里就有了大概,Windows下访问物理内存,出现错误是很重要的。之后和产线要到的源代码,简单读了了一下很快就定位了问题。这个软件需要在物理内存中搜索,于是作者调用了一个 Window API 做了一下映射,将 0xF0000开始的64K物理内存映射到应用程序的内存上,然后用 memcmp 进行查找。发生问题的原因是,要查找的字符串刚好卡在结尾处,比如我们需要在内存中查找“LAB-Z.COM”这个字符串,但是刚好碰到这个字符串在内存中分布如下:
0xFFFFA | 0xFFFFB | 0xFFFFC | 0xFFFFD | 0xFFFFE | 0xFFFFF | 0x10 0000 | 0x10 0001 | 0x10 0002 | 0x10 0003 |
L | A | B | – | Z | . | C | O | M | 0 |
当直接使用 memcpy 查找的时候,它会先找到 “LAB-Z”,但是继续比较字符串剩余部分的时候就碰到“指针出界”的问题。如果在正常的Windows下是可以抛出这个问题继续运行的,但是在WinPE环境下就直接变为重启。最终,经过努力这次的问题没有让BIOS工程师来背锅。
另外多说一句:即便相同的产线,相同的物料,白班和夜班的质量也会有差别。原因是白天人全,技术和后端都在,出了问题会有人处理;夜班的话,人不全,出了问题通常的处理方法是“小车不倒只管推”了。
参考:
1. https://www.lab-z.com/wdbg/ WinDBG 分析键盘生成的 Dump 文件