Win10 下通过BCDEDIT 增加启动选项

最近在看《软件调试(第二版)》,第四章讲述启动过程的时候作者提到了 bcdedit 相关内容。这次根据指引进行实验。

1.创建一个新的引导项目,这里我们只是将目前的引导选项多制作一个拷贝

通过拷贝生成一个引导选项

2.重启后会出现下面的界面,可以选择

选择引导项

3.《软件调试》书中介绍了下面的命令可以将这个界面切换为 Win7 类似的

切换为 Windows7 风格的启动菜单

4.之后重启启动界面变成下面这种

5.可以在系统下运行 msconfig 编辑启动项

MSConfig

6.使用下面的命令可以恢复为 2. 这种样式

恢复为 Windows 10 的方法

参考

  1. https://www.howtogeek.com/245175/how-to-add-safe-mode-to-the-windows-8-and-10-boot-menu/ How to Add Safe Mode to the Windows 8 and 10 Boot Menu
  2. https://blog.csdn.net/qq_25368751/article/details/80660286 多系统的福音,bcdedit找回传统启动菜单。取消(恢复)Modern UI风格启动菜单~菜单~

SerialRead() 结果为何不是想要的?

代码如下,功能很简单:判断输入的是否为 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 即可。

FireBeetle的USB Host Shield

目前市面上最成熟的 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 不足的缺点,但是本次设计并未使用这些引脚。

这个可以看作时 Max4321e 的最小系统了

上述芯片和 FireBeetle接口如下图,二者是通过 SPI 来进行通讯的。下图中IO18/23/19/13 就是 SPI 接口。特别注意,我在板子上预留了 JP3/JP2 这是为以后堆叠使用可能发生的引脚冲突预留的,正常使用的时候 JP1和JP3(称作短接电阻) 是需要焊接起来的;JP2 的功能是预留给某些情况下 USB 设备需要功耗较高,FireBeetle 无法提供时就需要考虑使用外部5V进行供电,此时如果你还使用FIreBeetle 上的 USB端口调试,既有可能出现外部5V 和USB 上面的5V 电压不同的情况。因此,这种情况下需要断开 JP2。

Fire Beetle 端

接下来继续进行硬件设计,绘制PCB。特别注意,下面电路图时有缺陷的,再晶振下面走线,有可能对信号有影响。建议需要的朋友重新设计 PCB。

3D 预览结果:

之后,打板,焊接成品如下,黑色PCB 很 DFRobot 出品的感觉。

接下来就用这个板子配合 FireBeetle来实现一个 USB 键盘转蓝牙的作品。

  1. 为了驱动这个 USB Host Shield 需要对 USB Host Library 做一点修改。
    1. 1 UsbCore.h 中修改为我们使用的SS和INT Pin
#elif defined(ESP32)
//LABZ typedef MAX3421e<P5, P17> MAX3421E; // ESP32 boards
typedef MAX3421e<P13, P26> MAX3421E; // ESP32 boards  // LABZ
#else
  1. 2 usbhost.h 中修改为我们使用的 SPI
#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站看到

https://www.bilibili.com/video/BV1zy4y1W7oh

VC 运行 PowerShell 命令的方法

有时候,我们需要执行 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();
}

下面是运行结果,可以看到二者完全相同。

代码运行结果和 Power Shell 运行结果相同

特别注意:如果遇到下面这样的错误提示,那么需要扩大 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/S2 不推荐使用的GPIO Pin

ESP32 不建议使用的 GPIO 如下

  1. IO0 Strapping,用于选择 SPI 启动还是下载启动
  2. IO1 TXD , 用于串口下载
  3. IO2 Strapping,下载启动需要用
  4. IO3 RXD,用于串口下载
  5. IO5 Strapping, SDIO 从机信号输入输出时序
  6. IO6-11 内部 SPI FLASH
  7. IO12 Strapping, MTDI信号
  8. IO15 Strapping MTDO信号

ESP32S2 不建议使用的 GPIO 如下(这个是我自己总结的,缺少佐证):

  1. GPIO0 系统启动模式选择
  2. GPIO1 TXD 用于串口下载
  3. GPIO3 RXD 用于串口下载
  4. GPIO43 TXD 用于串口下载
  5. GPIO44 RXD 用于串口下载
  6. GPIO37 SPI NOR/PSRAM 的SPIHD
  7. IO39 SPI NOR的SPICS0
  8. 6.IO40 SPI NOR/PSRAM 的SPICLK
  9. IO41 SPI NOR/PSRAM 的SPIQ
  10. IO42 SPI NOR/PSRAM 的SPID
  11. IO38 SPI NOR/PSRAM 的 SPIWP
  12. IO26 用作PSRAM SPICS1
  13. IO27 用作PSRAM SPIHD
  14. IO28用作PSRAM SPIWP
  15. IO29 用作PSRAM SPICS0
  16. IO30 用作PSRAM SPICLK
  17. IO31 用作PSRAM SPIQ
  18. IO32 用作PSRAM SPID
  19. GPIO45 VDD_SPI 电压选择
  20. GPIO46 系统启动是否打印 ROM Code

关于 S2 的 PSRAM 在【参考3】有描述:

特别提醒:如果你使用开发板,例如 S2 Saola 这种, IO18 上有LED,如果直接使用这个pin作为SPI CLOCK可能会导致不断重启的问题。

参考:

1.http://www.360doc.com/content/20/0312/20/42387867_898729516.shtml

2.ESP32­WROOM­32D &ESP32­WROOM­32U 技术规格书

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

  • Strapping 管脚:GPIO2、GPIO3、GPIO45 和 GPIO46 是 Strapping 管脚。更多信息请参考 ESP32-S3 技术规格书。
  • SPI0/1:GPIO26-32 通常用于 SPI flash 和 PSRAM,不推荐用于其他用途。当使用八线 flash 或八线 PSRAM 或同时使用两者时,GPIO33~37 会连接到 SPIIO4 ~ SPIIO7 和 SPIDQS。因此,对于内嵌 ESP32-S3R8 或 ESP32-S3R8V 芯片的开发板,GPIO33~37 也不推荐用于其他用途。
  • USB-JTAG:GPIO19 和 GPIO20 默认用于 USB-JTAG。用做 GPIO 时驱动程序将禁用 USB-JTAG。

上述来自:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s3/api-reference/peripherals/gpio.html

联宝招聘(合肥,昆山,台北内部推荐,20210705)

职位部门级别位置
软件工程师研发部工程师,高级工程师合肥
嵌入式开发工程师研发部工程师,高级工程师合肥,昆山
计算机视觉博士研究员研发部高级工程师合肥
数据挖掘博士研究员研发部高级工程师合肥
EDA应用软件开发工程师研发部工程师,高级工程师合肥,昆山
软件BIOS高级工程师研发部高级工程师台北
IT PLM方案工程师研发部工程师台北
软件应用高级工程师(driver)研发部高级工程师合肥,昆山
软件项目管理研发部工程师合肥

*合肥地址:中国安徽省合肥市经济技术开发习友路5899号联想科技港

*昆山地址:江苏省昆山市高新区登云路288号海创大厦C座

有兴趣或者想进一步咨询的朋友可以通过如下邮件地址接洽:

372790124@qq.com

YModem 串口测试软件

最近研究 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 之间可以看到当前速度

2,000,000 波特率通讯测试

编译好的Windows 可执行文件在下面(QT 框架编译出来的程序160K, 支持这个文件的 DLL 32MB):

链接: https://pan.baidu.com/s/1qPJT_jFvkZW1LO02BFjOWA 提取码: b9vz 复

修改后的源代码下载