发布网友
共1个回答
热心网友
直接给你贴一个我用过的
C/C++ code
//iic.h
//for EEPROM
#ifndef _IIC_H_
#define _IIC_H_
#include "macro.h"
#include <stdint.h>
#include "DrvGPIO.h"
#include <stdlib.h>
//定义页长度
#define PAGELEN 32
//定义地址位数,如果是16位地址,移除下面定义
//#define ADDRESS_8BITS
#define SDA1 E_GPA,10
#define SCL1 E_GPA,11
void delay(void);
void delay_ms(unsigned long ms);
void I2C_Start();
void I2C_Stop();
bool Test_Ack();
void SendData(uint8_t buffer);
bool I2C_WriteNByte(uint8_t sla,uint16_t addr,uint8_t *s,uint16_t n);
bool I2C_ReadNByte(uint8_t sla,uint16_t addr,uint8_t *p,uint16_t n);
bool ReadPByte(uint8_t sla,uint16_t addr,uint8_t *p,uint16_t n);
bool WritePByte(uint8_t sla,uint16_t addr,uint8_t *p,uint16_t n);
uint32_t geteepsize(void);
#endif
C/C++ code
//FileName:
//Device:
//Interface:
//BaseFile:
//Description: HY3116的驱动(iic接口)
#include "iic.h"
#include "global.h"
#define _nop_() __NOP()
void SDA_H(void)
{
DrvGPIO_SetBit(SDA1);
}
void SDA_L(void)
{
DrvGPIO_ClrBit(SDA1);
}
void SCL_H(void)
{
DrvGPIO_SetBit(SCL1);
}
void SCL_L(void)
{
DrvGPIO_ClrBit(SCL1);
}
uint8_t GetSDA(void)
{
return DrvGPIO_GetBit(SDA1);
}
void delay(void)
{
uint8_t i;
for(i=100;i>0;i--){__NOP();}
}
//不精确
void delay_ms(uint32_t ms)
{
uint8_t i;
while(ms>0)
{
for(i=0;i<125;i++)
{
__NOP();
}
ms--;
}
}
/*********************************************************
**名称:I2C_Start
**功能:启动I2C
**输入:无
**返回:无
*********************************************************/
void I2C_Start()
{
SDA_H();
delay();
SCL_H();
delay();
SDA_L();
delay();
SCL_L();
}
/**********************************************************
**名称:I2C_Stop
**功能:停止I2C
**输入:无
**返回:无
**********************************************************/
void I2C_Stop()
{
SDA_L();
delay();
delay();
SCL_H();
delay();
delay();
SDA_H();
delay();
delay();
}
/**********************************************************
**名称:Ack
**功能:应答信号
**输入:无
**返回:无
**********************************************************/
void Ack()
{
SDA_L();
delay();
SCL_H();
delay();
SCL_L();
delay();
SDA_H();
delay();
}
/********************************************************
**名称:NoAck
**功能:发送非应答信号
**输入:无
**返回:无
********************************************************/
void NoAck()
{
SDA_H();
delay();
delay();
SCL_H();
delay();
delay();
SCL_L();
delay();
delay();
SDA_L();
delay();
delay();
}
/********************************************************
**名称:Test_Ack()
**功能:检测应答位
**输入:无
**返回:flag,有应答时flag为0,无应答时flag为1
*********************************************************/
bool Test_Ack()
{
bool flag;
SCL_L();
SDA_H();//读入数据
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
SCL_H();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
if(GetSDA()==0)
flag=true;
else flag=false;
SCL_L();
return(flag);
}
/********************************************************
**名称:SendData()
**功能:发送一字节数据
**输入:buffer
**返回:
*******************************************************/
void SendData(uint8_t buffer)
{
uint8_t BitCnt=8;//一字节8位
uint8_t temp=0;
do
{
temp=buffer;
SCL_L();
delay();
if((temp&0x80)==0) //
SDA_L();
else
SDA_H();
delay();
SCL_H();
// temp=_crol_(buffer,1);//rl buff
// buffer=temp;
buffer<<=1;
BitCnt--;
}
while(BitCnt);
SCL_L();
}
/**************************************************************
**名称:uint ReceiveData()
**功能:接收一字节数据
**输入:
**返回:ucReceData
**说明:将接收的数据存放在ucReceData中
**************************************************************/
uint8_t ReceiveData()
{
uint8_t ucReceData=0;
uint8_t BitCnt=8;
SDA_H();//读入数据
do
{
SCL_L();
delay();
SCL_H();
delay();
if(GetSDA()==1)
ucReceData=ucReceData|0x01;
// else
// ucReceData=ucReceData&0x0fe;
if(BitCnt-1)
{
ucReceData<<=1;
}
BitCnt--;
}
while(BitCnt);
SCL_L();
return(ucReceData);
}
bool I2C_WriteNByte(uint8_t sla,uint16_t addr,uint8_t *s,uint16_t n)
{
uint16_t i;
uint8_t suba;
uint8_t subab;
DrvGPIO_ClrBit(EEP_WP);
suba=(addr>>8);//地址高8位
subab=addr&0x00ff;//地址低8位
I2C_Start();
SendData(sla);
if(Test_Ack()==false) return(false);
#ifndef ADDRESS_8BITS
SendData(suba);
if(Test_Ack()==false) return(false);
#endif
SendData(subab);
if(Test_Ack()==false) return(false);
for(i=0;i<n;i++)
{
SendData(*(s+i));
if(Test_Ack()==false)return(false);
}
I2C_Stop();
delay_ms(7);
DrvGPIO_SetBit(EEP_WP);
return(true);
}
bool I2C_ReadNByte(uint8_t sla,uint16_t addr,uint8_t *p,uint16_t n)
{
uint16_t i;
uint8_t suba;
uint8_t subab;
suba=(addr>>8);
subab=addr&0x00ff;
I2C_Start();
SendData(sla);
if(Test_Ack()==false){return false;}
#ifndef ADDRESS_8BITS
SendData(suba);
if(Test_Ack()==false){return false;}
#endif
SendData(subab);
if(Test_Ack()==false){return false;}
I2C_Start();
SendData(sla+1);
if(Test_Ack()==false){return false;}
for(i=0;i<n-1;i++)
{
*(p+i)=ReceiveData();
Ack();
}
*(p+n-1)=ReceiveData();
NoAck();
I2C_Stop();
delay_ms(7);
return true;
}
/**************************************************************************
Name:
Return:
Parameter:
Description: 当读/写的字节数可能超过一页时,用这个
***************************************************************************/
bool ReadPByte(uint8_t sla,uint16_t addr,uint8_t *p,uint16_t n)
{
uint16_t i;
uint16_t newadd;
bool t=true;
i=addr%PAGELEN;
i=PAGELEN-i;
newadd=addr+i;
if(I2C_ReadNByte(sla,addr,p,i)==false)t=false;
p+=i;
n-=i;
i=n/PAGELEN;
if(i<=0)return t;
for(;i!=0;i--)
{
if(I2C_ReadNByte(sla,newadd,p,PAGELEN)==false)t=false;
p+=PAGELEN;
newadd+=PAGELEN;
}
i=n%PAGELEN;
if(i>0)if(I2C_ReadNByte(sla,newadd,p,i)==false)t=false;
return t;
}
bool WritePByte(uint8_t sla,uint16_t addr,uint8_t *p,uint16_t n)
{
uint16_t i;
uint16_t newadd;
bool t=true;
i=addr%PAGELEN;
i=PAGELEN-i;
newadd=addr+i;
if(I2C_WriteNByte(sla,addr,p,i)==false)t=false;
p+=i;
n-=i;//剩余字节数
i=n/PAGELEN;
if(n<=0)return t;
for(;i!=0;i--)
{
if(I2C_WriteNByte(sla,newadd,p,PAGELEN)==false)t=false;
p+=PAGELEN;
newadd+=PAGELEN;
}
i=n%PAGELEN;
if(i>0)if(I2C_WriteNByte(sla,newadd,p,i)==false)t=false;
return t;
}
//获取EEPROM的大小
//原理过程
//1.读取0x0000出的数据并保存D0
//2.读取0xffff处的数据并保存DX
//3.写入一个!=DX并且!=D0的数DC至0xffff
//4.再读取0xffff的数,如果该数==DC并且0x0000中的数还是==D0则是K否则再测试地址0x7fff
//!如果SIZE小于512字节则返回0,因为256字节的EEPROM地址只有8位,如果要检测则需要调整地址位数
//这里为简化处理,256及256以下的EEPROM直接返回0
uint32_t geteepsize(void)
{
uint16_t addr=0xffff;
uint8_t d00;//存放EEPROM中原0x0000地址内的数据
uint8_t dx0;//测试字节(EEPROM中最后一个字节)的数据
uint8_t d01;//0x0000处第二次读取的值
uint8_t dx1;//测试字节的第二次读数
uint8_t test;
I2C_ReadNByte(0xa0,0x00,&d00,1);
for(addr=0xffff;addr>=511;addr>>=1)
{
I2C_ReadNByte(0xa0,addr,&dx0,1);
if(d00!=0x71&&dx0!=0x71)
test=0x71;
else if(d00!=0xe6&&dx0!=0xe6)
test=0xe6;
else test=0x3c;
I2C_WriteNByte(0xa0,addr,&test,1);
delay_ms(7);
I2C_ReadNByte(0xa0,addr,&dx1,1);
I2C_ReadNByte(0xa0,0x00,&d01,1);//看看是不是写最后一个字节时回滚到第一个字节
if(dx1==test&&d01==d00)
{
I2C_WriteNByte(0xa0,0,&d00,1);//将2个地方的数据写回去,这样EEPROM的数据就不会变化
delay_ms(10);
I2C_WriteNByte(0xa0,addr,&dx0,1);
return addr+1;
}
}
return 0;
}
void clr_rom(void)
{
uint32_t i;
uint8_t temp[PAGELEN];
for(i=0;i<PAGELEN;i++)temp[i]=0;
for(i=0;i<ESIZE;i+=PAGELEN)
{
I2C_WriteNByte(0xa0,i,temp,PAGELEN);
delay_ms(7);//页面写入时间大约需要5ms
}
}
缺的一些定义什么的,你根据编译的错误提示加上去就行了