OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 15492|回复: 10

请教:I2C读写24C02正常,读别的I2C,相同地址数值每次读的不一样

[复制链接]

5

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2012-4-15
在线时间
0 小时
发表于 2012-4-15 19:58:54 | 显示全部楼层 |阅读模式

原子哥你好:

24cxx.c中添加
#define at24c02 1  //1-24C02   0---另一个器件,地址0X20.另外一个器件多了RESET(复位)和INTI(INTI),用51的代码读写240C02和另一个器件都可以正常读写,但是
//STM32读另一个器件,读相同的地址,每次读出数据都不一样
void IIC_Init(void)  //修改为PA口

 
     RCC->APB2ENR|=1<<2;//先使能外设IO PORTa时钟
  GPIOA->CRL&=0XFFFF0000;//PA 0 1 2 3推挽输出
  GPIOA->CRL|=0X00003333;    
  
  GPIOA->ODR|=15;       //PA 0 1 2 3 输出高  
  
}


myiic.h修改为:

#define SDA_IN()  {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8;}
#define SDA_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3;}
#define INTI_IN()  {GPIOA->CRL&=0XFFFFF0FF;GPIOA->CRL|=8<<8;}   // INTI
#define INTI_OUT() {GPIOA->CRL&=0XFFFFF0FF;GPIOA->CRL|=3<<8;}    //INTI


  #define IIC_SCL    PAout(1) //SCL
  #define IIC_SDA    PAout(0) //SDA 
  #define READ_SDA   PAin(0)  //输入SDA
  #define IIC_INTI   PAout(2)  //INTI
  #define READ_INTI  PAin(2)  //INTI
  #define IIC_CE     PAout(3) //SCL

u8 AT24CXX_ReadOneByte(u16 ReadAddr)  //另一个器件的I2C地址为0X20,左移后为0X40;
{ u8 ack;    
 u8 temp=0;                         
    IIC_Start();
  
 if(at24c02)
 IIC_Send_Byte(0Xa0);
 else
 IIC_Send_Byte(0X40);     
  ack=IIC_Wait_Ack();
    
    IIC_Send_Byte(ReadAddr);  
  ack=IIC_Wait_Ack(); 
      
 IIC_Start(); 
      
 if(at24c02)
 IIC_Send_Byte(0Xa1);
 else
 IIC_Send_Byte(0X41);     
  ack=IIC_Wait_Ack();
  
    temp=IIC_Read_Byte(0);
 //ack=IIC_Wait_Ack();     
    IIC_Stop();    
 return temp;
}

void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)   ////另一个器件的I2C地址为0X20,左移后为0X40,读为0X41;

{ u8  ack;                               
    IIC_Start();
 
    if(at24c02)
 IIC_Send_Byte(0Xa0);
 else
 IIC_Send_Byte(0X40);     
 ack=IIC_Wait_Ack();
    
    IIC_Send_Byte(WriteAddr);   //发送低地址
  ack=IIC_Wait_Ack();                   
 IIC_Send_Byte(DataToWrite);     //发送字节         
    ack=IIC_Wait_Ack();             
    IIC_Stop();//产生一个停止条件
 delay_ms(10); 
}




test.c
中修改为
 int main(void)
{  
 u8 key,t,times=0;
 u16 i=0;
 u8 datatemp[SIZE];
 u8 data11;
 u8 data;

 u8 USART_RX_BUF[64];
 u8 USART_RX_STA=0;
     
   Stm32_Clock_Init(9);//系统时钟设置
 delay_init(72);  //延时初始化
 uart_init(72,9600); //串口1初始化  
 LED_Init();      //LED初始化
 KEY_Init();      //按键初始化
 LCD_Init();      //TFTLCD液晶初始化
 AT24CXX_Init();  //IIC初始化


  OINT_COLOR=RED;//设置字体为蓝色   
 LCD_ShowString(60,50,"zini STM32"); 
 LCD_ShowString(60,70,"IIC TEST"); 
 
 
  IIC_CE=1;
  delay_ms(50);
   IIC_CE=0;
   delay_ms(50);
    IIC_CE=1;
    delay_ms(50);

 OINT_COLOR=BLUE;

//IIC_INTI=1;  

  AT24CXX_WriteOneByte(0x20,0x20);
  AT24CXX_WriteOneByte(0x21,0x22);
  AT24CXX_WriteOneByte(0x22,0x24);
  AT24CXX_WriteOneByte(0x23,0x26);  
  AT24CXX_WriteOneByte(0x24,0x28);
  AT24CXX_WriteOneByte(0x25,0x2a);
  
  data11=AT24CXX_ReadOneByte(0x20);
   data=AT24CXX_ReadOneByte(0x21);
     
 while(1)
 {

 
   data11=AT24CXX_ReadOneByte(0x20);
   data=AT24CXX_ReadOneByte(0x21);
    
      // INTI_IN();

   // if(!READ_INTI)   {
   times++;
   if(times%5000==0)
   { USART_RX_BUF[0]=AT24CXX_ReadOneByte(0x20);
    USART_RX_BUF[1]=AT24CXX_ReadOneByte(0x21);
    USART_RX_BUF[2]=AT24CXX_ReadOneByte(0x22);
    USART_RX_BUF[3]=AT24CXX_ReadOneByte(0x23);
    USART_RX_BUF[4]=AT24CXX_ReadOneByte(0x24);
    USART_RX_BUF[5]=AT24CXX_ReadOneByte(0x25);
     printf("\n坐标如下:\n");
    printf("\n坐标1:0x %x\n",USART_RX_BUF[0]);
    printf("\n坐标2:0x %x\n",USART_RX_BUF[1]);
    printf("\n坐标3:0x %x\n",USART_RX_BUF[2]);
    printf("\n坐标4:0x %x\n",USART_RX_BUF[3]);
    printf("\n坐标5:0x %x\n",USART_RX_BUF[4]);
    printf("\n坐标6:0x %x\n",USART_RX_BUF[5]);
  
   delay_ms(10);   }
  }
 
 
    }
 
 //}


在while(1)
中stm32循环读0X20和0X21的数值,读写24C02正常,读另外一个器件,每次读的数值都不一样;



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2012-4-15
在线时间
0 小时
 楼主| 发表于 2012-4-15 20:03:03 | 显示全部楼层
回复【楼主位】promcu:
---------------------------------
SDA--PA0
SCL--PA1
INTI--PA2
CE(RESET)--PA3
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-4-15 23:18:40 | 显示全部楼层
说明你的代码有问题了.
你是在我们开发板上做实验的么?
因为我们的开发板读取IIC是无问题的.想了解下你的硬件连接情况.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2012-4-15
在线时间
0 小时
 楼主| 发表于 2012-4-16 09:16:05 | 显示全部楼层
我刚开始是在原子哥开发板上做的,我自己焊接了一个24C02,用原子哥开发板,接的是PC4接24C02的SDA,PC5接24C02的SCL,将void IIC_Init(void)  和myiic.h修改后, 读写24C02是OK的,
接另一个新的I2C,PC4接新I2C的SDA,PC5接新I2C的SCL,PC1接新I2C的INTI,PC13接新I2C的CE(RESET);将void IIC_Init(void)  和myiic.h修改后,用JTAG8单步运行,有时候读的数据时正确的,有时候读的数据不正确,每次数据都在改变;读的大概是三个数据 随机出现的;

然后我就将代码移植到我另外一个STM32板上,用PA口,读写24C02还是OK的,但是读新的I2C,还是不行,上边发的代码就是PA口的程序;
代码读写用的是原子哥的,我就只是改了void IIC_Init(void)  和myiic.h。读新的I2C器件,每次读的数据不一样,读的大概是三个数据 随机出现的。

用51单片机读写24C02和新的I2C都是OK的。
回复 支持 反对

使用道具 举报

5

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2012-4-15
在线时间
0 小时
 楼主| 发表于 2012-4-16 09:24:53 | 显示全部楼层
51测试代码如下:
#include<string.h>
     #include<reg51.h>
     #include<intrins.h>
     #define DELAY_TIME 60
     #define TRUE 1
     #define FALSE 0 
 #define uchar unsigned char 
     sbit SCL=P1^1;/*假设由P1.7和P1.6控制*/
     sbit SDA=P1^0;
 sbit CE=P1^2;
 sbit INTI=P1^3;
void delay02s(void);
 #define     LED_BIT     4    
uchar  code segments[] = {0x03, 0x9f, 0x25, 0x0d, 0x99, 0x49, 0x41, 0x1f,
                           0x01, 0x09, 0x11, 0xc1, 0x63, 0x85, 0x61, 0x71};
uchar  code mask = 0x0F0; 
uchar  code arrayBit[LED_BIT] ={0x7F, 0xBF, 0xDF, 0xEF};
void disp(int nNum)
{
    unsigned char i=0;        //数码管计数
  unsigned char Left[4];   //数码管 左边数第一个 2.7
   
#if 0 
 Left[3] =   nNum % 10;           //个
 Left[2] = ( nNum / 10 ) % 10;    //十
 Left[1] = ( nNum / 100) % 10;    //百
 Left[0] = ( nNum / 1000) % 10;   //千  //千
#else
 Left[3] =  nNum&0x000f;   //个
 Left[2] =  nNum>>4&0x000f;   //十

 Left[1] = nNum>>8&0x000f;   //百
 Left[0] = nNum>>12&0x000f;   //千
#endif


 
    for(i =0; i < 4; i++)
    {
        2  |= mask;    
//  2  = 0xff;               //0x0F0; 关显示
        0   = segments[  Left ]; //通过 Left的内容查 segments表 找到要显示的内容 送段码
        2  &= arrayBit;          //送位码 

       delay02s(); 
    }
    
}


/********** Function Definition 函数定义 ************/

     void DELAY(unsigned int t) /*延时函数*/
     {
         while(t!=0)
             t--;
     }

     void I2C_Start(void)
     {
         /*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
         SDA=1;
         SCL=1;
         DELAY(DELAY_TIME);
         SDA=0;
         DELAY(DELAY_TIME);
         SCL=0;
         DELAY(DELAY_TIME);
     }

     void I2C_Stop(void)
     {
         /*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
         SDA=0;
         SCL=1;
         DELAY(DELAY_TIME);
         SDA=1;
         DELAY(DELAY_TIME);
         SCL=0;
         DELAY(DELAY_TIME);
     }

     void SEND_0(void)    /* SEND ACK */
     {
         /*发送0,在SCL为高电平时使SDA信号为低*/
         SDA=0;
         SCL=1;
         DELAY(DELAY_TIME);
         SCL=0;
         DELAY(DELAY_TIME);
     }

     void SEND_1(void)
     {
         /*发送1,在SCL为高电平时使SDA信号为高*/
         SDA=1;
         SCL=1;
         DELAY(DELAY_TIME);
         SCL=0;
         DELAY(DELAY_TIME);
     }

     bit Check_Acknowledge(void)
     {
         bit ack;/*发送完一个字节后检验设备的应答信号*/
         SDA=1;
         SCL=1;
         DELAY(DELAY_TIME/2);
         ack=SDA;
         DELAY(DELAY_TIME/2);
         SCL=0;
         DELAY(DELAY_TIME);
         if(!ack)
             return 1;
 else
         return 0;
     }

     bit WriteI2CByte(char b)
     {  bit ack;
         char i;
 bit acktemp=1;
         for(i=0;i<8;i++)
           { 
     if((b<<i)&0x80)
              SDA=1; 
      else   
              SDA=0;  
    SCL=1;
         DELAY(DELAY_TIME);
         SCL=0;
         DELAY(DELAY_TIME);


 // 
 }

//acktemp=Check_Acknowledge();  
     }


     char ReadI2CByte(void)
     {
         /*从I2C总线读一个字节*/
         char b=0,i;
         for(i=0;i<8;i++)
         {
             SDA=1;     /*释放总线*/
             SCL=1;     /*接受数据*/
             DELAY(10);
             F0=SDA;
             DELAY(10);
             SCL=0;
             if(F0==1)
                 {
                     b=b<<1;
                     b=b|0x01;
                 }
             else
                 b=b<<1;
         }
         return b;
 
     }


/**********以下为读写24c02的函数**********/
void Write_One_Byte(char addr,char thedata)
{
           bit acktemp=1;
           /*write a byte to mem*/
           I2C_Start();
           WriteI2CByte(0x40);
           acktemp=Check_Acknowledge();
           WriteI2CByte(addr);/*address*/
           acktemp=Check_Acknowledge();
           WriteI2CByte(thedata);/*thedata*/
            acktemp=Check_Acknowledge();
           I2C_Stop();

}

char Read_One_Byte(char addr)
{          bit acktemp=1;
           char mydata;
            /*read a byte from mem*/
           I2C_Start();
           WriteI2CByte(0x40);
           acktemp=Check_Acknowledge();
           WriteI2CByte(addr);/*address*/
          acktemp=Check_Acknowledge();
           I2C_Start();
           WriteI2CByte(0x41);
           acktemp=Check_Acknowledge();


           mydata=ReadI2CByte();
          acktemp=Check_Acknowledge();
 I2C_Stop();
           return mydata;
          
}



void delay02s(void)
{
  unsigned char j,k;
 
      for(j=5;j>0;j--)
        for(k=2;k>0;k--)
        {
          ;      
             
        }
}



void main()
{
           int i;
          
           uchar mybyte;
             CE=1;
      DELAY(DELAY_TIME);
     
         CE=0;
  DELAY(DELAY_TIME);
   CE=1;
           

           Write_One_Byte(0x70,0x28);


           mybyte=Read_One_Byte(0x70);
          
   while(1)
   {
    disp(mybyte); 
   
   }

}
 



回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-4-16 09:36:49 | 显示全部楼层
回复【4楼】promcu:
---------------------------------
你的什么IIC?还有INT1,CE之类的信号?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2012-4-15
在线时间
0 小时
 楼主| 发表于 2012-4-16 09:42:57 | 显示全部楼层
这个是一个电容屏控制芯片,
用的是I2C通讯,功能是来读取坐标的;
这个芯片用的是是标准IIC协议;
不读坐标时就类似普通的IIC。
INTI是中断,按了触摸INTI就会变低,
CE(RESET)是复位;
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-4-16 09:51:37 | 显示全部楼层
哦,那你还是检查代码的问题吧.底层IIC应该是无问题的.
我用来驱动过24Cxx,mma7660,ADXL345,PT23XX,TEA5767,RDA5820,OV7670等一系列芯片...没出过问题.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2012-4-15
在线时间
0 小时
 楼主| 发表于 2012-4-16 09:54:00 | 显示全部楼层
好的,谢谢。
回复 支持 反对

使用道具 举报

19

主题

248

帖子

2

精华

高级会员

Rank: 4

积分
842
金钱
842
注册时间
2012-2-8
在线时间
19 小时
发表于 2012-7-16 10:29:11 | 显示全部楼层
回复【8楼】正点原子:

---------------------------------
原子哥,能否共享一下ADXL345的的程序呢?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-7-16 12:42:32 | 显示全部楼层
这个网上很多啊~
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-22 12:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表