近期帮同学做一个项目,开发板是EFM8单片机,支持SPI和I2C协议(SMBus)。非常久没搞过单片机了,并且条件限制,为了使单片机和外设成功通信。花了一个星期时间。刚開始使用SPI。发现代码逻辑都没问题,就是结果不正确(后来知道是由于带中断的程序单步调试导致的。说多了都是泪),调了几天发现SPI确实调不通。就换了I2C。半天时间搞定,哈哈。本文重点解释I2C,废话少说了。

1、简单介绍

I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛採用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等长处。这些长处不是吹的,仅仅须要两个IO口即可了,比起并行传输节省了不知道多少成本。

2、连接图

2条双向串行线,一条数据线SDA,一条时钟线SCL。SDA数据传输是大端传输,每次传输8bit,即一字节。支持多主控(multimastering)。不论什么时间点仅仅能有一个主控。总线上每一个设备都有自己的一个addr,共7个bit。广播地址全0。

本文用的是ADXL345,CS引脚拉高至VDD。ADXL345处于I2C模式,须要简单2线式连接。ALT ADDRESS(SDO)引脚处于高电平,器件的7位I2C地址是0x1D。随后为R/W位。这转化为0x3A写入,0x3B读取。通过ALT ADDRESS引脚(引脚12)接地,能够选择备用I2C地址0x53(随后为R/W位)。这里特别说明,外设和MCU不须要共GND,也不须要共VDD。我刚開始纠结了好久,查了非常多资料,硬是没查到。这转化为0xA6写入。0xA7读取。

连线方式例如以下图:

3、读写流程

I2C的时序这些就不多介绍了,网上一搜一大堆,想用IO口模拟I2C能够。大多数MCU都内置I2C模块,仅仅要连线正确,配置和操作寄存器就能正常通信了。

只是,I2C读写数据的流程是必须了解的。

3.1、写流程

写寄存器的标准流程为:

1.    Master发起START

2.    Master发送I2C addr(7bit)和w操作0(1bit),等待ACK

3.    Slave发送ACK

4.    Master发送reg addr(8bit),等待ACK

5.    Slave发送ACK

6.    Master发送data(8bit),即要写入寄存器中的数据,等待ACK

7.    Slave发送ACK

8.    第6步和第7步能够反复多次,即顺序写多个寄存器

9.    Master发起STOT

3.2、读流程

读流程比写略微麻烦一点,在读之前要先把寄存器地址写入,然后再開始读:

1.    Master发起START

2.    Master发送I2C addr(7bit)和w操作1(1bit)。等待ACK

3.    Slave发送ACK

4.    Master发送reg addr(8bit),等待ACK

5.    Slave发送ACK

6.    Master发起START

7.    Master发送I2C addr(7bit)和r操作1(1bit)。等待ACK

8.    Slave发送ACK

9.    Slave发送data(8bit)。即寄存器里的值

10.    Master发送ACK

11.    第8步和第9步能够反复多次,即顺序读多个寄存器

4、程序原理

程序是依据配置和操作寄存器实现I2C通信。将I2C设为忙状态,START标志開始,兴许全部收发数据在中断子程序中处理。中断子程序中,依据SMB0CN0寄存器推断是什么状态,然后做出响应的处理。

特别说明,寄存器地址和读写的数据复用放在数组SMB_DATA_OUT里。

读写函数:

        void SMB_Write(uint8_t Flag)
        {
         while(SMB_BUSY); // Wait for SMBus to be free.
         SMB_BUSY = 1; // Claim SMBus (set to busy)
         SMB_RW = Flag; // Mark this transfer as a WRITE
         SMB0CN0_STA = 1; // Start transfer
         while(SMB_BUSY);
        }         void SMB_Read(void)
        {
         while(SMB_BUSY); // Wait for bus to be free.
         SMB_BUSY = 1; // Claim SMBus (set to busy)
         SMB_RW = 1; // Mark this transfer as a READ          SMB0CN0_STA = 1; // Start transfer          while(SMB_BUSY); // Wait for transfer to complete
        }

中断处理子程序:

      switch (SMB0CN0 & 0xF0)          // Status vector
{
// Master Transmitter/Receiver: START condition transmitted.
case SMB_MTSTA:
SMB0DAT = TARGET; // Load address of the target slave
SMB0DAT &= 0xFE; // Clear the LSB of the address for the
// R/W bit
SMB0DAT |= RW_FLAG; // Load R/W bit
SMB0CN0_STA = 0; // Manually clear START bit
sent_byte_counter = 1; // Reset the counter
break; // Master Transmitter: Data byte transmitted
case SMB_MTDB:
if (SMB0CN0_ACK) // Slave SMB0CN0_ACK?
{
if (RW_FLAG == WRITE) // If this transfer is a WRITE,
{
if (sent_byte_counter <= NUM_BYTES_WR)
{
// send data byte
SMB0DAT = SMB_DATA_OUT[sent_byte_counter-1];
sent_byte_counter++;
}
else
{
SMB0CN0_STO = 1; // Set SMB0CN0_STO to terminate transfer
SMB_BUSY = 0; // And free SMBus interface
}
}
}
else // If slave NACK,
{
SMB0CN0_STO = 1; // Send STOP condition, followed
SMB0CN0_STA = 1; // By a START
}
break; // Master Receiver: byte received
case SMB_MRDB:
         SMB_DATA_OUT = SMB0DAT; // Store received byte
SMB_BUSY = 0; // Free SMBus interface
SMB0CN0_ACK = 0; // Send NACK to indicate last byte of this transfer SMB0CN0_STO = 1; // Send STOP to terminate transfer
break; default:
FAIL = 1; // Indicate failed transfer
// and handle at end of ISR
break;

EFM8单片机与I2C外设通信的更多相关文章

  1. 理解一下单片机的I2C和SPI通信

    应某位网友要求,今天说一下单片机的I2C SPI通信,可能说不清楚,因为这毕竟要做实验才可完全理解. I2C和SPI是两种不同的通信协议. 听到协议,似乎高不可攀,其实协议就是人们定义的一个标准而已, ...

  2. linux i2c 的通信函数i2c_transfer在什么情况下出现错误

    问题: linux i2c 的通信函数i2c_transfer在什么情况下出现错误描述: linux i2c设备驱动 本人在写i2c设备驱动的时候使用i2c transfer函数进行通信的时候无法进行 ...

  3. Android单片机与蓝牙模块通信实例代码

    Android单片机与蓝牙模块通信实例代码 参考路径:http://www.jb51.net/article/83349.htm 啦啦毕业了,毕业前要写毕业设计,需要写一个简单的蓝牙APP进行交互,通 ...

  4. STM32F10x_硬件I2C主从通信(轮询发送,中断接收)

    Ⅰ.写在前面 关注我分享文章的朋友应该知道我在前面讲述过(软件.硬件)I2C主机控制从机EEPROM的例子.在I2C通信主机控制程序是比较常见的一种,可以说在实际项目中,很多应用都会使用到I2C通信. ...

  5. 如何在niosII中添加i2c外设_winday_新浪博客

    如何在niosII中添加i2c外设_winday_新浪博客 如何在niosII中添加i2c外设 winday 摘要:本文说明了如何在niosII添加第三方i2c外设,以供参考. 由于本人使用的Alte ...

  6. usb-host与外设通信(二)

    本文是接着上一篇的的usb-host与外设通信(一)接着写的 3.枚举设备 当你的程序运行时,如果应用程序对当前连接的USB设备都感兴趣的,程序可以枚举所以当前的设备.使用getDeviceList( ...

  7. I2C总线通信

    UART 属于异步通信,比如电脑发送给单片机,电脑只负责把数据通过TXD 发送出来即可,接收数据是单片机自己的事情.而 I2C 属于同步通信, SCL 时钟线负责收发双方的时钟节拍, SDA 数据线负 ...

  8. 51单片机 | 基于I2C总线的秒表模拟应用

    ———————————————————————————————————————————— 参考地址: http://blog.csdn.net/junyeer/article/details/4648 ...

  9. 张高兴的 .NET Core IoT 入门指南:(三)使用 I2C 进行通信

    什么是 I2C 总线 I2C 总线(Inter-Integrated Circuit Bus)是设备与设备间通信方式的一种.它是一种串行通信总线,由飞利浦公司在1980年代为了让主板.嵌入式系统或手机 ...

随机推荐

  1. Centos7 下安装mysql

    #prepare for install yum install http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm   ...

  2. Largest Divisible Subset -- LeetCode

    Given a set of distinct positive integers, find the largest subset such that every pair (Si, Sj) of ...

  3. Why DNS Based Global Server Load Balancing (GSLB) Doesn’t Work

    Why DNS Based Global Server Load Balancing (GSLB) Doesn't Work    

  4. 【JVM】调优笔记1-----堆栈概念的对碰

    关于JVM的工作原理以及调优是一个向往已久的模块,终于有幸接触到:http://pengjiaheng.iteye.com/blog/518623 那就顺着这个思路,来梳理一下自己看到后的结论和感想. ...

  5. redis基本命令,配置参数

    https://www.w3cschool.cn/redis/redis-pub-sub.html redis-server --maxclients 100000 客户端命令CLIENT LIST ...

  6. 学习实践:使用模式,原则实现一个C++数据库訪问类

    一.概述 在我參与的多个项目中.大家使用libMySQL操作MySQL数据库,并且是源代码级复用,在多个项目中同样或相似的源代码.这种复用方式给开发带来了不便. libMySQL的使用比較麻烦.非常e ...

  7. Yii2系列教程六:集成编辑器

    上一篇文章我们实现了简单的用户权限管理,至于更先进的RBAC,我后面会单独出一篇文章来说说.在这一篇文章当中,我主要想写的是在Yii2中集成一个编辑器,因为在我们的实际开发当中,一个简单的textar ...

  8. asp.net购物车,订单以及模拟支付宝支付(一)---购物车表及添加购物车流程

    在开发一个Web程序的时候用到了网购这个功能,上来分享并记录一下,以便以后忘记了可以自己看看(电脑东西太多,笔记都不知道放哪里去了啊啊啊啊啊!!!) 没有什么高并发量,什么什么技术理论,只是一个最最基 ...

  9. angular directive 的controllerAs的用法

    原文: https://stackoverflow.com/questions/31857735/using-controlleras-with-a-directive --------------- ...

  10. arduino小车入门教学——第三天(arduino基础)

    大家好,我是小编, 记上一节内容点击打开链接 我们今天讲arduino基础. 首先在arduino官网上下载程序. Windows解压版 苹果系统的版本号 好,下载过编程软件.我们就来讲编程. 这是类 ...