你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32f0 iic从机

[复制链接]
乐乐棠 提问时间:2020-6-24 09:54 /
       最近在捣鼓stm32f0的IIC从机,之前一直使用的是IIC主机,IIC主机主要用的是IO口模拟的,实现起来没什么问题。但是转到IIC从机后,发现通信读取数据过程中偶尔会出现串码的现象,大概一小时会出现两三次。以下是IIC从机的部分代码:

/*-- defined -----------------------------------------------------------------*/
#define     SLAVE_ADDR               0x16


#define     POLYNOME                 0x07

#define     I2C_REC_BYTES            64
#define     I2C_TX_BYTES              64



/*-- private variables -------------------------------------------------------*/
static   I2C_HandleTypeDef  hi2c1;

static   u8_t     slaveTxBuff[I2C_TX_BYTES] = {0};
static   u8_t     slaveRxBuff[I2C_REC_BYTES] = {0};


static  u8_t     rsoc;
static  u16_t    battVolt;
static  s16_t    current;
static  u16_t    Temper;
static  u16_t    cellVolt[3];

/*-- functions ---------------------------------------------------------------*/
static  void  tx_match(u8_t cmd);


/**@brief  
  * @brief       IIC初始化
  * @param     
  * @return  
  */

void   hal_iic_init(void)
{
  u32_t  tmpisr = 0;
       
  /* Peripheral clock enable */
  __HAL_RCC_I2C1_CLK_ENABLE();
       
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x2000090E;
  hi2c1.Init.OwnAddress1 = SLAVE_ADDR;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_ENABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {

  }
       
  /* Configure Analogue filter */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {

  }
       
  /* Configure Digital filter */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {

  }
       
  /* I2C1 interrupt Init */
  HAL_NVIC_SetPriority(I2C1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(I2C1_IRQn);
       
  /**
      I2C_IT_ADDRI:     Address match interrupt.
      I2C_IT_STOPI:     STOP detection interrupt.
      I2C_IT_NACKI:     NACK received interrupt.
      I2C_IT_ERRI:      Errors interrupt.
      I2C_IT_TCI:       TC interrupt.
     I2C_XFER_RX_IT:   REC interrupt.
  */
  tmpisr |= I2C_IT_ADDRI | I2C_IT_STOPI | I2C_IT_NACKI | I2C_IT_ERRI | I2C_IT_RXI | I2C_IT_TXI;
  __HAL_I2C_ENABLE_IT(&hi2c1, tmpisr);
}


/**@brief  
  * @brief   
  * @param     
  * @return  
  */
void  i2c_err_irq_handler(I2C_HandleTypeDef *hi2c, u32_t isrFlag)     
{
  if((isrFlag & I2C_FLAG_ARLO) == I2C_FLAG_ARLO)
  { /* ARLO Err */
    __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO);
  }

  if((isrFlag & I2C_FLAG_BERR) == I2C_FLAG_BERR)
  { /* BERR Err */
    __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR);
  }

  if((isrFlag & I2C_FLAG_OVR) == I2C_FLAG_OVR)
  { /* OVR Err */
    __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR);
  }       
}



/**@brief
  * @brief   
  * @param     
  * @return  
  */
void  i2c_evt_irq_handler(I2C_HandleTypeDef *hi2c, u32_t isrFlag)     
{
  static   u8_t   txCounter = 0;
  static   u8_t   rxCounter = 0;
  u32_t  transferDir = 0;
       
  if(hi2c->Instance == hi2c1.Instance)
  {
    if((isrFlag & I2C_FLAG_ADDR) == I2C_FLAG_ADDR)
    {
       /* EV1 */     
       transferDir = isrFlag & I2C_ISR_DIR;   
       /* 判断方向 */
       if(transferDir)
       {   
          /* 方向为从机发送 */
          I2C1->ISR |= I2C_ISR_TXE;
          I2C1->TXDR = slaveTxBuff[0];         
          txCounter = 1;   
        }  
       else
       {
          /* 方向为从机接收 */
          rxCounter = 0;
       }

       __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ADDR);      
    }   
    else if((isrFlag & I2C_FLAG_TXIS) == I2C_FLAG_TXIS)
    {
       /* EV3 */         
       I2C1->TXDR = slaveTxBuff[txCounter++];
    }   
    else if((isrFlag & I2C_FLAG_RXNE) == I2C_FLAG_RXNE)
    {
       /* EV2 */        
       if(rxCounter < I2C_REC_BYTES)  
       {
          slaveRxBuff[rxCounter] = hi2c->Instance->RXDR;

          /* 进行命令匹配 */
          if(rxCounter == 0)
          {
              tx_match(slaveRxBuff[0]);
          }

           rxCounter++;
       }
    }   
    else if((isrFlag & I2C_FLAG_STOPF) == I2C_FLAG_STOPF)
    {
       /* EV4 */
       hi2c->Instance->ISR |= I2C_ISR_TXE;
       hi2c->Instance->ISR |= I2C_ISR_TXIS;
       txCounter = 0;
       rxCounter = 0;
       __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF);      
     }   
    else if((isrFlag & I2C_FLAG_AF) == I2C_FLAG_AF)
    {
       /* EV3_2 */
       __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF);     
     }
  }
}



/**
  * @brief   This function handles I2C1 global interrupt.
  * @param   
  * @param   
  * @return  
  */
void I2C1_IRQHandler(void)
{
  u32_t isrFlag = 0;

  isrFlag = hi2c1.Instance->ISR;

  if (isrFlag & (I2C_FLAG_BERR | I2C_FLAG_ARLO | I2C_FLAG_OVR))
  {
     /* 异常处理 */
     //HAL_I2C_ER_IRQHandler(&hi2c1);
     i2c_err_irq_handler(&hi2c1, isrFlag);
  }
  else
  {
     /* 事件处理 */
     //HAL_I2C_EV_IRQHandler(&hi2c1);
     i2c_evt_irq_handler(&hi2c1, isrFlag);
  }
}


/** @function  
  * @brief       IIC从机匹配发送数据,发现如果使用switch-case出错率会更高,不知为何。
  * @param   
  * @return  
  */
static  void  tx_match(u8_t cmd)
{
  u8_t  counter = 0;

  if(cmd == 0x08)
  {
    slaveTxBuff[counter++] = Temper&0x00ff;
    slaveTxBuff[counter++] = (Temper&0xff00)>>8;
    Temper++;   
  }
  else if(cmd == 0x09)
  {
    slaveTxBuff[counter++] = battVolt&0x00ff;
    slaveTxBuff[counter++] = (battVolt&0xff00)>>8;
    battVolt++;   
  }
  else if(cmd == 0x0A)
  {
    slaveTxBuff[counter++] = current&0x00ff;
    slaveTxBuff[counter++] = (current&0xff00)>>8;   
  }   
  else if(cmd == 0x0D)
  {
    slaveTxBuff[counter++] = rsoc&0x00ff;
    slaveTxBuff[counter++] = (rsoc&0xff00)>>8;   
  }
  else if(cmd == 0x3F)
  {
    slaveTxBuff[counter++] = cellVolt[0]&0x00ff;
    slaveTxBuff[counter++] = (cellVolt[0]&0xff00)>>8;     
  }   
  else if(cmd == 0x3E)
  {
    slaveTxBuff[counter++] = cellVolt[1]&0x00ff;
    slaveTxBuff[counter++] = (cellVolt[1]&0xff00)>>8;     
  }  
  else if(cmd == 0x3D)
  {
    slaveTxBuff[counter++] = cellVolt[2]&0x00ff;
    slaveTxBuff[counter++] = (cellVolt[2]&0xff00)>>8;   
  }  

  slaveTxBuff[counter] = CRC8(slaveTxBuff, counter, POLYNOME);  
}

    可能是因为本人对IIC从机原理理解得不够深,折腾了两天还是没什么进展,望由此经验的朋友多多指教,谢谢!



收藏 评论1 发布时间:2020-6-24 09:54

举报

1个回答
乐乐棠 回答时间:2020-8-15 08:40:57
我把IIC从机中断优先级调整为最高级,经过几个小时的测试,数据一次都没有出错过,暂时认定为是其他中断影响了IIC从机中断的发送。

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版