Difference between revisions of "STM32F107VC/Using I²C"

From Teknologisk videncenter
Jump to: navigation, search
m (Links)
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
=Keil MCBSTM32C board=
 
=Keil MCBSTM32C board=
 
I²C bus connected to [[STM32F107VC]] [[STM32F107VC/GPIO|GPIO]] Port B SDA (Data) on pin 9 and SCL (Clock) on pin 8.
 
I²C bus connected to [[STM32F107VC]] [[STM32F107VC/GPIO|GPIO]] Port B SDA (Data) on pin 9 and SCL (Clock) on pin 8.
 +
=I²C Operation=
 +
*[[Media:I2C.pdf|I2C]] (Loads PDF - in danish)
 
==Peripheral Addresses==
 
==Peripheral Addresses==
 
*[http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00259166.pdf M24C64] EEPROM (Loads PDF) on Slave address 0x0
 
*[http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00259166.pdf M24C64] EEPROM (Loads PDF) on Slave address 0x0
 
*[http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00135460.pdf LIS302DL] 3 Axis motion Sensor (Loads PDF) on Slave address 0x1C
 
*[http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00135460.pdf LIS302DL] 3 Axis motion Sensor (Loads PDF) on Slave address 0x1C
 +
*[http://www.cirrus.com/en/pubs/proDatasheet/CS42L52_F1.pdf CS42L52] Stereo CODEC (Loads PDF) on Slave address 0x94
 +
 
==Software Examples==
 
==Software Examples==
 
*[http://mars.tekkom.dk/data/MotionSensor1.zip MotionSensor1.zip] (Not yet functional. Code works from Cold Reset - but not from Warm Reset)
 
*[http://mars.tekkom.dk/data/MotionSensor1.zip MotionSensor1.zip] (Not yet functional. Code works from Cold Reset - but not from Warm Reset)
 +
<source lang=c>
 +
/*******************************************************************************
 +
* I2C communication status                                                    *
 +
*  Parameter:                                                                *
 +
*  Return:              status                                              *
 +
*******************************************************************************/
 +
 +
static __inline unsigned int I2C_sr (void) {
 +
  unsigned int sr;
 +
 +
  sr  = I2C1->SR1;
 +
  sr |= I2C1->SR2 << 16;
 +
  return (sr);
 +
}
 +
 +
/************************ Exported functions **********************************/
 +
 +
/*******************************************************************************
 +
* Initialize I2C interface in master mode                                      *
 +
*  Parameter:                                                                *
 +
*  Return:                                                                    *
 +
*******************************************************************************/
 +
 +
void I2C_Init (void) {
 +
  unsigned int tout;
 +
 +
  /* Enable clock for I2C1, GPIOB and AFIO                                    */
 +
  RCC->APB2ENR |= (1 << 3) | (1 << 0); //
 +
  RCC->APB1ENR |= (1 << 21);
 +
 +
  /* I2C1 pins remapped, use PB8, PB9                                        */
 +
  AFIO->MAPR  |= 0x00000002;  // Remap=1: (SCL/PB8, SDA/PB9)
 +
  GPIOB->CRH  |= 0x000000FF;  // Alternate IO PB8 and PB9
 +
 +
  I2C1->CR1    = 0x8000;              /* Reset I2C peripheral              */
 +
  for (tout = 1000000; tout; tout--);
 +
  I2C1->CR1    = 0x0000;
 +
 +
  /* Configure I2C peripheral                                                */
 +
  I2C1->CR1    = 0x0001; // PE - Peripheral Enable
 +
  I2C1->CR2    = 0x0024;   // Freq 36 MHz
 +
  I2C1->CR1    = 0x0000; // PE Disable
 +
  I2C1->TRISE  = 0x0025;  //Time Rise - program when PE=0
 +
  I2C1->CCR    = 0x00B4;  // 0x005A = 400 KHz (36MHz / 90) 0x00B4 = 200 KHz
 +
  I2C1->CR1    |= 0x0401;
 +
  I2C1->OAR1    = 0x40A0;
 +
}
 +
 +
 +
/*******************************************************************************
 +
* Generate start condition on I2C bus                                          *
 +
*  Parameter:                                                                *
 +
*  Return:                                                                    *
 +
*******************************************************************************/
 +
 +
void I2C_Start (void) {
 +
if ( I2C1->CR1 & ( 1 << 10 ) ) {
 +
I2C1->CR1 &= ~(1 << 10 );
 +
}
 +
  I2C1->CR1 |= 0x0100; //start genneration when bus free
 +
  while (!(I2C_sr() & 0x0001));
 +
}
 +
 +
 +
/*******************************************************************************
 +
* Generate stop condition on I2C bus                                          *
 +
*  Parameter:                                                                *
 +
*  Return:                                                                    *
 +
*******************************************************************************/
 +
 +
void I2C_Stop (void) {
 +
 +
  I2C1->CR1 |= 0x0200;
 +
  while (I2C_sr() & 0x00020000);        /* Wait until BUSY bit reset          */
 +
}
 +
 +
 +
/*******************************************************************************
 +
* Write address on I2C interface                                              *
 +
*  Parameter:    adr:    address to be written                                *
 +
*  Return:                                                                    *
 +
*******************************************************************************/
 +
 +
void I2C_Addr (unsigned char adr) {
 +
 +
  I2C1->DR = adr;
 +
  while (!(I2C_sr() & 0x0002)); //Addr sent
 +
}
 +
 +
 +
/*******************************************************************************
 +
* Write a byte to I2C interface                                                *
 +
*  Parameter:    c:      data to be written                                  *
 +
*  Return:                                                                    *
 +
*******************************************************************************/
 +
 +
void I2C_Write (unsigned char c) {
 +
 +
  I2C1->DR = c;
 +
  while (!(I2C_sr() & 0x00000004));    /* Wait until BTF bit set            */
 +
}
 +
 +
 +
/*******************************************************************************
 +
* Read a byte from I2C interface                                              *
 +
*  Parameter:                                                                *
 +
*  Return:              read data                                            *
 +
*******************************************************************************/
 +
 +
unsigned char I2C_Read (int ack) {
 +
 +
  /* Enable/disable Master acknowledge                                        */
 +
  if (ack) I2C1->CR1 |=  0x0400;
 +
  else    I2C1->CR1 &= ~0x0400;
 +
 +
  while (!(I2C_sr() & 0x00000040));    /* Wait until RxNE bit set            */
 +
  return (I2C1->DR);
 +
}
 +
 +
/******************************************************************************/
 +
 +
unsigned char I2C_getbyte(unsigned char address, unsigned char cmd) {
 +
unsigned char uc;
 +
I2C_Start();   // Initial Start bit sequence
 +
I2C_Addr(address); // Address I2C Device. (Base address is Write Address)
 +
I2C_Write(cmd); // Transfer Command to I2C Device (Register to be Read)
 +
I2C_Start(); // Repeated start bit sequence
 +
I2C_Addr(address+1); // Address I2C Device. (Base address + 1 is Read Address)
 +
uc = I2C_Read(0); // Read 1 byte without Acknowledge
 +
I2C_Stop(); // Stop I2C transfer
 +
return( uc );
 +
}
 +
 +
unsigned short int I2C_getword(unsigned char address, unsigned char cmd) {
 +
unsigned short int uw;
 +
//unsigned short int uw2;
 +
I2C_Start();   // Initial Start bit sequence
 +
I2C_Addr(address); // Address I2C Device. (Base address is Write Address)
 +
I2C_Write(cmd); // Transfer Command to I2C Device (Register to be Read)
 +
I2C_Start(); // Repeated start bit sequence
 +
I2C_Addr(address+1); // Address I2C Device. (Base address + 1 is Read Address)
 +
uw = I2C_Read(1) << 8; // Read MSB  without Acknowledge
 +
uw |= I2C_Read(0); // Read LSB with Acknowledge
 +
I2C_Stop(); // Stop I2C transfer
 +
return( uw );
 +
}
 +
void I2C_putbyte(unsigned char address, unsigned char cmd, unsigned char data) {
 +
I2C_Start();   // Initial Start bit sequence
 +
I2C_Addr(address); // Address I2C Device. (Base address is Write Address)
 +
I2C_Write(cmd); // Transfer Command to I2C Device (Register to be Read)
 +
I2C_Write(data); // Transfer Data to I2C device
 +
I2C_Stop(); // Stop I2C transfer
 +
}
 +
 +
int I2C_getbytearray(unsigned char address, unsigned char cmd, int number, unsigned char *data) {
 +
int count;
 +
I2C_Start();   // Initial Start bit sequence
 +
I2C_Addr(address); // Address I2C Device. (Base address is Write Address)
 +
I2C_Write(cmd); // Transfer Command to I2C Device (Register to be Read)
 +
I2C_Start(); // Repeated start bit sequence
 +
I2C_Addr(address+1); // Address I2C Device. (Base address + 1 is Read Address)
 +
// Read number - 1 bytes with Acknowledge
 +
for ( count=0; count < number - 2; count++ ) {
 +
data[count] = I2C_Read(1); // Read with Acknowledge
 +
}
 +
data[count] = I2C_Read(0); // Last byte without Acknowledge
 +
I2C_Stop(); // Stop I2C transfer
 +
return( count+1 );
 +
}
 +
</source>
  
 
=Links=
 
=Links=
 
*[http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/CD00209826.pdf STM32F10xxx I2C optimized examples] Application Note (Loads PDF)
 
*[http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/APPLICATION_NOTE/CD00209826.pdf STM32F10xxx I2C optimized examples] Application Note (Loads PDF)
 +
*[http://www.esacademy.com/en/library/technical-articles-and-documents/miscellaneous/i2c-bus.html Articles regarding I²C]
 +
[[Category:Elektronik]][[Category:Embedded]][[Category:ARM]]

Latest revision as of 09:34, 3 January 2012

Keil MCBSTM32C board

I²C bus connected to STM32F107VC GPIO Port B SDA (Data) on pin 9 and SCL (Clock) on pin 8.

I²C Operation

  • I2C (Loads PDF - in danish)

Peripheral Addresses

  • M24C64 EEPROM (Loads PDF) on Slave address 0x0
  • LIS302DL 3 Axis motion Sensor (Loads PDF) on Slave address 0x1C
  • CS42L52 Stereo CODEC (Loads PDF) on Slave address 0x94

Software Examples

  • MotionSensor1.zip (Not yet functional. Code works from Cold Reset - but not from Warm Reset)
/*******************************************************************************
* I2C communication status                                                     *
*   Parameter:                                                                 *
*   Return:               status                                               *
*******************************************************************************/

static __inline unsigned int I2C_sr (void) {
  unsigned int sr;

  sr  = I2C1->SR1;
  sr |= I2C1->SR2 << 16;
  return (sr);
}

/************************ Exported functions **********************************/

/*******************************************************************************
* Initialize I2C interface in master mode                                      *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Init (void) {
  unsigned int tout;

  /* Enable clock for I2C1, GPIOB and AFIO                                    */
  RCC->APB2ENR |= (1 << 3) | (1 << 0); //
  RCC->APB1ENR |= (1 << 21);

  /* I2C1 pins remapped, use PB8, PB9                                         */
  AFIO->MAPR   |= 0x00000002;  // Remap=1: (SCL/PB8, SDA/PB9)
  GPIOB->CRH   |= 0x000000FF;  // Alternate IO PB8 and PB9

  I2C1->CR1     = 0x8000;               /* Reset I2C peripheral               */
  for (tout = 1000000; tout; tout--);
  I2C1->CR1     = 0x0000;

  /* Configure I2C peripheral                                                 */
  I2C1->CR1     = 0x0001;		// PE - Peripheral Enable
  I2C1->CR2     = 0x0024;	  	// Freq 36 MHz
  I2C1->CR1     = 0x0000; 		// PE Disable
  I2C1->TRISE   = 0x0025;  		//Time Rise - program when PE=0 
  I2C1->CCR     = 0x00B4;  		// 0x005A = 400 KHz (36MHz / 90) 	0x00B4 = 200 KHz
  I2C1->CR1    |= 0x0401;
  I2C1->OAR1    = 0x40A0;
}


/*******************************************************************************
* Generate start condition on I2C bus                                          *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Start (void) {
if ( I2C1->CR1 & ( 1 << 10 ) ) {
		I2C1->CR1 &= ~(1 << 10 );
	} 
  I2C1->CR1 |= 0x0100; //start genneration when bus free
  while (!(I2C_sr() & 0x0001));
}


/*******************************************************************************
* Generate stop condition on I2C bus                                           *
*   Parameter:                                                                 *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Stop (void) {

  I2C1->CR1 |= 0x0200;
  while (I2C_sr() & 0x00020000);        /* Wait until BUSY bit reset          */
}


/*******************************************************************************
* Write address on I2C interface                                               *
*   Parameter:    adr:    address to be written                                *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Addr (unsigned char adr) {

  I2C1->DR = adr;
  while (!(I2C_sr() & 0x0002));	//Addr sent 
}


/*******************************************************************************
* Write a byte to I2C interface                                                *
*   Parameter:    c:      data to be written                                   *
*   Return:                                                                    *
*******************************************************************************/

void I2C_Write (unsigned char c) {

  I2C1->DR = c;
  while (!(I2C_sr() & 0x00000004));     /* Wait until BTF bit set             */ 
}


/*******************************************************************************
* Read a byte from I2C interface                                               *
*   Parameter:                                                                 *
*   Return:               read data                                            *
*******************************************************************************/

unsigned char I2C_Read (int ack) {

  /* Enable/disable Master acknowledge                                        */
  if (ack) I2C1->CR1 |=  0x0400;
  else     I2C1->CR1 &= ~0x0400;

  while (!(I2C_sr() & 0x00000040));     /* Wait until RxNE bit set            */
  return (I2C1->DR);
}

/******************************************************************************/

unsigned char I2C_getbyte(unsigned char address, unsigned char cmd) {
	unsigned char uc;
	I2C_Start();		  	// Initial Start bit sequence
	I2C_Addr(address);	 	// Address I2C Device. (Base address is Write Address)
	I2C_Write(cmd);			// Transfer Command to I2C Device (Register to be Read) 
	I2C_Start(); 			// Repeated start bit sequence
	I2C_Addr(address+1);	// Address I2C Device. (Base address + 1 is Read Address)
	uc = I2C_Read(0);		// Read 1 byte without Acknowledge
	I2C_Stop();				// Stop I2C transfer
	return( uc );
}

unsigned short int I2C_getword(unsigned char address, unsigned char cmd) {
	unsigned short int uw;
	//unsigned short int uw2;
	I2C_Start();		  	// Initial Start bit sequence
	I2C_Addr(address);	 	// Address I2C Device. (Base address is Write Address)
	I2C_Write(cmd);			// Transfer Command to I2C Device (Register to be Read) 
	I2C_Start(); 			// Repeated start bit sequence
	I2C_Addr(address+1);	// Address I2C Device. (Base address + 1 is Read Address)
	uw = I2C_Read(1) << 8;		// Read MSB  without Acknowledge
	uw |= I2C_Read(0); 			// Read LSB	 with Acknowledge
	I2C_Stop();				// Stop I2C transfer
	return( uw );
}
void I2C_putbyte(unsigned char address, unsigned char cmd, unsigned char data) {
	I2C_Start();		  	// Initial Start bit sequence
	I2C_Addr(address);	 	// Address I2C Device. (Base address is Write Address)
	I2C_Write(cmd);			// Transfer Command to I2C Device (Register to be Read) 
	I2C_Write(data);		// Transfer Data to I2C device
	I2C_Stop();				// Stop I2C transfer
}

int I2C_getbytearray(unsigned char address, unsigned char cmd, int number, unsigned char *data) {
	int count;
	I2C_Start();		  	// Initial Start bit sequence
	I2C_Addr(address);	 	// Address I2C Device. (Base address is Write Address)
	I2C_Write(cmd);			// Transfer Command to I2C Device (Register to be Read) 
	I2C_Start(); 			// Repeated start bit sequence
	I2C_Addr(address+1);	// Address I2C Device. (Base address + 1 is Read Address)
	// Read number - 1 bytes with Acknowledge
	for ( count=0; count < number - 2; count++ ) {
		data[count] = I2C_Read(1);		// Read with Acknowledge
	}
	data[count] = I2C_Read(0);		// Last byte without Acknowledge
	I2C_Stop();				// Stop I2C transfer
	return( count+1 );
}

Links