EFM32 模拟I2C通讯案例(一)

概述       

       最近搞项目使用了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);
    }

}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ch_champion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值