【GigaDevice GD32H759I-EVAL】Hardware I2C driver for OLED display
[Copy link]
Test the hardware I2C method to drive the OLED display.
1. Hardware
The hardware I2C uses the interface I2C1, and the pinout is as follows:
I2C1 PH4 and PB11 are on the PIN3 and PIN4 pins of the camera to facilitate external connection to the OLED display.
In the data sheet, the definition of the corresponding pin
2. Procedure
2.1、you are_i2c.c
#include "main.h"
#include "oled/codetab.h"
void i2c_write_nbytes(uint8_t *p_buffer, uint8_t write_address, uint8_t number_of_byte)
{
i2c_process_enum state = I2C_START;
uint32_t timeout = 0;
uint8_t end_flag = 0;
while(!end_flag) {
switch(state) {
case I2C_START:
/* configure slave address */
i2c_master_addressing(I2CX, OLED_ADDRESS, I2C_MASTER_TRANSMIT);
/* configure number of bytes to be transferred */
i2c_transfer_byte_number_config(I2CX, number_of_byte + 1);
/* clear I2C_TDATA register */
I2C_STAT(I2CX) |= I2C_STAT_TBE;
/* enable I2C automatic end mode in master mode */
i2c_automatic_end_enable(I2CX);
/* i2c master sends start signal only when the bus is idle */
while(i2c_flag_get(I2CX, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if(timeout < I2C_TIME_OUT) {
i2c_start_on_bus(I2CX);
timeout = 0;
state = I2C_SEND_ADDRESS;
} else {
/* timeout, bus reset */
i2c_bus_reset();
timeout = 0;
state = I2C_START;
printf("i2c bus is busy in page write!\n");
}
break;
case I2C_SEND_ADDRESS:
/* wait until the transmit data buffer is empty */
while((!i2c_flag_get(I2CX, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if(timeout < I2C_TIME_OUT) {
/* send the EEPROM's internal address to write to : only one byte address */
i2c_data_transmit(I2CX, write_address);
timeout = 0;
state = I2C_TRANSMIT_DATA;
} else {
timeout = 0;
state = I2C_START;
printf("i2c master sends address timeout in page write!\n");
}
break;
case I2C_TRANSMIT_DATA:
while(number_of_byte--) {
/* wait until TI bit is set */
while((!i2c_flag_get(I2CX, I2C_FLAG_TI)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if(timeout < I2C_TIME_OUT) {
/* while there is data to be written */
i2c_data_transmit(I2CX, *p_buffer);
/* point to the next byte to be written */
p_buffer++;
timeout = 0;
state = I2C_STOP;
} else {
/* wait TI timeout */
timeout = 0;
state = I2C_START;
printf("i2c master sends data timeout in page write!\n");
return ;
}
}
break;
case I2C_STOP:
/* wait until the stop condition is finished */
while((!i2c_flag_get(I2CX, I2C_FLAG_STPDET)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if(timeout < I2C_TIME_OUT) {
/* clear STPDET flag */
i2c_flag_clear(I2CX, I2C_FLAG_STPDET);
timeout = 0;
state = I2C_END;
end_flag = 1;
} else {
/* stop detect timeout */
timeout = 0;
state = I2C_START;
printf("i2c master sends stop signal timeout in page write!\n");
}
break;
default:
/* default status */
state = I2C_START;
end_flag = 1;
timeout = 0;
printf("i2c master sends start signal in page write!\n");
break;
}
}
}
void I2C_WriteByte(uint8_t addr,uint8_t data)
{
uint8_t data_buf[3];
data_buf[0] = data;
i2c_write_nbytes(data_buf, addr, 1);
}
void WriteCmd(unsigned char I2C_Command)
{
I2C_WriteByte(0x00, I2C_Command);
}
void WriteDat(unsigned char I2C_Data)
{
I2C_WriteByte(0x40, I2C_Data);
}
void OLED_WrCmd(unsigned char IIC_Command)
{
WriteCmd(IIC_Command);
}
void OLED_Init(void)
{
delay_1ms(100);
WriteCmd(0xAE); //display off
WriteCmd(0x20); //Set Memory Addressing Mode
WriteCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
WriteCmd(0xc8); //Set COM Output Scan Direction
WriteCmd(0x00); //---set low column address
WriteCmd(0x10); //---set high column address
WriteCmd(0x40); //--set start line address
WriteCmd(0x81); //--set contrast control register
WriteCmd(0xff); //亮度调节 0x00~0xff
WriteCmd(0xa1); //--set segment re-map 0 to 127
WriteCmd(0xa6); //--set normal display
WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
WriteCmd(0x3F); //
WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
WriteCmd(0xd3); //-set display offset
WriteCmd(0x00); //-not offset
WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
WriteCmd(0xf0); //--set divide ratio
WriteCmd(0xd9); //--set pre-charge period
WriteCmd(0x22); //
WriteCmd(0xda); //--set com pins hardware configuration
WriteCmd(0x12);
WriteCmd(0xdb); //--set vcomh
WriteCmd(0x40); //0x20,0.77xVcc
WriteCmd(0x8d); //--set DC-DC enable
WriteCmd(0x14); //
WriteCmd(0xaf); //--turn on oled panel
}
void OLED_SetPos(unsigned char x, unsigned char y)
{
WriteCmd(0xb0+y);
WriteCmd(((x&0xf0)>>4)|0x10);
WriteCmd((x&0x0f)|0x01);
}
void OLED_Fill(unsigned char fill_Data)//全屏填充
{
unsigned char m,n;
for(m=0;m<8;m++)
{
WriteCmd(0xb0+m); //page0-page1
WriteCmd(0x00); //low column start address
WriteCmd(0x10); //high column start address
for(n=0;n<128;n++)
{
WriteDat(fill_Data);
}
}
}
void OLED_CLS(void)//清屏
{
OLED_Fill(0xff);
}
void OLED_ON(void)
{
WriteCmd(0X8D); //设置电荷泵
WriteCmd(0X14); //开启电荷泵
WriteCmd(0XAF); //OLED唤醒
}
void OLED_OFF(void)
{
WriteCmd(0X8D); //设置电荷泵
WriteCmd(0X10); //关闭电荷泵
WriteCmd(0XAE); //OLED休眠
}
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
unsigned char c = 0,i = 0,j = 0;
switch(TextSize)
{
case 1:
{
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 126)
{
x = 0;
y++;
}
OLED_SetPos(x,y);
for(i=0;i<6;i++)
WriteDat(F6x8[c][i]);
x += 6;
j++;
}
}break;
case 2:
{
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 120)
{
x = 0;
y++;
}
OLED_SetPos(x,y);
for(i=0;i<8;i++)
WriteDat(F8X16[c*16+i]);
OLED_SetPos(x,y+1);
for(i=0;i<8;i++)
WriteDat(F8X16[c*16+i+8]);
x += 8;
j++;
}
}break;
}
}
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
unsigned char wm=0;
unsigned int adder=32*N;
OLED_SetPos(x , y);
for(wm = 0;wm < 16;wm++)
{
WriteDat(F16x16[adder]);
adder += 1;
}
OLED_SetPos(x,y + 1);
for(wm = 0;wm < 16;wm++)
{
WriteDat(F16x16[adder]);
adder += 1;
}
}
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
unsigned int j=0;
unsigned char x,y;
if(y1%8==0)
y = y1/8;
else
y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_SetPos(x0,y);
for(x=x0;x<x1;x++)
{
WriteDat(BMP[j++]);
}
}
}
void oled_test(void)
{
OLED_Init();
OLED_Fill(0x00);
OLED_ShowStr(0,0,"GD32H759 BOARD",2);
OLED_ShowStr(0,2,"I2C OLED TEST",2);
}
2.2、you are_i2c.h
#ifndef __OLED_I2C_H
#define __OLED_I2C_H
typedef enum {
I2C_START = 0,
I2C_SEND_ADDRESS,
I2C_RESTART,
I2C_TRANSMIT_DATA,
I2C_RELOAD,
I2C_STOP,
I2C_END
} i2c_process_enum;
#define I2C_TIME_OUT (uint32_t)(50000)
#define EEP_FIRST_PAGE 0x00
#define I2C_OK 0
#define I2C_FAIL 1
#define OLED_ADDRESS 0x78 //通过调整0R电阻,屏可以0x78和0x7A两个地址 -- 默认0x78
void I2C_Configuration(void);
void I2C_WriteByte(uint8_t addr,uint8_t data);
void WriteCmd(unsigned char I2C_Command);
void WriteDat(unsigned char I2C_Data);
void OLED_Init(void);
void OLED_SetPos(unsigned char x, unsigned char y);
void OLED_Fill(unsigned char fill_Data);
void OLED_CLS(void);
void OLED_ON(void);
void OLED_OFF(void);
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize);
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N);
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
void oled_test(void);
#endif
2.3、main.c
#include "main.h"
void cache_enable(void);
int main(void)
{
cache_enable();
systick_config();
init_usart(115200);
gpio_config();
i2c_config();
OLED_Init();
oled_test();
while(1)
{
}
}
void cache_enable(void)
{
/* enable i-cache */
SCB_EnableICache();
/* enable d-cache */
SCB_EnableDCache();
}
3. Operation Results
After downloading the program, the OLED displays
4. Attachments
Program source code:
|