Например TDA7294

Форум РадиоКот • Просмотр темы - STM32F0 I2C EEPROM
Форум РадиоКот
Здесь можно немножко помяукать :)



Текущее время: Ср мар 03, 2021 08:46:57

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: STM32F0 I2C EEPROM
СообщениеДобавлено: Вт апр 28, 2015 18:31:17 
Открыл глаза

Зарегистрирован: Сб июн 14, 2014 09:05:06
Сообщений: 56
Рейтинг сообщения: 0
Всем привет!

Пытаюсь работать с I2C EEPROM при помощи STM32F0. Почти получилось. Чтение работает без проблем (вроде как), а вот запись не работает. Причем так: если пройтись отладчиком - записывается, а если просто запустить - нет.

Код ниже, заранее спасибо!


Определения.
Код:
/* Macros */
#define SET_BIT(REG, BIT)                       ((REG) |= (BIT))
#define CLEAR_BIT(REG, BIT)                     ((REG) &= ~(BIT))
#define READ_BIT(REG, BIT)                      ((REG) & (BIT))

#define SET_REG(REG, VAL)                       ((REG) = (VAL))
#define CLEAR_REG(REG)                          ((REG) = (0))
#define READ_REG(REG)                           ((REG))

#define MODIFY_REG(REG, CLEARMASK, SETMASK)     SET_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
/* Macros */

#define EEPROM_PAGE_SIZE 16


Функции.
Код:
void I2C_EEPROM_Read(void);
uint32_t I2C_EEPROM_Write(void);
uint32_t I2C_EEPROM_WritePage(uint32_t argAddress, uint8_t *argData, uint32_t argDataSize);


Инициализация I2C.
Код:
    /* I2C Initialization */
    SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);
    SET_BIT(RCC->CFGR3, RCC_CFGR3_I2C1SW);
    MODIFY_REG(I2C1->TIMINGR,
        I2C_TIMINGR_PRESC | I2C_TIMINGR_SCLDEL | I2C_TIMINGR_SDADEL | I2C_TIMINGR_SCLH | I2C_TIMINGR_SCLL,
        (1 << 28) | (8 << 20) | (0 << 16) | (94 << 8) | (137 << 0)); /* 0x10805E89 */
    /* I2C Initialization */


Работа с EEPROM.
Код:
    /* EEPROM */
    I2C_EEPROM_Read();

    if(globalData.firstRun != 13)
    {
        SB_Init();
        while(I2C_EEPROM_Write() != 0);
    }
    /* EEPROM */


Чтение из EEPROM.
Код:
void I2C_EEPROM_Read(void)
{
    uint8_t localDataBuf[sizeof(EEPROM_Data)];
    uint32_t localCounter;


    SET_BIT(I2C1->CR1, I2C_CR1_PE);

    SET_REG(I2C1->CR2, (1 << 16) | I2C_CR2_START | 0xA0);
    while((I2C1->ISR & I2C_ISR_TXIS) != I2C_ISR_TXIS);
    SET_REG(I2C1->TXDR, 0x00);
    while((I2C1->ISR & I2C_ISR_TC) != I2C_ISR_TC);

    SET_REG(I2C1->CR2, I2C_CR2_AUTOEND | (sizeof(EEPROM_Data) << 16) | I2C_CR2_START | I2C_CR2_RD_WRN | 0xA0);
    for(localCounter = 0; localCounter < sizeof(EEPROM_Data); localCounter++)
    {
        while((I2C1->ISR & I2C_ISR_RXNE) != I2C_ISR_RXNE);
        localDataBuf[localCounter] = (uint8_t)I2C1->RXDR;
    }
   
    CLEAR_BIT(I2C1->CR1, I2C_CR1_PE);

    memcpy(&globalData, localDataBuf, sizeof(EEPROM_Data));
}


Запись в EEPROM.
Код:
uint32_t I2C_EEPROM_Write(void)
{
    uint8_t localDataBuf[sizeof(EEPROM_Data)];
    uint32_t localCounter;
    uint32_t localLast;
    uint32_t localOffset;
   
   
    memcpy(localDataBuf, &globalData, sizeof(EEPROM_Data));
   
    for(localCounter = 0; localCounter < (sizeof(EEPROM_Data) / EEPROM_PAGE_SIZE); localCounter++)
    {
        localOffset = localCounter * EEPROM_PAGE_SIZE;
        if(I2C_EEPROM_WritePage(localOffset, &localDataBuf[localOffset], EEPROM_PAGE_SIZE) != 0)
        {
            return 1;
        }
    }
       
    localLast = sizeof(EEPROM_Data) % EEPROM_PAGE_SIZE;
    if(localLast > 0)
    {
        localOffset += EEPROM_PAGE_SIZE;
        if(I2C_EEPROM_WritePage(localOffset, &localDataBuf[localOffset], localLast) != 0)
        {
            return 1;
        }
    }
       
    return 0;
}


Запись страницы (максимум 16 байт).
Код:
uint32_t I2C_EEPROM_WritePage(uint32_t argAddress, uint8_t *argData, uint32_t argDataSize)
{
    uint32_t localCounter;


    SET_BIT(I2C1->CR1, I2C_CR1_PE);

    SET_REG(I2C1->CR2, I2C_CR2_RELOAD | (1 << 16) | I2C_CR2_START | 0xA0);
    while((I2C1->ISR & I2C_ISR_TXIS) != I2C_ISR_TXIS);
    SET_REG(I2C1->TXDR, argAddress);
    while((I2C1->ISR & I2C_ISR_TCR) != I2C_ISR_TCR);

    SET_REG(I2C1->CR2, I2C_CR2_AUTOEND | (argDataSize << 16) | 0xA0);
    for(localCounter = 0; localCounter < argDataSize; localCounter++)
    {
        if((I2C1->ISR & I2C_ISR_NACKF) == I2C_ISR_NACKF)
        {
            CLEAR_BIT(I2C1->CR1, I2C_CR1_PE);
            return 1;
        }
        while((I2C1->ISR & I2C_ISR_TXIS) != I2C_ISR_TXIS);
        I2C1->TXDR = (uint32_t)argData[localCounter];
    }
   
    CLEAR_BIT(I2C1->CR1, I2C_CR1_PE);

    return 0;
}


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 I2C EEPROM
СообщениеДобавлено: Пт май 01, 2015 06:11:42 
Прорезались зубы

Зарегистрирован: Вт июл 02, 2013 09:17:49
Сообщений: 219
Рейтинг сообщения: 0
Если под отладчиком работает, а при обычном прогоне нет, то нужно вставить где нибудь паузу методом научного тыка.
Обычно после команды записи байта/страницы нужна пауза.


Вернуться наверх
 
Друзья! Скоро Новый Год! Китайский! Но мы работаем и в праздники тоже!

JLCPCB, всего $2 за прототип печатной платы! Цвет - любой!

Отличное качество, подтвержденное более чем 600,000 пользователей! Более 10,000 заказов в день.

Зарегистрируйтесь и получите два купона по 5$ каждый:https://jlcpcb.com/quote

Не в сети
 Заголовок сообщения: Re: STM32F0 I2C EEPROM
СообщениеДобавлено: Ср май 06, 2015 15:59:22 
Открыл глаза

Зарегистрирован: Сб июн 14, 2014 09:05:06
Сообщений: 56
Рейтинг сообщения: 2
Купил логический анализатор. Нашел проблемы. Исправил. Делюсь рабочим кодом. Если что - задавайте вопросы и вносите поправки! :beer: Без злоебучего SPL! :))

Инициализация

Код:
void I2C_Initialization(void)
{
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
    GPIOB->MODER |= GPIO_MODER_MODER9_1 | GPIO_MODER_MODER8_1;
    GPIOB->OTYPER |= GPIO_OTYPER_OT_9 | GPIO_OTYPER_OT_8;
    GPIOB->AFR[1] |= (1 << (1 * 4)) | (1 << (0 * 4));
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
    RCC->CFGR3 |= RCC_CFGR3_I2C1SW;
    I2C1->TIMINGR = 0x10805E89;
    I2C1->CR1 |= I2C_CR1_PE;
}


Чтение

Код:
void I2C_EEPROMRead(void)
{
    uint8_t localDataBuf[sizeof(EEPROM_Data)];
    uint32_t localCounter;

    I2C1->CR2 = (1 << 16) | I2C_CR2_START | 0xA0;
    while((I2C1->ISR & I2C_ISR_TXIS) != I2C_ISR_TXIS);
    I2C1->TXDR = 0;
    while((I2C1->ISR & I2C_ISR_TC) != I2C_ISR_TC);
    I2C1->CR2 = I2C_CR2_AUTOEND | (sizeof(EEPROM_Data) << 16) | I2C_CR2_START | I2C_CR2_RD_WRN | 0xA0;
    for(localCounter = 0; localCounter < sizeof(EEPROM_Data); localCounter++)
    {
        while((I2C1->ISR & I2C_ISR_RXNE) != I2C_ISR_RXNE);
        localDataBuf[localCounter] = (uint8_t)I2C1->RXDR;
    }
    SYSTICK_DelayMs(5);
    memcpy(&globalData, localDataBuf, sizeof(EEPROM_Data));
}



Запись

Код:
void I2C_EEPROMWrite(void)
{
    uint8_t localDataBuf[sizeof(EEPROM_Data)];
    uint32_t localCounter1;
    uint32_t localCounter2;
    uint32_t localPtr;

    memcpy(localDataBuf, &globalData, sizeof(EEPROM_Data));
    localPtr = 0;
    for(localCounter2 = 0; localCounter2 < (sizeof(EEPROM_Data) / EEPROM_PAGE_SIZE); localCounter2++)
    {
        I2C1->CR2 = I2C_CR2_RELOAD | (1 << 16) | I2C_CR2_START | 0xA0;
        while((I2C1->ISR & I2C_ISR_TXIS) != I2C_ISR_TXIS);
        I2C1->TXDR = localPtr;
        while((I2C1->ISR & I2C_ISR_TCR) != I2C_ISR_TCR);
        I2C1->CR2 = I2C_CR2_AUTOEND | (EEPROM_PAGE_SIZE << 16) | 0xA0;
        for(localCounter1 = 0; localCounter1 < EEPROM_PAGE_SIZE; localCounter1++)
        {
            while((I2C1->ISR & I2C_ISR_TXIS) != I2C_ISR_TXIS);
            I2C1->TXDR = (uint32_t)localDataBuf[localPtr];
            localPtr++;
        }
        SYSTICK_DelayMs(5);
    }
    if(sizeof(EEPROM_Data) % EEPROM_PAGE_SIZE)
    {
        I2C1->CR2 = I2C_CR2_RELOAD | (1 << 16) | I2C_CR2_START | 0xA0;
        while((I2C1->ISR & I2C_ISR_TXIS) != I2C_ISR_TXIS);
        I2C1->TXDR = localPtr;
        while((I2C1->ISR & I2C_ISR_TCR) != I2C_ISR_TCR);
        I2C1->CR2 = I2C_CR2_AUTOEND | ((sizeof(EEPROM_Data) % EEPROM_PAGE_SIZE) << 16) | 0xA0;
        for(localCounter1 = 0; localCounter1 < (sizeof(EEPROM_Data) % EEPROM_PAGE_SIZE); localCounter1++)
        {
            while((I2C1->ISR & I2C_ISR_TXIS) != I2C_ISR_TXIS);
            I2C1->TXDR = (uint32_t)localDataBuf[localPtr];
            localPtr++;
        }
        SYSTICK_DelayMs(5);
    }
}


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: STM32F0 I2C EEPROM
СообщениеДобавлено: Ср май 06, 2015 19:58:53 
Встал на лапы

Карма: 1
Рейтинг сообщений: 38
Зарегистрирован: Ср фев 01, 2012 10:55:53
Сообщений: 145
Рейтинг сообщения: 2
Про EEPROM.
- Страница начинается только с адреса кратного размеру страницы.
- Цикл записи начинается по STOP условию.
- Запись длится около 3 мс, отслеживать состояние готовности после записи лучше постоянно опрашивая EEPROM: START+адрес, пока идет запись не будет ACK'а.


Вернуться наверх
 
Запускаем новый BLE 5.2-чип BlueNRG-LP от STMicroelectronics

Любая разработка начинается с чтения документации и изучения доступных средств разработки. Данный материал целиком посвящен средствам разработки, включая детальные инструкции по запуску вашего первого приложения на BlueNRG-LP. Описана работа с отладкой STEVAL-IDB011V1, набором инструментов и пакетом ПО позволяющим разработчику быстро войти в курс дела.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: STM32F0 I2C EEPROM
СообщениеДобавлено: Сб июн 01, 2019 13:36:55 
Встал на лапы

Карма: 3
Рейтинг сообщений: 8
Зарегистрирован: Вт июн 03, 2008 01:39:47
Сообщений: 125
Рейтинг сообщения: 3
В надежде на то, что библиотеки облегчают жизнь, два дня мучился для написания кода чтения и записи EEProm памяти с помощью библиотеки LL (Low layer libraries).
Не помогло. Пришлось читать документацию и запоминать какой бит какого регистра за что отвечает. Нафига тогда библиотека, если она не облегчает написание кода?
Даже примеров толком нет.

Короче, все таки набил код для записи, а потом чтения памяти. Без прерываний, просто, чтобы кто-то потратил на 2 дня меньше времени на освоение этой дури.

Код:
MX_I2C1_Init();

После базовой инициализации:
Код:
   uint8_t slave_address = 0xA0;   // Адрес ведомого устройства в шине I2C (микросхема памяти EEprom)
   uint16_t write_address = 0x0007; // Адрес в памяти EEprom, по которому будем записывать байт
   uint8_t wr_byte = 0xA4; // Записывать будем такой байт

   /* Запись байта.
    * Номер I2C, по которому передавать данные, адрес ведомого устройства, к которому обращаемся, режим адресации 7 бит,
    * количество передаваемых байт 3, после завершения передачи сгенерировать СТОП-сигнал,
    * перед началом сгенерировать СТАРТ-сигнал с признаком записи байта
    */
   LL_I2C_HandleTransfer(I2C1, slave_address , LL_I2C_ADDRSLAVE_7BIT, 3, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
   while(!(LL_I2C_IsActiveFlag_TXE(I2C1)));
   LL_I2C_TransmitData8(I2C1, (uint8_t)(write_address >> 16));
   while(!(LL_I2C_IsActiveFlag_TXE(I2C1)));
   LL_I2C_TransmitData8(I2C1, (uint8_t)(write_address));
   while(!(LL_I2C_IsActiveFlag_TXE(I2C1)));
   LL_I2C_TransmitData8(I2C1, wr_byte);
   // Передача закончилась, автоматически сгенерирован СТОП-сигнал

   HAL_Delay(3); // Ждем 3 мс, пока микросхема памяти прожует полученное.


   uint16_t read_address = 0x0000; // Адрес в памяти EEprom, с которого начнем считывать байты (начнем с нуля)

   /* Чтения байтов начиная с заданного адреса.
    * Номер I2C, по которому передавать данные, адрес ведомого устройства, к которому обращаемся, режим адресации 7 бит,
    * количество передаваемых байт 3, после завершения передачи НЕ генерировать СТОП-сигнал,
    * перед началом сгенерировать СТАРТ-сигнал с признаком записи байта (ДА, ЗАПИСИ, сначала отправляем адрес в памяти,
    * с которого хотим начать чтение)
    */
   LL_I2C_HandleTransfer(I2C1, slave_address, LL_I2C_ADDRSLAVE_7BIT, 2, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE);
   while(!(LL_I2C_IsActiveFlag_TXE(I2C1)));   // Флаг означает, что Выходной буфер свободен и можно записывать следующее значение
   LL_I2C_TransmitData8(I2C1, (uint8_t)(read_address >> 16));
   while(!(LL_I2C_IsActiveFlag_TXE(I2C1)));
   LL_I2C_TransmitData8(I2C1, (uint8_t)(read_address));

   while(!(LL_I2C_IsActiveFlag_TC(I2C1)));      // Флаг означает, что все (два) байта переданы
   // Передача закончилась, но СТОП-сигнал не генерируется (такой формат общения с памятью)

   /*
    * Генерируем СТАРТ-сингал с признаком чтения байта. Будем принимать 13 байт, после окончания приема сгенерировать
    * СТОП-сигнал.
    */
   LL_I2C_HandleTransfer(I2C1, slave_address, LL_I2C_ADDRSLAVE_7BIT, 13, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);

   uint8_t i;
   uint8_t receive_buf[32] = {0};   // Массив для записи принятых байт

   for(i=0; i<13; i++){
      while(!(LL_I2C_IsActiveFlag_RXNE(I2C1)));   // Флаг означает, что в Приемном буфере появились данные
      receive_buf[i] = LL_I2C_ReceiveData8(I2C1);   // Списываем байт из Приемного буфера
   }
   // Все байты приняты, автоматически генерируется СТОП-сигнал

Как выглядит Запись в анализаторе:
Изображение

Как выглядит чтение 13 байт начиная с адреса 0x0000:
Изображение


Вернуться наверх
 
Революция в силовой электронике. Начало

Что привлекает в SiC по сравнению с кремнием, и какие особенности делают компоненты SiC часто используемыми, несмотря на более высокую стоимость в сравнении с кремниевыми высоковольтными устройствами? – Объясняет специалист ведущего разработчика силовых приборов из карбида кремния, компании Infineon.

Читать статью>>
Не в сети
 Заголовок сообщения: Re: STM32F0 I2C EEPROM
СообщениеДобавлено: Вс июн 09, 2019 20:31:04 
Это не хвост, это антенна
Аватар пользователя

Карма: 5
Рейтинг сообщений: 136
Зарегистрирован: Ср май 26, 2010 18:53:57
Сообщений: 1358
Рейтинг сообщения: 0
Странные вы ребята, на HAL есть встроенные функции специально для чтения записи ЕЕПРОМ - работают без проблем.

_________________
[AMS]


Вернуться наверх
 


Не в сети
 Заголовок сообщения: Re: STM32F0 I2C EEPROM
СообщениеДобавлено: Чт авг 20, 2020 03:44:59 
Родился
Аватар пользователя

Зарегистрирован: Вт июл 14, 2015 06:33:29
Сообщений: 11
Рейтинг сообщения: 0
Странные вы ребята, на HAL есть встроенные функции специально для чтения записи ЕЕПРОМ - работают без проблем.


При использовании HAL например на STM32F030F4 с 16 кб, оный сожрет 2\3 флэша, после чего вы откроете референс мануал, обматерите HAL LL SPL, и сделаете все руками. При этом скажите большое спасибо человеку выложившему свои наработки!


Вернуться наверх
 


Не в сети
 Заголовок сообщения: Re: STM32F0 I2C EEPROM
СообщениеДобавлено: Пт ноя 27, 2020 03:11:23 
Мучитель микросхем
Аватар пользователя

Карма: 10
Рейтинг сообщений: 68
Зарегистрирован: Сб янв 28, 2006 22:47:24
Сообщений: 435
Рейтинг сообщения: 0
Спасибо :)

_________________
Астролябия-сама меряет, было бы что мерять!!!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: STM32F0 I2C EEPROM
СообщениеДобавлено: Пт ноя 27, 2020 21:15:17 
Друг Кота
Аватар пользователя

Карма: 3
Рейтинг сообщений: 122
Зарегистрирован: Пн окт 11, 2010 19:00:08
Сообщений: 3109
Рейтинг сообщения: 0
Ironium писал(а):
например на STM32F030F4 с 16 кб, оный сожрет 2\3 флэша, после чего вы откроете референс мануал, обматерите HAL LL SPL
Видимо нужно научится правильно собирать проект и оптимально выбирать опции сборки потому что вы не правы.
Результат компиляции Blink с HAL
Код:
Program size (bytes):    1356
Data size    (bytes):       4
BSS size     (bytes):       4

Total size   (bytes):    1364   (R/W Memory: 8)

=== Сборка закончена: 0 errors, 0 warnings (0 minutes, 3 seconds) ===
Тоже с SPL.
Код:
Program size (bytes):     676
Data size    (bytes):       0
BSS size     (bytes):       0

Total size   (bytes):     676   (R/W Memory: 36)

=== Сборка закончена: 0 errors, 0 warnings (0 minutes, 2 seconds) ===
Где вы увидели 2\3 флеша?
Причем это не "пустой" код, а Blink в состав которого входит код инициализации в том числе настройка тактирования.


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y