shute0000 发表于 2008-3-3 12:02:32

马老师,可不可以帮我看看我的i2c的程序

我用模拟i2c去对24c256进行读写,通过了编译,但是读不出来数,请问该怎么去思考
解决问题,以下是我的程序

#include <iom16v.h>
#include <macros.h>
#include <delay.h>

#define uchar unsigned char
uchar mid;


#define        SCL                0x01                //        IIC clock
#define        SDA                0x02                //        IIC data
#define true 1
#define false 0
/*===================================================================
//        函数功能:        模拟I2C接口初始化函数
//        形参:                void
//        返回:                void
//        编写:                2004/6/27
//        备注:                放于端口初始化之后调用
===================================================================*/
void        Lib_I2C_Ini(void)
{
        DDRC |= SCL;
        DDRC |= SDA;
        PORTC |= SCL;
        PORTC |= SDA;
}

/*===================================================================
//        函数功能:        模拟I2C接口延时函数
//        形参:                void
//        返回:                void
//        编写:                2004/6/27
//        备注:                约延时7us,这样,I2C速度大约为100kHz
===================================================================*/
void        Lib_I2C_Delay(void)
{
        unsigned char tmp;
        for(tmp = 0; tmp < 200; tmp++)
                _NOP();
}

/*===================================================================
//        函数功能:        模拟I2C接口启动
//        形参:                void
//        返回:                void
//        编写:                2004/6/27
//        备注:                在SCL为高时间内变化SDA由高到低即为总线启动
===================================================================*/
void        Lib_I2C_Start(void)
{
        DDRC |= SDA;
        PORTC |= SCL;
        PORTC |= SDA;
        Lib_I2C_Delay();                                                        //        START condition setup time
        PORTC &= ~SDA;
        Lib_I2C_Delay();                                                        //        START condition hold time
}

/*===================================================================
//        函数功能:        模拟I2C接口停止
//        形参:                void
//        返回:                void
//        编写:                2004/6/27
//        备注:                在SCL为高时间内变化SDA由低到高即为总线停止
===================================================================*/
void        Lib_I2C_Stop(void)
{
        DDRC |= SDA;
        PORTC &= ~SDA;
        PORTC &= ~SCL;
        PORTC |= SCL;
        Lib_I2C_Delay();                                                        //        STOP condition setup time
        PORTC |= SDA;
        Lib_I2C_Delay();                                                        //        STOP condition hold time
}

void        Lib_I2C_CLK(void)
{
        PORTC |= SCL;
        Lib_I2C_Delay();
        PORTC &= ~SCL;
}

/*===================================================================
//        函数功能:        模拟I2C接口接收一个ACK
//        形参:                void
//        返回:                unsigned char        收到的回复
//        编写:                2004/6/27
===================================================================*/
unsigned char        Lib_I2C_ACK(void)
{
        PORTC &= ~SCL;
        DDRC &= ~SDA;
        PORTC |= SCL;                                                                   //        Clock the ACK bit
        Lib_I2C_Delay();
        if((SDA & PINC) == SDA)                                                //        Check the ACK bit
        {
                PORTC &= ~SCL;
                return true;
        }
        else
        {
                PORTC &= ~SCL;
                return false;
        }
}

/*===================================================================
//        函数功能:        模拟I2C接口送出一个数据
//        形参:                data        要送出的数据
//        返回:                void
//        编写:                2004/6/27
//        备注:                SCL的下降沿读数
===================================================================*/
unsigned char        Lib_I2C_Send(unsigned char data)
{
        unsigned char i;
        DDRC |= SDA;
        PORTC &= ~SCL;
        for(i = 0; i < 8; i++)
        {
                if((data & 0x80) == 0x80)
                        PORTC |= SDA;
                else
                        PORTC &= ~SDA;
                Lib_I2C_CLK();
                data <<= 1;
        }
//        if(!Lib_I2C_ACK())                                                        //        no ack
//                return        false;       
//        else
//                return        true;
        while(Lib_I2C_ACK());
        return        true;
}

/*===================================================================
//        函数功能:        模拟I2C接口接收一个字节数据
//        形参:                void
//        返回:                unsigned char        接收到的数据
//        编写:                2004/6/27
===================================================================*/
unsigned char        Lib_I2C_Rcv(void)
{
        unsigned char i;
        unsigned char indata;
        DDRC &= ~SDA;
        for(i = 0; i < 8; i++)
        {
                indata <<= 1;
                if(SDA & PINC)                                                        //        receive logic 1
                        indata ++;
                Lib_I2C_CLK();
        }
        Lib_I2C_CLK();
        return indata;
}



//***********************************初始化M16硬件**********8
void port_init(void)
{
PORTA = 0x00;
DDRA = 0xff;
PORTB = 0x00;
DDRB = 0xff;
PORTC = 0x00; //m103 output only
DDRC = 0xff;
PORTD = 0x00;
DDRD = 0xff;
}


void Send_NByte(unsigned int Rom_add,unsigned int Adata)//********************************多字节数据的发送
{
Lib_I2C_Start();
Lib_I2C_Send(0xa0);//24C02的物理地址
Lib_I2C_Send(Rom_add);//数据存储地址
Lib_I2C_Send(Adata);//想要存储的数据
Lib_I2C_Stop();
delay_nms(10);
}

void Receive_NByte(unsigned int addr)//********************多字节接收
{
Lib_I2C_Start();
Lib_I2C_Send(0xa0);
Lib_I2C_Send(addr>>8);
Lib_I2C_Send(addr);
Lib_I2C_Start();
Lib_I2C_Send(0xa1);
mid=Lib_I2C_Rcv();
if (Lib_I2C_ACK())
delay_nus(10);
else
Lib_I2C_Stop();
}


void main(void)
{
unsigned char temp=0;
port_init();
uart_init();
Send_NByte(0x00aa,0x5a);
delay_nms(1000);
Receive_NByte(0x00aa);   
    while(1)
    {
    Receive_NByte(0x00aa);
    PORTB=mid;
    PORTB=0xff;
    delay_nms(500);
        }
}

hl0716 发表于 2008-3-3 17:26:02

马老师 估计没有时间啊!

shute0000 发表于 2008-3-3 18:50:20

哦,那我发在哪儿比较好呀,本来这个叫别人看程序就是比较麻烦的,我也不知道问谁好,哎
都整了一星期了,还是没有调出来

machao 发表于 2008-3-4 00:01:38

就是有时间我也不会看这样的程序,抱歉了。

请你买本我的<<AVR单片机嵌入式系统原理与应用实践>>书,里面有4个不同方式对24C256操作的例程,我自信比LZ从别人那里搬来的程序(或自己写)要好的多。

shute0000 发表于 2008-3-4 13:14:34

你的书我买了的,并且也是看你的书入门的,但是对于这个程序,我不知道怎么用iccavr移植你的cvavr所编译的程序,
于是我在网上找了一个i2c.h,并参照你的书写了24c256的读写函数,但是现在没有成功。
不过我觉得cvavr比iccavr好用,你觉得我应该换换编译器来学习吗?

machao 发表于 2008-3-4 17:57:38

如果你真正掌握了I2C的协议规程,读懂了书中的例子,那么将例16.2移植到ICCAVR应该不困难.

zelos 发表于 2008-3-5 00:54:23

我觉得各位不要发这么大的程序量才好.我们交流的目的获得一种启迪或说一个知识点.如果都来看大程序的话,效率太低了,对发贴本人也没有什么真的提升效果

armok 发表于 2008-3-5 08:16:20

shute0000 发表于 2008-3-5 12:28:20

哦,我明白了,以后不会发这么大的程序上来了,谢谢各位的回帖

dack 发表于 2008-3-5 12:55:12

硬件正常吗?上拉了吗?上拉电阻多大?

解决这种问题的方法最好是用存储示波器(逻辑分析仪更好)看波形,对照datasheet上的时序图,一下就能分析出哪里出问题了。没有的话,就只能根据程序流程自己慢慢走一遍,分析时序了。

machao 发表于 2008-3-5 17:39:27

如果不懂I2C通信规程,有再先进的工具和设备也是没有用的.

shute0000 发表于 2008-3-6 14:16:38

硬件电路我已经搭完了的,但是在示波器上表现为SDA持续高电平,而SCL上有上下电沿的跳变,波形确实不象书上的时序图
用proteus仿真也是同样的结果,那么请问9楼的,是不是当我的波形确实看起来象书上画的那样了就表示时序没有问题了呢?
我的上拉电阻是5.1k的,vcc加的5伏,其他引脚接地

shute0000 发表于 2008-3-6 14:21:35

马老师,你的程序的定义我不理解,不知道是不是你慌忙写错了
前面定义
#define SCL_Hight        SCL = 0
#define SCL_Low        SCL = 1
#define SDA_Hight        SDA = 0
#define SDA_Low        SDA = 1
后面一系列的程序我都认为应该是
#define SCL_Hight        SCL = 1
#define SCL_Low        SCL = 0
#define SDA_Hight        SDA = 1
#define SDA_Low        SDA = 0

dack 发表于 2008-3-6 16:11:54

波形看起来象书上的还不一定行,还要看时序,就是各个波形之间的时间差,这个也符合标准了,就一定行了。

上拉电阻5.1k可能最高速度能达到200khz,我一般使用1k上拉,速度会快些。

有示波器慢慢查一下就好了。

machao 发表于 2008-3-6 16:17:25

为什么不打全?

SCL的定义是什么?
前面有:
#define SCL          DDRC.0
#define SCL_Output   PORTC.0

注意:I2C总线上有上拉电阻,初始化时SCL_Output(PORTC.0) = 0,
SCL_Hight==> SCL = 0 ==> DDRC.0 = 0 ==> PINC.0为高阻输入方式,内部上拉无效(PORTC.0 = 0) 但I2C总线上的SCL线由于外部上拉呈现高电平(相当SCL输出1)

SCL_Low==> SCL = 1 ==> DDRC.0 = 1 ==> PINC.0为输出方式,由于PORTC.0 = 0,输出为0,就把I2C总线上的SCL线拉低了,就是SCL输出0.

这是巧妙的利用了AVR的I/O口特性,用51是不行的.书中都有解释(P477).沉下心来,认真把基础打扎实.

shute0000 发表于 2008-3-6 21:33:04

感谢这几天各位的回帖,尤其是马老师在百忙中抽出时间来看我的帖子,还给我回了那么多,尤其感谢,非常感谢,我的程序今晚上调通了,确实原来的程序输入输出没有搞对
我是应该沉下心来,认真的打基础了
支持OurAVR,支持马潮专栏
页: [1]
查看完整版本: 马老师,可不可以帮我看看我的i2c的程序