打印
[51单片机]

关于C51和IIC总线传输的疑问

[复制链接]
796|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
darkthomas|  楼主 | 2015-11-21 11:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg52.h>
   #define uchar unsigned char
   #define uint unsigned int
   unsigned char flag,a,b[]={0,0,0,0,0},l,s[]={0,0},x[]={0},m,n;
  sbit led1=P3^4;
   sbit led2=P1^5;
    sbit led3=P3^7;
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;



/*******************************************************************************
* 函 数 名         : Delay1us()
* 函数功能                   : 延时
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void I2C_Delay10us()
{
        uchar a, b;
        for(b=1; b>0; b--)
        {
                for(a=2; a>0; a--);
        }
}


/*******************************************************************************
* 函 数 名         : I2C_Start()
* 函数功能                   : 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
* 输    入         : 无
* 输    出         : 无
* 备    注         : 起始之后I2C_SDA和I2C_SCL都为0
*******************************************************************************/

void I2C_Start()
{
        I2C_SDA = 1;
        I2C_Delay10us();
        I2C_SCL = 1;
        I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
        I2C_SDA = 0;
        I2C_Delay10us();//保持时间是>4us
        I2C_SCL = 0;                       
        I2C_Delay10us();               
}
/*******************************************************************************
* 函 数 名           : I2C_Stop()
* 函数功能                 : 终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
* 输    入           : 无
* 输    出                  : 无
* 备    注           : 结束之后保持I2C_SDA和I2C_SCL都为1;表示总线空闲
*******************************************************************************/

void I2C_Stop()
{
        I2C_SDA = 0;
        I2C_Delay10us();
        I2C_SCL = 1;
        I2C_Delay10us();//建立时间大于4.7us
        I2C_SDA = 1;
        I2C_Delay10us();               
}
/*******************************************************************************
* 函 数 名           : I2cSendByte(uchar num)
* 函数功能                  : 通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,
*                    * 保持发送信号I2C_SDA保持稳定
* 输    入           : num ,ack
* 输    出                  : 0或1。发送成功返回1,发送失败返回0
* 备    注           : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0
*******************************************************************************/

uchar I2C_SendByte(uchar dat, uchar ack)
{
        uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。
                       
        for(a=0; a<8; a++)//要发送8位,从最高位开始
        {
                I2C_SDA = dat >> 7;         //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
                dat = dat << 1;
                I2C_Delay10us();
                I2C_SCL = 1;
                I2C_Delay10us();//建立时间>4.7us
                I2C_SCL = 0;
                I2C_Delay10us();//时间大于4us               
        }

        I2C_SDA = 1;
        I2C_Delay10us();
        I2C_SCL = 1;
        while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
        {
                b++;
                if(b > 200)         //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
                {
                        I2C_SCL = 0;
                        I2C_Delay10us();
                        return 0;
                }
        }

        I2C_SCL = 0;
        I2C_Delay10us();
        return 1;               
}
/*******************************************************************************
* 函 数 名           : I2cReadByte()
* 函数功能                     : 使用I2c读取一个字节
* 输    入           : 无
* 输    出                  : dat
* 备    注           : 接收完一个字节I2C_SCL=0
*******************************************************************************/

uchar I2C_ReadByte()
{
        uchar a = 0,dat = 0;
        I2C_SDA = 1;                        //起始和发送一个字节之后I2C_SCL都是0
        I2C_Delay10us();
        for(a=0; a<8; a++)//接收8个字节
        {
                I2C_SCL = 1;
                I2C_Delay10us();
                dat <<= 1;
                dat |= I2C_SDA;
                I2C_Delay10us();
                I2C_SCL = 0;
                I2C_Delay10us();
        }
        return dat;               
}
/*******************************************************************************
* 函 数 名         : Delay10ms
* 函数功能                   : 延时函数,延时10ms
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void Delay10ms(unsigned int c)   //误差 0us
{
    unsigned char a, b;

        //--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
    for (;c>0;c--)
        {
                for (b=38;b>0;b--)
                {
                        for (a=130;a>0;a--);
                }         
        }      
}

/*******************************************************************************
* 函 数 名         : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能                   : 往24c02的一个地址写入一个数据
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void At24c02Write(unsigned char addr,unsigned char dat)
{
        I2C_Start();
        I2C_SendByte(0xa0, 1);//发送写器件地址
        I2C_SendByte(addr, m);//发送要写入内存地址
        I2C_SendByte(dat, 0);        //发送数据
        I2C_Stop();
}
/*******************************************************************************
* 函 数 名         : unsigned char At24c02Read(unsigned char addr)
* 函数功能                   : 读取24c02的一个地址的一个数据
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

unsigned char At24c02Read(unsigned char addr)
{
        unsigned char num;
        I2C_Start();
        I2C_SendByte(0xa0, 1); //发送写器件地址
        I2C_SendByte(addr, 0x00); //发送要读取的地址
        I2C_Start();
        I2C_SendByte(0xa1, 1); //发送读器件地址
        num=I2C_ReadByte(); //读取数据
        I2C_Stop();
        return num;       
}

      void init()
   {   
      SCON=0x50;
      PCON=0x80;
      TMOD=0x20;
      TH1=0xff;
      TL1=0xff;
      TR1=1;
      EA=1;
      ES=1;
             }
  void main ()
        {  
          init();
          while(1)
           {  
              if(flag==1)
               {   
                 EA=0;
                 led1=0;
                 led2=0;
                 led3=0;
                               

                        m=At24c02Read(2);
                         n=b[2];
                         At24c02Write(2,n);
                                                               
                                       

flag=0;
l=0;
                  led1=1;
                  led3=1;
                  led2=1;
                   EA=1;

               }
           }
                   }

          void ser()interrupt 4
          {
            if(RI)
               {
                if(l<5)
                  {  
                    b[l]=SBUF;
                     l++;

                  }
                                  RI=0;
                   if(l==5)
                     {
                     flag=1;
                                         

                   }
                   }
                }
这是我的程序,读取24c02中 00H内容 然后把其内容当作地址  再把串口接受到的数据标b[2]写入到这个地址中。
下面为同学写的读取IIC 的一个子程序(非全部)。但是他每次读出来的和我写进去的不一样。因为他是汇编,我是C我俩都不知道哪里出了问题。

IIC_BUSY1         BIT     P3.2        ; 1-- BUSY
IIC_BUSY2         BIT     P3.3        ; 1-- BUSY
AZIMU_H                      EQU     37H  ;已使用
AZIMU_L                      EQU     38H   ;已使用
R2                          EQU                  39H          ;
;**********************************
;           READ1  READ2
;**********************************
RANDOM_READ1:
    ACALL   IIC_STA
    MOV     A,#0A0H
        ACALL   IIC_WRBYT
        ACALL   IIC_CACK
        JB      F0,RANDOM_READ1
    ACALL   IIC_STA
    MOV     A,#00H
        ACALL   IIC_WRBYT
        ACALL   IIC_CACK
        JB      F0,RANDOM_READ1
        MOV     AZIMU_H,A
        ACALL   IIC_WRBYT
        ACALL   IIC_CACK
        JB      F0,RANDOM_READ1

        ACALL   IIC_STOP
RET       
;**********************************************
;******************IIC OPREATE*****************
;----------------------------------------------
IIC_STA:
        SETB    IIC_SDA
        SETB    IIC_SCK
        NOP
        NOP
        CLR     IIC_SDA
        NOP
        NOP
        CLR     IIC_SCK
        RET
IIC_STOP:
        CLR     IIC_SDA
        SETB    IIC_SCK
        NOP
        NOP
        SETB    IIC_SDA
        NOP
        NOP
        CLR     IIC_SCK
        RET
IIC_MACK:
        CLR     IIC_SDA
        SETB    IIC_SCK
        NOP
        NOP
        CLR     IIC_SCK
        SETB    IIC_SDA
        RET
IIC_MNACK:
        SETB    IIC_SDA
        SETB    IIC_SCK
        NOP
        NOP
        CLR     IIC_SCK
        CLR     IIC_SDA
        RET
IIC_CACK:       
        SETB    IIC_SDA
        SETB    IIC_SCK
        CLR     F0
        MOV     C,IIC_SDA
        JC     CEND
        SETB    F0
CEND:
        CLR     IIC_SCK
        NOP
        RET

IIC_WRBYT:
        MOV     R0,#08H
WLP:
        RLC     A
        JC      WR1
        SJMP    WR0
WLP1:
        DJNZ    R0,WLP
        SETB    IIC_SDA
        RET
WR1:
        SETB    IIC_SDA
        SETB    IIC_SCK
        NOP
        NOP
        CLR     IIC_SCK
        CLR     IIC_SDA
        SJMP    WLP1
WR0:
        CLR     IIC_SDA
        SETB    IIC_SCK
        NOP
        NOP
        CLR     IIC_SCK
        SJMP    WLP1
RET
IIC_RDBYT:
        MOV R0, #08H
RLP:
        SETB    IIC_SDA
        SETB    IIC_SCK
        MOV     C,IIC_SDA
        JC     RD0
        SJMP    RD1
RLP1:
        DJNZ    R0,RLP
        RET
RD0:
        CLR     C
        MOV     A,R2
        RLC     A
        MOV     R2,A
        CLR     IIC_SCK
        SJMP    RLP1
RD1:
        SETB    C
        MOV     A,R2
        RLC     A
        MOV     R2,A
        CLR     IIC_SCK
        SJMP    RLP1
RET  

求解答。。。。。

相关帖子

沙发
darkthomas|  楼主 | 2015-11-21 13:17 | 只看该作者
主要是C语言在IIC地址写入是否正确的问题

使用特权

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

本版积分规则

1

主题

2

帖子

0

粉丝