STM32F107VC/Using I²C
From Teknologisk videncenter
Contents
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
- STM32F10xxx I2C optimized examples Application Note (Loads PDF)
- Articles regarding I²C