STM32F103 I2C 24Cxx

Software e Hardware para uC STM

Moderadores: andre_luis, 51

STM32F103 I2C 24Cxx

Mensagempor vtrx » 09 Mai 2018 09:42

Deixei por ultimo fazer uma rotina para ler/escrever numa 24C02/32,mas encontrei várias e não entendi muito bem como endereçar etc.
Meu setup está assim:
Código: Selecionar todos
void I2C_Setup(void)
{

    GPIO_InitTypeDef  GPIO_InitStructure;
    I2C_InitTypeDef  I2C_InitStructure;

    /*enable I2C*/
    I2C_Cmd(I2C1,ENABLE);

    /* I2C1 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Enable GPIOB Clock

    /* I2C1 SDA and SCL configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    /*SCL is pin06 and SDA is pin 07 for I2C1*/

    /* I2C1 configuration */
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x30;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED ;
    I2C_Init(I2C1, &I2C_InitStructure);

}


Uma dúvida é qual o significado deste trecho:I2C_InitStructure.I2C_OwnAddress1 = 0x30;
O que seria o0x30?
Alguém tem uma rotina testada para ler ou escrever numa Eeprom externa 24Cxx,antes de sair procurando erros de ligações?
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Re: STM32F103 I2C 24Cxx

Mensagempor tcpipchip » 09 Mai 2018 12:50

endereço do dispositivo i2c ?
------------------------------------------
http://www.youtube.com/tcpipchip
Avatar do usuário
tcpipchip
Dword
 
Mensagens: 6560
Registrado em: 11 Out 2006 22:32
Localização: TCPIPCHIPizinho!

Re: STM32F103 I2C 24Cxx

Mensagempor vtrx » 09 Mai 2018 14:19

Só encontrei na net referencia que não importava o valor no modo Master.
As rotina de leitura que encontrei,não entendi como endereçar o dispositivo no barramento.
Anos passados,implementei nos PICs I2C bit bang,por hardware,leitura por blocos etc,mas neste STM ta osso entender.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Re: STM32F103 I2C 24Cxx

Mensagempor eliveltonpsantos » 09 Mai 2018 16:34

Dá uma olhada no meu GitHub; talvez encontre algo que te ajude: https://github.com/eliveltonpsantos/STM ... pse%20Code
Procure os arquivos lib_24c32.c e .h dentro de scr e include, respectivamente, que te darão um início.

Pra agilizar um pouco o processo:
Código: Selecionar todos
HAL_StatusTypeDef eeprom_24c32_write(I2C_HandleTypeDef *hi2c,
      const uint16_t device_address,
      const uint16_t memory_address,
      const char *data_write,
      EEPROM_ConfigTypeDef config)
{
   HAL_StatusTypeDef return_value = 0;

   // Allocate on memory all bytes required (2 bytes of address + n bytes of the message) to send.
   uint8_t *data = (uint8_t*)malloc(sizeof(uint8_t)*(strlen(data_write)+3));

   // Split the address in 2 bytes.
   data[0] = (uint8_t)(memory_address >> 8);
   data[1] = (uint8_t)memory_address;

   // Merge address with the message.
   memcpy(data+2, (uint8_t*)data_write, strlen(data_write)+1);

   // Transmit the message.
   return_value = HAL_I2C_Master_Transmit(hi2c, (device_address << 1), data, (strlen(data_write)+3),
         HAL_MAX_DELAY);

   // Check if is needed to wait for the write routine is completed.
   if (config == EEPROM_CONFIG_WAIT)
      while(HAL_I2C_Master_Transmit(hi2c, (device_address << 1), 0, 0, HAL_MAX_DELAY) != HAL_OK);

   // Unallocated memory
   free(data);

   return return_value;
}
eliveltonpsantos
Bit
 
Mensagens: 40
Registrado em: 30 Jun 2017 09:14

Re: STM32F103 I2C 24Cxx

Mensagempor vtrx » 09 Mai 2018 18:07

eliveltonpsantos escreveu:Dá uma olhada no meu GitHub; talvez encontre algo que te ajude: https://github.com/eliveltonpsantos/STM ... pse%20Code
Procure os arquivos lib_24c32.c e .h dentro de scr e include, respectivamente, que te darão um início.

Pra agilizar um pouco o processo:
Código: Selecionar todos
HAL_StatusTypeDef eeprom_24c32_write(I2C_HandleTypeDef *hi2c,
      const uint16_t device_address,
      const uint16_t memory_address,
      const char *data_write,
      EEPROM_ConfigTypeDef config)
{
   HAL_StatusTypeDef return_value = 0;

   // Allocate on memory all bytes required (2 bytes of address + n bytes of the message) to send.
   uint8_t *data = (uint8_t*)malloc(sizeof(uint8_t)*(strlen(data_write)+3));

   // Split the address in 2 bytes.
   data[0] = (uint8_t)(memory_address >> 8);
   data[1] = (uint8_t)memory_address;

   // Merge address with the message.
   memcpy(data+2, (uint8_t*)data_write, strlen(data_write)+1);

   // Transmit the message.
   return_value = HAL_I2C_Master_Transmit(hi2c, (device_address << 1), data, (strlen(data_write)+3),
         HAL_MAX_DELAY);

   // Check if is needed to wait for the write routine is completed.
   if (config == EEPROM_CONFIG_WAIT)
      while(HAL_I2C_Master_Transmit(hi2c, (device_address << 1), 0, 0, HAL_MAX_DELAY) != HAL_OK);

   // Unallocated memory
   free(data);

   return return_value;
}



É de sua autoria?
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Re: STM32F103 I2C 24Cxx

Mensagempor eliveltonpsantos » 10 Mai 2018 15:25

Esse código fui eu que escrevi quando estava aprendendo o STM32, mas, como sempre, a lógica/estrutura do código é baseada em outros exemplos disponíveis por aí.
eliveltonpsantos
Bit
 
Mensagens: 40
Registrado em: 30 Jun 2017 09:14

Re: STM32F103 I2C 24Cxx

Mensagempor vtrx » 11 Mai 2018 22:16

Baseado em vários trechos,fiz a rotina de leitura o mais simples possível para 24C02 até 24C512:

Código: Selecionar todos
#define EEPROM_HW_ADDRESS      0xA0   /* E0 = E1 = E2 = 0 */
#define I2C_EE                 I2C1   //interface number
...
u8 I2C_EE_ByteRead( u16 ReadAddr)
{
    u8 tmp;

   /* While the bus is busy */
    while(I2C_GetFlagStatus(I2C_EE, I2C_FLAG_BUSY));

    /* Send START condition */
    I2C_GenerateSTART(I2C_EE, ENABLE);

    /* Test on EV5 and clear it */
    while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2C_EE, EEPROM_HW_ADDRESS, I2C_Direction_Transmitter);

    /* Test on EV6 and clear it */
    while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

     // 24C32 até 512 utiliza o trecho comentado
    /* Send the EEPROM's internal address to read from: MSB of the address first */
 //   I2C_SendData(I2C_EE, (u8)((ReadAddr & 0xFF00) >> 8));

    /* Test on EV8 and clear it */
 //   while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send the EEPROM's internal address to read from: LSB of the address */
 //   I2C_SendData(I2C_EE, (u8)(ReadAddr & 0x00FF));
     
      I2C_SendData(I2C_EE, (u8)(ReadAddr & 0x00FF));

    /* Test on EV8 and clear it */
    while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


    /* Send STRAT condition a second time */
    I2C_GenerateSTART(I2C_EE, ENABLE);

    /* Test on EV5 and clear it */
    while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for read */
    I2C_Send7bitAddress(I2C_EE, EEPROM_HW_ADDRESS, I2C_Direction_Receiver);

    /* Test on EV6 and clear it */
    while(!I2C_CheckEvent(I2C_EE,I2C_EVENT_MASTER_BYTE_RECEIVED));//I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    tmp=I2C_ReceiveData(I2C_EE);


    I2C_AcknowledgeConfig(I2C_EE, DISABLE);

    /* Send STOP Condition */
    I2C_GenerateSTOP(I2C_EE, ENABLE);

    return tmp;
    }


Ok,mas a gravação ainda não consegui resultado esperado:

Código: Selecionar todos
void I2C_EE_ByteWrite(u8 val, u16 WriteAddr)
{
    /* Send START condition */
    I2C_GenerateSTART(I2C_EE, ENABLE);

    /* Test on EV5 and clear it */
    while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2C_EE, EEPROM_HW_ADDRESS, I2C_Direction_Transmitter);

    /* Test on EV6 and clear it */
    while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    /* Send the EEPROM's internal address to write to : MSB of the address first */
 //   I2C_SendData(I2C_EE, (u8)((WriteAddr & 0xFF00) >> 8));

    /* Test on EV8 and clear it */
//    while(!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send the EEPROM's internal address to write to : LSB of the address */
    I2C_SendData(I2C_EE, (u8)(WriteAddr & 0x00FF));

    /* Test on EV8 and clear it */
    while(! I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

     I2C_SendData(I2C_EE, val);

        /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C_EE, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


    /* Send STOP condition */
    I2C_GenerateSTOP(I2C_EE, ENABLE);

    //delay between write and read...not less 4ms
    Delay_ms(5);
}
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Re: STM32F103 I2C 24Cxx

Mensagempor eliveltonpsantos » 13 Mai 2018 21:50

O endereço da EEPROM, acho que no seu caso é EEPROM_HW_ADDRESS, está deslocado para esquerda?
Como o endereço possui 7 bits, eu precisei deslocar 1 bit para esquerda, onde o bit da direita é "preenchido automaticamente" pelo comando R/W. Bati a cabeça um tempinho até descobrir meu erro em HAL_I2C_Master_Transmit(hi2c, (device_address << 1), data, (strlen(data_write)+3), HAL_MAX_DELAY);.
eliveltonpsantos
Bit
 
Mensagens: 40
Registrado em: 30 Jun 2017 09:14

Re: STM32F103 I2C 24Cxx

Mensagempor vtrx » 14 Mai 2018 09:18

eliveltonpsantos escreveu:O endereço da EEPROM, acho que no seu caso é EEPROM_HW_ADDRESS, está deslocado para esquerda?
Como o endereço possui 7 bits, eu precisei deslocar 1 bit para esquerda, onde o bit da direita é "preenchido automaticamente" pelo comando R/W. Bati a cabeça um tempinho até descobrir meu erro em HAL_I2C_Master_Transmit(hi2c, (device_address << 1), data, (strlen(data_write)+3), HAL_MAX_DELAY);.

Pois é,eles sempre complicam para agente.
A rotina está gravando,eu que lia o valor errado.
Não desloco o byte de comando,supondo que a rotina faria isso,e fez pois sem alteração consigo le e gravar.
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Re: STM32F103 I2C 24Cxx

Mensagempor vtrx » 19 Mai 2018 19:29

eliveltonpsantos escreveu:O endereço da EEPROM, acho que no seu caso é EEPROM_HW_ADDRESS, está deslocado para esquerda?
Como o endereço possui 7 bits, eu precisei deslocar 1 bit para esquerda, onde o bit da direita é "preenchido automaticamente" pelo comando R/W. Bati a cabeça um tempinho até descobrir meu erro em HAL_I2C_Master_Transmit(hi2c, (device_address << 1), data, (strlen(data_write)+3), HAL_MAX_DELAY);.


Parece que a linha STM32F1X tem um bug no I2C por Hardware.
Dei uma olhada nos fóruns e não achei solução.
A leitura só acontece uma vez,depois 'trava'.
Voce tem uma implementação do I2c por Software?
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Re: STM32F103 I2C 24Cxx

Mensagempor eliveltonpsantos » 20 Mai 2018 22:08

Nunca tive esse problema, mas também usei pouco a I2C.
O que aconteceu comigo foi de dar 2 comandos muito rápidos, a EEPROM não tinha terminado executado o primeiro e, por isso, perdia o segundo comando; por isso implementei esse trecho:

Código: Selecionar todos
if (config == EEPROM_CONFIG_WAIT)
      while(HAL_I2C_Master_Transmit(hi2c, (device_address << 1), 0, 0, HAL_MAX_DELAY) != HAL_OK);


Faça o seguinte teste: coloque um HAL_Delay grande, de uns 2 segundos ou mais, entre os comandos e veja se resolve. Se funcionar, está aí o problema; caso contrário, não sei o que possa ser.
eliveltonpsantos
Bit
 
Mensagens: 40
Registrado em: 30 Jun 2017 09:14

Re: STM32F103 I2C 24Cxx

Mensagempor vtrx » 21 Mai 2018 08:23

Segundo os fóruns,é um bug e eu achei uma implementação (China Bug Fix)que contorna isso.
iamjustinwang.blogspot.com.br/2016/03/stm32f103-i2c-master-driver.html
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Re: STM32F103 I2C 24Cxx

Mensagempor vtrx » 21 Mai 2018 16:56

Tem algum exemplo de uso com o RTC?
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Re: STM32F103 I2C 24Cxx

Mensagempor eliveltonpsantos » 21 Mai 2018 18:11

Da EEPROM pro RTC muda pouca coisa: se você aprendeu bem como funciona o protocolo I2C, não terá problemas.
Novamente, lá no meu GitHub (https://github.com/eliveltonpsantos/STM ... 07/Eclipse) tem um exemplo bem simples que eu fiz com o DS1307.
eliveltonpsantos
Bit
 
Mensagens: 40
Registrado em: 30 Jun 2017 09:14

Re: STM32F103 I2C 24Cxx

Mensagempor vtrx » 21 Mai 2018 19:58

eliveltonpsantos escreveu:Da EEPROM pro RTC muda pouca coisa: se você aprendeu bem como funciona o protocolo I2C, não terá problemas.
Novamente, lá no meu GitHub (https://github.com/eliveltonpsantos/STM ... 07/Eclipse) tem um exemplo bem simples que eu fiz com o DS1307.

Não me expressei direito,é o RTC nativo do STM.
www.st.com/content/ccc/resource/technical/document/application_note/b0/34/9f/35/17/88/43/41/CD00207941.pdf/files/CD00207941.pdf/jcr:content/translations/en.CD00207941.pdf
Avatar do usuário
vtrx
Dword
 
Mensagens: 2239
Registrado em: 20 Abr 2008 21:01

Próximo

Voltar para STMicroelectronics

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x