Пытаюсь работать с 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 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 */
I2C_EEPROM_Read();
if(globalData.firstRun != 13)
{
SB_Init();
while(I2C_EEPROM_Write() != 0);
}
/* 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));
}
Код: Выделить всё
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;
}
Код: Выделить всё
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;
}




