【GD32L233C-START Review】12. Hardware IIC drive OLED
[Copy link]
For previous posts, please refer to:
【GD32L233C-START Review】1. Unboxing
[GD32L233C-START Review] 2. Create a new project step by step
[GD32L233C-START Evaluation] 3. Porting FreeRTOS to GD32L233
【GD32L233C-START Review】4. Porting RT-Thread to GD32L233
【GD32L233C-START Review】5. IIC driving OLED
【GD32L233C-START Review】6. Get RTC time and display it through OLED
【GD32L233C-START Review】7. PWM LED Driver
[GD32L233C-START Review] 8. TRNG True Random Number Generation
【GD32L233C-START Review】9. CRC Check
【GD32L233C-START Review】10. ADC reads the internal temperature of the chip
[GD32L233C-START Review] 11. DAC output voltage value_ADC reads external voltage value
In my 5th post, I used software IIC to drive the OLED, and in the 6th post I added RTC to display the time. This post will use hardware IIC to complete the OLED display and time display.
Why use hardware IIC? First, the hardware IIC implementation logic lacks the IIC communication logic part compared to software IIC, which is relatively much simpler; second, the hardware IIC speed is much faster than software IIC.
1. Understand Hardware IIC
To successfully use the hardware IIC, we first need to understand the relevant knowledge of the hardware IIC and check the data manual content. The reference is Chapter 21 of the "User Manual" 21. Inter-Integrated Circuit Bus Interface I2C) .
Hardware I2C has four working modes:
Slave sends
Slave receives
Master sends
Master receives
This post is mainly about the operation of OLED, which does not require reading, and OLED is controlled as a slave, so our microcontroller will act as a host to send data and only work in this mode.
Important information about the validity, format, principle, and communication timing of IIC data communication are described in detail in the User Manual. If you don’t understand, you can read it by yourself.
2. Interface Information
After checking the User Manual to understand the communication principle and related registers of IIC, we need to check the Data Manual to understand the interface configuration related to IIC to facilitate program writing.
The IIC interfaces brought out by the GD32L233C development board are PB10 and PB11. We can directly look up the multiplexing information of these two pins in the "Data Manual".
As shown below:
Multiplexing optional AF4, where
PB10 -- AF5 -- SCL of I2C1
PB11 -- AF4 -- SDA of I2C1
3. Software Code
1. Initialize GPIO
Initializing GPIO mainly sets PB10 and PB11 as multiplexed ports and multiplexes IIC functions.
void i2c_gpio_config(void)
{
/* enable GPIOB clock */
rcu_periph_clock_enable(RCU_GPIOB);
/* connect PB10 to I2C1_SCL */
gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_10);
/* connect PB11 to I2C1_SDA */
gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_11);
/* configure GPIO pins of I2C1 */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_11);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
}
2. Initialize hardware IIC
To initialize the hardware IIC, you need to set:
IIC address of the IIC host, set bit 0x72, represented by macro I2C_OWN_ADDRESS7
The IIC address of the IIC slave, that is, the address of the OLED, bit 0x78, represented by the macro I2C_SLAVE_OLED_ADDRESS7
The number of data transmitted each time by hardware IIC, OLED has a write data register 0x40 and a write command register 0x00, and data needs to be written to these two registers each time, so it is 2 bytes, represented by I2C_DATA_BYTES.
void i2c_config(void)
{
/* enable I2C1 clock */
rcu_periph_clock_enable(RCU_I2C1);
/* configure I2C timing */
i2c_timing_config(I2C1, 0, 0x3, 0);
i2c_master_clock_config(I2C1, 0x13, 0x36);
/* configure I2C address */
i2c_address_config(I2C1, I2C_OWN_ADDRESS7, I2C_ADDFORMAT_7BITS);
/* configure slave address */
i2c_master_addressing(I2C1, I2C_SLAVE_OLED_ADDRESS7, I2C_MASTER_TRANSMIT);
/* configure number of bytes to be transferred */
i2c_transfer_byte_number_config(I2C1, I2C_DATA_BYTES);
/* enable I2C1 */
i2c_enable(I2C1);
}
3. OLED write command and write data function implementation
Because IIC was used before, and IIC is used this time, I used a macro definition to distinguish hardware IIC code from hardware IIC code. When I need to use hardware IIC or software IIC, I only need to modify some macro definitions , as follows:
#define OLED_IIC_TYPE_SW 0U /*IIC for software*/
#define OLED_IIC_TYPE_HW 1U /*IIC for hardware*/
#define OLED_IIC_TYPE OLED_IIC_TYPE_HW
Write data function implementation:
void OLED_WrDat(unsigned char IIC_Data)
{
#if(OLED_IIC_TYPE == OLED_IIC_TYPE_HW)
uint8_t i2c_transmitter[2]={0x40, IIC_Data};
uint8_t i;
i2c_transmitter[0] = 0x40;
i2c_transmitter[1] = IIC_Data;
/* wait until I2C bus is idle */
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);
/* wait until the transmit data buffer is empty */
I2C_STAT(I2C1) |= I2C_STAT_TBE;
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
for(i = 0; i < 2; i++) {
/* data transmission */
i2c_data_transmit(I2C1, i2c_transmitter[i]);
/* wait until the TI bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_TI));
}
/* wait for transfer complete flag */
while(!i2c_flag_get(I2C1, I2C_FLAG_TC));
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);
/* wait until stop condition generate */
while(!i2c_flag_get(I2C1, I2C_FLAG_STPDET));
/* clear the STPDET bit */
i2c_flag_clear(I2C1, I2C_FLAG_STPDET);
#elif(OLED_IIC_TYPE == OLED_IIC_TYPE_SW)
IIC_Start();
IIC_Send_Byte(0x78);
IIC_Wait_Ack();
IIC_Send_Byte(0x40); //write data
IIC_Wait_Ack();
IIC_Send_Byte(IIC_Data);
IIC_Wait_Ack();
IIC_Stop();
#endif
}
Write command function implementation
void OLED_WrCmd(unsigned char IIC_Command)
{
#if(OLED_IIC_TYPE == OLED_IIC_TYPE_HW)
uint8_t i2c_transmitter[2]={0x00, IIC_Command};
uint8_t i;
i2c_transmitter[0] = 0x00;
i2c_transmitter[1] = IIC_Command;
/* wait until I2C bus is idle */
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);
/* wait until the transmit data buffer is empty */
I2C_STAT(I2C1) |= I2C_STAT_TBE;
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
for(i = 0; i < 2; i++) {
/* data transmission */
i2c_data_transmit(I2C1, i2c_transmitter[i]);
/* wait until the TI bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_TI));
}
/* wait for transfer complete flag */
while(!i2c_flag_get(I2C1, I2C_FLAG_TC));
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2C1);
/* wait until stop condition generate */
while(!i2c_flag_get(I2C1, I2C_FLAG_STPDET));
/* clear the STPDET bit */
i2c_flag_clear(I2C1, I2C_FLAG_STPDET);
#elif(OLED_IIC_TYPE == OLED_IIC_TYPE_SW)
IIC_Start();
IIC_Send_Byte(0x78); //Slave address,SA0=0
IIC_Wait_Ack();
IIC_Send_Byte(0x00); //write command
IIC_Wait_Ack();
IIC_Send_Byte(IIC_Command);
IIC_Wait_Ack();
IIC_Stop();
#endif
}
4. OLED display code
The display code of OLED has not changed. You can directly refer to my sixth post: [GD32L233C-START Review] 6. Get RTC time and display it through OLED
4. Effect display
The display effect is as follows. The video was shot upside down, please forgive me :
5. Source code
The source code is shared below for reference.
GD32L233C_Prj_OLED_HW_IIC.zip
(784.54 KB, downloads: 31)
|