关于429开发板I2C操作AT24C02的疑问

2019-07-20 11:17发布

本帖最后由 mrmzyking 于 2017-10-27 11:56 编辑

我最近产品线切线,需要从原来使用的M4切换到意法的429上面,在测试的时候发现I2C有点问题。代码中如果将Debug设置为1,允许串口打印调试输出,则I2C操作AT24C02就完全正常,如果将Debug设置为0,则会出现错误。
请大家帮我看看,429的I2C需要怎么修改。不甚感激。

详细代码如下所示。

一、头文件部分
#ifndef __i2c_H
#define __i2c_H
#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "main.h"
#define Debug 0
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */
extern I2C_HandleTypeDef hi2c2;

/* USER CODE BEGIN Private defines */

/* USER CODE END Private defines */

extern void _Error_Handler(char *, int);

void MX_I2C2_Init(void);

/* USER CODE BEGIN Prototypes */
extern void I2C_Start( void ) ;
extern void I2C_Stop( void ) ;
extern unsigned char I2C_ReadByte( unsigned char DevAddr , unsigned char MemAddr ) ;
extern unsigned char I2C_WriteByte( unsigned char DevAddr , unsigned char MemAddr , unsigned char Data ) ;
extern unsigned char I2C_WriteByte_Interrupt( unsigned char DevAddr , unsigned char MemAddr , unsigned char Data ) ;
extern unsigned char I2C_ReadByte_Interrupt( unsigned char DevAddr , unsigned char MemAddr ) ;

extern unsigned char I2C_ReadBuff( unsigned char DevAddr , unsigned char MemAddr , unsigned char *Buf , unsigned short Len ) ;
extern unsigned char I2C_WriteBuff(  unsigned char DevAddr , unsigned char MemAddr , unsigned char *Buf , unsigned short Len ) ;

/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif
#endif /*__ i2c_H */



二、I2C操作代码部分
/* Includes ------------------------------------------------------------------*/
#include "i2c.h"

#include "gpio.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

I2C_HandleTypeDef hi2c2;
//struct I2C_Struct AT24C02 ;
/* I2C2 init function */
void MX_I2C2_Init(void)
{

  hi2c2.Instance = I2C2;
  hi2c2.Init.ClockSpeed = 200000;
  hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c2.Init.OwnAddress1 = 0;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }
        __HAL_I2C_ENABLE_IT( &hi2c2 , I2C_IT_EVT | I2C_IT_ERR ) ;
        
        //HAL_NVIC_EnableIRQ(I2C2_EV_IRQn);
}

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(i2cHandle->Instance==I2C2)
  {
  /* USER CODE BEGIN I2C2_MspInit 0 */

  /* USER CODE END I2C2_MspInit 0 */

    /**I2C2 GPIO Configuration   
    PH4     ------> I2C2_SCL
    PH5     ------> I2C2_SDA
    */
    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C2;
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

    /* I2C2 clock enable */
    __HAL_RCC_I2C2_CLK_ENABLE();

    /* I2C2 interrupt Init */
    HAL_NVIC_SetPriority(I2C2_EV_IRQn, 0, 0);
    //HAL_NVIC_EnableIRQ(I2C2_EV_IRQn);
  /* USER CODE BEGIN I2C2_MspInit 1 */
        
  /* USER CODE END I2C2_MspInit 1 */
  }
}

void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{

  if(i2cHandle->Instance==I2C2)
  {
  /* USER CODE BEGIN I2C2_MspDeInit 0 */

  /* USER CODE END I2C2_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_I2C2_CLK_DISABLE();

    /**I2C2 GPIO Configuration   
    PH4     ------> I2C2_SCL
    PH5     ------> I2C2_SDA
    */
    HAL_GPIO_DeInit(GPIOH, GPIO_PIN_4|GPIO_PIN_5);

    /* I2C2 interrupt Deinit */
    HAL_NVIC_DisableIRQ(I2C2_EV_IRQn);
  /* USER CODE BEGIN I2C2_MspDeInit 1 */

  /* USER CODE END I2C2_MspDeInit 1 */
  }
}
/* USER CODE BEGIN 1 */
void I2C_Start( void )
{        
        I2C2->CR1 |= 0x0400 ; //ack enable
        I2C2->CR1 |= 0x0100 ; //generate Start signal         
        while( ( I2C2->SR1 & 0x0001 ) != 0x0001 )  //EV5 detect the Start signal is send success ;
        {
                #if Debug
                printf("I2C Read ( Debug Start ) : I2C2->SR1 = 0x%X ",I2C2->SR1) ;
                #endif        
        }
        
}
void I2C_Stop( void )
{        
        I2C2->CR1 &= ~0x0400 ; //ack enable
        I2C2->CR1 |= 0x0200 ;
        //printf("I2C Read : Send STOP signal ") ;
}
unsigned char I2C_ReadByte( unsigned char DevAddr , unsigned char MemAddr )
{
        unsigned char tmpreg ;
        unsigned char Data ;
        #if Debug
        printf("-----------I2C Read Operation Begin---------------- ") ;
        #endif
        while( (I2C2->SR2 & 0x0002 ) == 1 )  //detect the I2C busy
        {
                #if Debug
                printf("I2C Read : 0.I2C bus is busy! ");
                #endif
        }
        //1.Send Start signal
        I2C_Start(  ) ;
        #if Debug
        printf("I2C Read : 1.Send START signal ");
        #endif
        //2.Send Device Addr ;
        tmpreg = DevAddr & 0xFE ;
        //I2C2->CR1 |= 0x0400 ; //ack enable
        I2C2->DR = tmpreg ;
        while( ( I2C2->SR1 & 0x0082 ) != 0x82 )  //EV6 EV8_1
        {
                #if Debug
                printf("I2C Read ( Debug ) : 2.I2C2->SR1 = 0x%X ",I2C2->SR1) ;
                #endif
        }
        tmpreg = I2C2->SR2 ; //read SR2 reg to clean ADDR bit
        #if Debug
        printf("I2C Read : 2.Send Device Address ");
        #endif
        //3.Send Memery Addr ;
        //I2C2->CR1 |= 0x0400 ; //ack enable
        I2C2->DR = MemAddr ;
        while( ( I2C2->SR1 & 0x0080 ) != 0x80 ) //EV8
        {
                #if Debug
                printf("I2C Read ( Debug ) : 3.I2C2->SR1 = 0x%X ",I2C2->SR1) ;
                #endif
        }               
        #if Debug
        printf("I2C Read : 3.Send Memery Address ");
        #endif
        //4.Send ReStart signal
        I2C_Start(  ) ;
        #if Debug
        printf("I2C Read : 4.Send RESTART signal ") ;
        #endif
        //5.Send Device Addr ;
        tmpreg = DevAddr | 0x01 ;
        I2C2->CR1 &= ~0x0400 ; //ack disable
        I2C2->DR = tmpreg ;        
        while( ( I2C2->SR1 & 0x0002 ) != 0x02 )  //EV6
        {
                #if Debug
                printf("I2C Read ( Debug ) : 4.I2C2->SR1 = 0x%X ",I2C2->SR1) ;
                #endif
        }
        tmpreg = I2C2->SR2 ; //read SR2 reg to clean ADDR bit
        #if Debug
        printf("I2C Read : 5.Send Device Address ") ;
        #endif
        //6.Read Byte
        while( ( I2C2->SR1 & 0x0040 ) != 0x40 )  //EV7_1        
        {
                #if Debug
                printf("I2C Read ( Debug ) : 6.I2C2->SR1 = 0x%X ",I2C2->SR1) ;
                #endif
        }        
        I2C2->CR1 &= ~0x0400 ; //ack enable debug
        Data = I2C2->DR ;        
        #if Debug
        printf("I2C Read : 6.Read Data ") ;
        #endif        
        //7.Send Stop signal
//        while( ( I2C2->SR1 & 0x0044 ) != 0x44 ) //EV7
//        {
//                #if Debug
//                printf("I2C Read ( Debug ) : 7.I2C2->SR1 = 0x%X ",I2C2->SR1) ;
//                #endif
//        }        
        I2C_Stop( ) ;
        //printf("I2C Read : 7.Send STOP signal Read Value = 0x%X ",Data) ;        
        #if Debug
        printf("I2C Read : 7.Send STOP signal Read Value = 0x%X ",Data) ;        
        printf("-----------I2C Read Operation End---------------- ") ;
        #endif
        return Data ;
}
unsigned char I2C_WriteByte( unsigned char DevAddr , unsigned char MemAddr , unsigned char Data )
{
        unsigned char tmpreg ;
        //unsigned char Result ;
        #if Debug
        printf("-----------I2C Write Operation Begin---------------- ") ;
        #endif
        while( (I2C2->SR2 & 0x0002 ) == 1 )  //detect the I2C busy
        {
                #if Debug
                printf("I2C Write : 0.I2C BUS is Busying now. ") ;
                #endif
        }
        //1.send start
        I2C_Start(  ) ;
        #if Debug
        printf("I2C Write : 1.Send START signal ");
        #endif
        //2.send device address
        tmpreg = DevAddr & 0xFE ;
        I2C2->DR = tmpreg ;
        while( ( I2C2->SR1 & 0x0082 ) != 0x82 )  //EV6 EV8_1
        {
                #if Debug
                printf("I2C Write : 2.I2C2->SR1 = 0x%X ",I2C2->SR1) ;
                #endif
        }
        tmpreg = I2C2->SR2 ; //read SR2 REG to clean ADDR bit
        #if Debug
        printf("I2C Write : 2.Send Device Address ");
        #endif
        //3.send memery address
        I2C2->DR = MemAddr ;
        while( ( I2C2->SR1 & 0x0080 ) != 0x80 )//EV8
        {
                #if Debug
                printf("I2C Write ( Debug ) : 3.I2C2->SR1 = 0x%X ",I2C2->SR1) ;
                #endif
        }
        #if Debug
        printf("I2C Write : 3.Send Memery Address ");
        #endif
        //4.send data
//        I2C2->CR1 |= 0x0400 ; //ack enable
        I2C2->DR = Data ;
        #if Debug
        printf("I2C Write : 4.Send Data ");
        #endif
        //5.send stop
        while( ( I2C2->SR1 & 0x0084 ) != 0x84 ) //EV8_2
        {
                #if Debug
                printf("I2C Write ( Debug ) : 5.I2C2->SR1 = 0x%X ",I2C2->SR1) ;
                #endif
        }
        I2C_Stop( ) ;
        //printf("I2C Write : Write Data = 0x%X ",Data) ;        
        #if Debug
        printf("I2C Write : Write Data = 0x%X ",Data) ;        
        printf("I2C Write : 5.Send STOP signal ");
        printf("-----------I2C Write Operation End---------------- ") ;
        #endif
        return 1 ;
}
unsigned char I2C_ReadBuff( unsigned char DevAddr , unsigned char MemAddr , unsigned char *Buf , unsigned short Len )
{
        unsigned short i ;
        if( Len >= ( 256 - MemAddr ) )
        {
                return 0 ;
        }
        for( i = 0 ; i < Len ; i++ )
        {
                *( Buf + i ) = I2C_ReadByte( DevAddr , MemAddr + i ) ;
        }
        return 1 ;
}
unsigned char I2C_WriteBuff(  unsigned char DevAddr , unsigned char MemAddr , unsigned char *Buf , unsigned short Len )
{
        unsigned short i ;
        if( Len > ( 256 - MemAddr ) )
        {
                return 0 ;
        }
        for( i = 0 ; i < Len ; i++ )
        {
                I2C_WriteByte( DevAddr , MemAddr + i , *( Buf + i ) ) ;
        }
        return 1 ;
}
/* USER CODE END 1 */


三、主函数部分
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

int main(void)
{
        unsigned short i ;
        unsigned char ReadI2C[255] ;
        unsigned char WriteI2C[256] ;
        unsigned char DeviceAddress , MemeryAddress , Len ;
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C2_Init();
  MX_USART2_UART_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

                //I2C WRITE
               
                for( i = 0 ; i < 256 ; i++ )
                {
                        WriteI2C =  i % 255;
                        ReadI2C = 0 ;
                }               
                DeviceAddress = 0xA0 ;
                MemeryAddress = 0x00 ;
                Len = 10 ;
                I2C_WriteBuff( DeviceAddress , MemeryAddress , &WriteI2C[0] , Len ) ;
                printf("Write AT24C02 Device Address = %X , Memery Address = %X , Length = %d ",DeviceAddress,MemeryAddress,Len) ;
                printf("Writing Data = ");
                for( i = 0 ; i < Len ; i++ )
                {
                        printf(" 0x%X ",WriteI2C ) ;
                }
                printf(" ") ;
                //I2C READ
                WriteI2C[0] = 0 ;
                ReadI2C[0] = 0 ;
                DeviceAddress = 0xA1 ;
                MemeryAddress = 0x00 ;
                Len = 10 ;
                I2C_ReadBuff( DeviceAddress , MemeryAddress , &ReadI2C[0] , Len ) ;
                printf("Read AT24C02 Device Address = %X , Memery Address = %X , Length = %d ",DeviceAddress,MemeryAddress,Len) ;
                printf("Read Data = ");
                for( i = 0 ; i < Len ; i++ )
                {
                        printf(" 0x%X ",ReadI2C ) ;
                }
                printf(" ") ;
        while (1)
  {
  }
  /* USER CODE END 3 */

}
int fputc(int c, FILE *f)
{
        unsigned char data ;
        SendChar( ( ( unsigned char )( c & 0xFF ) ) ) ;
  return 1 ;
}
int fgetc(FILE *f)
{
    return 1;
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Configure the main internal regulator output voltage
    */
  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 15;
  RCC_OscInitStruct.PLL.PLLN = 216;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Activate the Over-Drive mode
    */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void _Error_Handler(char * file, int line)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  while(1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT

/**
   * @brief Reports the name of the source file and the source line number
   * where the assert_param error has occurred.
   * @param file: pointer to the source file name
   * @param line: assert_param error line source number
   * @retval None
   */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
    ex: printf("Wrong parameters value: file %s on line %d ", file, line) */
  /* USER CODE END 6 */

}

#endif


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
7条回答
mrmzyking
2019-07-21 00:32
主要问题是HAL_I2C_Init函数中对于
hi2c->Instance->CR2 = 10;
hi2c->Instance->TRISE = 3;
hi2c->Instance->CCR = 100;
这三个寄存器的配置是有错误的,特别是对于CR2的值配置超出了范围造成的,而且必须结合AT24C02的操作时序进行配置才行。我现在将I2C的操作时序配置为50KHz,SCL上升沿最大为300ns,在while查询语句中加入了超时防护,这样就可以了。
但是总的来说STM32F429的I2C操作过程中SR1寄存器的状态一直不太稳定,SR1寄存器中的值可能会与数据手册中说的不一样,因为我项目赶进度,这个问题留到以后再来查证了!

一周热门 更多>