RISC是“精简指令集计算机”的缩写:Reduced Instruction Set Computing RISC)。RISC的指令系统相对简单,它只要求硬件执行很有限且最常用的那部分指令,大部分复杂的操作则使用成熟的编译技术,由简单指令合成。RISC结构采用精简的,长短划一的指令集,使大多数的操作获得了尽可能高的效率。某些在传统结构中要用多周期指令实现的操作,在RISC结构中,通过机器语言编程,就代之以多条单周期指令了。【参考1】
接下来用一个例子来说明二者的区别。
假设我们有一个这样的计算机:内存是一个 6×4 的数组, 有A-F 6个寄存器。
对于 CISC 来说,如果想完成内存中2个数值的相乘的操作,可以直接使用下面的指令:
MULT 2:3,5:2
这里的 MULT 就是一个“复杂指令”。 进一步,如果设定变量 x 为内存 2:3 中的值。 y 为内存 5:2 的值,上面的指令就可以理解为C语言的 x=x*y。
如果用 RISC 来完成,那么需要写成如下的指令:
LOAD A, 2:3 LOAD B, 5:2 PROD A, B STORE 2:3, A
从这个结果上来看,RISC 效率更低,因为需要执行更多的代码,使用更多的内存。但是实际上 RISC 的指令通常只需要1个机器周期来完成,所以整体上消耗时间和CISC 的 MULT 指令相同,另外因为 RISC 机器码指令长度相同,执行时只需要一个机器周期所以更适合流水线方式执行(我的理解是方便硬件预读取和判断)。【参考2】
虽然 Intel X86 CPU 是 CISC 的典型代表,但是它的内部也存在RISC 的设计概念。所有的操作都会被分解为微指令再执行。微指令是典型的 CISC 的指令。
USB 键盘鼠标是最常见的输入设备了,之前如果想在 Arduino 上使用这两种设备,一个可行的方法是使用 USB Host Shield。这种方法的缺点是:成本比较高(MAX3421E芯片贵),操作复杂(SPI接口),资料少。因为这样缺点的存在,USB Host Shield 在使用上存在诸多不便。偶然间看到USB键鼠转串口通讯控制芯片CH9350(南京沁恒,WCH,阅读过我文章的朋友都知道CH340 也是他们家的产品)。这款能够将 USB 键盘鼠标的有效信息转为串口数据。芯片特点如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management;
using System.Collections;
namespace ConsoleApplication29
{
class Program
{
private static void GatherUsbInformation()
{
var mos = new ManagementObjectSearcher("select DeviceID from Win32_PnPEntity");
var mbos = new ArrayList(mos.Get());
var data = new Dictionary<string, string[]>();
for (var i = 0; i < mbos.Count; i++)
{
var managementBaseObject = mbos[i] as ManagementBaseObject;
if (managementBaseObject == null)
{
continue;
}
var deviceId = managementBaseObject.Properties["DeviceID"].Value as string;
if (deviceId == null || !deviceId.StartsWith("USB"))
{
continue;
}
if (!data.ContainsKey(deviceId))
{
data.Add(deviceId, new string[8]);
}
else if (data.ContainsKey(deviceId))
{
continue;
}
var mo = managementBaseObject as ManagementObject;
var inParams = mo.GetMethodParameters("GetDeviceProperties");
var result = mo.InvokeMethod(
"GetDeviceProperties",
inParams,
new InvokeMethodOptions()
);
if (result?.Properties["deviceProperties"].Value == null)
{
continue;
}
foreach (var deviceProperties in result.Properties["deviceProperties"].Value as ManagementBaseObject[])
{
var keyName = deviceProperties.Properties["KeyName"].Value as string;
var value = deviceProperties.Properties["Data"].Value as string;
if (string.IsNullOrWhiteSpace(value) || string.IsNullOrWhiteSpace(keyName))
{
//MachineInformationGatherer.Logger.LogTrace(
// $"KeyName {keyName} or Value {value} was null or whitespace for device ID {deviceId}");
continue;
}
Console.WriteLine(keyName);
Console.WriteLine(value);
switch (keyName)
{
case "DEVPKEY_Device_BusReportedDeviceDesc":
{
data[deviceId][0] = value;
break;
}
case "DEVPKEY_Device_DriverDesc":
{
data[deviceId][1] = value;
break;
}
case "DEVPKEY_Device_DriverVersion":
{
data[deviceId][2] = value;
break;
}
case "DEVPKEY_Device_DriverDate":
{
var year = int.Parse(value.Substring(0, 4));
var month = int.Parse(value.Substring(4, 2));
var day = int.Parse(value.Substring(6, 2));
var hour = int.Parse(value.Substring(8, 2));
var minute = int.Parse(value.Substring(10, 2));
var second = int.Parse(value.Substring(12, 2));
data[deviceId][3] =
new DateTime(year, month, day, hour, minute, second).ToString();
break;
}
case "DEVPKEY_Device_Class":
{
data[deviceId][4] = value;
break;
}
case "DEVPKEY_Device_DriverProvider":
{
data[deviceId][5] = value;
break;
}
case "DEVPKEY_NAME":
{
data[deviceId][6] = value;
break;
}
case "DEVPKEY_Device_Manufacturer":
{
data[deviceId][7] = value;
break;
}
case "DEVPKEY_Device_Children":
{
var children = deviceProperties.Properties["DEVPKEY_Device_Children"];
if (children.Value != null)
{
if (children.IsArray)
{
foreach (var child in children.Value as string[])
{
mos.Query = new ObjectQuery(
$"select * from Win32_PnPEntity where DeviceID = {child}");
var childs = mos.Get();
foreach (var child1 in childs)
{
mbos.Add(child1);
}
}
}
}
break;
}
}
}
}
}
static void Main(string[] args)
{
GatherUsbInformation();
Console.ReadKey();
}
}
}