/*
* I2C.c
*
* Created on: 2017-9-4
* Author: 代忠
* func
tion: implment i2c function
*/
#include "includes.h"
/********************************************************************
*以下为24C0X 系列的EEROM操作函数
*******************************************************************/
#define __IIC24C0x_h__
#include "includes.h"
#include "unistd.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#define false 0
#define true 1
/******************************************************************************
* 功能:读取SDA数据线上的数据
* 入口参数:无
* 返回值:返回数据线上的电平情况
*/
alt_u8 SDA_READ(void)
{
return IORD_ALTERA_AVALON_PIO_DATA(SDA_BASE);//读取I2C总线数据线上的数据信息
}
/********************************************************************
*功能:I2C总线初始化函数,在main函数中应该先调用该函数对i2C总线进行相关的初始化工作
*入口参数:无
*返回值:无
********************************************************************/
void I2C_init(void)
{
SCL_DATA(0);
delay(1);
I2C_stop();
}
/********************************************************************
*功能:I2C总线产生起始信号函数
*入口参数:无
*返回值:无
********************************************************************/
void I2C_start(void)
{
SDA_DRE(1);//设置数据信号线的工作方式为输出模式
SDA_DATA(1);
delay(1);
SCL_DATA(1);
delay(1);
SDA_DATA(0);
delay(1);
SCL_DATA(0);//保持时钟信号线
delay(1);
}
/********************************************************************
*功能:I2C总线产生停止信号
*入口参数:无
*返回值:无
********************************************************************/
void I2C_stop(void)
{
SDA_DRE(1);//设置数据信号线的工作方式为输出模式
SDA_DATA(0);
delay(1);
SCL_DATA(1);
delay(1);
SDA_DATA(1);
delay(1);
SCL_DATA(0);
delay(1);//保持时钟信号线
}
/********************************************************************
*功能:I2C总线上写入1个字节的数据
*入口参数:待写入的数据
*返回值:无
********************************************************************/
alt_u8 I2C_sendByte(alt_u8 I2C_data)
{
alt_u8 i;
alt_u8 ack;
SDA_DRE(1);//设置数据信号线的工作方式为输出模式
for (i=0;i<8;i++)
{
if(I2C_data & 0x80)
SDA_DATA(1);
else
SDA_DATA(0);
I2C_data = I2C_data << 1;
delay(1);
SCL_DATA(1);
delay(1);
SCL_DATA(0);
}
delay(1);
SDA_DATA(1);
delay(1);
SDA_DRE(0);//设置数据信号线的工作方式为输入模式
SCL_DATA(1);
delay(1);
if (SDA_READ())//等待从器件应答
ack = 0;
else
ack = 1;
SCL_DATA(0);
return ack; //返回从器件所发送应答信号进行取反返回
}
/********************************************************************
*I2C总线上读取一个字节的内容
********************************************************************/
alt_u8 I2C_receiveByte(void)
{
alt_u8 I2C_data = 0x00;
alt_u8 i;
SDA_DRE(1);//设置数据信号线的工作方式为输出模式
SDA_DATA(1);
SDA_DRE(0);//设置数据信号线的工作方式为输入模式
delay(1);
for (i=0;i<8;i++)
{
delay(1);
I2C_data *= 2; //接受到的数据进行相关的左移
SCL_DATA(1);
delay(1);
if (SDA_READ()) I2C_data++;
SCL_DATA(0);
}
return (I2C_data);
}
/********************************************************************
*I2C总线上向从器件写入器件地址和从寄存器地址
********************************************************************/
void I2C_issue_add(alt_u8 chipAdd,alt_u16 subAdd)
{
alt_u8 low_add;
alt_u8 wd = 0;
low_add = subAdd; //24C04有两页的一个地址空间,此处为计算地址空间位于那一页,详情参观24C04的datasheet
subAdd >>= 7;
wd = subAdd & 0x02; //计算位于那一页
wd |= chipAdd;
I2C_start();
I2C_sendByte(wd);
I2C_sendByte(low_add);
}
/********************************************************************
*I2C总线等待从器件内部完成写操作
********************************************************************/
void I2C_waitforwrite(alt_u8 chip)
{
alt_u8 ack;
do
{
I2C_start();
ack = I2C_sendByte(chip);
}while (!ack);
}
/********************************************************************
*将指针地址buf中的数据想入到器件chipAdd中的 s_add处
*写入数据的地址是连续写的,连续所写的内容最多为4个
********************************************************************/
void I2C_write_block(alt_u8 chipAdd,alt_u16 S_add,alt_u8 n_buf,alt_u8 *buf)
{
alt_u8 i;
I2C_issue_add(chipAdd,S_add);
for (i=0;i<n_buf;i++)
{
I2C_sendByte(*(buf+i));
}
I2C_stop();
//I2C_waitforwrite(chipAdd);
}
/********************************************************************
* 从EEROM中寄存器地址为S_add出读取n_buf个数据信息,存放于buf指针里面
********************************************************************/
void I2C_read_block(alt_u8 chipAdd,alt_u16 S_add,alt_u8 n_buf,alt_u8 *buf)
{
alt_u8 i;
alt_u8 rd=0;
I2C_issue_add(chipAdd,S_add);
S_add >>= 7;
rd = S_add & 0x02; //地址页计算
rd |= chipAdd;
rd |= 0x01; //进行读写位置位
I2C_start(); //重新产生启动信号,详情请参观I2C协议读取EEROM协议手册
I2C_sendByte(rd);
for (i=0;i<n_buf-1;i++)
{
*(buf+i) = I2C_receiveByte();
delay(1);
SDA_DRE(1);
SDA_DATA(0); //应答是否需要连续读取数据
delay(1);
SCL_DATA(1);
delay(1);
SCL_DATA(0);
delay(1);
SDA_DATA(1);
}
*(buf+i) = I2C_receiveByte();
I2C_stop();
}
希望大神帮我看看问题出在那边了,我在板子上不能读取到相关数据,上面是底层代码,没有吧测试代码发出来,求大神们帮忙看下
一周热门 更多>