March 28, 2024, 06:02:21 PM

I2C temperature sensor TCN75A

Started by melajmi, August 10, 2014, 08:20:35 PM

Previous topic - Next topic

melajmi

HI,

I am a new user STM32F207.
I use Kit Eval Olimex STM32-P207.
I would like send data to TCN75A. I can't have SDA and SCL.
SDA and SCL are low.
There is my code
Thanks for your help
Best regards
Elajmi

/* Includes ------------------------------------------------------------------*/
#include "stm32f2xx.h"
#include "stm32f2xx_conf.h"
#include "stm32f2xx_i2c.h"
#include "delay.h"
#include "gpio.h"
#include <stdio.h>

#define I2C_SPEED 100000
#define I2C_DUTYCYCLE I2C_DutyCycle_2

/* Function declaration -------------------------------------------------------------*/
void I2C1_init(void);
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction);
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data);
uint8_t I2C_read_ack(I2C_TypeDef* I2Cx);
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx);
void I2C_stop(I2C_TypeDef* I2Cx);


/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

#define SLAVE_ADDRESS 0x4B

   void I2C1_init(void)
   {

      GPIO_InitTypeDef GPIO_InitStruct;
      I2C_InitTypeDef I2C_InitStruct;
      I2C_DeInit(I2C1);

      // enable APB1 peripheral clock for I2C1
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
      // enable clock for SCL and SDA pins
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
      
      RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, DISABLE);
      RCC_AHB3PeriphResetCmd(RCC_AHB3Periph_FSMC, DISABLE);

      
// Connect I2C1 pins to AF
GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, GPIO_AF_I2C1);   // SCL
      GPIO_PinAFConfig(GPIOG, GPIO_PinSource12, GPIO_AF_I2C1); // SDA
   
      /* setup SCL and SDA pins
       * You can connect the I2C1 functions to two different
       * pins:
        * 1. SCL on PG10
        * 2. SDA on PG12
       */
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_12; // we are going to use PG10 and PG12
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;   // set pins to alternate function
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;   // set GPIO speed
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;   // set output to open drain
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;   // enable pull up resistors
      GPIO_Init(GPIOG, &GPIO_InitStruct);   // init GPIOG

      /* Configure I2C1 ***********************************************************/   
      I2C_DeInit(I2C1);   /* I2C DeInit */
   
// configure I2C1
I2C_InitStruct.I2C_ClockSpeed = 100000; // 100kHz
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;   // I2C mode
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;   // 50% duty cycle --> standard
I2C_InitStruct.I2C_OwnAddress1 = 0x00;   // own address, not relevant in master mode
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;   // Enable acknowledge when reading     
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length
I2C_Init(I2C1, &I2C_InitStruct);   // init I2C1

      // enable I2C1
      I2C_Cmd(I2C1, ENABLE);
   }

   /* This function issues a start condition and
   * transmits the slave address + R/W bit
   *
   * Parameters:
   * I2Cx --> the I2C peripheral e.g. I2C1
   * address --> the 7 bit slave address
   * direction --> the transmission direction can be:
   * I2C_Direction_Tranmitter for Master transmitter mode
   * I2C_Direction_Receiver for Master receiver
   */
   void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction)
   {
      // wait until I2C1 is not busy any more
      while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
 
      // Send I2C1 START condition : SDA =0, SCL=0
      I2C_GenerateSTART(I2Cx, ENABLE);

      // wait for I2C1 EV5 --> Slave has acknowledged start condition
      while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

      // Send slave Address for write
      I2C_Send7bitAddress(I2Cx, address, direction);

      /* wait for I2Cx EV6, check if
       * either Slave has acknowledged Master transmitter or
       * Master receiver mode, depending on the transmission
       * direction
       */
      if(direction == I2C_Direction_Transmitter)
         {
            while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
         }
      else if(direction == I2C_Direction_Receiver)
         {
            while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
         }
   }

   /* This function transmits one byte to the slave device
    * Parameters:
    * I2Cx --> the I2C peripheral e.g. I2C1
    * data --> the data byte to be transmitted
    */
   void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
   {
      // wait for I2C1 EV8 --> last byte is still being transmitted (last byte in SR, buffer empty), next byte can already be written
      while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
      I2C_SendData(I2Cx, data);
   }

   /* This function reads one byte from the slave device
    * and acknowledges the byte (requests another byte)
    */
   uint8_t I2C_read_ack(I2C_TypeDef* I2Cx)
   {
      uint8_t data;
      // enable acknowledge of received data
      I2C_AcknowledgeConfig(I2Cx, ENABLE);
      // wait until one byte has been received : EV7
      while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
      // read data from I2C data register and return data byte
      data = I2C_ReceiveData(I2Cx);
      return data;
   }

   /* This function reads one byte from the slave device
    * and doesn't acknowledge the received data
    * after that a STOP condition is transmitted
    */
   uint8_t I2C_read_nack(I2C_TypeDef* I2Cx)
   {
      uint8_t data;
      // disable acknowledge of received data
      // nack also generates stop condition after last byte received
      // see reference manual for more info
      I2C_AcknowledgeConfig(I2Cx, DISABLE);
      I2C_GenerateSTOP(I2Cx, ENABLE);
      // wait until one byte has been received : EV7
      while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) );
      // read data from I2C data register and return data byte
      data = I2C_ReceiveData(I2Cx);
      return data;
   }

   /* This function issues a stop condition and therefore
    * releases the bus
    */
   void I2C_stop(I2C_TypeDef* I2Cx)
   {

      // Send I2C1 STOP Condition after last byte has been transmitted
      I2C_GenerateSTOP(I2Cx, ENABLE);
      // wait for I2C1 EV8_2 --> byte has been transmitted
      while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
   }

   int main(void)
   {
   
uint8_t received_data;


/*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f2xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f2xx.c file
     */
      
   /* Configuration du Systick à 1 ms (1000) */
   SysTick_Config(SystemCoreClock / 1000);
   
   I2C1_init(); // initialize I2C peripheral

   I2C_start(I2C1, SLAVE_ADDRESS, I2C_Direction_Transmitter); // start a transmission in Master transmitter mode
   I2C_write(I2C1, 0x00); // write one byte to the slave
   I2C_stop(I2C1); // stop the transmission

   I2C_start(I2C1, SLAVE_ADDRESS, I2C_Direction_Receiver); // start a transmission in Master receiver mode
   received_data = I2C_read_nack(I2C1); // read one byte and don't request another byte, stop transmission

   while(1);
   
   }







LubOlimex

Hello Melajmi,

The GPIO pins used for TCN75A also go to pins 5 and 6 of the UEXT connector. Are you sure there isn't something attached to the UEXT keeping them low?

Unfortunately, the board lacked free hardware SDA/SCL pins and we had to go with GPIO pins, naming them SOFT_SDA and SOFT_SCL so people would know what to expect (e.g. that they would need to implement software I2C on PG9 and PG11 processor pins).

Best regards,
Lub/OLIMEX
Technical support and documentation manager at Olimex

montyto

who i can connect PG9 and PG11 in I2C by software

thanks