今天我给大家分享一下我写的I2C软件模拟程序库的用法,写的不好不要见谅呀。
因为大家每次为写I2C协议都很麻烦,尤其是多个总线I2C,协议重复写还要重命名,IO底层也要全部复制改写。每次还要考虑拉还是不拉,搞得头晕!!!
这个IC2软件优点有一下几点:
1. 它可以实现一个你不知道I2C协议是什么的也可以灵活运用。
2,它只需配置很少底层就可以完成所有操作。
3. 它可以实现多个总线自动切换功能。
4,他有多处检测判断总线异常报警。
I2C库分为两大部分,
i2c协议.
i2c协议头文件.
i2c外设配置(配置相应单片机).
i2c外设配置头文件(配置相应单片机引导头文件).
第一部分我们是不用动的,第二部分是要配置的,
基本每种单片机我们只需要修改一次(i2c_config.c)这个文件
以后再用时只需修改i2c_config.h 即可
下面我说一下关键的配置i2c_config.h的几个定义;
<1> #define I2C_AUTU_WAIT 1 /*屏蔽此宏定义自动等待应答信号关闭*/
<2>#define I2C_WAIT_MAX_CLOCK 200 /*I2C检测应答等待最大时钟*/
<3>#define I2C_SHORT_DELAY 168*3 /*通讯时短暂延时(根据IC协议修改(一般为2.5us~10us))*/
<1> 这个是ACK用的,如果它没有屏蔽表示ACK等待I2C从设发送应答信号,等待到退出;
<2>I2C检测应答等待最大时钟,如果<1>没有屏蔽它为最大等待周期,如果屏蔽它为等待200约两百个时钟,在读ACK;
<3>这个为最重要的一步了,因为上边两个参数可以不修改,但这个必须修改,根据每个平台不一样就要修改大概计算方法近似值
一般I2C为400K-100K 那么每个周期应该为(2.5us~10us);这个定义I2C_SHORT_DELAY值约表示最小周期值;我们来计算一下F4=168M
168次为1us,所以168*3=3us 其实实际CPU要比计算要大,就是说CPU运行后肯定时间比3us长,这个我们就不用管了,只要满足I2C工作就可以了。
呵呵,说了这么多我们来个实战演习
本次I2C库以F4为例,做一用法介绍;24C02读写一个或多个字节
开始,
1。上面的参数我已配好
2。配置IO口(i2c_config.c)程序我也已配好
3.大家现在在F4上只需配置这个
#define I2C1_CHANNEL 1
#define I2C2_CHANNEL 2
#define I2C3_CHANNEL 3
#define I2C1_SCL_PIN GPIO_Pin_8
#define I2C1_SCL_GPIO GPIOB
#define I2C1_SCL_CLOCK RCC_AHB1Periph_GPIOB
#define I2C1_SDA_PIN GPIO_Pin_9
#define I2C1_SDA_GPIO GPIOB
#define I2C1_SDA_CLOCK RCC_AHB1Periph_GPIOB
#define I2C2_SCL_PIN GPIO_Pin_6
#define I2C2_SCL_GPIO GPIOF
#define I2C2_SCL_CLOCK RCC_AHB1Periph_GPIOF
#define I2C2_SDA_PIN GPIO_Pin_7
#define I2C2_SDA_GPIO GPIOF
#define I2C2_SDA_CLOCK RCC_AHB1Periph_GPIOF
#define I2C3_SCL_PIN GPIO_Pin_2
#define I2C3_SCL_GPIO GPIOC
#define I2C3_SCL_CLOCK RCC_AHB1Periph_GPIOC
#define I2C3_SDA_PIN GPIO_Pin_3
#define I2C3_SDA_GPIO GPIOC
#define I2C3_SDA_CLOCK RCC_AHB1Periph_GPIOC
我已经帮大家写了3个总线了,已经可以满足常用的了
如果我们的系统中没有3个总线怎么办?
解决的办法,如果只有一个那我们把它3个写一样,如果是2个我们把后两个写一样,如果三个那正好。
配置好上面3个接口后我们现在就可以用了,用之前我们先要执行
I2C_Initialization(); /*I2C初始化*/程序,它来初始化我们的IO口的。下来看程序
int main(void)
{
unsigned char i=0;
unsigned char data[2]={1,2};
unsigned char buf[8]={0,1,2,3,4,5,6,7};
unsigned char tbuf[8];
I2C_write_data(0,&data[0],1);写一个字节
I2C_read_ndata(0,&data[1],1);读一个字节
if(data[0]==data[1])
{
//ok;
}
else
{
//error;
}
I2C_write_data(0,buf,8);写8个字节
Delayms(10);//根据E2ROM规定他要延时等E2PROM烧写完毕。
I2C_read_ndata(0,tbuf,8);读8个字节
}
呵呵自动切换在哪里呀,I2C_write_data,I2C_read_ndata
这两个程序在哪里呀;
大家看下面就是24C02内部程序了,自动切换在读写程序里了,呵呵
#include &quot;i2c.h&quot;
#define E2_ADDR 0xA0
//**I2C写数据**//
void I2C_write_data(unsigned int addr,unsigned char *buffer,unsigned char n)
{
unsigned char r;
I2C_ChannelSelection(I2C1_CHANNEL);
while(I2C_CheckBusBusy()!=0); //检查总线忙碌 //
I2C_Start();
I2C_SendByte(E2_ADDR);
while(I2C_CheckAck()!=0);
I2C_SendByte(addr);
while(I2C_CheckAck()!=0);
for(r=0 ; r<n ; r++)
{
I2C_SendByte(buffer[r]);
while(I2C_CheckAck()!=0);
}
I2C_Stop();
}
//**I2C读数据**//
void I2C_read_ndata(unsigned int addr,unsigned char *buffer,unsigned char count)
{
unsigned char i;
I2C_ChannelSelection(I2C1_CHANNEL);
while(I2C_CheckBusBusy()!=0); //检查总线忙碌 //
I2C_Start();
I2C_SendByte(E2_ADDR);
while(I2C_CheckAck()!=0);
I2C_SendByte(addr);
while(I2C_CheckAck()!=0);
I2C_Start();
I2C_SendByte(E2_ADDR+1);
while(I2C_CheckAck()!=0);
for(i=0 ; i<count ; i++)
{
buffer = I2C_ReadByte();
if(i<count-1)
I2C_ReadAck();
}
I2C_NoAck();
I2C_Stop();
}
呵呵看到了吧只需在读写前加
I2C_ChannelSelection(I2C1_CHANNEL);这个函数就可以啦
I2C1_CHANNEL就是我们开始填写的总线通道了,呵呵讲到这里我估计大家也迷糊,不如你们把附件带入你们的F4移植看看,就明白啦。
今天就讲到这里不会的可以提问,呵呵我写的程序如果大家发现有什么错误可要多多提醒呀,谢谢。!!!!!! |