从零构建嵌入式通信协议:UART数据帧的微观世界与实战解析

UART传输层通信协议详解:从原理到实战应用 UART历经数十年发展仍是嵌入式系统的通信基石。其设计精髓在于简单性与灵活性的平衡对于传感器数据采集、调试日志输出等场景,UART仍是首选方案在工业控制领域,结合RS-485可构建可靠的多节点网络通过软件协议扩展(如SLIP、COBS编码),可实现长数据包传输随着物联网设备的普及,UART在BLE模组、NB-IoT模组的AT指令控制中继续发挥重要作用。理解其底层机制,开发者便可更高效地解决实际工程问题。 阅读详情

从零构建嵌入式通信协议:UART数据帧的微观世界与实战解析

在嵌入式系统的世界里,通信协议如同设备之间的语言,而UART(通用异步收发传输器)无疑是最基础却又最常用的一种。对于刚踏入嵌入式开发领域的技术人员来说,理解UART不仅仅是学会配置几个寄存器那么简单,更是要深入数据帧的微观世界,掌握其底层时序逻辑和故障排查技巧。本文将带你从最基础的信号波形开始,通过逻辑分析仪捕获的真实数据,结合STM32F103的实战操作,一步步揭开UART通信稳定性的神秘面纱。

1. UART通信基础:从信号波形到数据帧结构

UART通信的核心在于其简单的两根线(TX和RX)实现全双工数据传输,但这种简单背后隐藏着精确的时序要求。每一帧数据都遵循严格的格式:起始位(低电平)、数据位(5-9位,常用8位)、可选的奇偶校验位以及停止位(高电平)。这种格式看似简单,但在实际应用中,任何细微的时序偏差都可能导致通信失败。

关键要点:

  • 起始位总是低电平,标志着数据帧的开始
  • 数据位传输顺序是从最低位(LSB)到最高位(MSB)
  • 停止位必须是高电平,为下一帧数据提供必要的间隔时间
  • 总线空闲时保持高电平状态

在实际调试中,我经常发现初学者容易忽略电平转换的细节。例如,STM32F103的I/O口默认是浮空输入状态,如果不正确配置为复用推挽输出(TX)和浮空输入(RX),即使寄存器配置正确也无法正常通信。

2. STM32F103的UART硬件配置实战

STM32F103的USART模块提供了丰富的配置选项,但核心配置集中在几个关键寄存器上。让我们通过实际代码来理解如何正确初始化和使用UART模块。

首先需要配置GPIO引脚,PA9作为TX引脚需要配置为复用推挽输出,而PA10作为RX引脚应配置为浮空输入。这一步很多开发者会忽视速度配置,实际上在高速通信时,GPIO速度设置不当会导致信号边沿不够陡峭,增加误码风险。

// GPIO初始化结构体配置
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;        // TX引脚
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;   // 复用推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // 速度设置很重要
GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;       // RX引脚  
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_Init(GPIOA, &GPIO_InitStruct);

USART本身的配置需要特别注意波特率计算。STM32F103使用分数波特率发生器,实际波特率计算公式为:波特率 = fCK / (16 * USARTDIV),其中USARTDIV是一个包含整数和小数部分的数值。如果计算不精确,就会产生累积误差,导致数据接收错误。

参数推荐值说明
波特率115200常用值,平衡速度与稳定性
数据位8位最常用的配置
停止位1位除非特殊要求,否则使用1位
奇偶校验无大多数应用不需要校验
硬件流控无简单应用中通常禁用

3. 数据帧的微观分析:逻辑分析仪实战技巧

要真正理解UART通信,必须学会使用逻辑分析仪观察实际的数据波形。通过连接逻辑分析仪的探头到TX和RX线,可以捕获到真实的通信时序,这是调试通信问题的最直接方法。

典型的数据帧分析步骤:

  1. 设置合适的采样率(至少为波特率的4倍)
  2. 捕获完整的通信过程,包括多个数据帧
  3. 测量起始位到第一个数据位的时间间隔
  4. 检查每个位的持续时间是否一致
  5. 验证停止位是否正确保持高电平

在实际项目中,我曾遇到一个典型的波特率不匹配问题:主机发送端使用115200波特率,而从机接收端配置为112500。虽然误差只有2.3%,但在大数据量传输时,误差累积导致接收端逐渐失去同步,最终出现帧错误。通过逻辑分析仪捕获的波形清晰显示了位宽度的微小差异,帮助快速定位问题。

调试提示:当遇到间歇性通信故障时,建议捕获至少100帧数据进行分析。随机错误往往是由时序偏差累积造成的,单次捕获可能无法发现问题。

波形分析中还需要注意电平电压的稳定性。虽然STM32F103使用3.3V逻辑电平,但长距离传输时可能会产生压降。使用示波器测量实际波形时,要确保高电平至少达到2.4V,低电平不超过0.4V,否则可能被误判为无效电平。

4. 高级调试技巧:异常情况处理与优化

在实际应用中,UART通信会遇到各种异常情况,需要具备相应的处理机制。STM32F103的USART提供了多个状态标志位来帮助诊断问题。

关键状态标志位及其含义:

  • RXNE(接收缓冲区非空):表示数据已接收并可以读取
  • TXE(发送缓冲区空):表示可以写入新的发送数据
  • ORE(溢出错误):数据丢失,因为前一个数据尚未读取
  • FE(帧错误):停止位检测失败
  • NE(噪声错误):在接收过程中检测到噪声
// 健壮的数据接收函数示例
uint8_t UART_ReceiveByte_Timeout(uint32_t timeout)
{
    uint32_t start_time = GetTickCount();
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
    {
        if(GetTickCount() - start_time > timeout)
        {
            return 0xFF; // 超时返回错误值
        }
    }
    
    // 检查错误标志
    if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) ||
       USART_GetFlagStatus(USART1, USART_FLAG_FE) ||
       USART_GetFlagStatus(USART1, USART_FLAG_NE))
    {
        USART_ClearFlag(USART1, USART_FLAG_ORE | USART_FLAG_FE | USART_FLAG_NE);
        return 0xFE; // 错误标志
    }
    
    return USART_ReceiveData(USART1);
}

对于大量数据通信,建议使用DMA而不是中断方式。DMA可以大大减少CPU开销,避免因中断响应延迟导致的数据丢失。特别是在高速通信(如921600波特率)时,中断服务程序可能无法及时处理每个字节。

DMA配置关键步骤:

  1. 配置USART的DMA请求
  2. 设置DMA通道和优先级
  3. 配置内存到外设或外设到内存的传输方向
  4. 设置数据传输的字节数
  5. 启用DMA和USART的相应功能

5. 上位机通信实战:数据协议设计技巧

与上位机(PC软件)通信时,仅仅实现字节传输是不够的,需要设计一套完整的数据协议。好的协议应该包含帧头、数据长度、校验和等字段,确保数据的完整性和正确性。

一个典型的通信协议帧结构:

字段长度说明
帧头2字节固定为0xAA55,用于帧同步
数据长度1字节指示数据字段的字节数
命令字1字节区分不同的功能命令
数据N字节实际传输的数据内容
校验和1字节前面所有字节的累加和校验
// 协议解析状态机示例
typedef enum {
    STATE_HEADER1,
    STATE_HEADER2, 
    STATE_LENGTH,
    STATE_CMD,
    STATE_DATA,
    STATE_CHECKSUM
} ParserState;

void ParseProtocol(uint8_t data)
{
    static ParserState state = STATE_HEADER1;
    static uint8_t buffer[256];
    static uint8_t index = 0;
    static uint8_t length = 0;
    static uint8_t checksum = 0;
    
    switch(state)
    {
        case STATE_HEADER1:
            if(data == 0xAA) {
                state = STATE_HEADER2;
                checksum = data;
            }
            break;
            
        case STATE_HEADER2:
            if(data == 0x55) {
                state = STATE_LENGTH;
                checksum += data;
            } else {
                state = STATE_HEADER1;
            }
            break;
            
        // 其他状态处理...
    }
}

在实际项目中,我发现添加超时机制至关重要。当一帧数据没有完整接收时,状态机应该能够自动重置,避免一直等待不完整的数据帧。通常设置20-50ms的超时时间,超过这个时间就重置状态机到初始状态。

6. 常见故障排查与性能优化

UART通信中最常见的问题包括波特率不匹配、电平异常、接地问题等。通过系统性的排查方法,可以快速定位并解决这些问题。

常见故障排查清单:

  1. 通信完全失败

    • 检查硬件连接:TX/RX是否交叉连接
    • 验证电平转换:3.3V与5V设备间需要电平转换
    • 确认共地:所有设备必须共地
  2. 数据错误或乱码

    • 检查波特率精度:使用示波器测量实际位宽度
    • 验证时钟配置:系统时钟是否正确配置
    • 检查电磁干扰:长距离传输时使用屏蔽线
  3. 间歇性通信故障

    • 检查电源稳定性:电压波动会影响通信
    • 验证缓冲区管理:避免数据溢出
    • 评估CPU负载:高负载可能导致中断丢失

性能优化方面,可以考虑以下几个方向:

  • 使用硬件流控:当传输大量数据时,CTS/RTS流控可以防止数据丢失
  • 优化缓冲区设计:使用环形缓冲区提高数据处理效率
  • 采用DMA传输:减少CPU开销,提高系统整体性能
  • 实现协议压缩:对传输数据进行压缩,减少传输时间
// 环形缓冲区实现示例
#define BUFFER_SIZE 256

typedef struct {
    uint8_t buffer[BUFFER_SIZE];
    uint16_t head;
    uint16_t tail;
} RingBuffer;

void RingBuffer_Init(RingBuffer *rb)
{
    rb->head = 0;
    rb->tail = 0;
}

uint8_t RingBuffer_Put(RingBuffer *rb, uint8_t data)
{
    uint16_t next = (rb->head + 1) % BUFFER_SIZE;
    if(next == rb->tail) return 0; // 缓冲区满
    
    rb->buffer[rb->head] = data;
    rb->head = next;
    return 1;
}

uint8_t RingBuffer_Get(RingBuffer *rb, uint8_t *data)
{
    if(rb->tail == rb->head) return 0; // 缓冲区空
    
    *data = rb->buffer[rb->tail];
    rb->tail = (rb->tail + 1) % BUFFER_SIZE;
    return 1;
}

通过深入理解UART通信的每个细节,并结合实际的调试经验,开发者能够构建出稳定可靠的嵌入式通信系统。记住,每一个成功的通信协议背后,都是对细节的精心把控和对异常情况的周密处理。

深入解析嵌入式通信协议:UART、SPI、IIC、CAN的实战对比 本文深入解析嵌入式系统中常用的UART、SPI、IIC、CAN四种通信协议,通过实战对比分析它们在连接方式、通信模式、时钟控制、抗干扰能力和扩展性等方面的差异。文章详细介绍了每种协议的工作原理、硬件连接、数据帧结构及常见问题解决方案,并提供了选型建议,帮助开发者根据项目需求选择最合适的通信协议。 阅读详情

相关推荐

从零构建嵌入式通信协议:HC32F005 UART多机通信中的SM2位与地址掩码实战解析

本文深入解析HC32F005微控制器UART多机通信中SM2位与地址掩码寄存器的实战应用。通过硬件级地址过滤机制,实现一主多从架构的高效稳定通信,涵盖核心配置、代码实现及常见调试问题解决方案,为嵌入式通信协议开发提供实用指导。

night的博客 948

UART 通信协议详解

UART (通用异步收发器) 是一种常用的串行通信协议,用于在计算机和外部设备之间传输数据。它是一种异步通信协议,也就是说数据的传输不需要事先建立好同步时钟信号。UART 协议定义了数据传输的格式和通信规则。它包括一系列的控制信号和数据线来实现双向的串行通信。常见的 UART 协议有 RS-232、RS-422 和 RS-485 等。UART 协议的数据传输是基于帧(Frame)的概念的。每个数据帧由一个起始位、若干个数据位、一个可选的奇偶校验位和一个或多个停止位组成。

Projectsauron 的博客 5万+

从零构建嵌入式人机交互:STM32与淘晶驰串口屏的协议对话艺术

本文详细介绍了如何从零构建STM32与淘晶驰串口屏之间的嵌入式人机交互系统。通过设计分层通信协议、实现数据帧解析状态机、应用抗干扰策略和错误处理机制,确保通信的稳定可靠。重点阐述了应用层协议设计,包括LED控制等具体实现,为工业控制和智能家居应用提供了一套完整的解决方案。

day7的博客 739

嵌入式通信协议完全解析:UART_SPI_I2C_CAN实战应用指南

CAN(Controller Area Network)是一种专门用于工业控制的串行通信协议。CAN的特点:高可靠性:错误检测和纠正机制完善多主架构:任何节点都可以发送数据优先级仲裁:基于消息ID的优先级长距离:可达数千米高速:可达1Mbps✅ 通信协议的基本原理✅ UART串口通信的配置和应用✅ SPI高速数据传输的实现✅ I2C多设备总线管理✅ CAN工业总线应用✅ 协议选型和系统设计✅ 调试技巧和问题诊断✅ 性能优化和错误处理。

Mumyi_的博客 1453

从零构建嵌入式GUI:淘晶驰串口屏与STM32的通信协议深度解析

本文深度解析淘晶驰串口屏与STM32的通信协议实现,涵盖从基础帧结构设计到STM32F103C8T6的串口发送与数据处理实战。通过自定义协议增强通信可靠性,整合CRC校验和超时重传机制,确保工业环境下数据显示的稳定性和实时性,为嵌入式GUI开发提供完整解决方案。

y2z3a4b5c的博客 960

UART接口设计与通信协议详解

文档中应包括以下内容:接口定义表:明确各引脚功能、电平标准、驱动能力等。| 引脚名称 | 功能描述 | 电气特性 | 连接方式 || TXD | 发送数据 | 3.3V TTL | 连接外设RXD || RXD | 接收数据 | 3.3V TTL | 连接外设TXD |

weixin_42418754的博客 1402

通信协议UART、i2c、SPI与电平标准梳理

记录一下嵌入式中经常容易混淆的几个概念

xi_xix_i的博客 7790

InfiniBand(IB)实战指南:从硬件配置到性能优化

本文是一份详尽的InfiniBand实战指南,涵盖从硬件选型、部署到驱动配置、性能优化的全流程。重点解析了InfiniBand作为AI训练与高性能计算(HPC)核心网络的优势,特别是其支持的RDMA技术如何实现微秒级低延迟。文章提供了硬件匹配、NCCL压测、内核参数调优及在PyTorch分布式训练中启用IB的实操步骤,旨在帮助工程师构建和优化高性能计算集群。

mqtt6iot的博客 582

【嵌入式开发】UART

通用异步收发器UART(Universal Asynchronous Receiver/Transmitter),是一种串行、异步、全双工的通信协议,在嵌入式领域应用的非常广泛。一般将UART通信描述为异步串行通信,即串口通信,包括RS232、RS485、RS422、TTL等。以上这些都属于串口通信,其区别是电平规范、硬件实现不同。

大雨淅淅的博客 1663

深入解析Linux Suspend/Resume机制——从用户态到内核态的完整流程

本文深入解析Linux Suspend/Resume机制,从用户态触发到内核态执行的完整流程。详细介绍了三种挂起模式(Freeze、Standby、Suspend to RAM)的实现原理,包括系统调用入口、状态验证、设备挂起流程及平台相关操作。同时提供实战调试技巧,帮助开发者解决电源管理中的常见问题。

weixin_29313239的博客 444

pytorch图像分类篇: 花分类数据集下载和AlexNet网络搭建训练

一、花分类数据集下载 data_setdata_set该文件夹是用来存放训练数据的目录 使用步骤如下: (1)在data_set文件夹下创建新文件夹"flower_data" (2)点击链接下载花分类数据集 (3)解压数据集到flower_data文件夹下 (4)执行"flower_data.py"脚本自动将数据集划分成训练集train和验证集val ├── flower_data ├── flower_photos(解压的数据集文件夹,3670个样本) ...

橙子的博客 8219

从零构建嵌入式通信协议:51单片机UART与上位机的双向握手

本文详细介绍了基于51单片机UART的嵌入式通信协议设计与实现,重点讲解了双向握手机制、数据帧结构和错误处理。通过Proteus仿真和实际代码示例,展示了如何构建可靠的串口通讯系统,包括硬件配置、状态机设计和超时重传等关键技术,适用于工业控制和物联网设备开发。

whisky的博客 968

Virtualbox “Kernel driver not installed (rc=-1908)”问题全面解析与修复指南

本文全面解析了Virtualbox出现'Kernel driver not installed (rc=-1908)'错误的原因及修复方法。详细介绍了如何通过重新安装virtualbox-dkms、处理Secure Boot特殊情况等步骤解决该问题,并提供了预防措施与最佳实践,帮助用户避免类似错误再次发生。

weixin_30352645的博客 531

UART、IIC、SPI通信协议详解

本文讲解了UART、IIC、SPI三种通信协议的硬件构成、协议特点、帧格式等内容,并在需要注意的点做了标注。同时,在实际通信的原理做出了较为详细的说明。

蔚成风 2541

selenium绕过检测,规避检测

现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为 undefined或者为false。而使用selenium访问则该值为true。那么如何解决这个问题呢?我们正常浏览器登录查看,window.navigator.webdriver的值为false我们通过selenium打开的网页,测试,可见window.navigator.webdriver的值为true。

景天科技苑 1万+

4.3 Langfuse 集成实战:追踪 OpenAI、LangChain 和 LangGraph 应用

本文介绍了如何将Langfuse集成到不同类型的AI应用中,包括原生OpenAI、LangChain和LangGraph应用。主要内容包括: 两种集成模式:手动追踪(精确控制)和自动追踪(通过回调机制) 三种应用场景的集成方案: 原生OpenAI应用:使用langfuse.trace()手动记录对话流程、LLM调用和工具执行 LangChain应用:通过LangfuseCallbackHandler自动追踪Agent执行过程 LangGraph应用:与LangChain相同的自动追踪方式,可可视化节点和状态

yonggeit的博客 3305

【漫谈C语言和嵌入式051】UART通信协议全解析:原理、特性及应用

UART因其简单性和灵活性在嵌入式系统中得到广泛应用。尽管它可能不如某些现代协议快速,但其可靠性、易用性和普遍支持使其成为许多应用的理想选择,特别是在调试和简单数据传输方面。随着物联网和智能设备的发展,UART仍然在扮演重要角色,特别是在传统系统集成和简单设备通信方面。深入理解UART协议的工作原理和特性,可以帮助开发者更好地在嵌入式项目中应用这一协议,实现高效可靠的通信。

2403_83044722的博客 1735

【PINN物理信息网络】基于PINN物理信息网络求解瞬态薛定谔方程(python)

【PINN物理信息网络】基于PINN物理信息网络求解瞬态薛定谔方程(python)

k8291121的博客 2724

深入解析单片机常用通信协议:UART、I2C、SPI与CAN

本文深入解析嵌入式系统四种核心通信协议:UART采用三线异步串行传输,需匹配波特率;I2C通过双线制实现主从通信,含地址帧和应答机制;SPI以四线全双工高速传输见长,支持多种时钟模式;CAN总线具备差分信号和仲裁机制,适合工业环境。文章详细说明了各协议的物理层特性、帧结构、典型应用场景及配置方法,并提供了常见问题解决方案,强调逻辑分析仪在协议验证中的重要性。掌握这些协议原理能有效提升嵌入式系统设计的可靠性和效率。

非科班出身,全靠兴趣硬啃单片机的打工人,踩坑无数但乐此不疲;偏爱用接地气的大白话聊技术,拒绝 “高大上” 黑话,代码示例力求简单到能跑;白天搬砖写项目,晚上回家捣鼓小实验,博客就是我的技术朋友圈。 1833

地方政府预算数据抓取:利用Python爬虫获取预算安排、资金分配与支出情况

爬虫是通过模拟浏览器行为,从互联网上自动获取数据的程序。在本案例中,我们将通过爬虫从地方政府的官方网站或预算公开平台抓取各类预算信息。这些信息一般以HTML网页的形式呈现,可以通过爬虫对网页内容进行解析,提取所需的预算数据。Python作为数据抓取的强大工具,凭借其简洁的语法、强大的第三方库(如requestsSelenium等)以及丰富的数据处理能力,成为了开发爬虫应用的首选语言。

2201_76125261的博客 943

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

嵌入式教育科普|UART接口全面解析

RS-232C标准中,其中EIA(Electronic Industry Association)代表美国电子工业协会,RS(Recommended Standard)代表标准,232是标识号,C代表RS232的第三次修改(1969年),在这之前,还有RS232B、RS232A。RS-485总线一般主要用于与外部各种工业设备进行信息传输和数据交换,所具备的对于噪声的有效抑制能力、高效的数据传输速率与良好的数据传输的可靠性能以及可扩展的通信电缆的长度是其他的许多工业通信标准所无法比拟的。

ElfBoard的博客 1765

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

通信协议的时空漫游:从物理信号到数据帧的微观世界

本文深入探讨了UART、I2C、SPI、RS485等核心通信协议的工作原理与应用场景。从物理信号传输到数据帧解析,详细分析了各协议的时序特性、电气标准及设计哲学,为电子工程和嵌入式系统开发提供实用指南,帮助读者构建稳定可靠的通信基础。

g5h6i的博客 628

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

嵌入式笔记:常用接口之UART通信

UART凭借其简单性、可靠性和低硬件成本,在嵌入式领域始终占据一席之地。尽管其速度不及SPI,扩展性不如I2C,但在调试、传感器连接和远距离通信中仍是首选方案。理解UART的原理与配置,是嵌入式开发者的必备技能。欢迎大家补充讨论,共同进步。

m0_75180351的博客 1668

从零构建嵌入式通信协议栈:UART帧封装与ACK确认机制的实战解析

本文详细解析了如何在资源受限的Arduino平台上从零构建嵌入式通信协议栈,重点介绍了UART帧封装设计与ACK确认机制的实现方法。通过帧结构定义、校验和计算、有限状态机管理和动态重传策略,构建了一套轻量级的可靠通信系统,适用于物联网边缘设备的稳定数据传输需求。

o5p6q的博客 286

UART、USART、I2C、SPI、CAN通信协议简介

UART、USART、I2C、SPI、CAN通信协议简介

qq_40700822的博客 1885

从零构建:ESP32与STM32的UART通信协议设计实战

本文详细介绍了如何从零构建ESP32与STM32之间的UART通信协议设计,涵盖硬件连接、数据帧设计、校验机制、错误处理及性能优化等关键环节。通过实战案例展示智能温控系统中两种微控制器的高效协同,为嵌入式开发者提供串口通讯的完整解决方案。

weixin_29191081的博客 386
上一篇: 深入实践 CANN:从 ACL 接口到自定义算子开发,全面释放昇腾 AI 算力
下一篇: 从GPIO到EMIF:嵌入式数据传输的架构演进与性能跃迁
devops8pract
博客等级 码龄4年 533粉丝 849原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值