Electoday 2025

ไมโครคอนโทรลเลอร์ => ARM Processors => Topic started by: TaoTao on February 25, 2017, 10:09:10 AM

Title: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on February 25, 2017, 10:09:10 AM
วันสองวันนี้
ได้ลอง ต่อ STM32F103 กับ EEPROM เบอร์ 24LC01B ของ Micro Chip ผ่านทาง I2C1
โดย HW ได้ Pull Up ขา I2C1_SDA และ I2C1_SCLK ด้วย R ทั้งสองขา เข้ากับไฟ 5V

Gen Initial Code ด้วย CubeMX

ทดสอบ RCC, TIM1 ก็ทำงานปกติครับ

แต่ พอลอง โคด ให้ MCU write, read EEPROM แบบ polling
ปรากฎว่า นิ่งเลยครับ เอาสโคปจับ ขา SDA,SCLK ไม่มีปฏิกริยาใดๆ  :-[

อันนี้ โคด ครับ


//ประกาศตัวแปร ------------------------------------------------------
uint8_t my_data = 123,
my_data_receive,
my_get[10]={0,0,0,0,0,0,0,0,0,0};

//โคด ----------------------------------------------------------------
my_get[0] = HAL_I2C_GetState(&hi2c1);
my_get[1] = HAL_I2C_IsDeviceReady(&hi2c1, 0xA1, 2, 10);

HAL_I2C_Master_Transmit(&hi2c1, 0xA0, &my_data, 1, 100);
HAL_I2C_Master_Receive(&hi2c1, 0xA1, &my_data_receive, 1, 100);

while(1){ // }


ค่าที่อ่านได้
my_get[0] = 0x20;   // Init I2C already
my_get[1] = 0x02;  // ERR


0xA0, กับ 0xA1
พอดี ใน Data Sheet ของ EEPROM บอกไว้น่ะครับ
ว่ามันคือ DevAddress ของ EEPROM
สั่ง 0xA0 = Write
สั่ง 0xA1 = Read

ใครเคยใช้ HAL Lib กับ STM32 ผ่าน I2C แล้ว Chip มันทำงานบ้างครับ
อืม ทำไมของมันไม่ทำงานหว่า  ขา SCLK ไม่เห็นจะมีรูปคลื่นอะไรเลย
งง  @_@!

ขอบคุณสำหรับคำตอบ ล่วงหน้าครับ
:-[
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: crywolf on February 25, 2017, 12:47:40 PM
ขา Address ของ IC ต่อยังไงครับ Address Hardware กับ Software ตรงกันป่าว
i2c initial ถูกรึป่าวครับ Config ขาสัญญาณตรงรึป่าว

เอาไฟล์มาดูหน่อยครับ
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on February 25, 2017, 03:03:47 PM
Quote from: crywolf on February 25, 2017, 12:47:40 PM
ขา Address ของ IC ต่อยังไงครับ Address Hardware กับ Software ตรงกันป่าว
i2c initial ถูกรึป่าวครับ Config ขาสัญญาณตรงรึป่าว

เอาไฟล์มาดูหน่อยครับ


/**
  ******************************************************************************
  * File Name          : main.c
  * Description        : Main program body
  ******************************************************************************
  *
  * COPYRIGHT(c) 2017 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f1xx_hal.h"

/* USER CODE BEGIN Includes */



/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

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

uint8_t my_data[3] = {0xA, 0xB, 0xC},

my_data_receive[3],

my_get[]={0,0,0,0,0,0};









/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);

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

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

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

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

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

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

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


//
my_get[0] = HAL_I2C_GetState(&hi2c1);

my_get[1] = HAL_I2C_IsDeviceReady(&hi2c1, 0xA1, 2, 10);

HAL_I2C_Mem_Write(&hi2c1,0xA0, 0, 1, &my_data[0], 3, 10);

my_get[2] = HAL_I2C_GetState(&hi2c1);


HAL_I2C_Mem_Read(&hi2c1, 0xA1, 0, 1, &my_data_receive[0], 3, 10);

my_get[3] = HAL_I2C_GetState(&hi2c1);
// */













  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }
  /* USER CODE END 3 */

}

/** System Clock Configuration
*/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Initializes the CPU, AHB and APB busses clocks
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

    /**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_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }

    /**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);
}

/* I2C1 init function */
static void MX_I2C1_Init(void)
{

  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }

}

/** Configure pins as
        * Analog
        * Input
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);

  /*Configure GPIO pin : PC13 */
  GPIO_InitStruct.Pin = GPIO_PIN_13;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}

/* 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(void)
{
  /* USER CODE BEGIN Error_Handler */
  /* User can add his own implementation to report the HAL error return state */
  while(1)
  {
  }
  /* USER CODE END Error_Handler */
}

#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\r\n", file, line) */
  /* USER CODE END 6 */

}

#endif

/**
  * @}
  */

/**
  * @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/



อันนี้ ไฟล์ทั้งหมดครับ
ประกอบด้วย ไฟล์จาก CubeMX และ KEIL :
https://www.dropbox.com/s/ztykmz0pbs63g55/i2c.zip?dl=0

เบอร์ EEPROM : 24LC01B
http://www.es.co.th/Schemetic/PDF/24LC01-2B.PDF

กับ STM32F103C8

>>การเชื่อมต่อขา<<
ขา EEPROM : ขา STM32
----------------------------
5(SDA) : PB7(I2C1_SDA) --> PullUp ด้วย R_4k7
6(SCL) : PB6(I2C1_SCL)  --> PullUp ด้วย R_4k7
7(WP) ลง GND

1,2,3(A0,A1,A2) ผมปล่อยลอยๆ ไว้ครับ
Supply 24LC01B ดึง 5V จาก USB

ส่วน board STM32F103C8
เป็น บอร์ดมินิ ไว้ทดลอง ซื้อที่เว็บ
ใช้ไฟจาก J-LINK 3.3V ครับ
ต่อแบบ SWD

>>การ Initial<<
ผมให้ CubeMX ทำให้ครับ
ตั้งค่า คล๊อก 72MHz HSE
RCC และ I2C1 แบบไม่ Interrupt, ไม่ DMA ครับ

เพิ่งเคยใช้ I2C ครั้งแรกครับ
หลังจาก RUN ขา SDA/SCL หลับปุ๋ย T_T!
งง มากมาย
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: crywolf on February 25, 2017, 06:41:20 PM
น่าจะมีสัญญาณออกมามั้งนะ ลองแบบนี้ดูครับ

  while(HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);
  while(HAL_I2C_IsDeviceReady(&hi2c1, 0xA0, 20, 100) != HAL_OK);

  if(HAL_I2C_Mem_Write(&hi2c1, 0xA0, 0, 1, &my_data[0], 3, 100) != HAL_OK)
    {
      Error_Handler();
    }

  if(HAL_I2C_Mem_Read(&hi2c1, 0xA0, 0, 1, &my_data_receive[0], 3, 100) != HAL_OK)
    {
      Error_Handler();
    }
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on February 25, 2017, 08:37:43 PM
Quote from: crywolf on February 25, 2017, 06:41:20 PM
น่าจะมีสัญญาณออกมามั้งนะ ลองแบบนี้ดูครับ

  while(HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);
  while(HAL_I2C_IsDeviceReady(&hi2c1, 0xA0, 20, 100) != HAL_OK);

  if(HAL_I2C_Mem_Write(&hi2c1, 0xA0, 0, 1, &my_data[0], 3, 100) != HAL_OK)
    {
      Error_Handler();
    }

  if(HAL_I2C_Mem_Read(&hi2c1, 0xA0, 0, 1, &my_data_receive[0], 3, 100) != HAL_OK)
    {
      Error_Handler();
    }


ครับ ลองแล้วครับ
พอเอาโค้ดวาง กลายเป็น J-LINK ไม่เห็น Chip เลย
ซึ่งเป็น ทั้งสองบอร์ดเลย @_@!

ตะกี๊ เลยลอง เสียบผ่าน UART
Set BOOT0=1, BOOT1=0
และ ALL ERASE ปรากฎว่า
กลับมาใช้ได้ละ

กำลัง อยู่ในช่วง งง @_@!
เดี๋ยวลอง I2C แต่จะลองกับ LCD ครับ
คงต้องหา Libraruy LCD แบบ I2C ก่อน
ไม่รู้จะมีเจอปล่าวอ่ะครับ

:-[
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: az on February 26, 2017, 06:02:29 PM
ขอเดาว่าน่าจะติด loop while

ลองใช้ LED On/Off ดูครับว่าปัญหาอยู่ตรงไหน


led on
while (condition) {

}
led off


ถ้า led ยังคงสถานะ on แสดงว่าติด loop
จากนั้น ลองไล่ led off ใน loop อีกครั้งเพื่อตรวจสอบ

ปล. ตรวจสอบ hw ว่าถูกต้อง
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on February 27, 2017, 01:40:27 PM
มันมาติดที่ Loop นี้ครับ  :-[


/**
  * @brief  This function handles I2C Communication Timeout.
  * @param  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @param  Flag: specifies the I2C flag to check.
  * @param  Status: The new Flag status (SET or RESET).
  * @param  Timeout Timeout duration
  * @retval HAL status
  */
static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout)
{
  uint32_t tickstart = 0;

  /* Get tick */
  tickstart = HAL_GetTick();

  /* Wait until flag is set */
  if(Status == RESET)
  {
    while(__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET)
    {
      /* Check for the Timeout */
      if(Timeout != HAL_MAX_DELAY)
      {
        if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
        {
          hi2c->State= HAL_I2C_STATE_READY;

          /* Process Unlocked */
          __HAL_UNLOCK(hi2c);

          return HAL_TIMEOUT;
        }
      }
    }
  }
  else
  {
    while(__HAL_I2C_GET_FLAG(hi2c, Flag) != RESET)                   // <<------<< มันหมุนอยู่ ใน Loop นี้ T_T!
    {
      /* Check for the Timeout */
      if(Timeout != HAL_MAX_DELAY)                                             // ลงมาที่นี่ ได้ True
      {
        if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))   // อันนี้ False แล้ววกกลับไป while ของมัน
        {
          hi2c->State= HAL_I2C_STATE_READY;

          /* Process Unlocked */
          __HAL_UNLOCK(hi2c);

          return HAL_TIMEOUT;
        }
      }
    }
  }
  return HAL_OK;
}



Initial ด้วย CubeMX ไป
แทบไม่มี Bit ไหน โดนSet เลย
@_@!

เดี๋ยว กะว่า จะลองมั่ว
Config ทีละ Bit ของ I2C->CR1, I2C->CR2 เลย
งานนี้ ถนัด
;D

เพราะ ตอนนี้ Clock ของ I2C หลับปุ๋ยเลย  :-[
อาจมีบางบิต ทำให้ Clock ถูกปล่อยออกมา
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: az on February 27, 2017, 03:00:48 PM
Quote from: TaoTao on February 27, 2017, 01:40:27 PM
เดี๋ยว กะว่า จะลองมั่ว
Config ทีละ Bit ของ I2C->CR1, I2C->CR2 เลย
งานนี้ ถนัด
;D

เพราะ ตอนนี้ Clock ของ I2C หลับปุ๋ยเลย  :-[
อาจมีบางบิต ทำให้ Clock ถูกปล่อยออกมา

เปิด datasheet อ้างอิงดีกว่าครับ ชัวร์สุดแล้ว
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on February 27, 2017, 08:55:57 PM
อย่างอื่น ที่ลองๆ มา ของ เบอร์นี้ ก็ทำงานดีนะครับ
ที่ยังไม่ทำงาน ก็ I2C ของเบอร์นี้อ่ะครับ

HW เช็คหลายรอบมากแล้ว ไม่มีอะไรผิดนะครับ
ค่า R Pullup ตาม Datasheet เลย

และ ให้ CubeMX Gererate Initial
ก็ไม่น่าจะผิดพลาดอะไร

ทำตาม Header Files ทุกข้อแล้ว ก็ยังไม่ยอมทำงาน

เช็ค Reference Manual ก็ Initial ครบแล้วนะครับ

งงที่ ทำไมมันวนใน while loop อยู่
และ ขา CLK ไม่ปล่อยออกมาต่อเนื่อง
มัน Pull Down ครั้งแรกครั้งเดียว ที่วิ่งเข้าฟังชั่น
จากนั้น ก็ถูก Pull Up ตาม HW ที่ต่อไว้

งมอยู่ 3 วันเต็มๆ ละ ยังไม่สำเร็จเลย
สโคปนิ่งสนิท
:-[
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: dec on February 27, 2017, 09:55:08 PM
I2C ปกติขา SCL ก็จ่ายออกมาเฉพาะตอนที่มีการส่งข้อมูลนิครับ ไม่ได้ปล่อยออกมาตลอด

I2C จะเริ่มการส่งโดยการ Generate Start ก่อน คือดึง SDA ลง Low ก่อน เว้นสักพัก SCL ก็จะลง Low ตาม

จากกนั้นก็จะเริ่มการส่งข้อมูล ถ้าขณะนั้นไม่มีข้อมูลส่ง SDA และ SCL จะอยู่ในสภาวะ Low ทั้งคู่

เมื่อส่งเสร็จ ก็ต้อง Generate Stop โดยการ ดึง SDA ขึ้น High ก่อน เว้นสักระยะ แล้วก็ดึง SCL ขึ้น High ตาม

(https://s24.postimg.org/c5s1uinh1/xi2c_tutorial_star_stop_png_pagespeed_ic_Nn_QPxx3.png)
ยืมภาพจาก Google การส่ง Start Stop ใน I2C
(https://s3.postimg.org/7eeakriir/Write_2_bytes_all_dummy.png)
ยืมภาพจาก Google การส่งส่งข้อมูล I2C

ปกติ HAL จะครอบการทำงานที่ว่าไว้แล้ว ถ้าอยากจะ test ว่า I2C ใช้ได้รึเปล่าก็ควรใช้ Scope วัดแบบ Single Shot Trigger
หรือไม่ก็ยังไม่ต้องต่อ EEPROM แล้วส่งอะไรก็ได้รัวๆ เพื่อดูสัญญาณครับ

พอดีผมไม่มี f103 เลยเลยช่วยลองไม่ได้ แต่คิดว่าแค่ I2C ตัว CubeMX มันไม่น่าพลาดนะ
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on February 28, 2017, 12:52:39 AM
ทดลอง มา 3-4 วันเต็มๆ ละ  :-[

คือ พอเรียกฟังชั่น มัน ไปติด while loop นานมากๆ ๆ ๆ ๆ ผิดปกติครับ
เรียก แค่ 3 รอบ รอตั้งนานกว่จะหลุด
ถ้าเรียกรัวๆ คงได้หลับแน่นอน  ;D

ผม Intial Code ด้วย CubeMX ครับ

ครับ อันนี้ โค้ดล่าสุด
วางที่ main ก่อน while(1) loop ครับ



uint8_t my_dat[3] = {1,2,3}, my_get[3] = {0,0,0}, my_stat[5];

my_stat[0] = HAL_I2C_IsDeviceReady(&hi2c1, 0xA1, 10, 10);

HAL_I2C_Mem_Write(&hi2c1, (uint16_t)0xA0, (uint16_t)0, (uint16_t)1, &my_dat[0], 3, 1000);

my_stat[1] = HAL_I2C_IsDeviceReady(&hi2c1, 0xA1, 10, 10);

HAL_I2C_Mem_Read(&hi2c1, (uint16_t)0xA1, (uint16_t)0, (uint16_t)1, &my_get[0], 3, 1000);

my_stat[2] = HAL_I2C_IsDeviceReady(&hi2c1, 0xA1, 10, 10);



ได้  my_stat[0] = 0x02
และ my_stat[1] = 0x02
      my_stat[2] = 0x02 ครับ

อันนี้ Header แจ้งไว้

//--------------------------------------------------------
/** @defgroup I2C_Error_Codes I2C Error Codes 
  * @{
  */
//-------------------------------------------------------- 
#define HAL_I2C_ERROR_NONE      ((uint32_t)0x00)    /*!< No error             */
#define HAL_I2C_ERROR_BERR      ((uint32_t)0x01)    /*!< BERR error           */
#define HAL_I2C_ERROR_ARLO      ((uint32_t)0x02)    /*!< ARLO error           */
#define HAL_I2C_ERROR_AF        ((uint32_t)0x04)    /*!< AF error             */
#define HAL_I2C_ERROR_OVR       ((uint32_t)0x08)    /*!< OVR error            */
#define HAL_I2C_ERROR_DMA       ((uint32_t)0x10)    /*!< DMA transfer error   */
#define HAL_I2C_ERROR_TIMEOUT   ((uint32_t)0x20)     /*!< Timeout error        */



ข้างล่างนี้ เอามาจาก RM0008 ครับ :

//-----------------------------------
Arbitration lost (ARLO)
//-----------------------------------
This error occurs when the I2C interface detects an arbitration lost condition. In this case,
• the ARLO bit is set by hardware (and an interrupt is generated if the ITERREN bit is
set)
• the I2C Interface goes automatically back to slave mode (the MSL bit is cleared). When
the I2C loses the arbitration, it is not able to acknowledge its slave address in the same
transfer, but it can acknowledge it after a repeated Start from the winning master.
• lines are released by hardware


Line are released by Hardware..
อันนี้ ไม่น่าใช่ case ผมนะ
เพราะบัดกรีแน่นหนามาก เช็คเป็น สิบรอบแล้ว T_T!

ไฟล์ภาพ OneShot ขา I2C1_SCL ตอนวิ่งเข้า main ครั้งแรกครับ

เดี๋ยว พรุ่งนี้ ว่าจะไปบ้านหม้อ ซื้อ EEPROM ตัวใหม่ รุ่น/ยี่ห้อ อื่นๆ มาเปลี่ยนดู
จนปัญญาละครับ เผื่อว่าจะ Work

กูเกิล มันแปล "Arbitration lost =  อนุญาโตตุลาการหายไป"
ไปไม่ถูกเลย เดี๋ยวต้องไปถาม ผู้พิพากษา ละ  ;D
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on February 28, 2017, 12:55:55 AM
Quote from: dec on February 27, 2017, 09:55:08 PM
I2C ปกติขา SCL ก็จ่ายออกมาเฉพาะตอนที่มีการส่งข้อมูลนิครับ ไม่ได้ปล่อยออกมาตลอด

I2C จะเริ่มการส่งโดยการ Generate Start ก่อน คือดึง SDA ลง Low ก่อน เว้นสักพัก SCL ก็จะลง Low ตาม

จากกนั้นก็จะเริ่มการส่งข้อมูล ถ้าขณะนั้นไม่มีข้อมูลส่ง SDA และ SCL จะอยู่ในสภาวะ Low ทั้งคู่

เมื่อส่งเสร็จ ก็ต้อง Generate Stop โดยการ ดึง SDA ขึ้น High ก่อน เว้นสักระยะ แล้วก็ดึง SCL ขึ้น High ตาม

(https://s24.postimg.org/c5s1uinh1/xi2c_tutorial_star_stop_png_pagespeed_ic_Nn_QPxx3.png)
ยืมภาพจาก Google การส่ง Start Stop ใน I2C
(https://s3.postimg.org/7eeakriir/Write_2_bytes_all_dummy.png)
ยืมภาพจาก Google การส่งส่งข้อมูล I2C

ปกติ HAL จะครอบการทำงานที่ว่าไว้แล้ว ถ้าอยากจะ test ว่า I2C ใช้ได้รึเปล่าก็ควรใช้ Scope วัดแบบ Single Shot Trigger
หรือไม่ก็ยังไม่ต้องต่อ EEPROM แล้วส่งอะไรก็ได้รัวๆ เพื่อดูสัญญาณครับ

พอดีผมไม่มี f103 เลยเลยช่วยลองไม่ได้ แต่คิดว่าแค่ I2C ตัว CubeMX มันไม่น่าพลาดนะ

อยากรับไปเลี้ยงดูสักบอร์ดไหมครับ ผมมี 2 บอร์ด
เดี๋ยวส่งให้ไปเลย 1 บอร์ด พูดจริงนะครับ
;D

เป็นบอร์ด minium ครับ
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: az on February 28, 2017, 09:38:48 AM
ชิป EEPROM มีปัญหารึป่าว

ได้ลอง I2C กับ Device อื่นๆ แล้วหรือไม่
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: dec on February 28, 2017, 12:37:45 PM
Quote from: TaoTao on February 28, 2017, 12:55:55 AM

อยากรับไปเลี้ยงดูสักบอร์ดไหมครับ ผมมี 2 บอร์ด
เดี๋ยวส่งให้ไปเลย 1 บอร์ด พูดจริงนะครับ
;D

เป็นบอร์ด minium ครับ

ไม่เป็นไรครับ ผมไปยืมบอร์ด stm3210c-eval มาลองดูแล้ว เป็น f107vct6 คล้ายๆ กับ 103 ต่างกันตรงมี ethernet แล้วก็ไม่มี sdio ซึ่งบนบอร์ดมี EEPROM เบอร์ m24c64 อยู่ อันนี้เป็น Code ที่ผมลองแล้วใช้ได้

ไฟล์ m24c64.c
#include "m24c64.h"

static I2C_HandleTypeDef I2C1_Handle;
static uint16_t M24C64_Addr;

/**
  * @brief  I2C Bus initialization
  * @retval None
  */
void M24C64_I2C_Init(uint16_t DevAddr)
{
  GPIO_InitTypeDef  gpioinitstruct = {0}; 

  M24C64_Addr = DevAddr;
 
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  gpioinitstruct.Pin       = GPIO_PIN_6 | GPIO_PIN_7;
  gpioinitstruct.Mode      = GPIO_MODE_AF_OD;
  gpioinitstruct.Pull      = GPIO_NOPULL;
  gpioinitstruct.Speed     = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &gpioinitstruct);
 
  __HAL_RCC_I2C1_CLK_ENABLE();

  /* Add delay related to RCC workaround */
  while (READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN) != RCC_APB1ENR_I2C1EN)
  {
  }
 
  /* Force the I2C Periheral Clock Reset */ 
  __HAL_RCC_I2C1_FORCE_RESET();
     
  /* Release the I2C Periheral Clock Reset */ 
  __HAL_RCC_I2C1_RELEASE_RESET();
 
  I2C1_Handle.Instance              = I2C1;
  I2C1_Handle.Init.ClockSpeed       = 400000;
  I2C1_Handle.Init.DutyCycle        = I2C_DUTYCYCLE_2;
  I2C1_Handle.Init.OwnAddress1      = 0;
  I2C1_Handle.Init.AddressingMode   = I2C_ADDRESSINGMODE_7BIT;
  I2C1_Handle.Init.DualAddressMode  = I2C_DUALADDRESS_DISABLE;
  I2C1_Handle.Init.OwnAddress2      = 0;
  I2C1_Handle.Init.GeneralCallMode  = I2C_GENERALCALL_DISABLE;
  I2C1_Handle.Init.NoStretchMode    = I2C_NOSTRETCH_DISABLE; 

  /* Init the I2C */
  HAL_I2C_Init(&I2C1_Handle);
}

/**
  * @brief  Write a value in a register of the device through BUS.
  * @param  MemAddr: The target memory address
  * @param  pBuffer: The target memory value to be written
  * @param  Length: buffer size to be written
  * @retval None
  */
HAL_StatusTypeDef M24C64_WriteBuffer(uint8_t MemAddr, uint8_t *pBuffer, uint16_t Length)
{
  return HAL_I2C_Mem_Write(&I2C1_Handle, M24C64_Addr, (uint16_t)MemAddr, 16, pBuffer, Length, 3000);
}

/**
  * @brief  Reads multiple data on the BUS.
  * @param  MemAddr: The target memory address
  * @param  pBuffer: pointer to read data buffer
  * @param  Length: length of the data
  * @retval 0 if no problems to read multiple data
  */
HAL_StatusTypeDef M24C64_ReadBuffer(uint8_t MemAddr, uint8_t *pBuffer, uint16_t Length)
{
  HAL_StatusTypeDef status = HAL_OK;

  status = HAL_I2C_Mem_Read(&I2C1_Handle, M24C64_Addr, (uint16_t)MemAddr, 16, pBuffer, Length, 3000);
 
  return status;
}

/**
* @brief  Checks if target device is ready for communication.
* @note   This function is used with Memory devices
* @param  Trials: Number of trials
* @retval HAL status
*/
HAL_StatusTypeDef M24C64_IsDeviceReady(uint32_t Trials)
{
  return (HAL_I2C_IsDeviceReady(&I2C1_Handle, M24C64_Addr, Trials, 3000));
}


ไฟล์ m24c64.h
#ifndef __M24C64_H
#define __M24C64_H

#include "stm32f1xx.h"

#ifdef __cplusplus
extern "C" {
#endif

void M24C64_I2C_Init(uint16_t DevAddr);
HAL_StatusTypeDef M24C64_WriteBuffer(uint8_t MemAddr, uint8_t *pBuffer, uint16_t Length);
HAL_StatusTypeDef M24C64_ReadBuffer(uint8_t MemAddr, uint8_t *pBuffer, uint16_t Length);
HAL_StatusTypeDef M24C64_IsDeviceReady(uint32_t Trials);

#ifdef __cplusplus
}
#endif
 
#endif /* __M24C64_H */


แล้วก็ code ใน main
int main(void)
{
  HAL_Init();

  /* Configure the system clock to 72 MHz */
  SystemClock_Config();


  /* Add your application code here */
  M24C64_I2C_Init(0xA0);
 
  if(M24C64_IsDeviceReady(300) == HAL_OK)
  {
    printf("OK\r\n");
   
    if(M24C64_WriteBuffer(0x0000, SendBuffer, sizeof(SendBuffer)) == HAL_OK)
    {
      M24C64_ReadBuffer(0x0000, RecvBuffer, sizeof(SendBuffer));
    }
    else
    {
      printf("WRITE ERROR\r\n");
    }
  }
  else
  {
    printf("ERROR\r\n");
  }

  /* Infinite loop */
  while (1)
  {
  }
}


ผมไม่ได้ใช้ CubeMX Generate นะ ส่วนตัวไม่ชอบการ Gen project จาก CubeMX
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on February 28, 2017, 01:43:05 PM
Quote from: dec on February 28, 2017, 12:37:45 PM


ผมไม่ได้ใช้ CubeMX Generate นะ ส่วนตัวไม่ชอบการ Gen project จาก CubeMX

ครับ เดี๋ยวผมจะสร้างเอกสารใหม่ ผ่าน CubeMX
(ใช้ Cube จนเป็นง่อย ลืมวิธีอื่นๆ หมดละ  ;D)

เพื่อให้มัน Include Souce ที่จำเป็น
แต่ไม่ให้มัน Initial pin I2C
เดี๋ยวขอ ไปซื้อ Chip บ้านหม้อก่อน
เผื่อตัวที่ทดลอง เจ๊ง

ครับ ขอบคุณมากมาย ครับ
ขอบคุณทุกๆ คน
:D
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on March 02, 2017, 10:43:04 AM
ล่าสุด กราฟ ออกสโคปละ
ส่ง DevAddr.. 0xA0 ตามด้วย
    MemAddr  0x00 ตามด้วย
    Data         0x55 ตามด้วย  0xA0

my_dat = 0x55;
my_get = 0x00;

//I2C_HandleTypeDef *hi2c, DevAddress, MemAddress,  MemAddSize, *pData, Size, Timeout
HAL_I2C_Mem_Write( &hi2c1, (uint16_t)0x00A0, (uint16_t)0, (uint16_t)1, &my_dat, 1, 3000);
HAL_I2C_Mem_Read(  &hi2c1, (uint16_t)0x00A1, (uint16_t)0, (uint16_t)1, &my_get, 1, 3000);


สั่ง 0xA1 นี่หว่า
งง  @_@!
:-[

Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: dec on March 02, 2017, 01:51:56 PM
ดูจากกราฟแล้ว ตัว EEPROM มันไม่ ack ตอบนะครับ กรณีปกติตอนส่ง address master จะส่ง bit ที่ 9 เป็น high ตามไปด้วย หลังจากส่ง address 7bit + RW 1 bit ไปแล้ว ถ้า slave ได้รับมันจะพยายามดึง bit ที่ 9 เป็น low ไว้ เป็นการ ack ตอบ master ครับ พอ slave ไม่ ack มันก็เลยจบการสื่อสารเลย
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on March 02, 2017, 04:40:19 PM
Quote from: dec on March 02, 2017, 01:51:56 PM
ดูจากกราฟแล้ว ตัว EEPROM มันไม่ ack ตอบนะครับ กรณีปกติตอนส่ง address master จะส่ง bit ที่ 9 เป็น high ตามไปด้วย หลังจากส่ง address 7bit + RW 1 bit ไปแล้ว ถ้า slave ได้รับมันจะพยายามดึง bit ที่ 9 เป็น low ไว้ เป็นการ ack ตอบ master ครับ พอ slave ไม่ ack มันก็เลยจบการสื่อสารเลย

อ่อ อย่างนี้นี่เอง  :-[

อันนี้ วิเคราะด้วย เครื่องมือใหม่ Saleae
(แต่เก่าเก็บ ซื้อไว้เป็นชาติ  ;D)

ข้อมูลสุดท้าย ผมสั่ง Read = 0xA1
Complier ตีความเป็น 0xA0
(เครื่องมือวัดมันบอก)

คงกลายเป็น คำสั่ง Write ไป รึเปล่า

ทีนี้ จะทำไงให้มันสั่ง 0xA1 ได้อ่ะครับ
เพิ่อจะสั่ง Read ข้อมูล จาก EEPROM

แต่ Saleae ตัวนี้ อ่านง่ายกว่า สโคปเยอะ
ไม่ต้องนั่งนับ เต้า
ตอนนอน เห็นเต้าเต็มไปหมด
;D
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on March 02, 2017, 05:02:03 PM
โค้ด บรรทัด 2 คำสั่ง Read 0xA1 from EEPROM
ยังผิดอยู่แน่เลย :
HAL_I2C_Mem_Read(     &hi2c1,   (uint16_t)0x00A1, (uint16_t)0,    (uint16_t)1,    &my_get,    1,       3000);

มันเลยกลายเป็น สั่ง Write ด้วย 0xA0 แล้ว NAK เลย
จะแก้ให้ Bit 0 กลายเป็น 1 ได้ยังไงอ่ะครับ
:-[
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: dec on March 02, 2017, 06:55:53 PM
Quote from: TaoTao on March 02, 2017, 05:02:03 PM
โค้ด บรรทัด 2 คำสั่ง Read 0xA1 from EEPROM
ยังผิดอยู่แน่เลย :
HAL_I2C_Mem_Read(     &hi2c1,   (uint16_t)0x00A1, (uint16_t)0,    (uint16_t)1,    &my_get,    1,       3000);

มันเลยกลายเป็น สั่ง Write ด้วย 0xA0 แล้ว NAK เลย
จะแก้ให้ Bit 0 กลายเป็น 1 ได้ยังไงอ่ะครับ
:-[

อันนี้ปกติครับ sequence ในการอ่านข้อมูลจาก EEPROM ขั้นแรก Master จะขอ Write ข้อมูลก่อน เพื่อทำการส่ง Memory Address ที่จะต้องการจะอ่านข้อมูลครับ เสร็จแล้ว Master จึงจะส่งขอ Read ครับ
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on March 04, 2017, 03:59:18 AM
ปัญหานี้ เคลียร์แล้วครับ

I2C Lib โดยเฉพาะ Memory ของ HAL ที่เจ้า CubeMX มัน Gen ให้
บางฟังชั่น ผมใช้แล้วไม่เวิร์คครับ
เข้าเว็บ st มา ฝรั่ง ก็เจอเป็นเช่นกัน

ที่ใช้ได้ คือ TRANSMIT
ส่วน Read ทดลองแล้ว ใช้ไม่ได้ครับ
เอา สโคปจับ กราฟมั่วไปหมด
(สั่ง Read 0xA1 แปลงเป็น 0xA0 เฉย
ซึ่ง อัลกอลิทึม มันไม่ตรงกับฝ่าย EEPROM ที่ต้องการ
เลยกลายเป็น NACK อยู่บ่อยๆ)

ต้องแก้โดย เอา I2C Timing-Read-Write ของ RM0008 และ Datasheet ของ STM มาวิเคราะห์
และปรับให้เข้ากับ DataSheet EEPROM โดยเฉพาะครับ จึงจะอ่านค่าได้

ผมเลยเขียน Functions ง่ายๆ มาใช้งานเอง
เฉพาะส่วน EEPROM I2C ทั้ง Write/Read ครับ
แล้วเอา Saleae จับ สามารถ บันทึก-อ่าน EEPROM ได้ตามที่ต้องการแว้ว
เดี๋ยว เล่นโหมด DMA ต่อ  ;D

ส่วน R pullup ที่ผมทดลอง เสถียรสุด คือ 2k - 5k ครับ

ขอบคุณทุกๆ คนมาก ครับ
:D
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: vbaserv on March 05, 2017, 07:27:46 AM
ขอปรบมือให้กับความมุ่งมั่นพยายามในการแก้ปัญหาครับ  เข้าถึง root cause เลย
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on March 07, 2017, 03:43:04 PM
Quote from: vbaserv on March 05, 2017, 07:27:46 AM
ขอปรบมือให้กับความมุ่งมั่นพยายามในการแก้ปัญหาครับ  เข้าถึง root cause เลย
ขอบคุณนะครับ

พูดถึง Hal Lib : EEPROM I2C  เล่นผมเป็น หมีแพนด้า
หลายวันเลย  ;D

แต่ ผลพลอยได้ คือ เลยได้เปรียบเทียบ EEPROM
หลายเบอร์ หลายยี่ห้อ ในหลายๆ มิติ

ได้ข้อสรุปเลย (สำหรับผมนะครับ)
เท่าที่หาซื้อได้ในไทย Atmel เจ๋งเป้งฝุดๆ
performance ดีกว่าเจ้าอื่น มากกว่าเท่าตัวเลย
และใช้ไฟต่ำ + high speed ด้วย
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: vbaserv on March 08, 2017, 08:58:03 AM
ไม่รู้ว่าได้ลองกับ eeprom ของ  nxp (philips เดิม  ต้นตำรับของ I2C bus)  ไหมครับ  เป็นอย่างไรบ้าง

ที่คุณกล่าวถึง performance  อยากทราบหน่อยครับ ว่าคุณพิจารณาในแง่ใดบ้าง  (ถ้าเป็นข้อปกปิดของขอบเขตงานคุณ ก็ไม่เป็นไรครับ)
Title: Re: STM32F103C8 กับ EEPROM_24LC01B_MCP ทาง I2C Gen_Code ด้วย CubeMX นิ่งเลย T_T!
Post by: TaoTao on March 08, 2017, 07:22:52 PM
Quote from: vbaserv on March 08, 2017, 08:58:03 AM
ไม่รู้ว่าได้ลองกับ eeprom ของ  nxp (philips เดิม  ต้นตำรับของ I2C bus)  ไหมครับ  เป็นอย่างไรบ้าง

ที่คุณกล่าวถึง performance  อยากทราบหน่อยครับ ว่าคุณพิจารณาในแง่ใดบ้าง  (ถ้าเป็นข้อปกปิดของขอบเขตงานคุณ ก็ไม่เป็นไรครับ)
พอดี es ตอนผมซื้อ มีสองยี่ห้อครับ
เท่าที่เครื่องมือวัดได้ ก็ ความถูกต้องของข้อมูล
และ ระยะเวลาที่มัน Busy

ในราคาเท่ากัน(เฉพาะตัวถูกๆ นะครับ
ตัวแพงๆ ยังไม่ได้เทส) Atmel สามารถ R/W
ต่อ page ได้ไวกว่ามากๆ ครับ
2 ms พร้อมรับคำสั่งใหม่ ที่ไฟ 3 - 5 V
ไฟไม่เสถียร ก็ไม่งอแง มัน ACK ทุก ไบท์เลย
ข้อมูลถูกต้องทุก Cycle เลยทีเดียว ทั้ง R/W

อย่าง ไฟล์แนบ คือ ของ Atmel ครับ

กับ MC 5 ms ครับ ที่ไฟ 5 V เท่านั้น
ไฟต่ำกว่านี้ หรือ ไฟไม่เสถียร
มัน NACK ทันที (จับด้วย Saleae)

เทียบกันที่ I2C BUS 400 kHz ครับ

พอดีช่วงเทส bus i2c mcu ผม
วิ่งได้ แค่ที่ 400 kHz ครับ
เดี๋ยวไว้โอกาศหน้า หาเบอร์ ที่วิ่งได้สัก 1 MHz
และ อาจจะลอง NXP ซะหน่อยครับ

ขอบคุณที่แนะนำนะครับ