I2C

PB8 is connected to SCL (clock), PB9 to SDA (data).

nucleo I2C
LCD I2C
  • orange is connected to SCL

  • white is connected to SDA

  • red to 3,3 V

  • black to Ground

Configure pins PB8 and PB9

Note that PB8 and PB9 are 5V tolerant. It gives a simple solution to the following problem.

The LCD needs 5V power, whereas the Nucleo I2C llines needs 3.3V logic.

tolerance

With PB8, PB9, we can supply +5V to the the crystal display without worrying about I2C signals.

Configure Port B with I2C1 alternate functions (AF4)

AF

This table can be found in the L476 datasheet. Note that we can also use PB5 and PB6.

// configure PB8, PB9 as AF mode
ldr  r1, =GPIOB_BASE        //  4800 0400
ldr  r2, [r1,#MODER]
bic  r2, #GPIO_MODER_MODE8_0  // reset bit 0 -> "x0" Alternate function mode
orr  r2, #GPIO_MODER_MODE8_1  //   set bit 1 -> "1x"
bic  r2, #GPIO_MODER_MODE9_0  // reset bit 0 -> "x0" Alternate function mode
orr  r2, #GPIO_MODER_MODE9_1  //   set bit 1 -> "1x"
str  r2, [r1,#MODER]
// set open-drain
ldr  r1, =GPIOB_BASE
ldr  r2, [r1,#OTYPER]
orr  r2, #GPIO_OTYPER_OT8   // 1: output open drain
orr  r2, #GPIO_OTYPER_OT9   // 1: output open drain
str  r2, [r1,#OTYPER]
// set pin speed
ldr  r2, [r1,#OSPEEDR]
orr  r2,r2, #GPIO_OSPEEDR_OSPEED8_0
orr  r2,r2, #GPIO_OSPEEDR_OSPEED8_1
str  r2, [r1,#OSPEEDR]
//  00: No pull-up, pull-down   01: Pull-up   10: Pull-down
ldr  r2, [r1,#PUPDR]
bic  r2, #GPIO_PUPDR_PUPD6_1   // pull-up 0x
orr  r2, #GPIO_PUPDR_PUPD6_0   // pull-up x1
str  r2, [r1,#PUPDR]

I2C configuration

Let’s find to which bus I2C1 is connected.

From the datasheet, we can find that I2C1 is clock by PCLK1 and is a APB1 peripheral:

LCD I2C

Note that there are two registers APB1ENR1 and APB1ENR2.

/Enable clock access to I2C1/

RCC->APB1ENR|=RCC_APB1ENR_I2C1EN;

// 1. enable I2C clock
RCC->APB1ENR1 |= RCC_APB1ENR1_I2C1EN; // bit 21 (1<<21) RM page 253

APB1 peripheral clock enable register 1 (RCC_APB1ENR1)
Address: 0x58
Reset value: 0x0000 0000
RCC_APB1ENR1
I2C_registers
RCC->CCIPR &= ~RCC_CCIPR_I2C1SEL; // clear bits
RCC->CCIPR |= RCC_CCIPR_I2C1SEL_0; // select SYSCLK
// RCC->CCIPR |= 0x1 << RCC_CCIPR_I2C1SEL_Pos; // bits 13:12 select SYSCLOCK p. 269
// 00 = PCLK, 01 = SYSCLK, 10 = HSI16, 11 = reserved
RCC->APB1RSTR1 |= RCC_APB1RSTR1_I2C1RST; // 1 = reset/ I2C1
RCC->APB1RSTR1 &= ~RCC_APB1RSTR1_I2C1RST; // complete the reset

Peripherals independent clock configuration register (RCC_CCIPR) Address: 0x88

RCC_CCIPR
Bits 13:12 I2C1 clock source selection
00: PCLK selected as I2C1 clock
01: System clock (SYSCLK) selected as I2C1 clock
10: HSI16 clock selected as I2C1 clock

I2C control register 1 (I2C_CR1) | Address offset: 0x00

I2C_registers

I2C reset

APB1 peripheral reset register 1 (RCC_APB1RSTR1) | Address offset: 0x38 | Reset value: 0x0000 0000

RCC_APB1RSTR1
bit 21 I2C1RST: I2C1 reset
Set and cleared by software -> 1: Reset I2C1

The reset of the I2C peripheral is performed by clearing the PE bit of the I2C_CR1 register. It has the effect of releasing the SCL and SDA lines. Internal state machines are reset and the communication control bits and the status bits revert to their reset values.

ldr  r1, =I2C1_BASE
ldr  r2, [r1,#I2C_CR1]
ldr  r3, =I2C_CR1_PE
bic  r4, r2, r3
str  r4, [r1,#I2C_CR1]
bit 0 PE: Peripheral enable
0: Peripheral disabled
1: Peripheral enabled

The reference manual spécifes that PE must be kept low during at least three APB clock cycles to perform the I2C reset. To ensure this, perform the following software sequence:

1.Write PE = 0
2.Check PE = 0
3.Write PE = 1

I2C master mode

Generate a START

For our first test we do not need to connect any I2C device. Just make sure that two pull-up resistors are connected between SCL and +V, and between SDA et +V. This is very important.

Let’s genererate a start, by setting the CR2 register START bit (bit 13).

// start I2C transaction
// I2C1->CR2 |= I2C_CR2_START;
ldr  r1, =I2C1_BASE
ldr  r2, [r1,#CR2]
orr  r2, #I2C_CR2_START
str  r2, [r1,#CR2]

This code will send not only the SDA start signal but also the target 7-bit address and a read/write bit.

Since no address was specified, 7 zero bits will be sent. A write bit will end the transaction.

This sequence corresponds to the contents of the register CR2 after reset

I2C CR2

and more specifically to the reset state of:

  • bit 11 ADD10=0 means the master operates in 7-bit addressing mode

  • bit 10 RD_WRN=0 means master requests a write transfer

  • bits 9:0

SADD[7:1] must be written with the 7-bit slave address to be sent. Bits 0, 8 and 9 are ignored.

Since bit 0 is ignored; the target address must be shifted 1 bit on the left (address<<1U).

Let’s add the following code:

orr  r2, #I2C_CR2_RD_WRN  // read from slave
orr  r2, = 0x48          // test address

before

orr r2, #I2C_CR2_START
str  r2, [r1,#CR2]

The I2C standard (UM10204 I2C-bus specification) specifies that the master (32L476) begin all transactions with a falling transition on the SDA line while SCL is HIGH (START condition).

After this transition, the master sends via the SDA the 7-bit address of the target. A bit is sent at every rising edge of SCL.

Then, on the 8th SCL rising edge, the master continues the transmission by sending a bit indicating whether the master requests to write (0) to the target or read (1) from it.

It is the role of I2C_CR2_RD_WRN (bit 10) of the register CR2 to specify the transfer direction.

scope start

On the 8th SCL falling edge, the master turns into listening mode, reading an acknowledgement provided by the slave on the 9th SCL rising edge.

Since there is no I2C target device, only a pull-up resistor, there is no acknowledment and the master takes over SDA line on the 9th SCL falling edge. The master stops the transaction by a rising SDA while SCL is high (STOP condition).

Device ID

The Device ID field (see Figure 20) is an optional 3-byte read-only (24 bits) word giving the following information:

  • Twelve bits with the manufacturer name, unique per manufacturer

  • Nine bits with the part identification, assigned by manufacturer (for example, PCA9698)

  • Three bits with the die revision, assigned by manufacturer (for example, RevX)

Not all I2C devices use a Device ID, the QPASS 1602 LCD does not.

In the automatic end mode a STOP bit is sent automatically when all bytes have been transferred.

automatic end mode bit 25 AUTOEND: Automatic end mode (master mode) 0: software end mode: TC flag is set when NBYTES data are transferred, stretching SCL low. 1: Automatic end mode: a STOP condition is automatically sent when NBYTES data are transferred.

Hardware clears the STOP flag when a STOP bit has been sent successfully. Similarly, the START bit is set by software and is cleared by hardware after the START bit followed by the slave address is sent.

TXIS flag

I2C interrupt and status register (I2C_ISR) Address offset: 0x18 Reset value: 0x0000 0001

ISR

// I2C_ISR.NACKF = 1? if 1 -> end // bit 4 NACKF: not acknowledge received flag This flag is set by hardware when a NACK is received after a byte transmission. It is cleared by software by setting the NACKCF bit.

Bit 25 AUTOEND: Automatic end mode (master mode) 0: software end mode: TC flag is set when NBYTES data are transferred, stretching SCL low. 1: Automatic end mode: a STOP condition is automatically sent when NBYTES data are transferred.

see Figure 407. Transfer sequence flow for I2C master transmitter, N ≤ 255 bytes

flow master

TXIS: Transmit interrupt status (transmitters) This bit is set by hardware when the I2C_TXDR register is empty and the data to be transmitted must be written in the I2C_TXDR register.

It is cleared when the next data to be sent is written in the I2C_TXDR register. This bit can be written to 1 by software only when NOSTRETCH = 1, to generate a TXIS event (interrupt if TXIE = 1 or DMA request if TXDMAEN = 1).

Bit 0 TXE: Transmit data register empty (transmitters) This bit is set by hardware when the I2C_TXDR register is empty. It is cleared when the next data to be sent is written in the I2C_TXDR register. This bit can be written to 1 by software in order to flush the transmit data register I2C_TXDR.

The flag TXIS - bit 1 ‘Transmit interrupt status’ is set when the I2C_TXDR register is empty and the I2C target is waiting the new byte in the I2C_TXDR register to be sent.

and that the master is required to send as many bytes as indicated by the NBYTES field of the CR2 register.

TXIS flag is not set after the address was sent. This is because TXIS does not really tell you that you CAN send a new byte. It tells you that you MUST send a byte.

How does it know that we must? We need to tell him. This is done by filling the NBYTES field in the CR2 register.

Looking back at the whole reading protocol, we can see that another START condition occurs right after the ‘Command code’ is sent. Therefore, the number of bytes we want to transfer for now is only one.

I2C transmit data register (I2C_TXDR) Address offset: 0x28

I2C_registers
I2C control register 2 (I2C_CR2)
Address offset: 0x04
I2C_registers