📄 i2c.c
字号:
/***************************************************
模块说明 :I2C控制接口模块
芯片类型 :Nios II
作 者 :柳军胜
公 司 :杭州自由电子科技
:http://www.freefpga.com
电 话 :0571-85084089
修 改 :
日期时间 :20060522
说 明 :本程序模块仅提供I2C接口设备底层读写流程,不涉及
具体应用芯片控制逻辑。
****************************************************/
#include <stdio.h>
#include <io.h>
#include <system.h>
#include <i2c_master.h>
static void *gBaseAddr=NULL;
/*********************************************
函数名:init_i2c
功 能:初始化I2C控制器、应用环境参数初始化设置
输 入:外设地址
返 回:
备 注:
应用I2C函数前必须先调用此函数设置I2C外设基地址
预分频允许100K~400K
**********************************************/
int init_i2c(void *baseAddr)
{
unsigned char uc,rdata;
if(gBaseAddr==NULL)
gBaseAddr=baseAddr;
//setup prer
IOWR(gBaseAddr , OC_I2C_PRER_LO ,0x63 );
IOWR(gBaseAddr, OC_I2C_PRER_HI, 0x00);
//setup ctr
IOWR(gBaseAddr , OC_I2C_CTR ,0x80 );
//read_status
//uc=IORD(gBaseAddr,OC_I2C_SR);
//send stop
IOWR(gBaseAddr,OC_I2C_TXR,0x55);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_WR|OC_I2C_STO);
return 0;
}
/*********************************************
函数名:wait_nTip_ACK
功 能:等待传输结束和应答
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断状态寄存器标志位完成功能
**********************************************/
//wait transmit over and wait ACK
int wait_nTip_ACK()
{
unsigned char uc;
int i;
if(gBaseAddr==NULL)
return -1;
i=0;
while(1){
//read_status TIP
uc=IORD(gBaseAddr,OC_I2C_SR);
if(OC_ISCLEAR(uc,OC_I2C_TIP))break;
i++;
if(i>10000)return -2;
}
i=0;
while(1){
//read_status ACK
uc=IORD(gBaseAddr,OC_I2C_SR);
if(OC_ISCLEAR(uc,OC_I2C_RXACK))break;
i++;
if(i>10000)
{
//I2C器件没有应答时加入STOP发送 20060523
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_STO);
return -3;
}
}
return 0;
}
/*********************************************
函数名:wait_nTip
功 能:等待传输结束
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断状态寄存器标志位完成功能
**********************************************/
//wait transmit over
int wait_nTip()
{
unsigned char uc;
int i;
if(gBaseAddr==NULL)
return -1;
i=0;
while(1){
//read_status TIP
uc=IORD(gBaseAddr,OC_I2C_SR);
if(OC_ISCLEAR(uc,OC_I2C_TIP))break;
i++;
if(i>10000)return -1;
}
return 0;
}
/*********************************************
函数名:wait_idle
功 能:等待空闲
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断状态寄存器标志位完成功能
**********************************************/
//wait i2c idle
int wait_idle()
{
unsigned char uc;
int i;
if(gBaseAddr==NULL)
return -1;
i=0;
while(1){
//read_status TIP
uc=IORD(gBaseAddr,OC_I2C_SR);
if(OC_ISCLEAR(uc,OC_I2C_BUSY))break;
i++;
if(i>10000)return -1;
}
return 0;
}
/*********************************************
函数名:start_write_waitack()
功 能:I2C启动、写数据、等待ACK
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断I2C状态寄存器标志位完成功能
**********************************************/
int start_write_waitack(unsigned char data)
{
int iRet;
if(wait_idle()<0){
printf("i2c control is busy\n");
return -1;
}
IOWR(gBaseAddr,OC_I2C_TXR,data);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_STA|OC_I2C_WR);
iRet=wait_nTip_ACK();
if(iRet<0){
printf("1wait _nTip_ACK timeover\n");
return -2;
}
return 0;
}
/*********************************************
函数名:start_read_waitack()
功 能:I2C启动、写数据、等待ACK
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断I2C状态寄存器标志位完成功能
**********************************************/
int start_read_waitack(unsigned char data)
{
int iRet;
/* restart时状态不是 IDLE 所以不需要等待idle */
/*
if(wait_idle()<0){
printf("i2c control is busy\n");
return -1;
}
*/
/* 这里写的数据里面 R/W位为1,但是控制标志置OC_I2C_WR控制输出从机地址 */
IOWR(gBaseAddr,OC_I2C_TXR,data);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_STA|OC_I2C_WR);
iRet=wait_nTip_ACK();
if(iRet<0){
printf("1wait _nTip_ACK timeover\n");
return -2;
}
return 0;
}
/*********************************************
函数名:write_waitack()
功 能:写数据、等待ACK
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断I2C状态寄存器标志位完成功能
**********************************************/
int write_waitack(unsigned char data)
{
int iRet;
IOWR(gBaseAddr,OC_I2C_TXR,data);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_WR);
iRet=wait_nTip_ACK();
if(iRet<0){
printf("1wait _nTip_ACK timeover\n");
return -2;
}
return 0;
}
/*********************************************
函数名:write_waitack_stop()
功 能:写数据、等待ACK、发送STOP
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断I2C状态寄存器标志位完成功能
**********************************************/
int write_waitack_stop(unsigned char data)
{
int iRet;
IOWR(gBaseAddr,OC_I2C_TXR,data);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_WR|OC_I2C_STO);
iRet=wait_nTip_ACK();
if(iRet<0){
printf("1wait _nTip_ACK timeover\n");
return -2;
}
return 0;
}
/*********************************************
函数名:read_sendack()
功 能:读数据、发送ACK
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断I2C状态寄存器标志位完成功能
**********************************************/
int read_sendack(unsigned char *data)
{
int iRet;
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_RD|OC_I2C_ACK);
iRet=wait_nTip();
if(iRet<0)
return -1;
*data=IORD(gBaseAddr,OC_I2C_RXR);
return 0;
}
/*********************************************
函数名:read_sendack_stop()
功 能:读数据、发送ACK、STOP
输 入:外设地址
返 回: 0 成功 <0失败
备 注:
判断I2C状态寄存器标志位完成功能
**********************************************/
int read_sendack_stop(unsigned char *data)
{
int iRet;
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_RD|OC_I2C_ACK|OC_I2C_STO);
iRet=wait_nTip();
if(iRet<0)
return -1;
*data=IORD(gBaseAddr,OC_I2C_RXR);
return 0;
}
/*********************************************
函数名:read_I2c_EEprom
功 能:读EEPROM
输 入:外设地址,设备地址,字节地址
返 回: 读取的数据
备 注:
**********************************************/
unsigned char read_I2C_EEprom(unsigned char slaveAddr,unsigned char addr)
{
unsigned char rdata;
//write chip addr and write bit
IOWR(gBaseAddr,OC_I2C_TXR,slaveAddr);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_STA|OC_I2C_WR);
wait_nTip_ACK();
//write eeprom addr
IOWR(gBaseAddr,OC_I2C_TXR,addr);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_WR);
wait_nTip_ACK();
//write chip addr and read bit
IOWR(gBaseAddr,OC_I2C_TXR,slaveAddr|0x01);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_STA|OC_I2C_WR);
wait_nTip_ACK();
//read eeprom data
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_RD|OC_I2C_STO|OC_I2C_ACK);
wait_nTip();
rdata=IORD(gBaseAddr,OC_I2C_RXR);
return rdata;
}
/*********************************************
函数名:write_I2c_EEprom
功 能:写EEPROM
输 入:外设地址,设备地址,字节地址
返 回:
备 注:
**********************************************/
unsigned char write_I2C_EEprom(unsigned char slaveAddr,unsigned char addr,unsigned char data)
{
unsigned char rdata;
unsigned char rc;
if(wait_idle()<0){
printf("i2c control is busy\n");
return 0;
}
//write chip addr and write bit
IOWR(gBaseAddr,OC_I2C_TXR,slaveAddr);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_STA|OC_I2C_WR);
printf("w1\n");
rc=wait_nTip_ACK();
//write eeprom addr
IOWR(gBaseAddr,OC_I2C_TXR,addr);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_WR);
printf("w2\n");
rc=wait_nTip_ACK();
//write data
IOWR(gBaseAddr,OC_I2C_TXR,data);
IOWR(gBaseAddr,OC_I2C_CR, OC_I2C_WR|OC_I2C_STO);
printf("w3\n");
rc=wait_nTip_ACK();
return data;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -