【GD32L233C-START Review】6. Hardware I2C drive 0.96-inch OLED
[Copy link]
Related articles:
[GD32L233C-START Review] 1. GD32L233C-START with obvious advantages and disadvantages (unboxing)
[GD32L233C-START Review] 2. Non-blocking way to light up, blink, blink, blink...
[GD32L233C-START Review] 3. PWM to achieve breathing light
[GD32L233C-START Review] 4. Serial port variable length data reception
[GD32L233C-START Review] 5. Flash Read and Write - Using Internal Flash to Store Data
1. About the I2C interface of GD32L233CCT6
It can be seen that there are two I2Cs , I2C0 and I2C1.
2. I2C pins on the development board
It can be seen that the pins of I2C1 are PB10 and PB11.
3. General pin multiplexing as I2C
It can be seen that it is multiplexing function 4.
4. Code Implementation
(1) Initialize i2c
void I2cInit(void)
{
rcu_periph_clock_enable(RCU_I2C1);
rcu_periph_clock_enable(RCU_GPIOB);
gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_10);
gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_11);
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);
/* 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_ADDRESS7, I2C_MASTER_TRANSMIT);
/* configure number of bytes to be transferred */
i2c_transfer_byte_number_config(I2C1, 2);
/* enable I2C1 */
i2c_enable(I2C1);
}
(2) Writing OLED
The commands and data are written separately below.
void SSD1306_WriteCmd(uint8_t var)
{
/* 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));
/* data transmission */
i2c_data_transmit(I2C1, 0x00);
/* wait until the TI bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
i2c_data_transmit(I2C1, var);
/* wait until the TI bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
/* 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);
}
void SSD1306_WriteData(uint8_t var)
{
/* 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));
/* data transmission */
i2c_data_transmit(I2C1, 0x40);
/* wait until the TI bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
i2c_data_transmit(I2C1, var);
/* wait until the TI bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
/* 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);
}
(3) OLED related drivers
//坐标设置:也就是在哪里显示
void OledSetPos(uint8_t x, uint8_t y)
{
//以下3个寄存器只在页寻址的模式下有效
SSD1306_WriteCmd(0xb0+y); //页地址设置 0xb0~0xb7
SSD1306_WriteCmd(((x&0xf0)>>4)|0x10); //列高位地址设置
SSD1306_WriteCmd((x&0x0f)); //列低位地址设置
}
//开启Oled显示
void OledDisplayOn(void)
{
SSD1306_WriteCmd(0X8D); //SET DCDC命令
SSD1306_WriteCmd(0X14); //DCDC ON
SSD1306_WriteCmd(0XAF); //DISPLAY ON
}
//关闭Oled显示
void OledDisplayOff(void)
{
SSD1306_WriteCmd(0X8D); //SET DCDC命令
SSD1306_WriteCmd(0X10); //DCDC OFF
SSD1306_WriteCmd(0XAE); //DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样
void OledClear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
SSD1306_WriteCmd (0xb0+i); //设置页地址(0~7)
SSD1306_WriteCmd (0x00); //设置显示位置—列低地址
SSD1306_WriteCmd (0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
SSD1306_WriteData(0);
} //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127,y:0~7
//Char_Size:选择字体 16/12
void OledShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size)
{
uint8_t c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>MAX_COLUMN-1)
{
x=0;
y=y+2;
}
if(Char_Size ==16)
{
OledSetPos(x,y);
for(i=0;i<8;i++)
{
SSD1306_WriteData(F8X16[c*16+i]);//先写上半部分
}
OledSetPos(x,y+1);
for(i=0;i<8;i++)
{
SSD1306_WriteData(F8X16[c*16+i+8]);//后写下半部分
}
}
else
{
OledSetPos(x,y);
for(i=0;i<6;i++)
{
SSD1306_WriteData(F6x8[c][i]);
}
}
}
//显示一个字符串
void OledShowString(uint8_t x,uint8_t y,char *str,uint8_t Char_Size)
{
unsigned char j=0;
while (str[j]!='\0')
{
OledShowChar(x,y,str[j],Char_Size);
x+=8;
if(x>120)
{
x=0;
y+=2;
}
j++;//移动一次就是一个page,取值0-7
}
}
//显示汉字
//由于汉字是16*16大小的,所以最多显示4行汉字
//index:在汉字取模中的索引
void OledShowCN(uint8_t x,uint8_t y,uint8_t index)
{
uint8_t t;
OledSetPos(x,y);
for(t=0;t<16;t++)
{
SSD1306_WriteData(Hzk[index][t]);
}
OledSetPos(x,y+1);
for(t=0;t<16;t++)
{
SSD1306_WriteData(Hzk[index][t+16]);
}
}
(4) OLED initialization
void OledInit(void)
{
DelayMs(300);
DelayMs(300);
//SSD1306复位之后,默认的是页寻址方式
SSD1306_WriteCmd(0xAE);//--display off
SSD1306_WriteCmd(0x00);//--set low column address
SSD1306_WriteCmd(0x10);//--set high column address
SSD1306_WriteCmd(0x40);//--set start line address
SSD1306_WriteCmd(0xB0);//--set page address
SSD1306_WriteCmd(0x81);// contract control
SSD1306_WriteCmd(0xFF);//--128
SSD1306_WriteCmd(0xA1);//set segment re-map 0 to 127
SSD1306_WriteCmd(0xA6);//set normal display
SSD1306_WriteCmd(0xA8);//set multiplex ratio(1 to 64)
SSD1306_WriteCmd(0x3F);//--1/32 duty
SSD1306_WriteCmd(0xC8);//Com scan direction
SSD1306_WriteCmd(0xD3);//set display offset
SSD1306_WriteCmd(0x00);//no offset
SSD1306_WriteCmd(0xD5);//set display clock divide ratio/oscillator frequency
SSD1306_WriteCmd(0x80);//
SSD1306_WriteCmd(0xD8);//set area color mode off
SSD1306_WriteCmd(0x05);//
SSD1306_WriteCmd(0xD9);//Set Pre-Charge Period
SSD1306_WriteCmd(0xF1);//
SSD1306_WriteCmd(0xDA);//set com pin hardware configuartion
SSD1306_WriteCmd(0x12);//
SSD1306_WriteCmd(0xDB);//set Vcomh
SSD1306_WriteCmd(0x30);//0x20,0.77xVcc
SSD1306_WriteCmd(0x8D);//set charge pump enable
SSD1306_WriteCmd(0x14);//
SSD1306_WriteCmd(0xAF);//--turn on Oled panel
}
(5) Display test
void OledDisplayTest(void)
{
I2cInit();
OledInit();
OledClear();
OledShowString(28,0,(char *)("EEWORLD"),16);
OledShowString(40,2,(char *)("GD32"),16);
OledShowString(40,4,(char *)("2022"),16);
OledShowCN(24,6,0);
OledShowCN(40,6,1);
OledShowCN(56,6,2);
OledShowCN(72,6,3);
}
5. Phenomenon
I wish EEWORLD and GD32 official a prosperous 2022.
|