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

From Teknologisk videncenter
Jump to: navigation, search
m (Peripheral Addresses)
m (Software Examples)
Line 9: Line 9:
 
*[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>
 
<source lang=c>
 
/************************ Local auxiliary functions ***************************/
 
 
 
/*******************************************************************************
 
/*******************************************************************************
 
* I2C communication status                                                    *
 
* I2C communication status                                                    *
Line 38: Line 35:
  
 
   /* Enable clock for I2C1, GPIOB and AFIO                                    */
 
   /* Enable clock for I2C1, GPIOB and AFIO                                    */
  //RCC->APB2ENR |= (1 << 4) | (1 << 0); //Really Port C?
 
 
   RCC->APB2ENR |= (1 << 3) | (1 << 0); //
 
   RCC->APB2ENR |= (1 << 3) | (1 << 0); //
 
   RCC->APB1ENR |= (1 << 21);
 
   RCC->APB1ENR |= (1 << 21);
Line 51: Line 47:
  
 
   /* Configure I2C peripheral                                                */
 
   /* Configure I2C peripheral                                                */
   I2C1->CR1    = 0x0001; // PE - Peripheral Enable
+
   I2C1->CR1    = 0x0001; // PE - Peripheral Enable
   I2C1->CR2    = 0x0024;   // Freq 36 MHz
+
   I2C1->CR2    = 0x0024;   // Freq 36 MHz
   I2C1->CR1    = 0x0000; // PE Disable
+
   I2C1->CR1    = 0x0000; // PE Disable
   I2C1->TRISE  = 0x0025; //Time Rise - program when PE=0
+
   I2C1->TRISE  = 0x0025; //Time Rise - program when PE=0  
   I2C1->CCR    = 0x00B4; // 0x005A = 400 KHz (36MHz / 90) 0x00B4 = 200 KHz
+
   I2C1->CCR    = 0x00B4; // 0x005A = 400 KHz (36MHz / 90) 0x00B4 = 200 KHz
 
   I2C1->CR1    |= 0x0401;
 
   I2C1->CR1    |= 0x0401;
 
   I2C1->OAR1    = 0x40A0;
 
   I2C1->OAR1    = 0x40A0;
 
  //I2C1->CR1    |= 0x8000;              /* Reset I2C peripheral              */
 
  //for (tout = 1000000; tout; tout--);
 
  //I2C1->CR1    &= ~0x8000;
 
 
}
 
}
  
Line 149: Line 141:
 
}
 
}
  
 +
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) {
 
void I2C_putbyte(unsigned char address, unsigned char cmd, unsigned char data) {
 
I2C_Start();   // Initial Start bit sequence
 
I2C_Start();   // Initial Start bit sequence
Line 155: Line 160:
 
I2C_Write(data); // Transfer Data to I2C device
 
I2C_Write(data); // Transfer Data to I2C device
 
I2C_Stop(); // Stop I2C transfer
 
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>
 
</source>

Revision as of 12:57, 23 September 2011

Keil MCBSTM32C board

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

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