2024年2月更新,Step to UEFI 文章索引:
给 EXE 加入 Resource
最近忽然想起来一个问题:如何给一个做好的 EXE 加入其他的内容?比如,我编写一个 EXE 需要更改内容而又不想重新 Build 代码。
经过研究,可以通过给EXE 添加 Resource 的方法来实现这一目标。在 https://github.com/tc-hib/go-winres 这里有一个从命令行给 EXE 添加Resource 的项目。配合这个项目可以实现前述目标。
首先,编写一个测试代码,使用 VC 编写在 VS2019 下编译通过:
#include <windows.h>
#include <iostream>
// 回调函数用于枚举资源
BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam) {
// 每找到一个资源,就增加计数
(*(int*)lParam)++;
return TRUE; // 继续枚举
}
int main()
{
HMODULE hModule = GetModuleHandle(NULL); // 获取当前模块句柄
int resourceCount = 0; // 用于计数的变量
// 枚举所有RT_RCDATA类型的资源
EnumResourceNames(hModule, RT_RCDATA, EnumResNameProc, (LONG_PTR)&resourceCount);
std::cout << "Number of RT_RCDATA resources: " << resourceCount << std::endl;
return 0;
}
代码非常简单,单纯的输出当前EXE RT_RCDATA类型的 Resource 数量。
接下来将go-winres.exe放在同一个目录下,然后运行下面的命令
go-winres.exe init
对应的会生成 winres 目录,其中有下面三个文件
前面2个是可以作为EXE 的图标的,winres.json是配置文件。例如,我们对这个目录放置一个 png 文件,然后修改如下,增加 RT_RCDATA的部分:
"RT_GROUP_ICON": {
"APP": {
"0000": [
"icon.png",
"icon16.png"
]
}
},
"RT_RCDATA": {
"OTHER": {
"0000": "2.png"
}
},
"RT_MANIFEST": {
"#1": {
"0409": {
"identity": {
"name": "",
"version": ""
运行如下命令:
go-winres.exe patch ResourceTest.exe
工具会自动给 ResourceTest.exe 添加内容,之后再次运行:
如果使用 CFF 工具还可以看到多了一个 Resource。这样,你可以在代码中先判断Resource数量,然后再进行动作。
官方提供的版本(和 Github上的相同,0.3.3版本)
VC 编写的WAVE测试文件生成器
最近为了调试,写了一个 WAVE 的生成器,能够生成指定采样率,指定格式的 WAVE文件,这样可以在输出端直接查看输出是否是指定的数据。特别注意的是,WAVE 中,使用 int16 (有符号十六进制)来表示当前的信号,更具体来说,负数使用补码来表示。代码如下:
// WaveGenerator.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#pragma pack(push, 1)
struct Chunk1 { // 'R', 'I', 'F', 'F'
char chunk_id[4];
uint32_t chunk_size;
char format[4]; // 'W', 'A', 'V', 'E'
};
struct Chunk2 {
char chunk_id[4];
uint32_t chunk_size;
int16_t wFormatTag;
int16_t nChannels;
int32_t nSamplesPerSec;
int32_t nAvgBytesPerSec;
int16_t nBlockAlign; // => num_channels * bits_per_sample / 8
int16_t wBitsPerSample;
};
struct Chunk3 {
char chunk_id[4];
uint32_t chunk_size;
};
#pragma pack(pop) // 恢复到之前的对齐设置
#define AUDIODURATION 5 // 音频时长,以秒为单位
#define SAMPLEBITS 16 // 采样位
#define SAMPLERATE 96000 // 采样率
#define CHANNELNUM 2 // Channel 数量
int main()
{
Chunk1 chunk1;
chunk1.chunk_id[0] = 'R'; chunk1.chunk_id[1] = 'I'; chunk1.chunk_id[2] = 'F'; chunk1.chunk_id[3] = 'F';
// 数据长度= Chunk123 总长 + RAW 数据长度(双声道,SAMPLEBITS Bits)
chunk1.chunk_size = sizeof(Chunk1)-8 + sizeof(Chunk2) + sizeof(Chunk3)+ AUDIODURATION* CHANNELNUM *(SAMPLEBITS/8)* SAMPLERATE;
chunk1.format[0] = 'W'; chunk1.format[1] = 'A'; chunk1.format[2] = 'V'; chunk1.format[3] = 'E';
Chunk2 chunk2;
chunk2.chunk_id[0] = 'f'; chunk2.chunk_id[1] = 'm'; chunk2.chunk_id[2] = 't'; chunk2.chunk_id[3] = ' ';
chunk2.chunk_size = sizeof(Chunk2)-8;
chunk2.wFormatTag = 0x0001; //PCM 格式
chunk2.nChannels = CHANNELNUM;
chunk2.nSamplesPerSec = SAMPLERATE;
chunk2.nAvgBytesPerSec = CHANNELNUM * SAMPLERATE * (SAMPLEBITS / 8);
chunk2.nBlockAlign = CHANNELNUM * (SAMPLEBITS / 8);
chunk2.wBitsPerSample = SAMPLEBITS;
Chunk3 chunk3;
chunk3.chunk_id[0] = 'd'; chunk3.chunk_id[1] = 'a'; chunk3.chunk_id[2] = 't'; chunk3.chunk_id[3] = 'a';
chunk3.chunk_size = AUDIODURATION * CHANNELNUM * SAMPLERATE * (SAMPLEBITS / 8);
// 打开文件用于写入,以二进制模式
FILE* file = fopen("C:\\WaveGenerator\\Debug\\example.wav", "wb");
fwrite(&chunk1, sizeof(chunk1), 1, file);
fwrite(&chunk2, sizeof(chunk2), 1, file);
fwrite(&chunk3, sizeof(chunk3), 1, file);
short int s=0,e=0;
for (int i = 0; i < AUDIODURATION* SAMPLERATE; i++) {
//s = sin(i * 2 * 3.1415 / (SAMPLERATE/1000)) * (65535 / 2);
// 左声道
s++;
fwrite(&s, sizeof(s), 1, file);
// 右声道
e = 0;
fwrite(&e, sizeof(e), 1, file);
}
fclose(file);
//getchar();
}
对于 FPF/FIT/BootGuard 的介绍
小米2代体脂秤维修
最近给一个朋友维修了一下小米2代体脂秤。他遇到的问题是:插入电池后电池发热。拿到手后,看到了现象:装入电池后,电池组和线都会发烫。
使用万用表进行测量,直接测量电池盒两端电阻为 170欧姆,装入电池后测量发现输出电流达到3A左右,这就是发热原因。
根据部分资料【参考1】,上图中红色框芯片为CST34M96,用于蓝牙通讯;绿色框中芯片为CS1256,这是用于获得体脂数据并且处理的单片机;紫色方框中是稳压(降压)芯片,型号未知丝印D3E1,照片是拆除这个芯片后拍摄。
不上电测量正常,上电后有问题猜测是电源芯片出了问题。于是拆除了稳压芯片。这部分电路如下:
VDD 是电池盒输入;经过芯片降压输出为 AVCC,最终提供给后端使用。万用表测试表明AGND 和 GND 是连通的。
拆除芯片后,从 AVCC 送入 3.3V,数码管会有动作,证明后面的芯片都是能够正常工作的,所以选择一个稳压芯片替换。
最终,替换稳压/降压芯片后,外加更换C4电容(测量发现C4短路了,可能被击穿了?)后,可以正常工作。
参考:
1. https://www.mydigit.cn/forum.php?mod=viewthread&tid=286533&page=1
SlimBootLoader 在 LattePanda Mu 上启动 Ubuntu
这次带来是全网唯一的开源 X86 BIOS 方案,通过它能够在 Latte Panda Mu上引导启动 Ubuntu。
为了在Latte Panda Mu使用SlimBootLoader,还需要额外准备如下硬件:
- 烧写IFWI的硬件工具,比如:SF100烧录器;
- 查看串口Log 的工具,比如:CH343 串口转 USB工具,用于配置安装Ubuntu;SBL 的Shell 没有提供字符或者图形界面,所有的数据都是通过串口进行交互的,所以需要准备串口工具;
- 准备2个U盘,一个用于制作 Ubuntu安装盘,我这边使用64GB 的金邦U盘,使用DiskGuinus格式化为 FAT32(注意不要使用 exFat)。将 Ubuntu 解压后全部放入 U盘根目录即可;另外U盘一个用于制作引导脚本。
第一步,生成能够启动的 Latte Panda Mu 的 IFWI。根据【参考1】,配置编译环境,首先确保能够编译通过 QEMU。
a.编译 BIOS 代码:
Python BuildLoader.py build adln
b.生成IFWI,这里没有使用 mFIT 而是直接使用代码替换原代码中的 BIOS Region。
python Platform/AlderlakeBoardPkg/Script/StitchLoader.py -i LattePanda.bin -s Outputs/adln/SlimBootloader.bin -o LattePanda_ifwi.bin -p 0xAA000007
上述的命令中,LattePanda.bin 是DFRobot 提供的原始的IFWI,其中的BIOS是AMI CodeBase;SlimBootloader.bin 是前面从 SBL Build出来的BIOS;最后的LattePanda_ifwi.bin就是生成的新的 IFWI。
d.关机状态下,将USB 转串口工具连接到LattePanda Mu 的PCH UART0 上
c.使用 SF100或者其他烧录器将LattePanda_ifwi.bin烧录到 LattePanda Mu上
d.启动LattePanda Mu后,会很快完成启动显示SBL Logo。 这时候 SBL 并不会从屏幕和键盘进行交互,而是通过串口。在另外一台电脑上打开串口工具即可看到一个文本的Shell界面,输入 boot 命令,然后调整从USB 设备启动例如:
至此,Firmware 方面的准备已经完成。
第二步,安装 Ubuntu 以及设定【参考2】。
- 其中需要一些时间,请耐心等待,之后进入下面这个界面。左边是直接在U盘提供的Live Linux 中工作,右边是进行安装,这里需要选择左侧按钮“Try Ubuntu”
从左上角的 Activities 打开一个 Terminal
e.使用 lsblk列出当前的设备,LattePanda Mu 内置了 eMMC,这里是mmcblk0设备
c.使用 sudo disk /dev/mmcblk0擦除硬盘,命令如下:
sudo gdisk /dev/mmcblk0
x
z
y
y
d. 创建GPT分区
sudo gdisk /dev/mmcblk0
o
y
w
y
e.接下来即可进行Ubuntu安装了
f.分区需要特别处理,划分出一个500MB 的FAT32分区用于引导
g.剩余容量减去4GB 左右,设定为 Ext4 分区
h.最后创建一个 4GB 的分区作为 SWAP 分区
i.接下来都选择 Continue
j.安装结束后,选择 Continue Testing
k.接下来使用 lsblk
l.输入如下命令:
Mkdir root
Sudo mount /dev/mmcblk0 root/
m.插入另外的U盘其中放入三个脚本以及内容如下的 cmdline.txt
echo "root=/dev/ mmcblk0 ro quiet splash" > cmdline.txt
n.运行如下批处理(其中的PEM文件来自编译SBL的代码中 )。
python3 GenContainer.py create -cl CMDL:cmdline.txt KRNL:./root/boot/vmlinuz-<kernel-version> INRD:./root/boot/initrd.img-<kernel-version> -k ./SblKeys/OS1_TestKey_Priv_RSA3072.pem -a RSA3072_PKCS1_SHA2_384 -t CLASSIC -o sbl_os
sudo cp sbl_os ./root/boot
sudo umount ./root
这里提供一个下载方便直接测试:
o.最终,拔掉U盘,即可启动
上述操作的完整视频:
这里只是简单的第一步,自行编译BIOS并且启动了X86的 Ubuntu,很多功能还没有调试,可能在使用中遇到问题(比如, X4 PCIE 支持, Audio 的支持)。如果你对性能和体积有一些要求,或者是对于BIOS定制有一些特别要求,不妨考虑 DFRobot推出的 LattePanda MU,它由一块核心板以及底板构成,厂家提供了电路图以及对应接口,可以很方便的实现定制。
本文提到的代码可以在 https://gitee.com/willok/slimbootloader 下载到,由天杀提供。
参考:
Timed GPIO
Timed GPIO 或者称作 Timed I/O 是基于系统时钟产生或者接收信号的功能。从 EHL/TGL(11代)平台开始,Intel 引入了这个功能。
这个功能的背景是:一些时候我们需要产生精确的 GPIO 时序,但是因为系统CPU分配的原因,这一点难以实现。比如,我们在代码中每隔0.001s需要反转一次GPIO,如果使用代码来驱动的话,无法保证CPU每隔0.001s执行一次,这样会导致实际生成的信号会有“抖动”(Jitter)。因此,引入了 Time-Aware GPIO(TGPIO)。直接从硬件上保证能够在指定的时间产生信号。除了能够输出信号(GPO),还能够作为 GPI,这样可以精确的测量两个信号的间隔。
有兴趣的朋友可以更深入的进行研究。
参考:
1.https://edc.intel.com/content/www/us/en/design/ipla/software-development-platforms/servers/platforms/intel-pentium-silver-and-intel-celeron-processors-datasheet-volume-1-of-2/005/timed-gpio-time-sync/
2.https://edc.intel.com/content/www/us/en/design/products/platforms/processor-and-core-i3-n-series-datasheet-volume-1-of-2/001/timed-gpio/
3.https://edc.intel.com/content/www/us/en/design/ipla/software-development-platforms/servers/platforms/intel-pentium-silver-and-intel-celeron-processors-datasheet-volume-1-of-2/005/timed-gpio-time-sync/
WIM安装解决方案
很多年前,Ghost 是通用的安装方案,但是随着时代的进步,Ghost 方案逐渐被淘汰。取而代之的是WIM 的方案,最新的 OS 和 Driver 都使用 WIM 的方式进行分发。需要注意的是:市面上很多能够实现 WIM 安装的 Windows PE 盘会在安装过程中对安装后的Windows 插入应用程序或者驱动程序。这样的结果可能导致影响你的测试结果。因此,这次制作了Windows PE 盘以及一个WIM 安装工具。这一套具有如下优点:
- 安装过程中不会添加任何额外软件;
- 方便使用,启动WindowPE 之后只需要键盘即可选择 WIM 文件进行安装;
- 体积较小,包括 WindowsPE 镜像,整体不超过350MB。
接下来介绍如何部署和使用这一套软件。
首先,使用 Ventoy 制作一个 USB 启动盘。需要注意的是:这个U盘上的内容会被完全清除掉。
安装完成 Ventoy 之后,需要手工将Winpe062907.iso和AutoWim目录拷贝到U盘Ventoy 的 exFAT分区上。同时,将需要安装的 WIM 同样放置于根目录下。
之后,使用这个U盘进行启动。
启动Ventoy后从菜单上选择从 Winpe062907.iso 启动。
启动之后,这个 WinPE 会自动执行 AutoWim 目录中的InWim.bat批处理。自动列出U盘根目录下的所有 WIM 请用户选择,选择之后会对硬盘进行自动分区,然后部署 WIM 内容。最后会执行 bcdboot 修复ESP 分区。
相信这个工具会成为你测试的得力助手,有兴趣的朋友不妨试试看。
ISO 镜像下载
AutoWim 目录下载
工作的视频可以在下面看到:
Intel Microcode PDB 格式转INC工具
Arduino 开发的 CH32V307 IIS 音频输出测试
这次介绍的是如何在 CH32V307上通过 Arduino 编程,从 IIS 接口输出一个正弦波然后通过 NS4168 播放出来。关于 NS4168的介绍,可以在【参考1】看到。
线路方面:
B12(I2S2_WS)连接到 LRCLK
B13(I2S2_CK) 连接到 BCKL
B15(I2S2_SD)连接到 SDAT
同时特别提醒 NS4168 的CTRL 需要连接 3.3V
之后,给 Ch32v307烧录如下代码:
//#include "ch32v30x_spi.h"
/* Global Variable */
#define Len 48*16*2
u16 I2S2_Tx[Len] = {
16383,16383,20660,20660,24864,24864,28922,28922,32767,32767,-29206,-29206,-25983,-25983,-23157,-23157,-20776,-20776,-18880,-18880,-17502,-17502,-16666,-16666,-16385,-16385,-16665,-16665,-17501,-17501,-18879,-18879,-20774,-20774,-23155,-23155,-25981,-25981,-29203,-29203,-32767,-32767,28925,28925,24867,24867,20663,20663,16386,16386,12109,12109,7906,7906,3847,3847,3,3,-3560,-3560,-6783,-6783,-9610,-9610,-11991,-11991,
-13887,-13887,-15266,-15266,-16102,-16102,-16383,-16383,-16104,-16104,-15268,-15268,-13891,-13891,-11996,-11996,-9615,-9615,-6790,-6790,-3568,-3568,-4,-4,3838,3838,7897,7897,12100,12100,16377,16377,20654,20654,24858,24858,28917,28917,32761,32761,-29210,-29210,-25987,-25987,-23161,-23161,-20779,-20779,-18882,-18882,-17504,-17504,-16667,-16667,-16385,-16385,-16665,-16665,-17500,-17500,-18876,-18876,-20771,-20771,
-23152,-23152,-25977,-25977,-29198,-29198,-32762,-32762,28931,28931,24873,24873,20669,20669,16392,16392,12115,12115,7911,7911,3852,3852,8,8,-3556,-3556,-6779,-6779,-9606,-9606,-11988,-11988,-13885,-13885,-15264,-15264,-16102,-16102,-16383,-16383,-16104,-16104,-15270,-15270,-13893,-13893,-11999,-11999,-9619,-9619,-6794,-6794,-3572,-3572,-10,-10,3833,3833,7891,7891,12094,12094,16371,16371,
20648,20648,24852,24852,28911,28911,32756,32756,-29215,-29215,-25992,-25992,-23164,-23164,-20782,-20782,-18885,-18885,-17505,-17505,-16667,-16667,-16385,-16385,-16664,-16664,-17498,-17498,-18874,-18874,-20768,-20768,-23148,-23148,-25972,-25972,-29194,-29194,-32756,-32756,28937,28937,24879,24879,20675,20675,16398,16398,12121,12121,7917,7917,3858,3858,13,13,-3551,-3551,-6775,-6775,-9602,-9602,-11985,-11985,
-13883,-13883,-15262,-15262,-16101,-16101,-16383,-16383,-16105,-16105,-15271,-15271,-13896,-13896,-12002,-12002,-9623,-9623,-6798,-6798,-3577,-3577,-15,-15,3827,3827,7885,7885,12088,12088,16365,16365,20642,20642,24846,24846,28906,28906,32751,32751,-29220,-29220,-25996,-25996,-23168,-23168,-20785,-20785,-18887,-18887,-17507,-17507,-16668,-16668,-16385,-16385,-16663,-16663,-17497,-17497,-18872,-18872,-20765,-20765,
-23144,-23144,-25968,-25968,-29189,-29189,-32751,-32751,28942,28942,24884,24884,20681,20681,16405,16405,12127,12127,7923,7923,3864,3864,18,18,-3546,-3546,-6770,-6770,-9598,-9598,-11982,-11982,-13880,-13880,-15261,-15261,-16100,-16100,-16383,-16383,-16106,-16106,-15273,-15273,-13898,-13898,-12005,-12005,-9626,-9626,-6803,-6803,-3582,-3582,-20,-20,3822,3822,7879,7879,12082,12082,16359,16359,
20636,20636,24840,24840,28900,28900,32746,32746,-29225,-29225,-26000,-26000,-23172,-23172,-20788,-20788,-18889,-18889,-17508,-17508,-16669,-16669,-16385,-16385,-16662,-16662,-17495,-17495,-18870,-18870,-20762,-20762,-23140,-23140,-25964,-25964,-29184,-29184,-32746,-32746,28948,28948,24890,24890,20687,20687,16411,16411,12133,12133,7929,7929,3869,3869,24,24,-3541,-3541,-6766,-6766,-9595,-9595,-11979,-11979,
-13878,-13878,-15259,-15259,-16099,-16099,-16383,-16383,-16107,-16107,-15274,-15274,-13900,-13900,-12008,-12008,-9630,-9630,-6807,-6807,-3587,-3587,-25,-25,3816,3816,7873,7873,12076,12076,16353,16353,20630,20630,24835,24835,28894,28894,32740,32740,-29230,-29230,-26005,-26005,-23176,-23176,-20791,-20791,-18892,-18892,-17510,-17510,-16670,-16670,-16385,-16385,-16661,-16661,-17493,-17493,-18867,-18867,-20759,-20759,
-23137,-23137,-25960,-25960,-29179,-29179,-32741,-32741,28953,28953,24896,24896,20693,20693,16417,16417,12139,12139,7935,7935,3875,3875,29,29,-3536,-3536,-6762,-6762,-9591,-9591,-11976,-11976,-13876,-13876,-15258,-15258,-16098,-16098,-16383,-16383,-16107,-16107,-15276,-15276,-13902,-13902,-12011,-12011,-9634,-9634,-6811,-6811,-3592,-3592,-31,-31,3810,3810,7867,7867,12070,12070,16347,16347,
20624,20624,24829,24829,28889,28889,32735,32735,-29235,-29235,-26009,-26009,-23179,-23179,-20794,-20794,-18894,-18894,-17512,-17512,-16671,-16671,-16385,-16385,-16661,-16661,-17492,-17492,-18865,-18865,-20756,-20756,-23133,-23133,-25955,-25955,-29174,-29174,-32735,-32735,28959,28959,24902,24902,20699,20699,16423,16423,12145,12145,7941,7941,3880,3880,34,34,-3532,-3532,-6757,-6757,-9587,-9587,-11973,-11973,
-13873,-13873,-15256,-15256,-16098,-16098,-16383,-16383,-16108,-16108,-15277,-15277,-13905,-13905,-12014,-12014,-9637,-9637,-6815,-6815,-3597,-3597,-36,-36,3805,3805,7862,7862,12064,12064,16341,16341,20618,20618,24823,24823,28883,28883,32730,32730,-29239,-29239,-26013,-26013,-23183,-23183,-20797,-20797,-18896,-18896,-17513,-17513,-16671,-16671,-16385,-16385,-16660,-16660,-17490,-17490,-18863,-18863,-20753,-20753,
-23129,-23129,-25951,-25951,-29170,-29170,-32730,-32730,28965,28965,24908,24908,20705,20705,16429,16429,12152,12152,7947,7947,3886,3886,39,39,-3527,-3527,-6753,-6753,-9584,-9584,-11970,-11970,-13871,-13871,-15255,-15255,-16097,-16097,-16383,-16383,-16109,-16109,-15279,-15279,-13907,-13907,-12017,-12017,-9641,-9641,-6820,-6820,-3601,-3601,-41,-41,3799,3799,7856,7856,12058,12058,16335,16335,
20612,20612,24817,24817,28878,28878,32724,32724,-29244,-29244,-26018,-26018,-23187,-23187,-20800,-20800,-18899,-18899,-17515,-17515,-16672,-16672,-16385,-16385,-16659,-16659,-17489,-17489,-18860,-18860,-20750,-20750,-23126,-23126,-25947,-25947,-29165,-29165,-32725,-32725,28970,28970,24914,24914,20711,20711,16435,16435,12158,12158,7953,7953,3892,3892,45,45,-3522,-3522,-6749,-6749,-9580,-9580,-11967,-11967,
-13869,-13869,-15253,-15253,-16096,-16096,-16383,-16383,-16110,-16110,-15280,-15280,-13909,-13909,-12020,-12020,-9645,-9645,-6824,-6824,-3606,-3606,-46,-46,3794,3794,7850,7850,12052,12052,16329,16329,20606,20606,24811,24811,28872,28872,32719,32719,-29249,-29249,-26022,-26022,-23190,-23190,-20803,-20803,-18901,-18901,-17516,-17516,-16673,-16673,-16385,-16385,-16658,-16658,-17487,-17487,-18858,-18858,-20747,-20747,
-23122,-23122,-25942,-25942,-29160,-29160,-32720,-32720,28976,28976,24920,24920,20717,20717,16441,16441,12164,12164,7958,7958,3897,3897,50,50,-3517,-3517,-6745,-6745,-9576,-9576,-11964,-11964,-13866,-13866,-15251,-15251,-16095,-16095,-16383,-16383,-16111,-16111,-15282,-15282,-13912,-13912,-12023,-12023,-9648,-9648,-6828,-6828,-3611,-3611,-52,-52,3788,3788,7844,7844,12046,12046,16323,16323,
20600,20600,24805,24805,28866,28866,32714,32714,-29254,-29254,-26026,-26026,-23194,-23194,-20806,-20806,-18903,-18903,-17518,-17518,-16674,-16674,-16385,-16385,-16657,-16657,-17486,-17486,-18856,-18856,-20744,-20744,-23118,-23118,-25938,-25938,-29155,-29155,-32714,-32714,28981,28981,24925,24925,20723,20723,16447,16447,12170,12170,7964,7964,3903,3903,55,55,-3512,-3512,-6740,-6740,-9573,-9573,-11961,-11961,
-13864,-13864,-15250,-15250,-16094,-16094,-16383,-16383,-16111,-16111,-15284,-15284,-13914,-13914,-12026,-12026,-9652,-9652,-6833,-6833,-3616,-3616,-57,-57,3782,3782,7838,7838,12040,12040,16316,16316,20594,20594,24799,24799,28861,28861,32709,32709,-29259,-29259,-26030,-26030,-23198,-23198,-20809,-20809,-18906,-18906,-17519,-17519,-16675,-16675,-16385,-16385,-16657,-16657,-17484,-17484,-18853,-18853,-20741,-20741,
-23115,-23115,-25934,-25934,-29150,-29150,-32709,-32709,28987,28987,24931,24931,20729,20729,16453,16453,12176,12176,7970,7970,3909,3909,60,60,-3507,-3507,-6736,-6736,-9569,-9569,-11958,-11958,-13862,-13862,-15248,-15248,-16094,-16094,-16383,-16383,-16112,-16112,-15285,-15285,-13916,-13916,-12029,-12029,-9656,-9656,-6837,-6837,-3621,-3621,-62,-62,3777,3777,7832,7832,12034,12034,16310,16310,
20588,20588,24793,24793,28855,28855,32703,32703,-29264,-29264,-26035,-26035,-23202,-23202,-20812,-20812,-18908,-18908,-17521,-17521,-16675,-16675,-16385,-16385,-16656,-16656,-17483,-17483,-18851,-18851,-20738,-20738,-23111,-23111,-25930,-25930,-29145,-29145,-32704,-32704,28993,28993,24937,24937,20735,20735,16459,16459,12182,12182,7976,7976,3914,3914,66,66,-3503,-3503,-6732,-6732,-9565,-9565,-11955,-11955,
-13859,-13859,-15247,-15247,-16093,-16093,-16383,-16383,-16113,-16113,-15287,-15287,-13919,-13919,-12032,-12032,-9659,-9659,-6841,-6841,-3625,-3625,-67,-67,3771,3771,7826,7826,12028,12028,16304,16304,20582,20582,24788,24788,28850,28850,32698,32698,-29268,-29268,-26039,-26039,-23205,-23205,-20815,-20815,-18910,-18910,-17523,-17523,-16676,-16676,-16385,-16385,-16655,-16655,-17481,-17481,-18849,-18849,-20735,-20735,
-23107,-23107,-25925,-25925,-29141,-29141,-32698,-32698,28998,28998,24943,24943,20741,20741,16465,16465,12188,12188,7982,7982,3920,3920,71,71,-3498,-3498,-6727,-6727,-9561,-9561,-11952,-11952,-13857,-13857,-15245,-15245,-16092,-16092,-16383,-16383,-16114,-16114,-15288,-15288,-13921,-13921,-12035,-12035,-9663,-9663,-6845,-6845,-3630,-3630,-73,-73,3766,3766,7821,7821,12022,12022,16298,16298,
20576,20576,24782,24782,28844,28844,32693,32693,-29273,-29273,-26043,-26043,-23209,-23209,-20818,-20818,-18913,-18913,-17524,-17524,-16677,-16677,-16385,-16385,-16654,-16654,-17479,-17479,-18846,-18846,-20732,-20732,-23104,-23104,-25921,-25921,-29136,-29136,-32693,-32693,29004,29004,24949,24949,20747,20747,16471,16471,12194,12194,7988,7988,3925,3925,76,76,-3493,-3493,-6723,-6723,-9558,-9558,-11949,-11949,
-13855,-13855,-15243,-15243,-16091,-16091,-16383,-16383,-16115,-16115,-15290,-15290,-13923,-13923,-12038,-12038,-9667,-9667,-6850,-6850,-3635,-3635,-78,-78,3760,3760,7815,7815,12016,12016,16292,16292,20570,20570,24776,24776,28838,28838,32688,32688,-29278,-29278,-26048,-26048,-23213,-23213,-20821,-20821,-18915,-18915,-17526,-17526,-16678,-16678,-16385,-16385,-16654,-16654,-17478,-17478,-18844,-18844,-20729,-20729,
-23100,-23100,-25917,-25917,-29131,-29131,-32688,-32688,29009,29009,24955,24955,20753,20753,16477,16477,12200,12200,7994,7994,3931,3931,82,82,-3488,-3488,-6719,-6719,-9554,-9554,-11946,-11946,-13852,-13852,-15242,-15242,-16090,-16090,-16383,-16383,-16115,-16115,-15291,-15291,-13926,-13926,-12041,-12041,-9670,-9670,-6854,-6854,-3640,-3640,-83,-83,3754,3754,7809,7809,12010,12010,
};
//#define Len 10
//u16 I2S2_Tx[Len] = { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888, 0x9999, 0xAAAA };
/*********************************************************************
* @fn I2S2_Init
*
* @brief Init I2S2
*
* @return none
*/
void I2S2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure={0};
I2S_InitTypeDef I2S_InitStructure={0};
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;//I2S_MCLKOutput_Disable;
I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_48k;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_High;
I2S_Init(SPI2, &I2S_InitStructure);
SPI_I2S_DMACmd( SPI2, SPI_I2S_DMAReq_Tx, ENABLE );
I2S_Cmd(SPI2, ENABLE);
}
/*********************************************************************
* @fn DMA_Tx_Init
*
* @brief Initializes the DMAy Channelx configuration.
*
* @param DMA_CHx - x can be 1 to 7.
* ppadr - Peripheral base address.
* memadr - Memory base address.
* bufsize - DMA channel buffer size.
*
* @return none
*/
void DMA_Tx_Init( DMA_Channel_TypeDef* DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize)
{
DMA_InitTypeDef DMA_InitStructure={0};
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
DMA_DeInit(DMA_CHx);
DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = bufsize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init( DMA_CHx, &DMA_InitStructure );
}
void setup() {
SPI_I2S_DeInit(SPI2);
I2S2_Init();
}
void loop() {
DMA_Tx_Init( DMA1_Channel5, (u32)&SPI2->DATAR, (u32)I2S2_Tx, Len);
DMA_Cmd( DMA1_Channel5, ENABLE );
while( (!DMA_GetFlagStatus(DMA1_FLAG_TC5))){};
DMA_Cmd( DMA2_Channel1, DISABLE );
}
即可工作。
I2S2_Tx 里面定义的是一个正弦波数据,通过如下C# 代码生成:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SinAudio
{
class Program
{
public const int LOOPS = 16;
static void Main(string[] args)
{
double sin,cos;
for (int i = 0; i < LOOPS * 48; i++) {
sin = (0.5 + Math.Sin(i * 2 * 3.1415 / 48))* 65535/2;
//cos = (0.5 + Math.Cos(i * 2 * 3.1415 / 48)) * 65535 / 2;
Console.Write("{0},{1},", (Int16)sin, (Int16)sin);// (Int16)() * );
if (i % 32 == 0) {
Console.WriteLine("");
}
}
Console.ReadLine();
}
}
}
数据可以看成是 48K 16Bits 采样结果,数据是int16 (负数使用补码形式表示)
工作的测试视频如下:
WordPress 标题中文检测工具
因为设置上的原因,Wordpress 最好不要使用中文作为标题。我的网站设置上支持中文标题,但是因为更换服务器的缘故,中文标题的文章又出现了无法访问的问题。于是,编写一个工具扫描网站上的所有文章,通过检查标题的 url 是否带有“%”来判断是否有中文。
扫描全部页面的方式是通过扫描全部日期归档链接实现的,类似"https://www.lab-z.com/2022/03/",发送 http 请求之后会对返回的结果进行分析,取出其中的 http://www.lab-z.com/ 为开头的 URL,然后进行检测,如果其中带有 “%”,那么就是带有汉字了。然后就可以根据指示在 WordPress 中手工进行修改。
代码比较简单,有兴趣的可以试试。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Text.RegularExpressions;
namespace WordPressUrlChecker
{
class Program
{
private static readonly HttpClient client = new HttpClient();
// 定义并初始化一个字符串列表
private static List<string> UrlToCheck = new List<string> {
"https://www.lab-z.com/2024/04/",
// 全部日期
"https://www.lab-z.com/2005/10/"
};
static async Task Main(string[] args)
{
string url = "https://www.lab-z.com/";
//Console.WriteLine(responseBody);
//string pattern = @"(http|https)://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";
//https://www.lab-z.com/2006/05/
string pattern = @"https://www\.lab-z\.com/[^\s]*";
foreach (string uString in UrlToCheck) {
Console.WriteLine("Checking in "+uString.ToString());
string responseBody = await GetRequest(uString);
MatchCollection matches = Regex.Matches(responseBody, pattern);
foreach (Match match in matches)
{
string getUrl = match.Value;
// 如果字符串中带有 " 那么就截取它之前的所有字符串
if (getUrl.IndexOf('\"')!=-1) {
getUrl= getUrl.Substring(0, getUrl.IndexOf('\"'));
//Console.WriteLine(getUrl);
}
if (ContainsChinese(getUrl))
{
Console.WriteLine(getUrl);
}
}
}
/*
*/
Console.ReadLine();
}
// 发送 HTTP 请求并且得到服务器返回
static async Task<string> GetRequest(string url)
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return responseBody;
}
// 检查字符串是否含有汉字
static bool ContainsChinese(string input)
{
for (int i = 0; i < input.Length; i++)
{
if (input[i] == '%')
return true;
}
return false;
}
}
}