打印
[STM8]

还是坑爹的I2C问题

[复制链接]
10188|30
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ww_升|  楼主 | 2015-8-14 15:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
I2c, TE, ST, ev, ck
STM8S003F3P6芯片
硬件I2C
产生问题:程序经常死机,偶尔正常,都是卡在I2C_CheckEvent函数里面,写了独立看门狗也没作用
搞的心塞,求大神打救
贴出程序:
#define I2C_Speed              100000
#define I2C1_SLAVE_ADDRESS7    0xA0
GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_OUT_OD_HIZ_FAST);//PB4 I2C_SCL 功能引脚,总线的时钟脚,设为高速开漏高阻输出。
GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_OD_HIZ_FAST);//PB5 I2C_SDA 功能引脚,总线的数据脚,设为高速开漏高阻输出
/*********************************************
I2C总线写一个字节
**********************************************/
void I2C_Write(unsigned char ADDR,unsigned char Wdata)
{
          ITStatus it_status;
                FlagStatus flag_status;
               
                I2C_GenerateSTART(ENABLE);                                               

//I2C启动  /* Send STRAT condition */
                /* Test on EV5 and clear it */
                //while(!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT ));
          
          I2C_Send7bitAddress(ADDR, I2C_DIRECTION_TX);   //写I2C从器件地址和写方式
                /* Test on EV6 and clear it */
    //while(!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));
                while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
          
          I2C_SendData(Wdata);                                 //写数据到器件相应寄存器
                /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING));
               
          /* Send STOP condition */
    I2C_GenerateSTOP(ENABLE);
}

/*********************************************
I2C总线读一个字节
返回:16位数值
**********************************************/
unsigned int I2C_Read(unsigned char ADDR)
{
   unsigned int temp;
                unsigned char tmp1,tmp2;
                  /* While the bus is busy */
                while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY));
       
                I2C_GenerateSTART(ENABLE);                                               

//I2C启动        /* Generate start & wait event detection */
          /* Test on EV5 and clear it */
                //while (!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));
    while (!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));
   
                I2C_Send7bitAddress(ADDR, I2C_DIRECTION_RX);   //写I2C从器件地址和写方式
                /* Test on EV6 and clear it */
    //while (!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));
                while (!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
                //I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);
                /* 2 variables are used to avoid any compiler optimization */
      /* Read the SR1 register */
      tmp1 = I2C->SR1;
      /* Read the SR3 register */
      tmp2 = I2C->SR3;
               
                while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED));
          temp = I2C_ReceiveData();//启动主I2C读方式
                             //读取I2C接收数据 第一字节
                /* Disable Acknowledgement */
                I2C_AcknowledgeConfig(I2C_ACK_NONE);
               
          
                while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED));
          temp = (temp<<8)+I2C_ReceiveData();        //读第二字节 合成16位数值
                I2C_GenerateSTOP(ENABLE);                      //I2C停止
                I2C_AcknowledgeConfig(I2C_ACK_CURR);                                    //启动主

I2C读方式,结果应答NO_ACK
               
          return temp;
}

沙发
gaoyang9992006| | 2015-8-14 16:26 | 只看该作者
坑爹的代码。我都难以理解了。

使用特权

评论回复
板凳
dirtwillfly| | 2015-8-14 16:27 | 只看该作者
gaoyang9992006 发表于 2015-8-14 16:26
坑爹的代码。我都难以理解了。

:lol

使用特权

评论回复
地板
STARM| | 2015-8-14 23:50 | 只看该作者
#define I2C_Speed              100000
#define I2C1_SLAVE_ADDRESS7    0xA0
void Init( void )
{
  //PB4 I2C_SCL 功能引脚,总线的时钟脚,设为高速开漏高阻输出。
  GPIO_Init( GPIOB, GPIO_PIN_4, GPIO_MODE_OUT_OD_HIZ_FAST );
  //PB5 I2C_SDA 功能引脚,总线的数据脚,设为高速开漏高阻输出
  GPIO_Init( GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_OD_HIZ_FAST );
}

/*********************************************
I2C总线写一个字节
**********************************************/
void I2C_Write( unsigned char ADDR, unsigned char Wdata )
{
  ITStatus it_status;
  FlagStatus flag_status;
  
  I2C_GenerateSTART( ENABLE );
  
  //I2C启动  
  /* Send STRAT condition */
  /* Test on EV5 and clear it */
  //while(!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));
  while ( !I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT ) )
    ;
  
  I2C_Send7bitAddress( ADDR, I2C_DIRECTION_TX );   //写I2C从器件地址和写方式
  /* Test on EV6 and clear it */
  //while(!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));
  while ( !I2C_CheckEvent( I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) )
    ;
  
  I2C_SendData( Wdata );                           //写数据到器件相应寄存器
  /* Test on EV8 and clear it */
  while ( !I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_TRANSMITTING ) )
    ;
  
  /* Send STOP condition */
  I2C_GenerateSTOP( ENABLE );
}

/*********************************************
I2C总线读一个字节
返回:16位数值
**********************************************/
unsigned int I2C_Read( unsigned char ADDR )
{
  unsigned int temp;
  unsigned char tmp1, tmp2;
  /* While the bus is busy */
  while ( I2C_GetFlagStatus( I2C_FLAG_BUSBUSY ) )
    ;
  
  I2C_GenerateSTART( ENABLE );
  
  //I2C启动        
  /* Generate start & wait event detection */
  /* Test on EV5 and clear it */
  //while (!I2C_CheckEvent(I2C_EVENT_MASTER_START_SENT));
  while ( !I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT ) )
    ;
  
  I2C_Send7bitAddress( ADDR, I2C_DIRECTION_RX );   //写I2C从器件地址和写方式
  /* Test on EV6 and clear it */
  //while (!I2C_CheckEvent(I2C_EVENT_MASTER_ADDRESS_ACKED));
  while ( !I2C_CheckEvent( I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) )
    ;
  //I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);
  /* 2 variables are used to avoid any compiler optimization */
  /* Read the SR1 register */
  tmp1 = I2C->SR1;
  /* Read the SR3 register */
  tmp2 = I2C->SR3;
  
  while ( !I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_RECEIVED ) )
    ;
  //启动主I2C读方式
  temp = I2C_ReceiveData( );   
  
  //读取I2C接收数据 第一字节
  /* Disable Acknowledgement */
  I2C_AcknowledgeConfig( I2C_ACK_NONE );
  
  while ( !I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_RECEIVED ) )
    ;
  temp = ( temp << 8 ) + I2C_ReceiveData( );      //读第二字节 合成16位数值
  I2C_GenerateSTOP( ENABLE );                     //I2C停止
  I2C_AcknowledgeConfig( I2C_ACK_CURR );          //启动主I2C读方式,结果应答NO_ACK
   
  return temp;
}


使用特权

评论回复
5
正版长小强| | 2015-8-15 17:52 | 只看该作者
在我印象中0系列的没有出过问题,工业环境。

使用特权

评论回复
6
ww_升|  楼主 | 2015-8-16 23:13 | 只看该作者

这个是你试过没问题的吗?

使用特权

评论回复
7
dragon_hn| | 2015-8-17 09:49 | 只看该作者
用while ( !I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_RECEIVED ) )这种死循环等,效率不会比IO口模拟的I2C好,为啥不用IO口模拟的I2C呢?

使用特权

评论回复
8
aaa1125456| | 2015-8-18 16:21 | 只看该作者
你死在哪里了啊 ,看我帖子 有个调试好的 只是我的用的stm8l052r8 反正差不多

使用特权

评论回复
9
aaa1125456| | 2015-8-18 16:22 | 只看该作者
估计清 标志位没清干净

使用特权

评论回复
10
aaa1125456| | 2015-8-18 16:29 | 只看该作者
你发送完地址  准备接收的时候忘了发停止位了吧 I2C_GenerateSTOP(I2C1,ENABLE);

使用特权

评论回复
11
aaa1125456| | 2015-8-18 16:32 | 只看该作者
state_tmp102 tmp102_read(unsigned int *byte)
{
    unsigned int x = 0x0fff;
    unsigned int byte1 = 0,byte2 = 0;
    if(tmp102_tmpConversion() == ERROR_TMP102)
    {
        return ERROR_TMP102;
    }
    x = 0x0fff;
    while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY))                               //总线忙
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
    I2C_GenerateSTART(I2C1,ENABLE);                                             //起始位
    x = 0x0fff;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))                  
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
    I2C_Send7bitAddress(I2C1,0x90,I2C_Direction_Transmitter);                   //从地址
    x = 0x0fff;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
    I2C_SendData(I2C1,0x00);                                                    // 指针地址
    x = 0x0fff;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
    I2C_GenerateSTOP(I2C1,ENABLE);                                              //停止位
    x = 0x0fff;
    while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY))
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
    I2C_GenerateSTART(I2C1,ENABLE);                                             //起始位
    x = 0x0fff;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
    I2C_Send7bitAddress(I2C1,0x91,I2C_Direction_Receiver);                      //从地址
    x = 0x0fff;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
   

    x = 0x0fff;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED))                //接收到数据高位
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
    byte1 = (unsigned char)I2C_ReceiveData(I2C1);
    x = 0x0fff;
    while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED))                //接收到数据低位
    {
        x -- ;
        if(x <= 1)
           return ERROR_TMP102;
    }
    byte2 = (unsigned char)I2C_ReceiveData(I2C1);
    I2C_AcknowledgeConfig(I2C1,DISABLE);
    I2C_GenerateSTOP(I2C1,ENABLE);
    *byte = (byte1 << 8) | byte2;   
    *byte = *byte >>4;                                                          //高12位为温度
    return SUCCESS_TMP102;

使用特权

评论回复
12
643757107| | 2015-8-18 19:23 | 只看该作者
我习惯用SPI,不习惯用IIC,因为经常出差错。

使用特权

评论回复
13
STARM| | 2015-8-19 11:46 | 只看该作者
ww_升 发表于 2015-8-16 23:13
这个是你试过没问题的吗?

没有,网上找的仅供参考。

使用特权

评论回复
14
ww_升|  楼主 | 2015-8-19 16:36 | 只看该作者
dragon_hn 发表于 2015-8-17 09:49
用while ( !I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_RECEIVED ) )这种死循环等,效率不会比IO口模拟的I2C好, ...

有没有模拟I2C程序可以参考下?

使用特权

评论回复
15
ww_升|  楼主 | 2015-8-19 16:38 | 只看该作者
aaa1125456 发表于 2015-8-18 16:22
估计清 标志位没清干净

请问哪里还需要清标志位呢?

使用特权

评论回复
16
ww_升|  楼主 | 2015-8-19 16:40 | 只看该作者
aaa1125456 发表于 2015-8-18 16:32
state_tmp102 tmp102_read(unsigned int *byte)
{
    unsigned int x = 0x0fff;

请问其中的ERROR_TMP102是在哪

使用特权

评论回复
17
lrhsx33| | 2015-8-21 09:40 | 只看该作者
淘宝20多元的逻辑分析仪 看看你的波形有没有问题,这那很方便学习用。

使用特权

评论回复
18
Thor9| | 2015-8-28 21:37 | 只看该作者
标志位清了没啊

使用特权

评论回复
19
zh113214| | 2015-8-29 08:42 | 只看该作者
收藏了,问题一时还看不出,有时间再帮楼主给看看吧。

使用特权

评论回复
20
天灵灵地灵灵| | 2015-8-29 08:52 | 只看该作者
IIC的协议就没有SPI的好用。我是偏爱SPI的。

使用特权

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

本版积分规则

1

主题

10

帖子

0

粉丝