I2C
PB8 is connected to SCL (clock), PB9 to SDA (data).
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.
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)
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:
Note that there are two registers APB1ENR1 and APB1ENR2.
- /Enable clock access to I2C1/
RCC->APB1ENR|=RCC_APB1ENR_I2C1EN;
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
I2C control register 1 (I2C_CR1) | Address offset: 0x00
I2C reset
APB1 peripheral reset register 1 (RCC_APB1RSTR1) | Address offset: 0x38 | Reset value: 0x0000 0000
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]
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:
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
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.
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
// 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
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