本帖最后由 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
HAL_StatusTypeDef HAL_I2C_Init_MY(I2C_HandleTypeDef *hi2c)
{
uint32_t freqrange = 0U;
uint32_t pclk1 = 0U;
/* Check the I2C handle allocation */
if(hi2c == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
assert_param(IS_I2C_CLOCK_SPEED(hi2c->Init.ClockSpeed));
assert_param(IS_I2C_DUTY_CYCLE(hi2c->Init.DutyCycle));
assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1));
assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode));
assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode));
assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2));
assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode));
assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode));
if(hi2c->State == HAL_I2C_STATE_RESET)
{
/* Allocate lock resource and initialize it */
hi2c->Lock = HAL_UNLOCKED;
/* Init the low level hardware : GPIO, CLOCK, NVIC */
HAL_I2C_MspInit(hi2c);
}
hi2c->State = HAL_I2C_STATE_BUSY;
/* Disable the selected I2C peripheral */
__HAL_I2C_DISABLE(hi2c);
/* Get PCLK1 frequency */
pclk1 = HAL_RCC_GetPCLK1Freq();
/* Calculate frequency range */
freqrange = I2C_FREQRANGE(pclk1);
/*---------------------------- I2Cx CR2 Configuration ----------------------*/
/* Configure I2Cx: Frequency range */
hi2c->Instance->CR2 = 10;
/*---------------------------- I2Cx TRISE Configuration --------------------*/
/* Configure I2Cx: Rise Time */
hi2c->Instance->TRISE = 3;
/*---------------------------- I2Cx CCR Configuration ----------------------*/
/* Configure I2Cx: Speed */
hi2c->Instance->CCR = 100;
/*---------------------------- I2Cx CR1 Configuration ----------------------*/
/* Configure I2Cx: Generalcall and NoStretch mode */
hi2c->Instance->CR1 = (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode);
/*---------------------------- I2Cx OAR1 Configuration ---------------------*/
/* Configure I2Cx: Own Address1 and addressing mode */
hi2c->Instance->OAR1 = (hi2c->Init.AddressingMode | hi2c->Init.OwnAddress1);
/*---------------------------- I2Cx OAR2 Configuration ---------------------*/
/* Configure I2Cx: Dual mode and Own Address2 */
hi2c->Instance->OAR2 = (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2);
/* Enable the selected I2C peripheral */
__HAL_I2C_ENABLE(hi2c);
hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
hi2c->State = HAL_I2C_STATE_READY;
hi2c->PreviousState = HAL_I2C_MODE_NONE;
hi2c->Mode = HAL_I2C_MODE_NONE;
return HAL_OK;
}
一周热门 更多>