简易软件IIC模块--可移植(附STM32f4及TM4c123例程)

我们写单片机代码时常常会用到软件IIC,网上大部分软件I2C协议将底层GPIO和时序写在了一起,而且要是用到了多条I2C总线时,移植时往往很尴尬,这里给大家提供一个封装好的简易I2C模块,只需要提供单片机上的GPIO读写操作方法就能完成I2C的读写操作。
注:该代码不建议初学者使用,希望刚接触I2C的小工程师们能踏踏实实先写一两次时序代码,读懂时序图

源代码下载地址:
百度云代码下载:https://pan.baidu.com/s/1v9WADsHb73a0k7sHF-w3hg 提取码:3h8l
Github下载地址:https://github.com/diceTZ/I2C.git

Z_I2C.h(由于篇幅过大Z_I2C.c未贴出,下载地址中含有Z_I2C.c文件)

//@作者   :tou_zi
//@编写时间 :2019年4月6日
//@修改时间 :2019年4月6日
//@文件名  :Z_I2C.h
//@描述   :模拟I2C时序结构模块
#ifndef _Z_I2C_H
#define _Z_I2C_H

#ifndef u8
#define u8 unsigned char
#endif

#define I2C_NORMAL 0
#define I2C_FAST 1

typedef struct I2C_SCLInterface
{	
	void(*write)(u8 lH);
}I2C_SCLInterface;

typedef struct I2C_SDAInterface
{
 	void(*selectRW)(u8 rW);
	void(*write)(u8 lH);
	u8(*read)(void);
}I2C_SDAInterface;

typedef struct I2C_Interface
{
	u8 mode;
	I2C_SCLInterface scl;	
	I2C_SDAInterface sda;
}I2C_Interface;

//初始化结构体
void initI2C_Interface(I2C_Interface *interface, u8 mode);
void setModeI2C_Interface(I2C_Interface *interface, u8 mode);
//I2CAPI
u8 writeByteI2C(I2C_Interface *interface, u8 dev, u8 reg, u8 data);
u8 readByteI2C(I2C_Interface *interface, u8 dev, u8 reg, u8 *data);

u8 writenByteI2C(I2C_Interface *interface, u8 dev, u8 reg, u8 len, u8 *data);
u8 readnByteI2C(I2C_Interface *interface, u8 dev, u8 reg, u8 len, u8 *data);
#endif

模块概述:I2C模块包含mode标志位、SCL子模块以及SDA子模块。

mode标志位:用于选择I2C的速率,在.c文件中可以自行修改
SCL子模块:SCL总线只需要写操作,不需要读操作,所以模块内是写(0或1)的函数指针。
SDA子模块:SDA总线需要读写操作,所以模块内含有写、读、以及读写转换的函数指针。

用户需要自己编写GPIO读、写函数,完成模块接口的连接。

使用方法(例程):
1、stm32F4

#include "Z_I2C.h

I2C_Interface i2c;
//SCL总线的写函数
static void writelH_SCL(u8 lH)
{
 	PBout(6) = (lH == 0) ? 0: 1;
}
//SDA总线的读写转换操作函数
static void selectRW_SDA(u8 rW)
{
 	GPIO_InitTypeDef  GPIO_InitStructure; 
  	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
 	if (rW == 0)
 	{
		  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
		  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
		  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
		  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
		  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
		  GPIO_Init(GPIOB, &GPIO_InitStructure);  
	 }
	 else
	 {
		  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
		  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
		  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
		  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
		  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
		  GPIO_Init(GPIOB, &GPIO_InitStructure);
	 }
}
//SDA总线的写函数
static void writelH_SDA(u8 lH)
{
	 PBout(7) = (lH == 0) ? 0: 1;
}
//SDA总线的读函数
static u8 readlH_SDA()
{
	 return PBin(7);
}
//配置I2C
void configI2C()
{
	 //GPIO初始化
	 GPIO_InitTypeDef  GPIO_InitStructure; 
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE );
	 GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	 GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	 GPIO_Init(GPIOB, &GPIO_InitStructure); 
	 
	 //模块初始化
	 initI2C_Interface(&i2c, 0);
	 i2c.scl.write = writelH_SCL; //将上面的方法与模块接口相连接
	 i2c.sda.selectRW = selectRW_SDA;
	 i2c.sda.write = writelH_SDA;
	 i2c.sda.read = readlH_SDA;
	 
	 u8 data[2] = {0x01, 0x02};
	 //向地址0x68,寄存器地址为0x05连续写入2个数据
	 writenByteI2C(&i2c, 0x68, 0x05, 2, data);
	 //向地址0x68,寄存器地址为0x05连续读入2个数据
	 readnByteI2C(&i2c, 0x68, 0x05, 2, data);
}

2、TM4C123

#include "Z_I2C.h

I2C_Interface i2c;

//SCL写方法
static void writelH_SCL(u8 lH)
{
	if (lH == 0)
  		GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, 0);
 	else
  		GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_PIN_6);
}
//SDA读写转换方法
static void selectRW_SDA(u8 rW)
{
	 if (rW == 0)
	 {
		HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; //解锁
		HWREG(GPIO_PORTA_BASE + GPIO_O_CR) = GPIO_PIN_7;   //确认
		HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = 0;       //重新锁定
		GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_7);
 		GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
	 }
	 else
	 {
	  	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; //解锁
	  	HWREG(GPIO_PORTA_BASE + GPIO_O_CR) |= GPIO_PIN_7;   //确认
	  	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = 0;       //重新锁定
	  	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7);
	  	GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
	 }
}
	//SDA写方法
static void writelH_SDA(u8 lH)
{
 	if (lH == 0)
  		GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, 0);
 	else
  		GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_PIN_7);
}
//SDA读方法
static u8 readlH_SDA()
{
 	return (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_7) & GPIO_PIN_7) == 0 ? 0 : 1;
}
//配置I2C
void configI2C()
{
 	//GPIO设置
 	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
 	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; //解锁
 	HWREG(GPIO_PORTA_BASE + GPIO_O_CR) |= GPIO_PIN_7;   //确认
 	HWREG(GPIO_PORTA_BASE + GPIO_O_LOCK) = 0;       //重新锁定
 	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6);
 	GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7);
 	GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
 	GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
 	GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_PIN_6);//设置高
  	GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_PIN_7);//设置高 
 
 	//I2C模块配置
 	initI2C_Interface(&i2c, 0);
 	i2c.scl.write = writelH_SCL;
 	i2c.sda.selectRW = selectRW_SDA;
 	i2c.sda.write = writelH_SDA;
 	i2c.sda.read = readlH_SDA;
 
 	u8 data[2] = {0x01, 0x02};
 	//向地址0x68,寄存器地址为0x05连续写入2个数据
 	writenByteI2C(&i2c, 0x68, 0x05, 2, data);
 	//向地址0x68,寄存器地址为0x05连续读入2个数据
 	readnByteI2C(&i2c, 0x68, 0x05, 2, data);
}

“望小小的举动,能改变世界“

发布了2 篇原创文章 · 获赞 2 · 访问量 240

猜你喜欢

转载自blog.csdn.net/weixin_39159599/article/details/104300283