概述

最近搞项目使用了EFM32这款单片机,感觉硬件I2C还是不够灵活,这次改成了模拟I2C方式通讯。

需要创建两个文件:i2c.h和i2c.c

以下是i2c.h文件实例代码:

#ifndef __IIC_H
#define __IIC_H
#include <stdint.h>void i2c_read(uint8_t addr, uint8_t reg, uint8_t* buf, uint32_t len);
void i2c_write(uint8_t addr, uint8_t reg, uint8_t* buf, uint32_t len);

以下是i2c.c文件实例代码:

#include "i2c.h"
#include <stdint.h>
#include "em_chip.h"
#include "em_cmu.h"
#include "em_gpio.h"#define SCK_TIME    2#define ACK_TIME    3#define START_TIME  5/* Using PA0 (SDA) and PA1 (SCL) */#define gpio_direction_input(a) \if(#a=="SDA")  \{              \GPIO_PinModeSet(gpioPortA, 0, gpioModeInput, 1); \}                #define gpio_direction_output(a,b) \if(#a=="SDA")   \{              \GPIO_PinModeSet(gpioPortA, 0, gpioModePushPull, b); \}             \else if(#a=="SCL")         \{              \GPIO_PinModeSet(gpioPortA, 1, gpioModePushPull, b); \}#define  gpio_set_value(a,b) \if(#a=="SDA")  \{              \if(b==1) GPIO_PinOutSet(gpioPortA,0);       \else if(b==0) GPIO_PinOutClear(gpioPortA,0);\}                \else if(#a=="SCL")         \{              \if(b==1) GPIO_PinOutSet(gpioPortA,1);       \else if(b==0) GPIO_PinOutClear(gpioPortA,1);\}\#define SDA   0
#define SCL   1
static uint8_t gpio_get_value(uint8_t sd) { return GPIO_PinInGet(gpioPortA, 0); } static void udelay(uint32_t t)
{for(; t!=0; t--);
}static void i2c_start(void)
{gpio_direction_output(SDA, 1);gpio_direction_output(SCL, 1);udelay(SCK_TIME);gpio_set_value(SDA, 0);udelay(START_TIME);gpio_set_value(SCL, 0);
}static void i2c_stop(void)
{udelay(SCK_TIME);gpio_direction_output(SDA, 0);gpio_set_value(SCL, 1);udelay(SCK_TIME);gpio_set_value(SDA, 1);
}static uint8_t i2c_read_ack(void)
{uint8_t r; gpio_direction_input(SDA);  udelay(ACK_TIME);gpio_set_value(SCL,1);udelay(1);r = gpio_get_value(SDA);   udelay(1);gpio_set_value(SCL,0);return r;
}static void i2c_send_ack(void)
{udelay(SCK_TIME);gpio_direction_output(SDA, 1);gpio_set_value(SCL,1);udelay(SCK_TIME);gpio_set_value(SCL,0);
}static void i2c_write_byte(uint8_t b)
{int i;for (i=7; i>=0; i--) {udelay(SCK_TIME);gpio_direction_output(SDA, b & (1<<i));udelay(SCK_TIME - 2);gpio_set_value(SCL, 1);udelay(SCK_TIME);gpio_set_value(SCL, 0);}i2c_read_ack();
}static uint8_t i2c_read_byte(void)
{int i;uint8_t r = 0;gpio_direction_input(SDA); for (i=7; i>=0; i--) {udelay(SCK_TIME * 5);gpio_set_value(SCL, 1);r |= (gpio_get_value(SDA) << i);udelay(SCK_TIME * 5);gpio_set_value(SCL, 0);}i2c_send_ack();return r;
}void i2c_read(uint8_t addr, uint8_t reg,uint8_t* buf, uint32_t len)
{uint8_t i,t;i2c_start();t = (addr << 1) | 0;i2c_write_byte(t);i2c_write_byte(reg);i2c_start();t = (addr << 1) | 1;i2c_write_byte(t);for (i=0; i<len; i++)buf[i] = i2c_read_byte();i2c_stop();
}void i2c_write(uint8_t addr, uint8_t reg, uint8_t* buf, uint32_t len)
{uint8_t i,t;i2c_start();t = (addr << 1) | 0;i2c_write_byte(t);i2c_write_byte(reg);for (i=0; i<len; i++)i2c_write_byte(buf[i]);i2c_stop();
}

测试

测试案例:(注,我这里使用了MPU9250  9轴传感器)void main(void)
{uint8_t res = 0;uint8_t buf[] = {0};buf[0] = 0x22;while(1){i2c_write(MPU9250_ADDR,MPU_INTBP_CFG_REG, buf, 1);delay_ms(1000);i2c_read(MPU9250_ADDR,MPU_INTBP_CFG_REG,&res,1);printf(" res : %d \r\n", res);}}

EFM32 模拟I2C通讯案例(一)相关推荐

  1. 单片机GPIO软件模拟I2C通讯程序

    文章原始地址:http://feotech.com/?p=98 本程序主要用于使用可编程芯片自身的IO管脚,模拟I2C通信的协议,实现I2C总线数据的传输. /******************** ...

  2. STM32F0+模拟I2C通讯

    所谓的硬件I2C就是STM32芯片上有其相应的外设和驱动电路,通过配置相应的寄存器,就可以完成I2C的通信.本节实验我们介绍软件模拟I2C,软件I2C一般是通过GPIO引脚,按照I2C的时序要求来控制 ...

  3. 外设驱动库开发笔记8:GPIO模拟I2C驱动

    I2C总线简单方便,是我们经常使用的一种总线.但有时候我们的MCU没有足够多的I2C控制器来实现我们的应用,所幸我可以使用普通的GPIO引脚来模拟低速的I2C总线通信.这一节我们就来实现使用软件通过普 ...

  4. STM32使用模拟I2C读取硒翔30mL流量传感器

    使用模拟I2C读取硒翔30mL/min流量传感器 该工程使用某些采样次数和时间不同会采集到的报文有问题. 我建议是可以换个次数和时间调下. 如果报文有问题的话 就修改延时就好了,延时指的是I2C每发送 ...

  5. I2C软件模拟EEPROM通讯实验

    I2C是一种串行通讯总线,由于只有串行数据线SDA和串行时钟线SCL两个总线而被广泛使用. I2C软件模拟通信的本质是用芯片上任意两个引脚模拟I2C通信,也就是说通过控制任意两个引脚电平的高低变化来模 ...

  6. I2C通讯过程中SDA被一直拉低

    I2C通讯过程中SDA被一直拉低 一.现象 二.分析原因 2.1 正常情况该部分数据 正常情况slave返回一个byte数据:0x00(该字节8bit都是0) 2.2 异常发生时该部分数据 出现该情况 ...

  7. GPIO模拟I2C程序实现

    GPIO模拟I2C程序实现. I2C是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA).I2C是总线结构,1个 ...

  8. S5PV210之GPIO模拟I2c时序之pcf8591与at24xx linux3.0.8驱动

    目录:一. 说明 二. 驱动程序说明及问题 三. 案例一       四. 案例二 一. 说明 mini210开发板上带了at24c08, 看了linux内核自带的at24.c的驱动程序,编译下载到看 ...

  9. 关于stm32通信协议:软件模拟SPI、软件模拟I2C的总结(fishing_8)

    趁着帮老师代上嵌入式实验课的机会,又重新熟悉了一遍stm32的通信协议:串口协议.SPI协议.I2C协议.RS485协议.大概半年前,是过了一遍的,但也只停留于读了遍代码,跑了下例程,最近又过了一遍( ...

最新文章

  1. 固定表头和首行_Excel一步制作斜线表头!还有这些高分Excel表头技巧,看完秒会...
  2. 音视频技术开发周刊 | 221
  3. Lucene分类统计示例
  4. vue父组件向子组件传递多个数据
  5. esp32 coredump分析
  6. code review手记3
  7. linux版本信息i686,Linux下如何查看版本信息
  8. 团队冲刺第二阶段04
  9. JNI读取assets资源文件
  10. 安装无奈7和Linux,linux7安装teamViewer
  11. java 双三次线性插值_三种常见的图像处理双三次插值算法
  12. PaddleOCR整体了解
  13. LODOP.ADD_PRINT_TEXT 参数解释说明
  14. hihoCoder 1039:字符消除(字符串处理)
  15. 一起学Python吧~re正则+MySQL
  16. 用Ogre实现画中画 [ 截图 ]
  17. 四十六、Fluent壁面函数的选取依据
  18. 读书笔记(C++)————【重载操作符与转换】
  19. geth配置中,genesis.json的几个问题
  20. vue中的动画效果与过渡效果

热门文章

  1. vue2使用轮播图插件swiper,vue-awesome-swiper
  2. 计算机贴膜教程,笔记本贴膜详细教程
  3. 手机计算机数字显示在桌面上,手机桌面上的应用如何取消显示的数字角标
  4. Spark2.1 内存管理详解
  5. 《刻意练习》和《原则》(达利欧)读书笔记
  6. php中smarty是什么意思,在{php}标签中使用smarty变量
  7. 电钢琴电子琴如何增加蓝牙MIDI模块BLE连接手机双模支持U盘播放
  8. QT学习笔记-画点线圆
  9. [附源码]计算机毕业设计财务管理系统Springboot程序
  10. matlab中散点图的线性拟合_Matlab直线拟合和平面拟合