555|2

441

帖子

3

TA的资源

纯净的硅(高级)

楼主
 

【兆易GD32H759I-EVAL】硬件I2C驱动OLED显示屏 [复制链接]

 

 

测试硬件I2C方式驱动OLED显示屏。

 

一、硬件部分

 

硬件I2C使用了接口I2C1,引脚部分如下:

 

I2C1 PH4和PB11在摄像头的PIN3和PIN4引脚,方便外部连接OLED显示屏。

数据手册中,相应引脚的定义

 

 

二、程序部分

 

2.1、oled_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、oled_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();
}

 

三、运行结果

 

下载程序后,OLED显示

 

四、附件

 

程序源码:

gd32h759_prj_oled.rar (823.23 KB, 下载次数: 3)

最新回复

ssd1306的地址是0x3C,不知道GD的i2c硬件是不是需要传入移位后的地址。 感谢楼主大佬提供源码,新手确实是个好的学习资源。   详情 回复 发表于 2024-6-2 08:29
点赞 关注(1)
 
 

回复
举报

755

帖子

5

TA的资源

纯净的硅(高级)

沙发
 

楼主分享的内容非常详细,对新手有很强的指导价值,非常感谢楼主的分享

 
 
 

回复

6992

帖子

11

TA的资源

版主

板凳
 

ssd1306的地址是0x3C,不知道GD的i2c硬件是不是需要传入移位后的地址。

感谢楼主大佬提供源码,新手确实是个好的学习资源。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表