воскресенье, 12 июня 2016 г.

Работа с EEPROM 24C16 на STM32 контроллере

Понадобилось по-быстрому запилить простой "программатор" EEPROM микросхемы, да чтоб читать/писать память её можно было через юзерское приложение в Windows. И что-то я подзатупил изначально с адресацией памяти.

Для работы с EEPROM (и не только) в STM32CubeF4 библиотеке есть функции HAL_I2C_Mem_Read и HAL_I2C_Mem_Write, инициализацию I2C генерит приложение STM32CubeMX, в общем-то халява, осталось использовать функции, передать данные из/в компьютер и девайс готов. Однако меня сбил с толка параметр функций uint16_t MemAddSize, который может быть равен I2C_MEMADD_SIZE_8BIT или I2C_MEMADD_SIZE_16BIT.  В моей микросхеме 2048 байт памяти и логично предположить, что мне нужен вариант I2C_MEMADD_SIZE_16BIT,  т.е. 16 бит на адрес,ибо 8 бит хватит только на адресацию 256 байт.


А вот и нет. Память "побита" на блоки по 256 байт, выбор ID блока происходит через запись соответствующего ID в биты 1,2,3 байта адреса устройства:









Их можно трактовать как ID 256-байтного блока или просто как старшие дополнительные 3 бита адреса памяти (как в таблице и указано). То есть адресация здесь 11 битная.

Собственно, адрес _устройства_ получаем таким образом:  0xA0 | ((memory_address >> 7) & 0xE).  Нулевой бит по идее контроллируется библиотекой и делать операцию битового чтения & 0xF по идее не нужно. Но опыт подсказывает, что доверять библиотеке Cube от ST не стоит )

Вдруг кому сэкономит время )

4 комментария:

  1. while (1)
    {
    HAL_I2C_Mem_Read(&hi2c1, 0x50 << 1, 0x03, 1, &xBuffer[0], 1, 1000);
    HAL_UART_Transmit(&huart1, &xBuffer[0], 1, 0xFFFF);
    HAL_Delay(1000);
    }
    не читает 24lc01. во все ячейки 24lc01 программатором записано значение 55.

    ОтветитьУдалить
  2. заработало. установил частоту 8Мгц вместо 16Мгц. камень stm32f103c8t6

    ОтветитьУдалить
  3. STM32F030F4P6 F_CPU 48 MHz, F_I2C48 MHz, F_USART48 MHz

    #define Device_ADD 0x00A0 // Адрес устройства
    #define Mem_ADD 0x005 // Адрес внутренней памяти
    #define Mem_ADD_Size 2 // Размер адреса внутренней памяти размер адреса 12 бит

    #define BufferSize_1 26

    uint8_t Data_Wrt [26];
    uint8_t Data_Rd [26];

    //================================================================================================================
    for(uint8_t Txt = 0x41; Txt < 0x5B; Txt ++)
    {
    Data_Wrt [Txt] = Txt;
    }
    uint8_t Op = 0x41;
    //================================================================================================================
    //1010000(0) //0x005 // 2 // 26
    if (HAL_I2C_Mem_Write(&hi2c1, Device_ADD, Mem_ADD, Mem_ADD_Size, & Data_Wrt[Op], BufferSize_1, 1000) == HAL_OK)
    {
    HAL_UART_Transmit (&huart1, (uint8_t*)"OK_W\r\n", 5, 0xFFFF);
    HAL_Delay (20);
    HAL_UART_Transmit (&huart1, & Data_Wrt[Op], 26, 0xFFFF);
    HAL_UART_Transmit (&huart1, (uint8_t*) "\r\n", 2, 0xFFFF);
    HAL_Delay (20);
    }
    else
    {
    HAL_UART_Transmit (&huart1, (uint8_t*)"EEROR_W\r\n", 8, 0xFFFF);
    }
    //================================================================================================================
    HAL_Delay (2000);
    //================================================================================================================if (HAL_I2C_Mem_Read (&hi2c1, Device_ADD, Mem_ADD, Mem_ADD_Size, & Data_Rd [0], BufferSize_1, 1000) == HAL_OK)
    {
    HAL_UART_Transmit (&huart1, (uint8_t*)"OK_R\r\n", 5, 0xFFFF);
    HAL_Delay (20);
    HAL_UART_Transmit (&huart1, & Data_Rd [0], 26, 0xFFFF);
    HAL_UART_Transmit (&huart1, (uint8_t*) "\r\n", 2, 0xFFFF);
    HAL_Delay (20);
    }

    else
    {
    HAL_UART_Transmit (&huart1, (uint8_t*)"EEROR_R\r\n", 8, 0xFFFF);
    }

    ОтветитьУдалить