文件IIC_driver.c
#include "I2C_Driver.h"
extern void Systick_Delay_1ms(u32 nCount);
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/ Configure I2C1 pins: SCL and SDA /
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void I2C_delay(void)
{
u8 i=100; //这里可以优化速度,经测试最低到5还能写入
while(i)
{
i--;
}
}
bool I2C_Start(void)
{
SDA_H;
SCL_H;
I2C_delay();
if(!SDA_read)return FALSE; //SDA线为低电平则总线忙,退出
SDA_L;
I2C_delay();
if(SDA_read) return FALSE; //SDA线为高电平则总线出错,退出
SDA_L;
I2C_delay();
return TRUE;
}
void I2C_Stop(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SDA_H;
I2C_delay();
}
void I2C_Ack(void)
{
SCL_L;
I2C_delay();
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
void I2C_NoAck(void)
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
bool I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
SCL_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
SCL_L;
return FALSE;
}
SCL_L;
return TRUE;
}
void I2C_SendByte(u8 SendByte) //数据从高位到低位//
{
u8 i=8;
while(i--)
{
SCL_L;
I2C_delay();
if(SendByte&0x80)
SDA_H;
else
SDA_L;
SendByte<<=1;
I2C_delay();
SCL_H;
I2C_delay();
}
SCL_L;
}
u8 I2C_ReceiveByte(void) //数据从高位到低位//
{
u8 i=8;
u8 ReceiveByte=0;
SDA_H;
while(i--)
{
ReceiveByte<<=1;
SCL_L;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
ReceiveByte|=0x01;
}
}
SCL_L;
return ReceiveByte;
}
//写入1字节数据 待写入数据 待写入地址 器件类型(24c16或SD2403)
bool I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress)
{
if(!I2C_Start())return FALSE;
I2C_SendByte(((WriteAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE);//设置高起始地址+器件地址
if(!I2C_WaitAck()){I2C_Stop(); return FALSE;}
I2C_SendByte((u8)(WriteAddress & 0x00FF)); //设置低起始地址
I2C_WaitAck();
I2C_SendByte(SendByte);
I2C_WaitAck();
I2C_Stop();
//注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
//Systick_Delay_1ms(10);
return TRUE;
}
//注意不能跨页写
//写入1串数据 待写入数组地址 待写入长度 待写入地址 器件类型(24c16或SD2403)
bool I2C_BufferWrite(u8* pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress)
{
if(!I2C_Start())return FALSE;
I2C_SendByte(((WriteAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE);//设置高起始地址+器件地址
if(!I2C_WaitAck()){I2C_Stop(); return FALSE;}
I2C_SendByte((u8)(WriteAddress & 0x00FF)); //设置低起始地址
I2C_WaitAck();
while(length--)
{
I2C_SendByte(* pBuffer);
I2C_WaitAck();
pBuffer++;
}
I2C_Stop();
//注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
//Systick_Delay_1ms(10);
return TRUE;
}
//跨页写入1串数据 待写入数组地址 待写入长度 待写入地址 器件类型(24c16或SD2403)
void I2C_PageWrite( u8* pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress)
{
u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
Addr = WriteAddress % I2C_PageSize; //写入地址是开始页的第几位
count = I2C_PageSize - Addr; //在开始页要写入的个数
NumOfPage = length / I2C_PageSize; //要写入的页数
NumOfSingle = length % I2C_PageSize; //不足一页的个数
if(Addr == 0) //写入地址是页的开始
{
if(NumOfPage == 0) //数据小于一页
{
I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //写少于一页的数据
}
else //数据大于等于一页
{
while(NumOfPage)//要写入的页数
{
I2C_BufferWrite(pBuffer,I2C_PageSize,WriteAddress,DeviceAddress);//写一页的数据
WriteAddress += I2C_PageSize;
pBuffer += I2C_PageSize;
NumOfPage--;
Systick_Delay_1ms(10);
}
if(NumOfSingle!=0)//剩余数据小于一页
{
I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //写少于一页的数据
Systick_Delay_1ms(10);
}
}
}
else //写入地址不是页的开始
{
if(NumOfPage== 0) //数据小于一页
{
I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //写少于一页的数据
}
else //数据大于等于一页
{
length -= count;
NumOfPage = length / I2C_PageSize; //重新计算要写入的页数
NumOfSingle = length % I2C_PageSize; //重新计算不足一页的个数
if(count != 0)
{
I2C_BufferWrite(pBuffer,count,WriteAddress,DeviceAddress); //将开始的空间写满一页
WriteAddress += count;
pBuffer += count;
}
while(NumOfPage--) //要写入的页数
{
I2C_BufferWrite(pBuffer,I2C_PageSize,WriteAddress,DeviceAddress);//写一页的数据
WriteAddress += I2C_PageSize;
pBuffer += I2C_PageSize;
}
if(NumOfSingle != 0)//剩余数据小于一页
{
I2C_BufferWrite(pBuffer,NumOfSingle,WriteAddress,DeviceAddress); //写少于一页的数据
}
}
}
}
//读出1串数据 存放读出数据 待读出长度 待读出地址 器件类型(24c16或SD2403)
bool I2C_ReadByte(u8* pBuffer, u8 length, u16 ReadAddress, u8 DeviceAddress)
{
if(!I2C_Start())return FALSE;
I2C_SendByte(((ReadAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE);//设置高起始地址+器件地址
if(!I2C_WaitAck()){I2C_Stop(); return FALSE;}
I2C_SendByte((u8)(ReadAddress & 0x00FF)); //设置低起始地址
I2C_WaitAck();
I2C_Start();
I2C_SendByte(((ReadAddress & 0x0700) >>7) | DeviceAddress | 0x0001);
I2C_WaitAck();
while(length)
{
*pBuffer = I2C_ReceiveByte();
if(length == 1)I2C_NoAck();
else I2C_Ack();
pBuffer++;
length--;
}
I2C_Stop();
return TRUE;
}
++++++++++++++++++++++++++++++++++++++++
文件IIC_driver.h
++++++++++++++++++++++++++++++++++++++++
#ifndef __I2C_Driver_H
#define __I2C_Driver_H
/ Includes ------------------------------------------------------------------/
#include "stm32f10x_lib.h"
#define SCL_H GPIOB->BSRR = GPIO_Pin_6
#define SCL_L GPIOB->BRR = GPIO_Pin_6
#define SDA_H GPIOB->BSRR = GPIO_Pin_7
#define SDA_L GPIOB->BRR = GPIO_Pin_7
#define SCL_read GPIOB->IDR & GPIO_Pin_6
#define SDA_read GPIOB->IDR & GPIO_Pin_7
#define I2C_PageSize 8 //24C02每页8字节
void I2C_GPIO_Config(void);
bool I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress);
bool I2C_BufferWrite(u8* pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress);
void I2C_PageWrite(u8* pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress);
bool I2C_ReadByte(u8* pBuffer, u8 length, u16 ReadAddress, u8 DeviceAddress);
#endif
|