打印

新出炉的程序,大家来找茬.

[复制链接]
1782|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
耕在此行|  楼主 | 2008-11-2 11:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
上午刚写的一个I2C接口程序,新手有疑问我可以解答,高手的指导我耐心接受.
希望大家不要吝惜你的意见.
(程序没调试过,这是我第一次用C语言写的接口程序.)

// ******************************************************************
typedef        unsigned char  bin08;  //  8位无符号二进制码
#define        I2C_DIR        DIRA 
#define        I2C_PORT       PTA        
#define        PSCL           BIT1
#define        PSDA           BIT0
#define        SCL_0          (I2C_PORT &= ~PSCL)
#define        SCL_1          (I2C_PORT |= PSCL)
#define        SCL_IN         (I2C_DIR &= ~PSCL)
#define        SCL_OUT        (I2C_DIR |= PSCL)  
#define        SDA_0          (I2C_PORT &= ~PSDA)
#define        SDA_1          (I2C_PORT |= PSDA)
#define        SDA_IN         (I2C_DIR &= ~PSDA)
#define        SDA_OUT        (I2C_DIR |= PSDA)

void    I2C_rec_ack     ( );
bin08   I2C_rec_byte    ( );
void    I2C_send_ack    ( );
void    I2C_send_clk    ( );
void    I2C_send_byte   (bin08);
void    I2C_start       ( );
void    I2C_stop        ( );

void    read_E2(bin08 E2_adr, bin08* RAM_adr, bin08 n)
    {
    I2Cerr=0;
    I2C_start();            // 启动I2C总线
    I2C_send_byte(0xa0);    // 发送设备写地址
    I2C_rec_ack();        // 收应答信号
    if(I2Cerr==0)
        {
        I2C_send_byte(E2_adr);// 发E2数据地址
        I2C_rec_ack();        // 收应答信号
        if(I2Cerr==0)
            {
            I2C_start();        // I2C总线重新开始
            I2C_send_byte(0xa1);// 发送设备读地址
            I2C_rec_ack();        // 收应答信号
            if(I2Cerr==0)
                {
                while(1)
                    {
                    *RAM_adr = I2C_rec_byte();    // 读回一个字节
                    RAM_adr++;                    // RAM地址加1
                    n--;
                    if(n==0)
                        {
                         I2C_send_clk();
                         break;
                        }
                    I2C_send_ack();
                    }
                }
            }
        }
    I2C_stop();
    }

void    write_E2(bin08 E2_adr, bin08* RAM_adr, bin08 n)
    {
    I2Cerr=0;
    I2C_start();            // 启动I2C总线
    I2C_send_byte(0xa0);    // 发送设备写地址
    I2C_rec_ack();          // 收应答信号
    if(I2Cerr==0)
        {
        I2C_send_byte(E2_adr);// 发E2数据地址
        I2C_rec_ack();        // 收应答信号
        if(I2Cerr==0)
            {
            for( ; n!=0; n-- )
                {
                I2C_send_byte(*RAM_adr);// 发送一个字节
                I2C_rec_ack();          // 读回
                RAM_adr++;              // RAM地址加1
                }
            }
        }
    I2C_stop();
    delay_mS(10);
    }

void    I2C_rec_ack()
    {
    SDA_IN;
    delay_clk();
    SCL_1;
    delay_clk();
    if( I2C_PORT & PSDA )
        {
        I2Cerr = 1;
        }
    SCL_0;
    delay_clk();
    }

bin08 I2C_rec_byte()
    {
    bin08 i,I2C_data;
    SDA_IN;
    I2C_data = 0;
    for(i=8;i!=0;i--)
        {
        I2C_data <<= 1;
        SCL_1;
        delay_clk();
        if( I2C_PORT & PSDA )
            {
            I2C_data++;
            }
        SCL_0;
        delay_clk();
        }
    return(I2C_data);
    }

void I2C_send_ack()
    {
    SDA_0;
    SDA_OUT;
    I2C_send_clk();
    }

void I2C_send_clk()
    {
    SCL_1;
    delay_clk();
    SCL_0;
    delay_clk();
    }

void I2C_send_byte( bin08 I2C_data)
    {
    bin08 i;
    SDA_OUT;
    for(i=8;i!=0;i--)
        {
        if( I2C_data&0x80 )
            {
            SDA_1;
            }
        else
            {
            SDA_0;
            }
        delay_clk();
        I2C_send_clk();
        I2C_data <<= 1;
        }
    }

void I2C_start ( )
    {
    SDA_1;
    SDA_OUT;
    SCL_1;
    SCL_OUT;
    delay_clk();
    SDA_0;
    delay_clk();
    SCL_0;
    delay_clk();
    }
    
void I2C_stop( )
    {
    SDA_OUT;
    SDA_0;
    delay_clk();
    SCL_1;
    delay_clk();
    SDA_1;
    delay_clk();
    SDA_IN;
    SCL_IN;
    }
所有的错误与不足都改过来了,如果还能挑出毛病的那绝对是高手中的高手.

相关帖子

沙发
耕在此行|  楼主 | 2008-11-2 11:21 | 只看该作者

呵呵

 自己先顶下
    路过的不要忘了留下你的身影哦.

使用特权

评论回复
板凳
ahai0306| | 2008-11-2 12:15 | 只看该作者

第一次写的

如果是按照别人的改的就没什么,如果完全是自己根据手册编写的,那你的编程能力还是很不错的,第一次就写这样的程序,很不错了
但一般写的程序,不调试是通不过的

使用特权

评论回复
地板
hotyong| | 2008-11-2 13:04 | 只看该作者

真有这么强?

第一次用C写程序就写了这么多??牛人呀,俺第一次写的时候就点亮了个LED,,,
楼主太牛了,俺们都不敢在这混了!!

使用特权

评论回复
5
耕在此行|  楼主 | 2008-11-2 13:59 | 只看该作者

呵呵

楼上的理解错啰,我说是第一次用C语言写接口程序,
原来用C430时接口程序用汇编写的.
因手头没有好的C51书,所以只好用C写了.

使用特权

评论回复
6
ayb_ice| | 2008-11-2 14:58 | 只看该作者

这里不太合适吧

if(I2Cerr==0)没有错误是可行的,如果有呢,没有相应处理.

使用特权

评论回复
7
耕在此行|  楼主 | 2008-11-2 14:59 | 只看该作者

呵呵

问题不在这啦

使用特权

评论回复
8
ayb_ice| | 2008-11-2 15:12 | 只看该作者

delay_mS(50);这里不能延时

否则对其它程序影响太大,这可以通过查询是否完成程序来完成...
至于细节问题我不太关心.

使用特权

评论回复
9
耕在此行|  楼主 | 2008-11-2 15:36 | 只看该作者

这个也是充许的.

你还是没找到问题啰

使用特权

评论回复
10
ayb_ice| | 2008-11-2 16:07 | 只看该作者

问题是读操作最后没有发送非应答信号

使用特权

评论回复
11
耕在此行|  楼主 | 2008-11-2 16:26 | 只看该作者

问题是读操作最后没有发送非应答信号

读操作最后直接就可以停止了啊

使用特权

评论回复
12
古道热肠| | 2008-11-2 16:30 | 只看该作者

哈哈,找茬有奖品吗?

有奖保准大家积极性高,找得也快!

使用特权

评论回复
13
耕在此行|  楼主 | 2008-11-2 16:33 | 只看该作者

发下读写的防错程序

/ 读 E2PROM 并验正读出数据是否正确
//-------------------------------------------
void    E2_Cread ( bin08 E2ad, bin08* RAMad,bin08 n )
    {
    bin08 i;
    bin08 j=0;
    bin08 sum;
    do
        {
        read_E2 ( E2ad, &buffer[0], (n+1) );
        sum = 0;
        for(i=0;i<n;i++)
            {
            sum += buffer+0x55;
            }
        I2Cerr=0;
        if ( sum == buffer[n] )
            {
            I2Cerr=1;
            }
        j++;
        }while ( (j<3)&& I2Cerr );
    memcopy(&buffer[0],RAMad,n);
    }
    
// 写 E2PROM 并在写完 5mS 后再读出,确定写入是否正确
//-------------------------------------------
void    E2_Cwrite ( bin08 E2ad, bin08* RAMad, bin08 n )
    {
    bin08 i;
    bin08 j=0;
    memcopy( RAMad,&buffer[0],n );
    do
        {
        buffer[n] = 0;
        for(i=n;i!=0;i--)
            {
            buffer[n] += buffer+0x55;
            }
        write_E2( E2ad, &buffer[0],(n+1) );
        read_E2 ( E2ad, &buffer[n+1],(n+1) );
        I2Cerr=0;
        for(i=n;i!=0;i--)
            {
            if (buffer != buffer[n+1+i])
                {
                I2Cerr=1;
                }
            }
        j++;
        }while ( (j<3)&& I2Cerr);
    }
此段程序已经通过调试没有问题,

使用特权

评论回复
14
ayb_ice| | 2008-11-2 18:15 | 只看该作者

看来LZ没有完全理解IIC协议

LZ并不知道非应答信号的作用.

使用特权

评论回复
15
耕在此行|  楼主 | 2008-11-2 19:03 | 只看该作者

呵呵

楼上说的我再确定下.

使用特权

评论回复
16
耕在此行|  楼主 | 2008-11-2 19:10 | 只看该作者

楼上说的对

在读完最后一个字节,应只给一个时钟(不给应答信号)而不应该直接停止.否则可能引起总线竞争.我先把这个问题改下.
不过你还是没找出其它的三个问题.

使用特权

评论回复
17
耕在此行|  楼主 | 2008-11-3 10:16 | 只看该作者

问题多多

昨天晚上想了下,又发现了几个潜在问题.不知大家有没看出?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

1108

帖子

0

粉丝