nios ii中操作24C04

2019-07-15 21:12发布

/*
* I2C.c
*
*  Created on: 2017-9-4
*      Author: 代忠
*      function: 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();
}

希望大神帮我看看问题出在那边了,我在板子上不能读取到相关数据,上面是底层代码,没有吧测试代码发出来,求大神们帮忙看下


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。