首页 > 其他分享 >嵌入式必备知识-IIC协议

嵌入式必备知识-IIC协议

时间:2024-12-13 14:34:10浏览次数:3  
标签:scl 1us IIC delay0 必备 uint8 drv iic 嵌入式

此篇文章在2023年8月8日被记录

1、概述

IIC(Inter-IntegratedCircuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器以及其外围设备,IIC也被称为I2C,其实两者是完全相同的。它是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。两根线定义如下:

  • 数据线SDA:数据线用来传输数据
  • 时钟线SCL:时钟线用来同步数据收发

2、信号分解

时钟图绘制由https://wavedrom.com/editor.html提供,在线绘制非常方便!

IIC信号总共可以分为五种信号:

  • 开始信号:当SCL为高电平的时候,SDA线上由高到低的跳变被定义为起始条件
    img
  • 结束信号:当SCL为高电平的时候,SDA线上由低到高的跳变被定义为停止条件
    img
  • 应答信号:每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据,从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答
    • 应答
      img
    • 非应答
      img
  • 发送/接受一个字节:在发送一个字节时,在SCL拉底时,SDA上的数据可以发生变化,在SCL拉高时,SDA上的数据需要保持不变,在读取数据时,SCL时钟线仍然需要主机提供,SDA设定为输入读取从机的数据
    img

3、编码实现

  • 开始信号
void drv_iic_start(void)
{
    _iic_sad_out();
    _iic_sda_high();
    _iic_scl_high();
    _iic_delay0_1us(3);
    _iic_sda_low();
    _iic_delay0_1us(6);
    _iic_scl_low();
    _iic_delay0_1us(3);
}
  • 结束信号
void drv_iic_stop(void)
{
    _iic_sad_out();
    _iic_sda_low();
    _iic_scl_high();
    _iic_delay0_1us(6);
    _iic_sda_high();
    _iic_delay0_1us(3);
}
  • 等待应答信号
uint8_t drv_iic_wait_ack(void)
{
    uint8_t ret = 0;
    _iic_sad_in();
    _iic_scl_high();
    _iic_delay0_1us(5);
    ret = (_iic_sda_read()) ? NAK : ACK;
    _iic_delay0_1us(5);
    _iic_scl_low();
    _iic_delay0_1us(2);
    return ret;
}
  • 发送应答 1 信号
void drv_iic_send_ack(void)
{
    _iic_sad_out();
    _iic_sda_low();
    _iic_delay0_1us(3);
    _iic_scl_high();
    _iic_delay0_1us(7);
    _iic_scl_low();
    _iic_delay0_1us(3);
}
  • 写一个字节
void drv_iic_send_byte(uint8_t data)
{
    uint8_t i = 0;
    _iic_sad_out();
    _iic_delay0_1us(3);
    for (i = 0; i < 8; i++)
    {
        _iic_scl_low();
        _iic_delay0_1us(3);
        (data & 0x80) ? _iic_sda_high() : _iic_sda_low();
        _iic_delay0_1us(13);
        _iic_scl_high();
        data <<= 1;
        _iic_delay0_1us(7);
    }
    _iic_scl_low();
    _iic_delay0_1us(2);
}
  • 读取一个字节
uint8_t drv_iic_recv_byte(void)
{
    uint8_t data = 0;
    uint8_t i = 0;
    _iic_sad_in();
    for (i = 0; i < 8; i++)
    {
        _iic_scl_low();
        data <<= 1;
        _iic_delay0_1us(13);
        _iic_scl_high();
        _iic_delay0_1us(5);
        if (_iic_sda_read())
        {
            data |= 0x01;
        }
        _iic_delay0_1us(2);
    }
    _iic_scl_low();
    return data;
}

4、实战练习

随便找一个具有IIC协议的芯片手册,通过查阅手册,得到总线通信图

  • 写总线时序图
    img
    编码实现:
void drv_write_reg(uint8_t reg,uint8_t data)
{
    drv_iic_start();
    drv_iic_send_byte(HW_I2C_ADDR & 0xFE);
    drv_iic_wait_ack();
    drv_iic_send_byte(reg);
    drv_iic_wait_ack();
    drv_iic_send_byte(data);
    drv_iic_wait_ack();
    drv_iic_stop();
}
  • 读总线时序图
    img
uint8_t drv_is3729_read_reg(uint8_t reg)
{
    uint8_t rec = 0x00;
    drv_iic_start();
    drv_iic_send_byte(HW_IS3730_I2C_ADDR & 0xFE);
    drv_iic_wait_ack();
    drv_iic_send_byte(reg);
    drv_iic_wait_ack();
    drv_iic_stop();
    drv_iic_start();
    drv_iic_send_byte(HW_IS3730_I2C_ADDR | 0x01);
    drv_iic_wait_ack();
    rec = drv_iic_recv_byte();
    drv_iic_send_nack();
    drv_iic_stop();
    return rec;
}

5、其他注意

  • IIC协议速度较慢,因此通常只用来传输较少的数据
  • 软件IIC可以通过调整间隙延时来提高速度,但是至少要满足手册所规定的最短时间

标签:scl,1us,IIC,delay0,必备,uint8,drv,iic,嵌入式
From: https://www.cnblogs.com/shumei52/p/18604890

相关文章

  • 嵌入式组件----shell
    此篇文章在2023年6月14日被记录1、介绍easy_shell是由纯C语言编写,运行于嵌入式设备上的shell,通过串口作为命令传入,调用程序中的函数,相比于litter-shell削减了很多用不上的功能,本组件shell.c只有三百多行,简单易用好理解,目前支持且仅支持int类型、char类型、char*类型、hex类型......
  • 嵌入式组件-----状态机
    此篇文章在2023年7月10日被记录1、简述状态机在C语言编程中,可以使用状态机来实现复杂的控制流程和状态管理。状态机通常由以下几个组成部分构成:状态(State):系统或程序可能处于的不同状态,例如"待机"、"运行"、"暂停"等。每个状态代表了系统或程序的一种行为或模式。事件(Event......
  • 嵌入式组件-fifo
    此篇文章在2023年4月26日被记录fifo适用于多种场景,例如在串口中断中来不及接受数据,可以将数据先缓存起来,在任务中再进行处理fifo也可以称为环形队列,填入数据时在头部填入,取数据从尾部取出FIFO.c#include"fifo.h"#include"stdio.h"voidfifo_init(fifo_t*obj,uint8_t......
  • 《安富莱嵌入式周报》第347期:分立元件自制14bit分辨率DAC,开源电池测试仪,大量位操作技
    周报汇总地址:http://www.armbbs.cn/forum.php?mod=forumdisplay&fid=12&filter=typeid&typeid=104 视频版https://www.bilibili.com/video/BV1SFq9YAE4j/目录:1、分立元件自制14bit分辨率DAC2、开源电池测试仪3、微软为VSCode制作的AIToolkit插件4、Zephyr相关(1)好消......
  • 职场必备神器 —— 工作提醒软件,掌控时间的魔法棒
    在当今快节奏的工作环境中,人们面临着繁多的任务和紧凑的时间安排,常常容易出现遗忘重要事项、错过截止日期的情况。工作提醒软件应运而生,成为了帮助职场人士有效管理时间、提高工作效率和专注力的关键工具。本文将深入探讨工作提醒软件的功能特点、应用场景、优势以及如何选择适合......
  • 面试必会(嵌入式)-C++面试高频(一)
    目录1.new和malloc的区别(使用和原理)⭐new的定义:malloc的定义:new与malloc的区别:(简单理解)new与malloc使用区别2.struct和class的区别⭐3.char和int之间的转换4.什么是野指针和悬挂指针⭐5.NULL和nullptr区别⭐6.指针常量和常量指针有何区别⭐7.虚拟内存和物理内存的......
  • 面试必会(嵌入式)-C语言面试高频(内存管理)
    1.(内存)堆和栈的区别⭐堆栈空间分配不同:栈由操作系统自动进行分配和释放,用于存放函数的参数值、局部变量的值等,具有高效性。堆:一般由程序员手动进行分配和释放,效率比栈低很多。data数据区:存放全局变量,静态变量。堆栈缓存方式不同:栈使用一级缓存,存储在处理器核心中,调用完......
  • 蓝桥杯嵌入式模板创建(STM32 CubeMx简单使用教程)
    蓝桥杯嵌入式新板模板创建&简单经验分享补充在最前:以下原文是22年还未毕业时写的,仅在把板子二手卖给别人的时候给别人分享了这份笔记。那时经验不多,现在也由于工作使用的芯片不同已很久没有使用CubeMX了,因此文章可能有很多错漏之处,欢迎在评论区指出。备注在前:uint8_t即un......
  • 韶音科技嵌入式面试题及参考答案
    Bootloader的启动流程是什么?Bootloader是在操作系统内核运行之前运行的一段小程序。它的启动流程主要分为以下几个阶段。首先是硬件初始化阶段。这个阶段会对处理器以及一些关键的硬件设备进行初始化。比如,会配置处理器的工作模式、设置堆栈指针等。以ARM处理器为例,会......
  • 前端开发必备-带你了解CSS-IN-JS解决方案的优缺点
    前端开发必备-带你了解CSS-IN-JS解决方案的优缺点https://www.bilibili.com/video/BV1Ss4y1k7hBP101.专题内容介绍3.Emotion库P202.为什么会有CSS-IN_JS这种解决方案CSS-IN-JS是WEB项目中将CSS代码捆绑在JavaScript代码中的解决方案.这种方案旨在解决CSS的局限......