0.96寸oled使用IIC协议调试

三世轮回 提交于 2020-01-23 16:50:55

 

很久很久以前,我买了这样的一个屏,然后一直吃灰,今年过年回来调教一下!

翻阅很多网上的教程和代码,大家都差不多是相互借鉴的,重要的时大家的调试代码都是一样的,有些命令不清楚。翻阅了很多的资料,才写出了我觉得清楚明白的代码。

首先,需要了解这块屏幕的控制器,是ssd_1306,这其实是费了很多周折的,因为卖家的资料里面根本没有这个文档;

其次,是驱动这块屏幕的iic协议的信号周期,其实上面的文档里面就有;

最后,就是自己的调试了,我在下面的代码里面写的初始化函数里面有屏幕扫描的方向和数据写入的方式设置,代码中有注释。

下面就来说说重点,这块屏幕的IIC协议信号:

请自行下载上面提到的文档,然后找到8.1.5.1 I2C-bus Write data 这一节,下面对图中的信号进行说明

开始信号:sck置1,data从1跳0

从设备地址:前6位是固定的011110,第7位无所谓,第8位为0时为写模式,其实读模式用不到

控制器的回应信号:这里我们其实用不到,必须要用一个时钟信号来跳过这个信号,如果要用的话也是为了保证操作的稳定性,回应信号为1时说明之前的数据并未写入,回应信号为0时,说明之前的数据写入成功

控制字节:参考文档和下面代码中初始化的说明====1

控制器的回应信号:同上====2

数据字节:配合控制字节一起使用====3

控制器的回应信号:同上====4

重复上面的1、2、3、4步骤

停止信号:sck置1,data从0跳1

参考了这个文档,调试屏幕一次成功

时钟和串行输入函数

 

​
void oled12864_iic_clock()
{
	oled12864_scl=0;
	oled12864_scl=1;
	oled12864_scl=0;
}
void oled12864_serial(u8 cdata)
{
	u8 i=8;
	while(i--)
	{
		
		if(cdata & 0x80)
		{
			oled12864_sda=1;
		}
		else
		{
			oled12864_sda=0;
		}
		oled12864_iic_clock();
		cdata = cdata << 1;
	}
}

 命令和显示函数

void oled12864_operate(u8 command_display, u8 w_data)
{
	//start signal
	oled12864_scl=1;
	oled12864_sda=1;
	oled12864_sda=0;
	
	//slave address,contains WR bit
	oled12864_serial(0x78);
	oled12864_iic_clock();//give a plus to consume the ack signal
	
	oled12864_serial(command_display);
	oled12864_iic_clock();
	
	oled12864_serial(w_data);
	oled12864_iic_clock();
	
	//结束信号
	oled12864_scl=1;
	oled12864_sda=0;
	oled12864_sda=1;
}

 初始化函数,注释英文的,屏幕显示方式的代码已标注

void oled12864_init()
{
	oled12864_operate(d_command, 0x81);//set contrast control register
	oled12864_operate(d_command, 0xff);//contrast value
	
	//set entire display off, reset has done
	
	oled12864_operate(d_command, 0xa6);//set normal display
	
	oled12864_operate(d_command, 0xae);//turn off oled panel
	
	oled12864_operate(d_command, 0x20);//set memory addressing mode
	oled12864_operate(d_command, 0x01);//vertical addressing mode
	
	//set column start and end address, reset has done
	
	//set page start and end address, reset has done

	oled12864_operate(d_command, 0x40);//set start line
	
	oled12864_operate(d_command, 0xa8);//set multiples ratio(1to64)
	oled12864_operate(d_command, 0x3f);//1/64 duty
	

    //这里设置屏幕显示方式
	oled12864_operate(d_command, 0xa1);//set segment re-map
	oled12864_operate(d_command, 0xc8);//set com output scan direction
	oled12864_operate(d_command, 0xda);//set com pins hardware configuration
	oled12864_operate(d_command, 0x12);

	//set display offset, reset has done

	oled12864_operate(d_command, 0xd5);//set frequency
	oled12864_operate(d_command, 0xf0);//set divide ratio

	oled12864_operate(d_command, 0xd9);//set pre-charge period
	oled12864_operate(d_command, 0xf1);

	oled12864_operate(d_command, 0xdb);//set vcomh
	oled12864_operate(d_command, 0x40);

	oled12864_operate(d_command, 0x8d);//set chare pump enable/disable
	oled12864_operate(d_command, 0x14);//set(0x10) disable

	oled12864_operate(d_command, 0xaf);//turn on oled panel
}

写入函数

void oled12864_write_with_cp(u8 char_index, u8 column, u8 page)
{
	u16 i=char_index*16;
	u16 j=0;
	oled12864_set_column(column, column+8);
	oled12864_set_page(page, page+1);
	for(j=0;j<16;++j)
	{
		oled12864_operate(d_display, alpher[i+j]);
	}
}

void oled12864_set_column(u8 startc, u8 endc)
{
	oled12864_operate(d_command, 0x21);  //set column address
	oled12864_operate(d_command, startc);//set start column
	oled12864_operate(d_command, endc);  //set end column
}

void oled12864_set_page(u8 startp, u8 endp)
{
	oled12864_operate(d_command, 0x22);  //set page address
	oled12864_operate(d_command, startp);//set start page
	oled12864_operate(d_command, endp);  //set end page
}

屏幕扫描方向使用测试字符串,每个字节里只有一个点是亮的,自行观察:
0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01

以上都是屏幕的基础操作,还有高级的滚屏的操作,就这样吧,已经满足基本需求了

使用stc90c516rd+单片机,完整代码如下:

oled_head.h

#ifndef __OLED12864_H__
#define __OLED12864_H__

#define d_command 0x00
#define d_display 0x40

//配置引脚
#define oled12864_scl P20
#define oled12864_sda P21

#include"STC_FUNC.h"

void oled12864_iic_clock();
void oled12864_serial(u8 cdata);
void oled12864_operate(u8 command_display, u8 w_data);

void oled12864_init();
void oled12864_clear_screen();
void oled12864_set_column(u8 startc, u8 endc);
void oled12864_set_page(u8 startp, u8 endp);
void oled12864_write_with_cp(u8 char_index, u8 column, u8 page);

#endif

oled_head.c

#include"OLED_HEAD.h"

code u8 alpher[]={
	0x00,0x00,0x00,0x19,0x80,0x24,0x80,0x24,0x80,0x12,0x00,0x3F,0x00,0x20,0x00,0x00,/*"a",0*/
	0x10,0x00,0xF0,0x3F,0x00,0x11,0x80,0x20,0x80,0x20,0x00,0x11,0x00,0x0E,0x00,0x00,/*"b",1*/
	0x00,0x00,0x00,0x0E,0x00,0x11,0x80,0x20,0x80,0x20,0x80,0x20,0x00,0x11,0x00,0x00,/*"c",2*/
	0x00,0x00,0x00,0x1F,0x80,0x20,0x80,0x20,0x80,0x20,0x90,0x10,0xF0,0x3F,0x00,0x20,/*"d",3*/
	0x00,0x00,0x00,0x1F,0x80,0x24,0x80,0x24,0x80,0x24,0x80,0x24,0x00,0x17,0x00,0x00,/*"e",4*/
	0x00,0x00,0x80,0x20,0x80,0x20,0xE0,0x3F,0x90,0x20,0x90,0x20,0x20,0x00,0x00,0x00,/*"f",5*/
	0x00,0x00,0x00,0x6B,0x80,0x94,0x80,0x94,0x80,0x94,0x80,0x93,0x80,0x60,0x00,0x00,/*"g",6*/
	0x10,0x20,0xF0,0x3F,0x00,0x21,0x80,0x00,0x80,0x00,0x80,0x20,0x00,0x3F,0x00,0x20,/*"h",7*/
	0x00,0x00,0x80,0x20,0x98,0x20,0x98,0x3F,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,/*"i",8*/
	0x00,0x00,0x00,0xC0,0x00,0x80,0x80,0x80,0x98,0x80,0x98,0x7F,0x00,0x00,0x00,0x00,/*"j",9*/
	0x10,0x20,0xF0,0x3F,0x00,0x24,0x00,0x06,0x80,0x29,0x80,0x30,0x80,0x20,0x00,0x00,/*"k",10*/
	0x00,0x00,0x10,0x20,0x10,0x20,0xF8,0x3F,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,/*"l",11*/
	0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0x00,0x80,0x3F,0x80,0x20,0x80,0x00,0x00,0x3F,/*"m",12*/
	0x80,0x20,0x80,0x3F,0x00,0x21,0x80,0x00,0x80,0x00,0x80,0x20,0x00,0x3F,0x00,0x20,/*"n",13*/
	0x00,0x00,0x00,0x1F,0x80,0x20,0x80,0x20,0x80,0x20,0x80,0x20,0x00,0x1F,0x00,0x00,/*"o",14*/
	0x80,0x80,0x80,0xFF,0x00,0x91,0x80,0x20,0x80,0x20,0x00,0x11,0x00,0x0E,0x00,0x00,/*"p",15*/
	0x00,0x00,0x00,0x0E,0x00,0x11,0x80,0x20,0x80,0x20,0x00,0x91,0x80,0xFF,0x00,0x80,/*"q",16*/
	0x80,0x20,0x80,0x20,0x80,0x3F,0x00,0x21,0x80,0x20,0x80,0x00,0x80,0x01,0x00,0x00,/*"r",17*/
	0x00,0x00,0x00,0x33,0x80,0x24,0x80,0x24,0x80,0x24,0x80,0x24,0x80,0x19,0x00,0x00,/*"s",18*/
	0x00,0x00,0x80,0x00,0x80,0x00,0xE0,0x1F,0x80,0x20,0x80,0x20,0x00,0x10,0x00,0x00,/*"t",19*/
	0x80,0x00,0x80,0x1F,0x00,0x20,0x00,0x20,0x00,0x20,0x80,0x10,0x80,0x3F,0x00,0x20,/*"u",20*/
	0x80,0x00,0x80,0x03,0x80,0x0C,0x00,0x30,0x80,0x0C,0x80,0x03,0x80,0x00,0x00,0x00,/*"v",21*/
	0x80,0x01,0x80,0x0E,0x00,0x30,0x80,0x0C,0x80,0x07,0x00,0x38,0x80,0x06,0x80,0x01,/*"w",22*/
	0x00,0x00,0x80,0x20,0x80,0x31,0x80,0x0E,0x00,0x2E,0x80,0x31,0x80,0x20,0x00,0x00,/*"x",23*/
	0x80,0x00,0x80,0x81,0x80,0x86,0x00,0x78,0x00,0x18,0x80,0x06,0x80,0x01,0x80,0x00,/*"y",24*/
	0x00,0x00,0x80,0x21,0x80,0x30,0x80,0x2C,0x80,0x22,0x80,0x21,0x80,0x30,0x00,0x00,/*"z",25*/
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",26*/
};
void oled12864_iic_clock()
{
	oled12864_scl=0;
	oled12864_scl=1;
	oled12864_scl=0;
}
void oled12864_serial(u8 cdata)
{
	u8 i=8;
	while(i--)
	{
		
		if(cdata & 0x80)
		{
			oled12864_sda=1;
		}
		else
		{
			oled12864_sda=0;
		}
		oled12864_iic_clock();
		cdata = cdata << 1;
	}
}
	
void oled12864_operate(u8 command_display, u8 w_data)
{
	//start signal
	oled12864_scl=1;
	oled12864_sda=1;
	oled12864_sda=0;
	
	//slave address,contains WR bit
	oled12864_serial(0x78);
	oled12864_iic_clock();//give a plus to consume the ack signal
	
	oled12864_serial(command_display);
	oled12864_iic_clock();
	
	oled12864_serial(w_data);
	oled12864_iic_clock();
	
	//结束信号
	oled12864_scl=1;
	oled12864_sda=0;
	oled12864_sda=1;
}

void oled12864_init()
{
	oled12864_operate(d_command, 0x81);//set contrast control register
	oled12864_operate(d_command, 0xff);//contrast value
	
	//set entire display off, reset has done
	
	oled12864_operate(d_command, 0xa6);//set normal display
	
	oled12864_operate(d_command, 0xae);//turn off oled panel
	
	oled12864_operate(d_command, 0x20);//set memory addressing mode
	oled12864_operate(d_command, 0x01);//vertical addressing mode
	
	//set column start and end address, reset has done
	
	//set page start and end address, reset has done

	oled12864_operate(d_command, 0x40);//set start line
	
	oled12864_operate(d_command, 0xa8);//set multiples ratio(1to64)
	oled12864_operate(d_command, 0x3f);//1/64 duty
	
	oled12864_operate(d_command, 0xa1);//set segment re-map
	oled12864_operate(d_command, 0xc8);//set com output scan direction
	oled12864_operate(d_command, 0xda);//set com pins hardware configuration
	oled12864_operate(d_command, 0x12);

	//set display offset, reset has done

	oled12864_operate(d_command, 0xd5);//set frequency
	oled12864_operate(d_command, 0xf0);//set divide ratio

	oled12864_operate(d_command, 0xd9);//set pre-charge period
	oled12864_operate(d_command, 0xf1);

	oled12864_operate(d_command, 0xdb);//set vcomh
	oled12864_operate(d_command, 0x40);

	oled12864_operate(d_command, 0x8d);//set chare pump enable/disable
	oled12864_operate(d_command, 0x14);//set(0x10) disable

	oled12864_operate(d_command, 0xaf);//turn on oled panel
}

void oled12864_set_column(u8 startc, u8 endc)
{
	oled12864_operate(d_command, 0x21);  //set column address
	oled12864_operate(d_command, startc);//set start column
	oled12864_operate(d_command, endc);  //set end column
}

void oled12864_set_page(u8 startp, u8 endp)
{
	oled12864_operate(d_command, 0x22);  //set page address
	oled12864_operate(d_command, startp);//set start page
	oled12864_operate(d_command, endp);  //set end page
}

void oled12864_write_with_cp(u8 char_index, u8 column, u8 page)
{
	u16 i=char_index*16;
	u16 j=0;
	oled12864_set_column(column, column+8);
	oled12864_set_page(page, page+1);
	for(j=0;j<16;++j)
	{
		oled12864_operate(d_display, alpher[i+j]);
	}
}

void oled12864_clear_screen()
{
	u8 row,collown;
	for(row=0;row<8;++row)
	{
		for(collown=0;collown<128;++collown)
		{
			oled12864_operate(d_display,0x00);
		}
	}
}

main.c

#include"STC_FUNC.h"
#include"OLED_HEAD.h"

/**
the characters use 8x16(w.h) size
**/
void main()
{
	u8 i,j,k;
	u8 str[]="abcdefgh";
	P0=0;P1=0;P2=0;P3=0;
	oled12864_init();
	oled12864_clear_screen();
	for(i=0;i<26;++i)
	{
		oled12864_write_with_cp(i,i,2);
		clear_watch_dog();
		delay_ms(20);
		oled12864_write_with_cp(26,i,2);
	}
	while(1)
	{
		clear_watch_dog();
	}
}

 stc_fun.h

#ifndef __STC_FUNC__
#define __STC_FUNC__

#include "STC_HEAD.h"

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;

void clear_watch_dog();
void delay_us(u8 times);
void delay_ms(u8 times);
void delay_s(u8 times);

#endif

stc_fun.c

#include "STC_FUNC.h"

void clear_watch_dog()
{
	WDT_CONTR = WDT_CONTR | 0x10;
}

void delay_us(u8 times)
{
	for(;times!=0;--times);
}

void delay_ms(u8 times)
{
	u8 i;
	for(;times!=0;--times)
		for(i=0;i<4;++i)
			delay_us(250);
}

void delay_s(u8 times)
{
	u8 i;
	for(;times!=0;--times)
		for(i=0;i<4;++i)
			delay_ms(250);
}

头文件为stc_head.h,根据单片机而异,不予展示了

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!