智能硬件复习
第一章
信息的主要特征:
-
时效性
-
共享性
-
传递性
-
真伪性
-
转换性
-
==可处理性==:信息可以被获取、存储、加工、检索和使用
传统信息处理手段:处理数据才能获取信息
传统方法特点:
- 信息(数据):结构化数据(数值、表格等)
- 方法:明确的规则、明确的算法为基础
- 鲁棒性:数据要准确、完成、干净
- 数据量:小,且领域必须相对固定
传统方法缺点:
- 信息(数据):难以处理视频等多媒体数据
- 方法:难以构建复杂的算法
- 鲁棒性:难以兼容多样性数据
- 数据量:难以适应信息量爆炸式的增长
==人工智能三大要素:数据,算法,算力==
AI时代,指人工智能成为社会核心驱动力的时代,也是机器具备学习能力和自主决策能力的时代,是数据处理方式变革的时代。
AI的特征:
- 数据驱动
- 智能化
- 高度自动化
- 创新导向
- 情景适应性
虚拟技术的关键技术:
- 虚拟现实(VR)
- 增强现实(AR)
- 混合现实(MR)
- 元宇宙(Metaverse)
- AI技术
- 区块链技术
- 未来网络
信息系统:由人、技术、数据和流程等要素构成的综合系统,用于采集、存储、处理、分析和传播信息,以支持系统的决策、协调、控制和运营。
信息系统的构成因素:人、技术、数据、流程、软件、硬件
硬件设备分类练习:
- 输入设备:温度传感器,鼠标,键盘,麦克风,摄像头,震动反馈手柄
- 处理设备:CPU,显卡
- 存储设备:内存,机械硬盘,固态硬盘SSD
- 通信设备:交换机,路由器,WIFI模块,无线接入点AP
- 输出设备:电机,打印机,风扇,LED指示灯,耳机,液晶屏幕,显卡,震动反馈手柄
软件分类练习:
- 操作系统:DOS,Windows,Android,Armbian,LINUX,iOS,MacOs
- 应用软件:Photoshop,Word,微信,QQ,Excel,Office,Chrome
- 数据库管理系统:MySQL,MongoDB
- 安全软件:360安全卫士
- 编程语言开发工具:VsCode,PyCharm
- 中间件:Apache,MQTT
智能硬件(Smart Hardware):是指集成计算、感知、通信和控制等功能的硬件设备,通常具有一定的自我学习、适应、推理和决策 能力,通过与外部环境或用户的交互,执行预定或自主决策任务。
智能硬件通常结合了硬件技术、传感器技术、人工智能和物联网技术等,能够在一定程度上实现智能化的操作或自动化功能。
==智能硬件的六大硬件组成==:
- 输入/感知:感知外部/内部状态,产生感知数据
- 通信:智能硬件之间或与外部系统的联网和数据通信
- 存储:保存操作系统、应用程序、数据和配置等内容
- 计算:进行运算和决策,控制智能硬件系统工作
- 输出/执行:输出计算结果,控制外部设备等
- 电源系统:智能硬件大多 是电池供电设 备,(电池)电 源系统为所有 系统设备供电
==智能硬件的六大软件组成==:
- 操作系统(OS):硬件抽象层、进程管理、内存管理、文件系统等功能,执行多任务并提供更高效的资源管理
- 固件(Firmware):直接与硬件进行交互,负责设备的初始化、硬件控制和低级功能实现
- 驱动(Drivers):对操作系统和上层应用屏蔽硬件之间的差异, 提供统一的控制和管理接口
- 协议栈(Stack):与其他设备或云端通信所使用的协议栈,比包括设备内部的,主要指网络通信和数据传输
- 应用软件(App):用户与智能硬件交互的主要软件部分。它通常负责提供具体的功能,如数据处理等
- 交互界面(UI):以直观的方式向用户输出系统信息、接收用户控制指令
智能硬件的功能特征:
- 功能完备性:具备感知、存储、通信、计算、输出
- 结构灵活性:功能在系统中可拆分、可结合
- 任务动态性:功能在系统中可以动态调整执行部件
- 单一规则设定
- 多源规则设定
- 外界控制设定
- 系统扩展性:设备可以加入其他系统,或被其他设备加入
- (硬件)设备扩展性
- (软件)功能扩展性
- 短板制约性:软硬件必须协调工作,才能达到系统最佳性能
第二章
小型智能硬件的计算需求(处理器特点):
- 运算能力满足需求,有针对性的应用在不同智能硬件设备
- 能针对处理任务的需求,工作在较低功耗甚至超低功耗下
- 芯片体积小、外围电路简单,有简单的外围电路即可工作
- 集成有常用的存储功能,以及通信和基本的输入输出部件
**两类智能硬件常用的计算部件:MCU和SoC
-
MCU(Microcontroller Unit):一种小型的单片计算机,通常用于嵌入式系统中,集成了处理器核心(CPU)、内存、外设接口以及基本的外设模块
- MCU用于执行 简单 的控制和计算任务,适合用于低功耗、低成本和小规 模功能的应用
-
SoC(System on Chip):一种将整个系统的多个功能集成到单个芯片上的技术。SoC不仅包含一个或多个CPU核心,还可以集成图形处理单元 (GPU)、通信模块(Wi-Fi、蓝牙、LTE等)、存储单元、音频、视频处理单元,甚至是AI加速器等。
- SoC适用于需要高性能和多功能的 **复杂 **系统,如智能手机、平板电脑、 智能电视、智能家居的核心设备等
32位MCU的特点:性能强大、外设全面,SoC趋势
32位MCU主流内核:ARM Cortex-M内核,RISC-V内核,Tensilica Xtensa内核
SoC的基本分类方法:按照性能进行分类:超高性能,高性能,中等性能,弱性能
总线(Bus)是处理器内部功能模块传输信息的公共通道,传统MCU/SoC总线:
- **数据总线(Data Bus)**传输数据
- **地址总线(Address Bus)**传输地址
- **控制总线(Control Bus)**传递控制信号
MCU/SoC主流使用AMBA(Advanced Microcontroller Bus Architecture)高级微处理器总线架构。
AHB(Advanced High-performance Bus):AHB可以将微控制器(CPU)、高带宽的片上RAM、高带宽的外部 存储器接口、DMA总线控制器, 以及各种AHB接口的控制器等连 接起来,构成一套独立的完整的SoC系统。其是单通道总线,不能并行读写。特点:高速,高性能。
是否SoC的所有部件都需要高速总线?答:低速外设连接高速总线会拉低系统性能,有低速外设的SoC一般都要有低速总线。
APB(Advanced Peripheral Bus):低功耗精简接口总线,可以连接多种不同低速外设;主要应用在低带宽的外设 上,如GPIO、UART、I2C、WDT等。其是单通道总线,不能并行读写。特点:低速、性能相对较弱。
AHB与APB对比:
- AHB:高速、高性能、复杂协议
- APB:低速、低功耗、简单协议
AHB与APB之间不能直接连接,而要用Bridge:
- Bridge的主要作用:相互转换,包括速度,协议,地址映射
其他AMBA架构的总线:AXI(Advanced extensible Interface),ACE(AXI Coherency Extensions),CHI(Coherent Hub Interface)。

按键-SoC-LED控制的代码段:
#define PD4(*((volatile unsigned int*)0x40011404)) // volatile:变量易变化,编译器不要优化,每次都需要重新读取
#define PB5(*((volatile unsigned int*)0x40010C08))
int main() {
while(1) {
if(PD4==1) {
PB5=0;
}else{
PB5=1;
}
}
}
按键状态 | PD4==输入==电压 | PD4==输入==逻辑 |
---|---|---|
按键松开 | 0V | 低电平(0) |
按键按下 | VCC(3.3V) | 高电平(1) |
PB5输出逻辑 | PB5==输出==电压 | LED状态 |
---|---|---|
低电平(0) | 0V | 点亮 |
高电平(1) | VCC(3.3V) | 熄灭 |
第三章
GPIO(General Purpose Input/Output)具备基本的输入或输出的功能。GPIO的输入功能的特征:输入就是获知外部信号的状态,信号是从外至内的。输入:具备识别外部数字信号的功能。
- 按键按下:电路VCC(3.3V),高电平信号 -> 逻辑“1”
- 按键松开:电路0V,低电平信号 -> 逻辑“0”
GPIO的基本控制:
- 寄存器访问方式:读取输入电平状态(按位访问方式)
// 举例,如何获取第bit位的值
value = ((someRegister & (1 << bit)) >> bit)
// 以下是一个示例
#define someRegister(*((volatile unsigned int*)0x40011404))
unsigned char inputValue = 0; //保存第七位的值
unsigned int temp;
temp = someRegister;
inputValue = (unsigned char)((temp & (1 << 7)) >> 7); //填写此处的内容
- 寄存器访问方式:设置输出电平状态(同样是按位访问方式)
#define someRegister(*((volatile unsigned int*)0x40010C08))
// 第bit位设置为1(置位)
someRegister = someRegister | (1<<bit); // 或:someRegister |= (1<<bit)
// eg: 第8位设置为1
someRegister = someRegister |= (1<<8);
// 第bit位设置为0(复位)
someRegister = someRegister & ~(1<<bit); //或:someRegister &= ~(1<<bit)
// eg: 第9位设置为0
someRegister = someRegister &= ~(1<<bit);
- API访问方式:设置输出电平状态
#define GPIO_04 4
#define SW2_GPIO GPIO_04
typedef enum gpio_level {
GPIO_LEVEL_LOW,
GPIO_LEVEL_HIGH
} gpio_level_t;
gpio_level_t inputValue;
inputValue = uapi_gpio_get_val(SW2_GPIO);
if(inputValue == GPIO_LEVEL_LOW) {⋯⋯}
- 引脚复用:MCU或SoC的一个物理引脚在使用时,可以设置成多种外设的功能,该功能可以节约引脚资源,减小芯片体积。
#define SW2_GPIO GPIO_04
#define LED_GPIO GPIO_05
static int *keyled_task(const char *arg) {
unused(arg);
gpio_level_t inputValue;
uapi_pin_set_mode(SW2_GPIO,PIN_MODE_2);// 设置引脚
uapi_pin_set_mode(LED_GPIO,PIN_MODE_4);
uapi_gpio_set_dir(SW2_GPIO,GPIO_DIRECTION_INPUT);
uapi_gpio_set_dir(LED_GPIO,GPIO_DIRECTION_OUTPUT);
while(1) {
inputValue = uapi_gpio_get_val(SW2_GPIO);
if(inputValue == GPIO_LEVEL_LOW) {
uapi_gpio_set_val(LED_GPIO, GPIO_LEVEL_HIGH);
}else{
uapi_gpio_set_val(LED_GPIO,GPIO_LEVEL_LOW);
}
}
return 0;
}
- GPIO的输入输出、功能切换(复用)是需要设置的。GPIO的是否工作是可以受控的
errcode_t uapi_gpio_set_dir(pin_t pin, gpio_direction_t dir) // 输入输出
errcode_t uapi_pin_set_mode(pin_t pin, pin_mode_t mode) // 功能切换(复用)
void uapi_gpio_init(void) // 工作状态
void uapi_gpio_deinit(void)
GPIO的电气特性:
- GPIO的上拉/下拉是可以受控的。
// 内部上拉/下拉电路的控制:以WS63为例,四种可用模式
typedef enum {
PIN_PULL_TYPE_DISABLE = 0, //悬空,仅用于输入确定电平
PIN_PULL_TYPE_DOWN = 1, //下拉
PIN_PULL_TYPE_STRONG_UP = 2, //强上拉
PIN_PULL_TYPE_UP = 3, //上拉
PIN_PULL_MAX = 4 //无效
}pin_pull_t;
上拉/下拉电路仅可用于防止输入悬空,不具有带载能力(一般只能流过mA级别以下的电流)
- GPIO的电流驱动能力十分有限,绝大多数MCU/SoC的GPIO的输出模式下的电流在30mA以下,两种电流流向的最大电流能力不同。
-
==灌电流:电流由外部电路流入到芯片内部==
- GPIO的灌电流驱动能力可达20~30mA
- 直接驱动小高亮LED、小继电器、中功率三极管
-
==拉电流:电流由芯片内部流出到外部电路==
- GPIO的拉电流驱动能力偏小,一般mA级别
- 驱动普通小LED、小功率三极管
==中断的作用:==
- 提高系统响应效率
- 实现实时性
- 降低智能硬件系统设计的复杂性
- 提升系统资源利用率、降低系统功耗
- 支持系统多任务运行
MCU/SoC的中断:处理器执行程序的过程中,外部或内部的某些事件触发处理器暂时中断当前执行的任务,转去执行与该事件相关的特定程序,处理完事件后再返回继续原任务的过程
中断的流程如下图:
在程序中使用单一中断的要点:
- 实现中断服务程序(函数)
- 实现中断触发的软硬件条件
- 注册、设置和启用对应中断
- 触发中断、响应中断(系统自动实现)
- 执行中断服务程序,执行必要对中断的设置(系统自动实现)
在程序中使用中断应避免的问题:
- 避免在中断服务程序(ISR)执行复杂或消耗时间长的工作
- 避免在中断服务程序(ISR)对资源进行操作,以防与主程序产生冲突
==电平变化事件:==
- 高电平 -> 低电平:下降沿Falling-edge
- 低电平 ->高电平:上升沿Rising-edge
中断应用示例:将LED控制示例改写为中断模式
static void gpio_callback_func(pin_t pin, uintptr_t param) {
//⋯⋯
inputValue = uapi_gpio_get_val(SW2_GPIO); //进入中断后,还需要判断上升沿或下降沿
if(inputValue == GPIO_LEVEL_LOW) { //低电平,按键松开了
uapi_gpio_set_val(LED_GPIO,GPIO_LEVEL_HIGH); //LED灭
}else{ //高电平,按键按下了
uapi_gpio_set_val(LED_GPIO,GPIO_LEVEL_LOW); //LED亮
}
}
static void *button_task(const char *arg) {
//⋯⋯ //初始化GPIO、按键和LED初始态等,略
errcode_tret = uapi_gpio_register_isr_func(SW2_GPIO,GPIO_INTERRUPT_DEDGE,gpio_callback_func);
if(ret != 0) {
uapi_gpio_unregister_isr_func(SW2_GPIO);
}
while(1) {
uapi_watchdog_kick(); //看门狗,后面会讲
osal_msleep(2000); //延时,模拟其他任务占用CPU
}
}
[!NOTE]
中断的引入,大幅度降低了按键查询对系统资源的占用,降低耦合,提高内聚,简化系统开发
uapi_gpio_set_val(LED_GPIO,GPIO_LEVEL_HIGH)
和uapi_gpio_set_val(LED_GPIO,GPIO_LEVEL_LOW)
两个函数,进行了对硬件的“控制”操作,在其他任务中,应避免对同一硬件的控制操作以防止硬件运行故障。可以使用互斥锁保证LED控制的唯一性。
Q:若有多个中断事件怎么办?
中断优先级:中断事件被处理的顺序机制。作用:中断优先级用于确保关键性或时间敏感的任务能够得到及时处理。中断涉及到现场保护等机制,每次处理中断都要占用系统资源
中断规则:
- 每个中断都需要分配(或使用默认的)优先级
- ==优先级数值(Prio(n))越小,优先级越高,优先级为0的中断的优先级最高==
- 高优先级的中断可以打断低优先级的中断服务程序
- 低优先级的中断不能打断高优先级的中断服务程序
- 相同优先级的中断不能打断同优先级的中断服务程序
eg:当Prio(SW2) >Prio(SW3):fucn2能够被打断,构成中断嵌套,fucn2执行过程中,执行func3,func3执行完,再继续执行func2,即fun3的时效性能够得到保障
以数字信号为主的现代信息系统,在输入/感知阶段就首先将模拟信号转换为数字信号再进行后续的处理。==模拟到数字转换的外设:ADC(Analog-to-Digital Converter,模数转换器)==
==ADC的关键参数:==
-
分辨率(Resolution):位数的多少
-
表征:ADC的量化精度,分辨率越高对模拟信号的表达越好
-
分辨率越高,精确程度越高
-
分辨率越高,存储空间越大
量化等级:n位 -> 2^n^个量化的等级
-
-
转换速率(Conversion Rate):ADC每秒钟能够完成的模数转换的次数,通常以SPS为单位
- 转换速率越快,单位时间采集的数据越多,对模拟信号的表达越好
- 转换速率越快,精确程度越高;转换速率越快,存储空间越大
-
**量程(Full-Scale Range):**ADC能够测量的输入信号的电压范围。对于N位分辨率的ADC而言
- 量程的最小值:输出数值为 0
- 量程的最大值:输出数值为 2^N^-1
- 超出该范围的电压:无法测量,甚至损坏ADC
- 数值上量程等于ADC的”参考电压V
ref”(共GND)
-
**输出形式(Output):**ADC以何种形式将转换后的结果输出
- 信息的形式:电信号、光信号、电磁波、其他形式
- 信息的格式:十进制、十六进制
- 通信的协议:以太网、Wi-Fi、BT、SLE、I2C、UART
==ADC的计算方式:==当分辨率为N时
-
量程范围:[0,V
ref] -
单端ADC(共GND)输出值:
eg: 假设某ADC分辨率N=12,V
ref=3.3V- 最低位的1位代表的电压值(LSB):≈0.0008V
- 输入0V的转换结果为:0
- 输入1.65V的转换结果为:=2047
- 输入3.3V的转换结果为:4095
- 如果V
ref=5.0V,输入1.65V对应的转换结果为:≈1351
第四章
信息系统中时间的表示方法:
-
时间戳形式 - 大尺度计时
- Unix时间:自1970年1月1日0时0分0秒起的秒数
- ISO8601标准(更易于人类理解),如2025-01-29T01:23:34+08:00、2025-03-01T02:34:45Z
-
时间间隔 - 小尺度计时:两个时间点时间间隔
-
逻辑时间:即事件的相对顺序
-
智能硬件系统内部一般使用时间间隔进行计时和任务调度,使用时间戳进行用户交互
信息设备(智能硬件设备)的计时实现基础:
-
有能够产生稳定的特定频率信号的器件 ->晶体振荡器或振荡电路
-
有能够对该器件产生的信号进行捕获/采集的电路或功能
-
有能够对该捕获信号的周期进行统计的电路或功能
常用的稳定的频率信号源:民用信息设备一般使用晶体振荡器作为高精度频率信号源。石英晶体振荡器是一种高度稳定的电子振荡器
信息设备(智能硬件设备)计时系统的主要结构:(按序号为处理顺序)
- 晶体振荡器:产生稳定的固定频率的信号
- 处理电路:信号形式和幅度达到要求
- 内部电路:产生系统时钟,供内部使用;也包括对频率信号的处理,例如调整频率、预分频等
- 计数器:对特定频率的信号进行计数,即可得到时间的间隔
- 理论计算演示:
-
计数器输入频率为32768Hz,计数器进行计数16384次的时间是多少?
时间 = = 0.5 秒
-
计数器输入频率为240MHz,计数器长度16位,达到最大计数时间是多少?
- 输入频率:240 MHz = 2.4×10^8^ Hz
- 计数器位数:16位 → 最大计数值 = 2^16^−1 = 65535(从0开始)
- 计数次数:从0计数到65535,共 65536 次(含0)
- 时间 = 计数次数 ÷ 频率
- 时间 = ≈ 273.07μs
系统时钟CLK(Clock):
- 由晶体振荡器(其他振荡器/信号源)输出的信号经处理后产生时钟信号
- 时钟信号可以被配置调整频率,如进行分频或PLL倍频等
- MCU/SoC内部可能会有多个系统时钟,提供不同的频率或备份
- 系统时钟为CPU、RAM和各类外设提供运行必须的时钟信号
- 同一外设,工作的时钟频率越高,功耗就越高
WS63定时器的控制流程:
- 定时器在智能硬件系统中的目的:特定时间间隔后的提醒
- 定时器的启用和销毁流程:
==定时器系统练习:==
- 要求:使用osal_printk(“%02d:%02d:%02d”,hour,min,sec)输出时间信息,每秒钟使用上述格式输出一次时间信息
// from RXCCCCCC
#include "timer.h"
#include "tcxo.h"
#include "chip_core_irq.h"
#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#define TIMER_INDEX 1
#define TIMER_PRIO 1
#define TIMER_DELAY_INT 5
#define TIMER_TASK_PRIO 24
#define TIMER_TASK_STACK_SIZE 0x1000
uint32_t hour = 0, min = 0, sec = 0;
timer_handle_t timer_index[1] = { 0 };//存储构建好的相应的定时器句柄
static uint8_t flag;//记录是否有发生过中断
static void timer_timeout_callback(uintptr_t data)//中断回调函数
{
uint32_t index = (uint32_t)data;//从data中得到是哪个计时器到点
flag=1;
uapi_timer_start(timer_index[index],1000000, timer_timeout_callback, index);//重启该计时器
}
static void *timer_task(const char *arg)
{
unused(arg);//不使用该参数
uapi_timer_init();//计时器初始化
uapi_timer_adapter(TIMER_INDEX, TIMER_1_IRQN, TIMER_PRIO);//计时器适应
uapi_timer_create(TIMER_INDEX, &timer_index[0]);//计时器创建
uapi_timer_start(timer_index[0], 1000000, timer_timeout_callback, 0);//计时器启动
while (1) {
if(flag){//中断触发过了
sec++;
if (sec >= 60) {
sec = 0;
min++;
if (min >= 60) {
min = 0;
hour++;
if (hour >= 24) {//别忘了小时
hour = 0;
}
}
}
osal_printk("%02d:%02d:%02d\r\n", hour,min,sec);
flag=0;
}
osal_msleep(TIMER_DELAY_INT);
}
uapi_timer_stop(timer_index[0]);//停止计时器,防止持续运行
uapi_timer_delete(timer_index[0]);//删除计时器
uapi_timer_deinit();//去初始化
return NULL;
}
static void timer_entry(void) {
osal_task *task_handle = NULL;
osal_kthread_lock();
task_handle = osal_kthread_create((osal_kthread_handler)timer_task, 0,
"TimerTask", TIMER_TASK_STACK_SIZE);
if (task_handle != NULL) {
osal_kthread_set_priority(task_handle, TIMER_TASK_PRIO);
osal_kfree(task_handle);
}
osal_kthread_unlock();
}
app_run(timer_entry)
==看门狗(Watchdog):==看门狗定时器是目前最简单且有效的软硬件协同的系统监控机制
-
信息系统(智能硬件)系统中的看门狗:一种简单的系统监控机制,基于软件和硬件的协同作业原理,确保系统能够在可预测的程序路径上执行,一 旦系统出现流程异常,能够在规定的时间内强迫系统复位,重新运行
-
看门狗定时器(Watchdog Timer,WDT)是一种硬件计时器,主要用于检测 和恢复系统故障,其核心作用是防止系统长时间无响应或陷入死循环,从 而提高系统的稳定性和可靠性
-
硬件:首次设置看门狗定时器的定时时间,开始进行减计数。
- 正常进行减计数的过程是按照WDT时钟进行的,减计数溢出之后,触发系统复位(WS63还可以选择先触发中断)
-
软件:可重新设置看门狗定时器的定时时间(喂狗),重新开始进行减计数
-
Systick:一种为系统提供连续的时间间隔计数的硬件定时器
-
用于实现延时函数、计算时间间隔、执行任务调度等
-
与常规定时器的区别:
- Systick结构简单,一般只进行初始化和读操作
- Systick随MCU/SoC不同,可能有增计数和减计数两种类型
- Systick的计数器长度更长,一般为24位、32位、48位或更长
- Systick通常具备中断能力,但一般被系统占用,用于任务切换
- Systick随系统启动之后一直运行,一般不会停止或复位
- 用户在使用Systick时,应对Systick的只进行读取访问
-
带有OS的MCU/SoC的Systick一般会被系统默认占用,用户应避免进行控制和写入操作
时间间隔定时器分为:
- 通用定时器Timer:用户设定定时时间,到达时间触发中断
- 看门狗定时器WDT:用户设定时间,软硬件协同监控系统状态
- 嘀嗒定时器Systick:系统设定,用户只进行读取操作(建议)
时间戳计时器:
- RTC(Real Time Clock)实时时钟,用于提供持续的、准确的时间跟踪功 能,以人类易于阅读的年月日时分秒的形式进行记录、计时和输出
- RTC在绝大多数MCU/SoC中,都需要外部备用电池功能(纽扣电池),RTC实现保持和计时功能的基础是外部供电,都是外部供电会导致全部信息丢失
- RTC的耗电量极低,工作电流一般在 uA 甚至更低的级别
- RTC自带年月日时分秒星期闰年等计算功能,无需用户计算(ISO8601)
第五章
时序图:描述电路中信号、事件、时钟等随时间变化行为,特别是多个信号或组件相互作用的时间和顺序。其被广泛用于描述信号的时序关系,例如时钟信号、控制信号、输入输出信号等
[!IMPORTANT]
- 检测到下降沿,再延迟Δt/2后,需要确认是L(低电平),再开始接收
- 每隔Δt读取一次并接收1bit,8Δt后共接受8bit,即1Byte
- 同样,接收完毕后读取到H(高电平)才算接收成功
- 双方Δt一致即可数据传输
UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,是信息系统最通用、最广泛、最经典的通信方式。特点/基本参数:
-
UART的传输速率灵活:△t时间不易记忆,转换为速率进行表示
- 波特率:每秒钟传输的位数(起始位+数据位+停止位+校验位)。常用波特率:9600、19200、38400、115200等
-
UART的数据格式灵活:数据位长度灵活、停止位灵活、校验位灵活
- 起始位:固定长度,统一为1位
- 数据位:多种长度设定,可5、6、7、8、9位
- 停止位:多种长度设定,可1、2位
- 校验位:多种校验方式:无0位、奇校验1位、偶校验1位
- 通常的位排列顺序:起始位(Start Bit) -> 数据位(Data Bits) -> 校验位(Parity Bit) -> 停止位(Stop Bit)
-
常用的UART格式:9600 8N1,115200 8N1
UART格式标准如下:[波特率] [数据位数] [校验类型] [停止位数]
例如9600 8N1表示:
-
波特率:9600 bps(bit per second)
-
数据位数:8 位(从0开始到7)
-
校验类型:N = None(无校验位)
-
停止位数:1 位
-
校验位类型常见的有:
-
符号 含义 N None(无校验) E Even(偶校验) O Odd(奇校验) M Mark(总是1) S Space(总是0)
-
-
UART的连接形式:TX -> RX
-
传输模式(不限于UART)
- 单工(Simplex):只能由A->B
- 半双工(Half-Duplex):可以由A->B,或者由B->A,但不能同时实现双向传输
- 双工(全双工)(Full-Duplex):可以同时实现A->B和B->A的双向传输
-
==UART机制主要问题:==
-
**通信速率低:**UART常见最高速率只有115200bps(信号层面的异步问题)
-
**异步通信、缺乏流控:**发送方和接收方需要通过软件来管理数据流,若接收方的缓冲区已满而发送方仍在发送数据,会引起数据丢失
-
**原生UART系统的设备数量受限:**UART只能连接两个设备,若需要多个设备相互通信,只能使用多个UART接口
- 可通过技术手段扩展成RS422/485,实现多个节点通信
- RS485双线差分,最大电压差能达到±10V以上,且只能半双工传输
-
**原生UART系统的通信距离受限:**高速下UART的安全通信距离不到1米
- 但可通过技术手段扩展成RS232/485,实现数十米至公里级的通信
-
后果:UART的通信设备数量受限,以及通信速率低,使MCU/SoC难以同时连接多个外设
-
I2C通信系统的结构与要点:
-
主设备Master:控制系统通信的设备,用于生成时钟信号,发起数据传输,指定通信目标
-
从设备Slave:响应Master请求,接收或发送数据,没有时钟控制能力
-
数据线SDA/SDL:Serial Data Line,串行数据线,用于传输数据
-
时钟线SCL:Serial Clock Line,串行时钟线,用于同步数据传输
-
设备地址:每个I2C设备都有唯一的地址,一般是7位(居多)或10位
-
数据传输:同步传输协议,Master控制时钟信号,控制数据传输同步
- 传输的数据以字节为最小单位,数据与控制信息共同构成I2C的帧结构
-
半双工通信:同一时刻只能有一个设备传输数据,但可分时双向传输
-
多设备支持:不仅支持多个Slave,也可以支持多个主设备
I2C通信格式的帧格式:
I2C的连接形式:所有的SDA连在一起,所有的SCL连在一起
I2C的传输形式:半双工通信,靠地址区分Slave,所有的通信(包括读取)都由Master发起
I2C的传输速率:标准模式(Standard Mode)100Kbps、快速模式(Fast Mode)400KBps、增强快速模式(Fast Mode+)1Mbps、高速模式(High Speed Mode)3.4Mbps
I2C与UART的主要不同点:
- UART双方通信上是对等的,没有主从之分
- I2C在通信上,Master控制着I2C总线全部设备的接收和发送行为
WS63 I2C的主要API - Master:
errcode_t api_i2c_master_init(i2c_bus_t bus,uint32_t baudrate,uint8_t hscode)
i2c_bus_t bus // 设置使用的I2C,WS63有两组I2C硬件外设,包括I2C_BUS_0和I2C_BUS_1
uint32_t baudrate // I2C总线SCL频率,数值即可,如4000000表示400Kbps
uint8_t hscode // I2C总线中Master的地址,可设定值为[0,7]
errcode_t api_i2c_master_write(i2c_bus_t bus,uint16_t dev_addr,i2c_data_t *data)
uint16_t dev_addr // 通信目标Slave的地址
i2c_data_t *data // 待发送的数据的结构体的指针
typedef struct i2c_data {
uint8_t *send_buf; //发送数据的buffer指针,保存Command(待发送的指令)
uint32_t send_len; //发送数据的buffer长度,按照图示为1
uint8_t *receive_buf; //接收数据的buffer指针,保存Data
uint32_t receive_len; //接收数据的buffer长度,按照图示为2
} i2c_data_t;
errcode_t api_i2c_master_read(i2c_bus_t bus,uint16_t dev_addr,i2c_data_t *data)
从slave读取的流程:
WS63 I2C与外部设备(RTC)通信示例:
I2C引脚复用 -> Master初始化速率 -> 初始化外设 -> …… -> 读外设数据 写外设状态
读取INS5699的时间数据:
ins5699s_time ins5699s_GetTime(void){
ins5699s_time time;
uint8_t t_reg;
t_reg = ins5699s_ReadREG(INS5699S_REG_SEC);
time.sec = (((t_reg&0x70)>>4)*10)+(t_reg&0x0F);
t_reg=ins5699s_ReadREG(INS5699S_REG_MIN);
time.min=(((t_reg&0x70)>>4)*10)+(t_reg&0x0F);
t_reg=ins5699s_ReadREG(INS5699S_REG_HOUR);
time.hour=(((t_reg&0x30)>>4)*10)+(t_reg&0x0F);
t_reg=ins5699s_ReadREG(INS5699S_REG_WEEK);
//处理星期time.week、日time.day、月time.month、年time.year的数据,略
return time;
}
芯片中的时间寄存器通常使用 BCD(Binary-Coded Decimal)编码,即每个十进制位用 4 个二进制位来存储
以如下代码为例:
t_reg = ins5699s_ReadREG(INS5699S_REG_SEC); time.sec = (((t_reg & 0x70) >> 4) * 10) + (t_reg & 0x0F);
读取秒寄存器的值
t_reg & 0x70
:提取高 3 位(十位的 BCD)
>> 4
:将其移到低位后乘以 10(得到“十位数”)
t_reg & 0x0F
:提取低 4 位(个位);相加后得到十进制秒数。
例如:
t_reg = 0x45 // 二进制 0100 0101 => ((0x40 >> 4) * 10) + 0x05 = (4 * 10 + 5) = 45 秒
SPI通信系统的特点与结构:
- 全双工通信:同一个时钟周期内同时进行发送和接收
- 同步通信:通过时钟进行与Slave的同步发送和接收
- 传输速率高:速率可以达到几十Mbps以上
- 无地址多设备:通过独立的信号线选择Slave进行通信
- MOSI(Master Out Slave In):主设备发送,所有从设备均能接收
- MISO(Master In Slave Out):某从设备发送,所有设备均能接收
- SCK(Serial Clock):主设备发送,所有从设备均能接收
- CS(Chip Select):主设备发送,只有特定的从设备被选中
==三种板内通信对比:==
特性 | UART | I2C | SPI |
---|---|---|---|
通信方式 | 全双工 | 半双工 | 全双工 |
引脚使用 | 2根 TX/RX | 2根 SDA/SCL | 4根 MISO/MOSISCK/CS |
主从模式 | 无主从 | 多主机/多从机 | 单主机/多从机 |
通信速率 | ~100Kbps | ~3.4Mbps | 几十Mbps |
设备数量 | 2 | 地址范围内 | 受CS引脚数量限制 |
协议复杂性 | 简单 | 较复杂 | 较简单 |
错误检测 | 校验位 | 无 | 无 |
设备地址 | 无 | 有 | 无 |
常见应用 | 设备调试、通信设备、卫星定位设备等 | 传感器、外扩存储、RTC、显示模块等 | 存储设备、音频设备、高速传感器等 |
第六章
==基于线性电压调节器的功率控制==
==脉冲宽度功率控制==:目前最常见的功率控制方法(没有之一),广泛应用于电源转换、电机驱动、LED调光等领域。
- 核心思想:控制开关器件的通断时间,调节等效输出功率或电压
- 使用一种信号(开关信号)控制另一种信号(电压)的形态:脉冲宽度调制
- ==脉冲宽度调制(PWM,Pulse Width Modulation)==的主要参数:
- **波形:**只有一种类型,方波信号(高低电平控制开关器件的通断)
- **频率:**PWM信号频率,表征开关器件的开关速度,受开关器件速度限制
- **占空比(Duty Cycle):**PWM信号中高电平持续的时间比例,其直接决定了平均电压和功率输出,占空比越大,输出功率或电压越高
==PWM的占空比(Duty Cycle)的计算:==
-
𝐷𝑢𝑡𝑦 𝐶𝑦𝑐𝑙𝑒 =
- 范围:[0,100]%
-
T
total= Ton+ Toff(高电平不一定对应on) -
占空比是比值,与频率无关
例:在PWM为10%的情况下
频率 高电平时间 低电平时间 1kHz 100 μs 900 μs 2kHz 50 μs 450 μs
上图中,ARR(自动重装载寄存器)决定周期时间,CCR(捕获比较寄存器)决定高电平持续时间
- ==占空比 = ==
发声类输出设备:蜂鸣器(Buzzer),用小功率三极管或MOSFET驱动
- 工作原理:利用压电效应,电流通过压电陶瓷片时使其变形,产生声音
- 声音类型:声音频率高,音调单一且连续(不同于喇叭)
- 无源蜂鸣器(常用):内部没有振荡电路,依靠外界信号控制声音属性
- 工作电压:MCU/SoC板载常用3V或5V
- 工作电流:几mA至几十mA
- PWM控制的声音主要属性:
- 音调(频率):频率越高,音调越尖锐;频率越低,音调越低沉
- 音量:占空比越高,蜂鸣器功率越大,声音越响;占空比越低,声音越弱
动作类输出设备:电机
-
改变旋转方向的本质:改变流经电机的电流方向:H-Bridge芯片L9110S(6.3mm×5.0mm×1.8mm)
-
L9110S内部集成逻辑控制电路、具备高效、低压工作等特性
IB H | IB L | |
---|---|---|
IA H | 刹车 | 正转 |
IA L | 反转 | 待机 |
WS63 PWM的使用流程(应先执行 init):
-
配置PWM属性的结构体
typedef struct pwm_config { uint32_t low_time; // 三个时间元素,如low_time,实际上的时间是low_time×T,课程使用的WS63版本的T=12.5ns uint32_t high_time; uint32_t offset_time; uint16_t cycles; // cycles为PWM信号周期数,有效范围[0,32767] bool repeat; } pwm_config_t; // 例如: pwm_config_t LEDConfig = {100, 100, 0, 0, true};
-
设置输出PWM的复用引脚
-
开启指定的PWM通道
errcode_t uapi_pwm_open(uint8_t channel, const pwm_config_t *cfg)
uint8_t channel
:PWM通道,有效范围[0, 7]const pwm_config_t *cfg
:PWM配置结构体
-
设置PWM分组,启动PWM分组
errcode_t uapi_pwm_set_group(uint8_t group, const uint8_t *channel_set, uint32_t channel_set_len)
uint8_t group
:分组ID,有效范围[0, 7]const uint8_t *channel_set
:包含有该分组中成员通道的数组uint32_t channel_set_len
:该分组中的通道数量errcode_t uapi_pwm_start_group(uint8_t group)
:启动指定分组