硬件IIC实战解析:从波形到寄存器的完整通信流程

【裸机开发】I2C 通信接口(一)—— I2C 通信时序协议及通信流程 阅读详情

1. IIC通信基础:两线制串行总线的核心原理

IIC(Inter-Integrated Circuit)是一种简单却强大的两线制串行通信协议,由飞利浦公司(现恩智浦)在1980年代开发。它只需要两根信号线——串行数据线(SDA)和串行时钟线(SCL),就能实现多个设备之间的可靠通信。这种简洁的设计使得IIC在嵌入式系统中广泛应用,特别适合传感器、EEPROM、实时时钟等外设的连接。

在实际项目中,我经常看到新手容易混淆硬件IIC和软件模拟IIC。硬件IIC直接使用微控制器内部的专用电路来处理通信时序,而软件IIC则是通过GPIO引脚模拟时序。硬件IIC的优势在于效率更高、占用CPU资源少,而且时序更加精确。当你需要高速通信或多个设备同时操作时,硬件IIC绝对是更好的选择。

IIC总线支持多主多从架构,这意味着总线上可以连接多个主设备和从设备。每个从设备都有唯一的7位或10位地址,主设备通过这个地址来选择通信对象。在实际调试中,我发现地址冲突是常见问题之一。有一次我调试一个温度传感器,总是读取失败,最后发现是地址配置错误——把7位地址和读写位混在一起计算了。

总线的电气特性也值得注意。SDA和SCL线都需要上拉电阻,通常取值在2.2kΩ到10kΩ之间。电阻值太大会导致上升沿太慢,容易产生时序问题;太小则会增加功耗。我在一个项目中就遇到过因为上拉电阻选择不当导致的通信不稳定,最后用示波器抓波形才找到问题根源。

2. 深入解析IIC通信时序:从起始信号到数据帧

2.1 起始和停止条件

IIC通信的开始和结束有着明确的信号定义。起始条件(START)是在SCL为高电平时,SDA线从高电平跳变到低电平。这个下降沿告诉所有设备:通信开始了!相应地,停止条件(STOP)是在SCL为高电平时,SDA从低电平跳变到高电平。

我在实际调试中经常用示波器观察这些信号。一个常见的误区是认为起始信号就是SDA变低,其实关键是在SCL高电平期间SDA的变化。有一次我调试一个IIC设备,发现起始信号总是被识别错误,最后发现是SCL和SDA的时序偏差太大了。用示波器的双通道测量功能,可以清楚地看到这两个信号的关系。

提示:使用示波器触发功能,设置SCL高电平时SDA下降沿触发,可以稳定捕获起始信号

2.2 数据传送与应答机制

IIC的数据传输以字节为单位,每个字节后都跟着一个应答位。数据在SCL高电平期间必须保持稳定,只有在SCL低电平时才能变化。这个特性很重要,因为很多时序问题都是由于数据变化时机不当造成的。

应答机制是IIC可靠性的关键。发送方(无论是主设备还是从设备)发送完8位数据后,会在第9个时钟周期释放SDA线。接收方需要在这个时钟周期内将SDA拉低,表示成功接收。如果接收方没有拉低SDA,就产生了非应答(NACK),通常意味着通信出了问题。

我在调试EEPROM时遇到过有趣的应答问题。当写入地址超出范围时,设备不会产生应答,但程序没有检查这个状态,导致一直等待超时。加上应答检查后,问题立即显现:

// 检查IIC应答状态的示例代码
if (I2C_CheckAck() == NACK) {
    printf("Device not responding!\n");
    I2C_GenerateStop();
    return ERROR;
}

2.3 地址帧格式解析

IIC的地址帧包含7位地址和1位读写标志。读写位为0表示主设备要向从设备写数据,为1表示要读数据。这里有个容易混淆的点:7位地址通常左移1位后与读写位组合,所以实际发送的是一个8位的值。

例如,一个7位地址0x50的设备,写操作时发送0xA0(0x50 << 1 | 0),读操作时发送0xA1(0x50 << 1 | 1)。我曾经就因为这个转换错误,浪费了半天时间调试一个温度传感器。

3. 硬件IIC寄存器详解:以STM32为例

3.1 控制寄存器配置

硬件IIC的实现离不开对寄存器的正确配置。以STM32F103的I2C为例,主要涉及CR1、CR2、SR1、SR2等寄存器。CR1用于使能I2C和配置各种功能,CR2用于设置中断和时钟频率。

在配置时钟时,需要根据APB1时钟频率计算分频值。例如,如果APB1时钟是36MHz,想要100kHz的标准模式,计算如下:

TPCLK1 = 1 / 36MHz = 27.78ns
TI2CSCL = 1 / 100kHz = 10μs
PRESC = TPCLK1 * (SCLL + SCLH + 3) = TI2CSCL

实际配置时需要查阅参考手册中的详细公式。

3.2 状态寄存器与中断处理

状态寄存器(SR1和SR2)反映了I2C总线的当前状态。例如,当SB位置1时表示起始条件已发送,ADDR置1表示地址已发送并收到应答。正确读取状态寄存器是成功通信的关键。

我在项目中习惯使用中断方式处理I2C通信,这样效率更高。设置好中断使能后,需要在中断服务函数中根据状态位执行相应操作:

void I2C1_EV_IRQHandler(void) {
    switch (I2C1->SR1) {
        case SB_MASK:  // 起始条件已发送
            I2C1->DR = DEVICE_ADDRESS | WRITE;
            break;
        case ADDR_MASK: // 地址已发送
            // 读取SR2清除ADDR位
            volatile uint32_t temp = I2C1->SR2;
            break;
        // 其他状态处理...
    }
}

3.3 数据寄存器操作

数据寄存器(DR)用于收发数据。写入DR的数据会在SCL时钟的驱动下逐位发送,读取DR则获取接收到的数据。这里要注意时序:必须在TXE(发送寄存器空)或RXNE(接收寄存器非空)标志置位时操作DR寄存器。

我遇到过一个问题:在快速连续发送时,没有检查TXE标志就写入数据,导致数据覆盖。后来加入标志检查后问题解决:

void I2C_WriteByte(uint8_t data) {
    // 等待发送寄存器为空
    while (!(I2C1->SR1 & I2C_SR1_TXE));
    I2C1->DR = data;
}

4. 实战演练:读写特定寄存器地址

4.1 寄存器地址0x400066A8的读写分析

让我们以一个具体的例子来演示完整流程。假设我们要操作地址为0x400066A8的寄存器,这是一个32位的控制寄存器。由于IIC通常按字节操作,我们需要多次读写来完成32位数据的传输。

首先是通过IIC写入这个寄存器:

// 写入0x400066A8寄存器的示例代码
void WriteControlRegister(uint32_t value) {
    I2C_GenerateStart();
    I2C_Send7bitAddress(I2C_ADDRESS, I2C_DIRECTION_WRITE);
    
    // 发送寄存器地址(32位,需要4字节)
    I2C_SendData(0x40);  // 高字节
    I2C_SendData(0x00);
    I2C_SendData(0x66);
    I2C_SendData(0xA8);  // 低字节
    
    // 发送数据
    I2C_SendData((value >> 24) & 0xFF);  // 最高字节
    I2C_SendData((value >> 16) & 0xFF);
    I2C_SendData((value >> 8) & 0xFF);
    I2C_SendData(value & 0xFF);           // 最低字节
    
    I2C_GenerateStop();
}

4.2 读操作的特殊处理

读取寄存器比写入复杂,因为需要先告诉从设备要读哪个寄存器,然后改变通信方向。这就是所谓的"哑写"操作:

uint32_t ReadControlRegister(void) {
    uint32_t result = 0;
    
    // 第一步:写入要读取的寄存器地址
    I2C_GenerateStart();
    I2C_Send7bitAddress(I2C_ADDRESS, I2C_DIRECTION_WRITE);
    I2C_SendData(0x40);
    I2C_SendData(0x00);
    I2C_SendData(0x66);
    I2C_SendData(0xA8);
    
    // 第二步:重启总线并改变方向
    I2C_GenerateStart();  // 重复起始条件
    I2C_Send7bitAddress(I2C_ADDRESS, I2C_DIRECTION_READ);
    
    // 第三步:读取数据
    result |= (uint32_t)I2C_ReceiveData() << 24;
    I2C_AcknowledgeConfig(I2C_ACK_ENABLE);
    result |= (uint32_t)I2C_ReceiveData() << 16;
    result |= (uint32_t)I2C_ReceiveData() << 8;
    I2C_AcknowledgeConfig(I2C_ACK_DISABLE);  // 最后一个字节前发送NACK
    result |= I2C_ReceiveData();
    
    I2C_GenerateStop();
    return result;
}

4.3 错误处理与超时机制

在实际项目中,一定要添加错误处理和超时机制。IIC通信可能因为各种原因失败,如设备未连接、地址错误、总线冲突等。

I2C_Status I2C_WriteWithTimeout(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
    uint32_t timeout = I2C_TIMEOUT;
    
    // 发送起始条件
    I2C_GenerateStart();
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT)) {
        if (--timeout == 0) return I2C_TIMEOUT_ERROR;
    }
    
    // 发送地址
    I2C_Send7bitAddress(devAddr, I2C_DIRECTION_WRITE);
    timeout = I2C_TIMEOUT;
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
        if (--timeout == 0) return I2C_TIMEOUT_ERROR;
    }
    
    // 后续操作...
}

5. 波形分析与调试技巧

5.1 使用示波器分析IIC波形

示波器是调试IIC通信的必备工具。通过观察SDA和SCL的波形,可以直观地看到通信过程中的各种信号和时序关系。

设置示波器时,我通常使用双通道模式,通道1接SCL,通道2接SDA。触发条件设置为SCL高电平时SDA的下降沿,这样可以稳定捕获起始信号。时间基准根据通信速度设置,100kHz标准模式可以设置为5μs/div,400kHz快速模式设置为2μs/div。

分析波形时要重点关注几个关键点:起始信号是否符合要求(SCL高时SDA下降)、数据变化是否在SCL低电平期间、应答位是否正确产生。我经常发现的问题包括数据变化时机不对、应答超时、起始/停止信号不规范等。

5.2 常见波形问题与解决方案

上升沿过缓是常见问题之一,表现为信号上升沿呈弧形而非直角。这通常是由于上拉电阻过大或总线电容过大造成的。解决方案是减小上拉电阻值或降低通信速度。

毛刺干扰表现为信号上有小的尖峰脉冲,可能源于电磁干扰或电源噪声。可以通过添加滤波电容或改善布线来解决。

时序偏差指SCL和SDA之间的时序关系不符合规范。例如数据变化在SCL高电平时发生,这会导致通信错误。这种问题通常需要通过调整软件时序或检查硬件设计来解决。

有一次我遇到一个特别棘手的问题:通信偶尔失败,波形看起来基本正常,但偶尔会出现SCL脉冲宽度不一致。最后发现是总线上某个设备的电源稳定性问题,更换电源滤波电容后问题解决。

5.3 使用逻辑分析仪辅助调试

虽然示波器能看到模拟波形,但逻辑分析仪在解析数字协议方面更有优势。现代逻辑分析仪通常带有IIC协议解码功能,能直接显示地址、数据、起始停止条件等信息。

我常用的设置是采样率至少为通信速度的4倍以上,100kHz IIC至少需要400kHz采样率。连接时注意接地要良好,否则可能引入噪声。逻辑分析仪的优势在于能长时间记录通信过程,便于分析间歇性故障。

6. 实际项目中的经验分享

6.1 多设备总线管理

当总线上有多个IIC设备时,需要特别注意总线管理和地址分配。每个设备必须有唯一地址,如果地址冲突,通信就会混乱。有些设备可以通过硬件引脚配置地址,有些则固定不变。

在我的一个项目中,需要连接4个相同的温度传感器,但它们地址相同。解决方案是使用IIC多路复用器(如PCA9548A),通过切换不同通道来区分设备。另一种方法是用GPIO控制设备的地址选择引脚,动态改变地址。

总线负载也是需要考虑的因素。设备越多,总线电容越大,可能影响通信质量。通常IIC总线最多支持8-10个设备,超过这个数量就需要使用总线缓冲器或分网段。

6.2 错误处理与恢复机制

健壮的IIC驱动必须有完善的错误处理机制。常见的错误包括总线忙、仲裁丢失、应答超时等。检测到错误后,应该进行相应的恢复操作。

我最常用的恢复序列是:先发送停止条件(如果可能),然后延时一段时间,重新初始化IIC控制器,最后重试操作。重试次数应该有限制,避免死循环。

#define MAX_RETRY 3

I2C_Status I2C_WriteWithRetry(uint8_t devAddr, uint8_t regAddr, uint8_t data) {
    I2C_Status status;
    uint8_t retry = 0;
    
    do {
        status = I2C_Write(devAddr, regAddr, data);
        if (status == I2C_SUCCESS) break;
        
        // 错误恢复
        I2C_Recovery();
        retry++;
    } while (retry < MAX_RETRY);
    
    return status;
}

6.3 性能优化技巧

虽然IIC不是高速总线,但在某些应用中仍需优化性能。以下是我总结的几个优化技巧:

使用DMA传输:对于大数据量传输,使用DMA可以大大减轻CPU负担。STM32的I2C支持DMA,配置好后可以实现自动数据传输。

合理设置通信速度:不是所有设备都支持高速模式,但在允许的情况下,使用400kHz快速模式比100kHz标准模式快4倍。

减少不必要的重启:每次起始/停止条件都会产生开销,连续读写时尽量使用重复起始条件而不是完全停止后再开始。

批量传输数据:许多IIC设备支持地址自动递增,可以利用这个特性一次性读写多个连续寄存器,减少地址传输开销。

我在一个传感器数据采集项目中,通过使用DMA和批量读取,将读取18个传感器数据的时间从15ms降低到3ms,效果非常明显。

调试IIC通信确实需要耐心和经验,但掌握基本原理和调试技巧后,大多数问题都能迎刃而解。最重要的是养成良好的调试习惯:仔细观察波形、逐步排查问题、添加充分的错误处理。

基于STM32F103C8T6的IIC通信协议及硬件通信和软件OLED温度显示项目 I2C通讯 阅读详情

相关推荐

如何使用示波器抓取IIC波形?

本文章将介绍使用示波器抓取IIC波形的方法

芯片是怎样炼成的的博客 3926

I2C通信协议详解和通信流程分析

1、I2C通信特征 1.1、物理接口:SCL + SDA 1.2、通信特征:串行、同步、非差分、低速率 1.3、通信模式:主设备+从设备 1.4、可以多个设备挂在一条总线上 1.5、主要用途 2、I2C控制器的结构框图 3、I2C控制器的模式 4、I2C的时序分析 4.1、时序介绍 4.2、通信起始条件和结束条件 4.3、数据有效性 4.4、响应ACK 4.5、I2C总线的三种状态 5、I2C总线的读/写数据操作 6、I2C的操作流程 6.1、主设备写数据 6.2、主设备读数据 7、I2C通信的主发送模式流

weixin_42031299的博客 6万+

STM8硬件IIC驱动BNO055传感器避坑指南:从模拟IIC失败到一次成功的完整流程

本文详细介绍了STM8硬件IIC驱动BNO055传感器的完整流程,从模拟IIC失败到成功实现硬件IIC通信。文章深入分析了BNO055传感器的选型优势、硬件连接细节、时序调试技巧,并提供了可直接复用的驱动代码和常见问题解决方案,帮助开发者高效获取精确的角度数据。

weixin_30571465的博客 667

一文搞懂I2C通信总线

本来不打算写这篇文章,因为网上关于I2C总线通信的资料很多很全。但是最近刚换工作,主要做驱动开发,第一个驱动就是I2C通信,想了想还是结合网上的资料再整理下思路,方便今后的查阅和温习。

不脱发的程序猿 14万+

STM32cubemax的硬件IIC和软件IIC+HAL库

HAL库硬件IIC和管脚模拟电平软件IIC。

m0_66709017的博客 1665

IIC通信协议详解

IIC通信协议详解IIC的概述IIC分为软件IIC和硬件IICIIC通信协议空闲状态开始信号与停止信号开始信号程序: IIC的概述 IIC:两线式串行总线,它是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。 在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbs以上。 时钟线SCL:在通信过程起到控制作用。 数据线SDA:用来一位一位的传送数据。 IIC分为软件IIC和硬件IIC 软件IIC:软件IIC通信指的是用单片机的两个I/O端口模拟出来的IIC,用

w492665264的博客 4469

I2C通信 读写数据过程

在通信之初,主从机必须根据自己的要求约定好通信规则:command的定义和位置、address的位数和位置。 以读写从机寄存器数据为例: 假设从机寄存器地址为8位、从机寄存器也位8位(被读取数据为8位); 约定读command为0x01,写command位0x02; 约定主机发起通信后,第一个slave address字节收到ack后,紧跟的一个字节为comma

guoguo295的专栏 3万+

AVEVA PDMS 二次开发之PML实战:从宏到自定义窗体的效率提升

本文详细介绍了AVEVA PDMS二次开发中PML语言的应用,从基础宏编写到高级窗体开发,全面提升工程设计效率。通过实战案例展示如何利用PML实现批量操作、流程自动化和交互优化,帮助工程师快速掌握这一强大工具。

weixin_42549451的博客 341

嵌入式学习笔记——I2C

IIC学习笔记

zxjiaya的博客 1414

python 编程 安卓脚本_详解基于Android的Appium+Python自动化脚本编写

1.AppiumAppium是一个开源测试自动化框架,可用于原生,混合和移动Web应用程序测试, 它使用WebDriver协议驱动iOS,Android和Windows应用程序。通过Appium,我们可以模拟点击和屏幕的滑动,可以获取元素的id和classname,还可以根据操作生成相关的脚本代码。下面开始Appium的配置。appPackage和APPActivity的获取任意下载一个app解压...

weixin_39523625的博客 2930

MS17-010(Eternal blue永恒之蓝)漏洞利用+修复方法

msf永恒之蓝漏洞复现过程以及修复建议

记录学习 8514

从IIC实测波形入手,搞懂IIC通信

玩单片机的朋友都知道IIC通信这个工具,但好多人只是会用,内部的原理不求甚解,或是想要了解其原理,但却对抽象的时序描述一头雾水。本文将从实测的IIC波形入手,带你看到真实的IIC样子,进而去理解IIC的通信原理。 1 IIC基础知识 首先复习一下IIC基础知识,这部分看不懂的请先带着疑问,然后我们通过分析IIC的真实波形,这些疑问可能就豁然开朗了~ 1.1 IIC是什么 IIC(Inter Integrated Circuit,集成电路总线)是一种由 PHILIPS 公司开发的两线式串行总线,用于连接微控制

码农爱学习的博客 2万+

OpenClaw Windows 安装指南

好的,我来一步一步带你在 Windows 上安装 OpenClaw。

m0_60605453的博客 551

[转]从IIC实测波形入手,搞懂IIC通信

通过真实的IIC波形分析,对IIC通信逻辑有没有更加直观的认识呢?原创不易,觉得有用请多多关注支持~作者:码农爱学习来源:优快云原文:https://blog.youkuaiyun.com/hbsyaaa/article/details/107450835版权声明:本文为作者原创文章,转载请附上博文链接!...

jfl558604的博客 3989

真格量化-bs套利

#!/usr/bin/env python # coding:utf-8 from PoboAPI import * import datetime import time import numpy as np from copy import * #开始时间,用于初始化一些参数 def OnStart(context) : context.myacc = None #登录交易账号 if context.accounts["回测期权"].Login() : co.

qq_26742269的博客 1321

【FPGA教程案例87】加解密1——基于FPGA的AES加解密算法verilog实现

DES已走到了它生命的尽头。56比特密钥实在太小,虽然三重DES可以解决密钥长度的问题,但是DES的设计主要针对硬件实现,而今在许多领域,需要用软件方法来实现它,在这种情况下,它的效率相对较低。1997年4月15日美国国家标准和技术研究所(NIST)发起征集AES(Advanced Encryption Standard)算法的活动,并成立了AES工作组。目的是为了确定一个非保密的、公开披露的、全球免费使用的加密算法,用于保护下一世纪政府的敏感信息。这里,我们对AES的基本原理进行介绍:

FPGA/MATLAB学习教程/源码/项目合作开发 2546

IIC通信协议——硬件IIC

IIC(Inter-Integrated Circuit)总线是一种由飞利浦(PHILIPS)公司开发的两线式串行通信总线结构,通常用于连接微控制器及其外围设备。IIC有着传输距离短,传输速率慢,适合在小数据量场合使用,支持多主多从等特性。IIC总线上可以连接多个主机和多个从机,任何一个能够进行发送和接收的设备都可以成为主机,能够控制信号传输和时钟频率。但任意时刻只能有一个主机和一个从机进行通信。IIC通信的典型速率在100kbps,高速模式下可达400kbps,超高速模式下可达1mbps。

你骄傲地飞远的博客 4139

基于matlab的LFM脉冲压缩仿真

传统雷达测距是通过发射点频脉冲串实现的,通过发射脉冲与回波的时延确定目标的距离。此类方法易于实现,对接收机的要求较低。一般要获取更好的距离分辨力,需要增加发射信号的带宽,对于点频脉冲信号即需要减小发射脉冲宽度;而为获取更大的探测距离,提升雷达威力,则需要发射更大占空比的脉冲串。由于点频信号的时宽带宽积约等于1,因此不能同时增加信号的时宽和带宽。若要保持距离分辨力,增大占空比就需要减少雷达的脉冲重复周期(PRT)。这样会减小雷达的无模糊探测距离,也会造成目标回波频繁被遮挡,损失雷达威力。

平时工作较为繁忙,私信消息一般晚上回复,谢谢大家~~ 1771

通信协议(三)——IIC协议

通信协议(三)——IIC协议

好好学习,天天向上 1万+

计算机视觉入门:从像素到理解的旅程

计算机视觉入门:从像素到理解的旅程,计算机视觉是人工智能领域的核心方向之一,旨在让计算机具备理解和解释视觉信息的能力。本文以系统化的知识框架,结合 Python 代码与经典案例,带您从像素级操作逐步掌握计算机视觉核心技术。涵盖图像处理、特征工程、传统机器学习到深度学习模型,助您构建从基础到进阶的完整能力体系。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 18万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

硬件IIC和软件IIC区别

原文地址:https://blog.youkuaiyun.com/Derricker406/article/details/77171223 所谓硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的;软件I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。 硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。 模拟I2C 是通过...

我云的博客 1万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

IIC接口硬件测试规范

B. 使用两路电压探头分别点测时钟信号SCL和数据信号SDA,通过软件命令读写IIC slave器件的寄存器,捕获完整的连续两个数据的IIC读写波形;B. 使用两路电压探头分别点测时钟信号SCL和数据信号SDA,通过软件命令读写IIC slave器件的寄存器,捕获完整的连续两个数据的IIC读写波形;B. 使用两路电压探头分别点测时钟信号SCL和数据信号SDA,通过软件命令读写IIC slave器件的寄存器,捕获完整的连续两个数据的IIC读写波形;

weixin_43381663的博客 6877

深度学习工具包 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")

STMF4 硬件IIC(天空星开发板)

下面只介绍不同的部分。使用宏定义,去写代码,这种函数是能够提升程序的执行速度,因为宏定义是预处理指令,在程序执行前,开始执行的,如果是将函数在次封装在调用,这种程序执行速度是比不上,宏定义。,硬件IIC效率远高于软件IIC, STMF4VET6上带有3个硬件IIC,允许与外部IIC接口进行通信,STMF4的硬件IIC使用特定的引脚复位,来进行数据和时钟信号的传输。来传输数据还有时序信号,达到IIC通信的效果目的,软件IIC通信好处是,在MCU内部没有集成硬件IIC电路的时候,可以使用软件IIC通信,

看,是大狗 1912
上一篇: 从零到一:构建Android RTSP播放器的架构演进与性能调优之旅
下一篇: 从DIY到量产:解析2.4G无线话筒的硬件选型与成本优化策略
寂静夜空35
博客等级 码龄3年 59粉丝 1797原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值