从 Windows XP 的中文版和英文版中拷贝而来的超级终端程序。最主要是它提供了 Xmodem,YModem和ZModem 文件传输协议,可以用来进行测试。

=====================================================
2023年1月13日更新
上述的超级终端在 Win10 下可以正常使用,但是运行之后不会出现图标。经过研究这个问题可以通过添加hticons.dll来解决。有需要的朋友可以在下面下载这个文件,放到超级终端同一个目录下即可。
喜欢军事的朋友一定经常听过这句话,这就是“只要推力大,板砖也能飞上天”。实际上,这句话并非玩笑之语,确有出处。当年,F-22是从“先进战术战斗机”(简称ATF)计划发展而来的。早期,好几家公司一起竞标,分别是波音,通用动力,洛克希德,诺思罗普,和麦道公司。大家提概念设计方案。结果,可能是因为洛克希德曾经设计出F-117隐形飞机的缘故,走老路当然是最轻松的,所以,洛克希德最初提出的F-22前身方案,它就像是F-117的放大版。设计跟F-117这个怪胎一样,为了隐身性能,以牺牲空气动力学为代价,飞机设计总重36吨。后来,有个人是这么评价这种早期设计的,他就是洛克希德在ATF计划中的项目经理巴特·奥斯本(bart osborne),1998年,一家杂志对奥斯本进行采访【参考1】,而他是这样说的:“我们知道,这个设计将会存在严重的超音速问题,我们的设计当然可以超音速飞行,但肯定蠢得像猪。显然,只要推力大,板砖也能飞上天(With enough power, you can make a brick fly)”
这句话出处就是这么来的,他当时想表达的本意是这样的:我们设计的这种飞机, 在高空高速上肯定会存在很多问题,当然,这并不是说,这种设计不能超音速飞行,完全不是,因为只要推力,你也能让砖头飞上天,也能它超音速。
巴特·奥斯本的评价很中肯,洛克希德提交这个概念设计方案后,美国空军对这种设计的评价最差,在其他7个项目设计中,排倒数第一。【参考1】
对于我们来说,只要 CPU 足够快,GPIO 足够快,能够模拟出各种总线,最常见的是软串口,再稍微复杂一些的是I2C, SPI。最近有一个项目使用 ESP32 来模拟 USB Host,当前因为 GPIO 不够快,目前只能解析键盘鼠标这样的低速设备(Low Speed)。项目地址是:https://github.com/sdima1357/esp32_usb_soft_host 当然,对于Arduino 玩家来说可以直接使用下面这个库 :https://github.com/tobozo/ESP32-USB-Soft-Host 。
库可以同时支持4个 USB Host, 这里我设计一个 FireBeetle Shield 提供了 2个 USB Host。具体电路如下:
PCB 如下:
Soft USB Host 和 FireBeetle
可以看到板子上有2个 USB 母头和1个USB 公头,其中母头是给 USB Host使用的,公头是为了在供电不足情况下通过充电宝之类直接对设备供电。库可以支持4组USB Host ,经过实验在FireBeetle上可以使用下面的组合:
16 | 13 | 19 | 25 |
17 | 15 | 18 | 26 |
测试代码:
#include <ESP32-USBSoftHost.hpp>
#include "usbkbd.h" // KeyboardReportParser
// default pins tested on FireBeetle
// + 16 13 19 25
// - 17 15 18 26
#define DP_P0 25 // always enabled
#define DM_P0 26 // always enabled
#define DP_P1 19 // -1 to disable
#define DM_P1 18 // -1 to disable
#define DP_P2 -1 // -1 to disable
#define DM_P2 -1 // -1 to disable
#define DP_P3 -1 // -1 to disable
#define DM_P3 -1 // -1 to disable
static void my_USB_DetectCB( uint8_t usbNum, void * dev )
{
sDevDesc *device = (sDevDesc*)dev;
printf("New device detected on USB#%d\n", usbNum);
printf("desc.bcdUSB = 0x%04x\n", device->bcdUSB);
printf("desc.bDeviceClass = 0x%02x\n", device->bDeviceClass);
printf("desc.bDeviceSubClass = 0x%02x\n", device->bDeviceSubClass);
printf("desc.bDeviceProtocol = 0x%02x\n", device->bDeviceProtocol);
printf("desc.bMaxPacketSize0 = 0x%02x\n", device->bMaxPacketSize0);
printf("desc.idVendor = 0x%04x\n", device->idVendor);
printf("desc.idProduct = 0x%04x\n", device->idProduct);
printf("desc.bcdDevice = 0x%04x\n", device->bcdDevice);
printf("desc.iManufacturer = 0x%02x\n", device->iManufacturer);
printf("desc.iProduct = 0x%02x\n", device->iProduct);
printf("desc.iSerialNumber = 0x%02x\n", device->iSerialNumber);
printf("desc.bNumConfigurations = 0x%02x\n", device->bNumConfigurations);
// if( device->iProduct == mySupportedIdProduct && device->iManufacturer == mySupportedManufacturer ) {
// myListenUSBPort = usbNum;
// }
}
static void my_USB_PrintCB(uint8_t usbNum, uint8_t byte_depth, uint8_t* data, uint8_t data_len)
{
// if( myListenUSBPort != usbNum ) return;
printf("in: ");
for(int k=0;k<data_len;k++) {
printf("0x%02x ", data[k] );
}
printf("\n");
}
usb_pins_config_t USB_Pins_Config =
{
DP_P0, DM_P0,
DP_P1, DM_P1,
DP_P2, DM_P2,
DP_P3, DM_P3
};
void setup()
{
Serial.begin(115200);
delay(200);
Serial.println("USB Test");
delay(1000);
USH.init( USB_Pins_Config, my_USB_DetectCB, my_USB_PrintCB );
}
void loop()
{
vTaskDelete(NULL);
}
运行结果, 上面是输出的Descriptor,下面是收到的鼠标数据:
目前这个库还存在一些兼容性问题,并非所有的鼠标都能正常工作。我测试了微软的IO1.01 是可以正常工作的。
参考:
使用上次的工具来测试 Ch55x(Ch551/2/4)开发板的串口速度。
实际测试的是 CH554 ,使用 Ch55xduino 编写代码如下:
#ifndef USER_USB_RAM
#error "This example needs to be compiled with a USER USB setting"
#endif
#include "src/userUsbCdc/USBCDC.h"
//This is a fairly large array, store it in external memory with keyword __xdata
__xdata char recvStr[64];
// 代码中出现的发送和接收
// 测试 Package 的大小
#define MAX_N 256
// 2秒超时
#define TIMEOUT 2000
// 接收数据 Buffer
// 设置为实际的2倍大小避免接收超过Buffer 的问题
__xdata byte receiveBuffer[MAX_N];
void setup() {
USBInit();
}
// 状态机记录
byte currentStatus = 0;
// 收到的数量
int counter = 0;
// 超时计时器
unsigned long Elsp;
// 发送标记,True 时发送,反之不发送
boolean sendOnce = true;
// 发生错误的数量
int failCount;
void loop() {
switch (currentStatus) {
case 0:
// 初始状态
while (USBSerial_available()) {
byte c = USBSerial_read();
// q命令查询当前状态(用于调试)
if (c == 'q') {
USBSerial_print_s("Current 0");
USBSerial_flush();
}
// 1(接收模式) 2(发送模式)
if ((c == '1') || (c == '2')) {
// 转移到下一个状态
currentStatus = c - '0';
// 如果是接收模式,那么开始计时
if (c == '1') {
Elsp = millis();
counter = 0;
}
}
}
break;
case 1: //接收模式
// 如果接收模式超时,那么直接返回到状态0
if (millis() - Elsp > TIMEOUT) {
// 返回状态 0
currentStatus = 0;
// 发送 "aaa" 表示当前超时
USBSerial_write('a'); USBSerial_write('a'); USBSerial_write('a');
USBSerial_flush();
}
// 接收数据
while (USBSerial_available()) {
byte c = USBSerial_read();
receiveBuffer[counter] = c;
// 统计接收到的数据量
counter++;
// 如果接收到足够的数据,那么转移到状态3 进行校验
if (counter == MAX_N) {
currentStatus = 3;
//Serial.print("St3");
}
}
break;
case 3:
// 校验接收模式收到的数据,数据是 0x55 0xaa 0x55....
failCount = 0;
for (int i = 0; i < MAX_N; i = i + 2) {
if (receiveBuffer[i] != 0x55) {
failCount++;
}
if (receiveBuffer[i + 1] != 0xAA) {
failCount++;
}
}
// 检查是否有错误
if (failCount == 0) {
// 返回"ppp" 表示校验通过
USBSerial_write('p'); USBSerial_write('p'); USBSerial_write('p');
USBSerial_flush();
}
else {
// 校验失败,返回 'f'+发生错误的数量错误数据
USBSerial_write('f');
USBSerial_write((byte)(failCount & 0xFF));
USBSerial_write((byte)(failCount >> 8));
}
counter = 0;
//Serial.println("Switch to status 1");
Elsp = millis();
currentStatus = 1;
break;
case 2:
// 发送模式,直接发送 MAX_N 个 0x55 0xaa 0x55 ....
if (sendOnce) {
for (int i = 0; i < MAX_N / 2; i++) {
USBSerial_write(0x55);
USBSerial_write(0xAA);
USBSerial_flush();
}
sendOnce = false;
}
while (USBSerial_available()) {
char c = USBSerial_read();
if (c == '0') {
currentStatus = 0;
//Serial.print("Switch to 0");
}
if (c == '2') {
sendOnce = true;
}
// 查询状态
if (c == 'q') {
USBSerial_print_s("Current 2");
USBSerial_flush();
}
}
break;
default: {
USBSerial_println_s("Unknown status");
USBSerial_flush();
}
}
1.PC端接收,Ch554发送,可以看到速度能达到37K/S左右
2.PC端发送,Ch554接收,可以看到速度能达到97K/S左右
从结果可以看出来,比 32U4 这样的芯片还是快一点点的(测试模式是 5V 24Mhz)
最近在看《软件调试(第二版)》,第四章讲述启动过程的时候作者提到了 bcdedit 相关内容。这次根据指引进行实验。
1.创建一个新的引导项目,这里我们只是将目前的引导选项多制作一个拷贝
2.重启后会出现下面的界面,可以选择
3.《软件调试》书中介绍了下面的命令可以将这个界面切换为 Win7 类似的
4.之后重启启动界面变成下面这种
5.可以在系统下运行 msconfig 编辑启动项
6.使用下面的命令可以恢复为 2. 这种样式
参考
代码如下,功能很简单:判断输入的是否为 0xaa, 如果是就输出一段字符,如果不是输出另外一段:
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available()) {
char c = Serial.read();
if (c == 0xaa) {
Serial.println("Get 0xaa");
} else {
Serial.print("Not 0xaa. You have input ");
Serial.println(c,HEX);
}
}
}
实验平台是 Leonardo, 实验结果如下:
为什么输入的 0xaa 会被判定为 ffffffaa
在 \arduino-1.8.4\hardware\arduino\avr\cores\arduino\CDC.cpp 有如下定义:
int Serial_::read(void)
{
if (peek_buffer >= 0) {
int c = peek_buffer;
peek_buffer = -1;
return c;
}
return USB_Recv(CDC_RX);
}
对于 0xaa 来说,转换为 int 之后的结果就是 ffffffaa,可以用下面的代码来验证:
char c=0xaa;
Serial.println((int)c,HEX);
结果
知道了原因,修改方法也很简单,在变量声明的地方定义为 byte c 即可。
目前市面上最成熟的 USB Host 库当属Oleg Mazurov的USB Host Shield Library 2.0(项目地址 https://github.com/felis/USB_Host_Shield_2.0),几乎可以兼容市面上的所有 Arduino 板,从 Atmel 328P/32U4到 ATMage 2560 再到 EP32都能够使用这个库来驱动 USB 设备。这次我专门为 FireBeetle设计了一个Shield 使得FireBeetle能够驱动一些USB 设备。
首先,依然是硬件设计部分。USB Host Shield Library是基于 MAX3421e实现的,下面可以看作是这个芯片的一个最小系统,需要外接一颗12Mhz 的晶振。此外可以看到这个芯片本身带有GPIO引脚,可以用来做 GPI或者 GPO ,在一些情况下可以弥补主控 GPIO 不足的缺点,但是本次设计并未使用这些引脚。
上述芯片和 FireBeetle接口如下图,二者是通过 SPI 来进行通讯的。下图中IO18/23/19/13 就是 SPI 接口。特别注意,我在板子上预留了 JP3/JP2 这是为以后堆叠使用可能发生的引脚冲突预留的,正常使用的时候 JP1和JP3(称作短接电阻) 是需要焊接起来的;JP2 的功能是预留给某些情况下 USB 设备需要功耗较高,FireBeetle 无法提供时就需要考虑使用外部5V进行供电,此时如果你还使用FIreBeetle 上的 USB端口调试,既有可能出现外部5V 和USB 上面的5V 电压不同的情况。因此,这种情况下需要断开 JP2。
接下来继续进行硬件设计,绘制PCB。特别注意,下面电路图时有缺陷的,再晶振下面走线,有可能对信号有影响。建议需要的朋友重新设计 PCB。
3D 预览结果:
之后,打板,焊接成品如下,黑色PCB 很 DFRobot 出品的感觉。
接下来就用这个板子配合 FireBeetle来实现一个 USB 键盘转蓝牙的作品。
#elif defined(ESP32)
//LABZ typedef MAX3421e<P5, P17> MAX3421E; // ESP32 boards
typedef MAX3421e<P13, P26> MAX3421E; // ESP32 boards // LABZ
#else
#elif defined(ESP32)
//LABZ typedef SPi< P18, P23, P19, P5 > spi;
typedef SPi< P18, P23, P19, P13 > spi; // LABZ
#else
2. 蓝牙键盘功能的实现。这里我们需要用到 ESP32 BLE Keyboard library,在 https://github.com/T-vK/ESP32-BLE-Keyboard 可以找到这个项目。
3.最终的代码如下:
#include <hidboot.h>
#include <SPI.h>
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
class KbdRptParser : public KeyboardReportParser
{
void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};
void KbdRptParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
{
if (bleKeyboard.isConnected()) {
KeyReport _keyReport;
_keyReport.modifiers=buf[0];
for (int i = 2; i < 8; i++) {
_keyReport.keys[i-2] = buf[i];
}
bleKeyboard.sendReport(&_keyReport);
}
Serial.print("Received "); Serial.println(len);
for (int i = 0; i < len; i++) {
Serial.print(buf[i]);
Serial.print(" ");
}
Serial.println(" ");
}
USB Usb;
HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
KbdRptParser Prs;
void setup()
{
Serial.begin( 115200 );
Serial.println("Start");
if (Usb.Init() == -1)
Serial.println("OSC did not start.");
bleKeyboard.begin();
delay( 200 );
HidKeyboard.SetReportParser(0, &Prs);
}
void loop()
{
Usb.Task();
}
简单的说上电之后,在PC上搜索蓝牙设备,配对之后就可以通过 USB Host Shield 解析键盘数据,然后将这个数据直接填写到蓝牙键盘的结构体中,FIreBeetle 随即将这个信息传递给 PC,PC上就能收到你的按键信息了。
电路图文件和PCB 在这里下载:
工作的视频可以在 B站看到
有时候,我们需要执行 PowerShell 命令来取得一些信息,通过下面的代码能在 VC 中执行命令并且获得返回值:
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
// 描述:execmd函数执行命令,并将结果存储到result字符串数组中
// 参数:cmd表示要执行的命令, result是执行的结果存储的字符串数组
// 函数执行成功返回1,失败返回0
#pragma warning(disable:4996)
int execmd(char* cmd, char* result) {
char buffer[128]; //定义缓冲区
FILE* pipe = _popen(cmd, "r"); //打开管道,并执行命令
if (!pipe)
return 0; //返回0表示运行失败
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe)) { //将管道输出到result中
strcat(result, buffer);
}
}
_pclose(pipe); //关闭管道
return 1; //返回1表示运行成功
}
int main(void)
{
char res[2048] = { 0 };
execmd("powershell $psversiontable", res);
printf("Result [%s]\r\n",res);
getchar();
}
下面是运行结果,可以看到二者完全相同。
特别注意:如果遇到下面这样的错误提示,那么需要扩大 res[] 。
Run-Time Check Failure #2 – Stack around the variable ‘a’ was corrupted.
参考:
1.https://www.cnblogs.com/htj10/p/13830785.html VC执行Cmd命令,并获取结果
2.https://blog.csdn.net/weixin_42395980/article/details/112123690 c++ 调用 powershell_十九,Powershell基础入门及常见用法(一)
ESP32 不建议使用的 GPIO 如下
ESP32S2 不建议使用的 GPIO 如下(这个是我自己总结的,缺少佐证):
关于 S2 的 PSRAM 在【参考3】有描述:
特别提醒:如果你使用开发板,例如 S2 Saola 这种, IO18 上有LED,如果直接使用这个pin作为SPI CLOCK可能会导致不断重启的问题。
参考:
1.http://www.360doc.com/content/20/0312/20/42387867_898729516.shtml
2.ESP32WROOM32D &ESP32WROOM32U 技术规格书
3.https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_cn.pdf
====================================================
2023年1月17日更新
ESP32S3不建议使用的 GPIO 如下:
1.GPIO0 Strapping
2.GPIO3 Strapping
3.GPIO19 USB-JTAG
4.GPIO20 USB-JTAG
5.GPIO26-37 SPI0/1
6.GPIO45 Strapping
7.GPIO46 Strapping
上述来自:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/api-reference/peripherals/gpio.html
职位 | 部门 | 级别 | 位置 |
软件工程师 | 研发部 | 工程师,高级工程师 | 合肥 |
嵌入式开发工程师 | 研发部 | 工程师,高级工程师 | 合肥,昆山 |
计算机视觉博士研究员 | 研发部 | 高级工程师 | 合肥 |
数据挖掘博士研究员 | 研发部 | 高级工程师 | 合肥 |
EDA应用软件开发工程师 | 研发部 | 工程师,高级工程师 | 合肥,昆山 |
软件BIOS高级工程师 | 研发部 | 高级工程师 | 台北 |
IT PLM方案工程师 | 研发部 | 工程师 | 台北 |
软件应用高级工程师(driver) | 研发部 | 高级工程师 | 合肥,昆山 |
软件项目管理 | 研发部 | 工程师 | 合肥 |
*合肥地址:中国安徽省合肥市经济技术开发习友路5899号联想科技港
*昆山地址:江苏省昆山市高新区登云路288号海创大厦C座
有兴趣或者想进一步咨询的朋友可以通过如下邮件地址接洽:
372790124@qq.com
最近研究 YModem 协议需要有对应的软件进行测试,开始使用的是 WinXP 的超级终端,但是发现它无法支持超过 1Mhz 的频率,之后使用 ExtraPutty 发现它在无法工作在 2Mhz 的情况下。最终找到了一个开源的 YModem 串口测试软件:SerialPortYmodem,这是一个开源的工具在:
https://github.com/1021256354/SerialPortYmodem
它提供了源代码,但是没有提供 Windows 的可执行程序,只好手工编译,编译过程又发现它使用的是 QT 5.7 ,于是又研究如何安全QT 最终得到的编译结果。有同样需求的朋友可以在这里下载到编译结果。编译出来的可执行程序真不大160K 左右,但是如果想让这个程序在Windows下执行起来需要 48MB 的DLL 。
我在源代码的基础上还做了如下修改:
1.将中文提示信息替换为英文;
2.增加了一些波特率,比如:1,500,000和 2,000,000
3.增加了速度的显示,在 Send 和 Receive 之间可以看到当前速度
编译好的Windows 可执行文件在下面(QT 框架编译出来的程序160K, 支持这个文件的 DLL 32MB):
链接: https://pan.baidu.com/s/1qPJT_jFvkZW1LO02BFjOWA 提取码: b9vz 复
修改后的源代码下载