【兆易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显示
四、附件
程序源码:
|