51-OLED显示代码


本文代码是软件IIC驱动的OLED,如果对启动,停止,应答,发送一个字节的代码稍加修改,即可适配硬件IIC, 新定义RD8T36P48使用USCI0的TWI功能点亮OLED 这个链接的代码就是从本文软件IIC修改为硬件IIC使用的。

初始化代码

SSD1305初始化代码

	I2C_Write_Command(0xa8); //set multiples ratio(1to64)
    I2C_Write_Command(0x3f);

    I2C_Write_Command(0xd3); //垂直偏移量 0~63
    I2C_Write_Command(0x00); //无偏移

    I2C_Write_Command(0x40); //设置起始行

    I2C_Write_Command(0xa1); //列地址127映射到SEG0

    I2C_Write_Command(0xC8); //--set COM scan direction

    I2C_Write_Command(0xda); //--set com pins hardware configuration
    I2C_Write_Command(0x02);

    I2C_Write_Command(0x81); //设置对比度
    I2C_Write_Command(0x7f);

    I2C_Write_Command(0xA4); //输出跟随RAM

    I2C_Write_Command(0xa6); //正常显示,不翻转A6/A7

    I2C_Write_Command(0xd5); //--set display clock divide ratio/oscillator frequency
    I2C_Write_Command(0x80); //--set divide ratio

    I2C_Write_Command(0x8d); //--set chare pump enable/disable
    I2C_Write_Command(0x14); //--set(0x10) disable

	I2C_Write_Command(0xaf); //开启显示

SSD1315初始化代码(来源于商家赠送)

I2C_Write_Command(0xae);	//--turn off oled panel

I2C_Write_Command(0x00);	//--set low column address
I2C_Write_Command(0x10);	//--set high column address

I2C_Write_Command(0x40);	//--set start line address

I2C_Write_Command(0xb0);	//--set page address

I2C_Write_Command(0x81);	//--set contrast control register
I2C_Write_Command(0xff);

I2C_Write_Command(0xa1);	//--set segment re-map 127 to 0   a0:0 to seg127
I2C_Write_Command(0xa6);	//--set normal display

I2C_Write_Command(0xc9);	//--set com(N-1)to com0  c0:com0 to com(N-1)

I2C_Write_Command(0xa8);	//--set multiples ratio(1to64)
I2C_Write_Command(0x3f);	//--1/64 duty

I2C_Write_Command(0xd3);	//--set display offset
I2C_Write_Command(0x00);	//--not offset

I2C_Write_Command(0xd5);	//--set display clock divide ratio/oscillator frequency
I2C_Write_Command(0x80);	//--set divide ratio

I2C_Write_Command(0xd9);	//--set pre-charge period
I2C_Write_Command(0xf1);

I2C_Write_Command(0xda);	//--set com pins hardware configuration
I2C_Write_Command(0x12);

I2C_Write_Command(0xdb);	//--set vcomh
I2C_Write_Command(0x40);

I2C_Write_Command(0x8d);	//--set chare pump enable/disable
I2C_Write_Command(0x14);	//--set(0x10) disable
//I2C_Write_Command(0x10);	//--set(0x10) disable
I2C_Write_Command(0xaf);	//--turn on oled panel

起动,停止,应答

启动

void I2C_Start()
{
    SDA = 1;
    //	uDelay(3);
    SCL = 1;
    //	uDelay(3);
    SDA = 0;
    SCL = 0;
    //	uDelay(3);
    I2C_SendByte(0x78); // 0111 1000,写
    I2C_Ack();
}

停止

void I2C_Stop()
{
    SCL = 1;
    //	uDelay(5);
    SDA = 0;
    //	uDelay(5);
    SDA = 1;
    //	uDelay(5);
}

应答

void I2C_Ack()
{
    SDA = 1;
    //	uDelay(3);
    SCL = 1;
    //	uDelay(3);
    SCL = 0;
    //	uDelay(3);
}

发送数据和命令

发送一个字节

void I2C_SendByte(uchar cmd)
{
    uchar i; // Send Command

    for(i=0;i<8;i++)
    {
        SDA = (cmd<<i)&0x80?1:0;
        SCL = 1;//让从机从SDA读取数据
        SCL = 0;//主机往SDA放数据
    }
}

发送1字节命令

void I2C_Write_Command(uchar Data)
{
    I2C_Start(); // 启动I2C
    I2C_SendByte(0x00);  // 接下来发送的字节视为命令
    I2C_Ack();   // 应答
    I2C_SendByte(Data);  // 写入1字节命令
    I2C_Ack();   // 应答
    I2C_Stop();  // I2C停止
}

发送1字节数据

void I2C_Write_Data(uchar Data)
{
    I2C_Start(); // 启动I2C
    I2C_SendByte(0x40);  // 接下来发送的数据存入RAM
    I2C_Ack();   // 应答
    I2C_SendByte(Data);  // 写入1字节数据
    I2C_Ack();   // 应答
    I2C_Stop();  // I2C停止
}

设置行列位置

设置行起始位置

//共8页,每个字符占2页,设置页面时需注意
void Page_set(uchar page)
{
	I2C_Write_Command(0xb0+(page-1));
}

设置列起始位置

//物理上总共128列,但本程序将其处理成了16列,每个汉字占2列,英文和字符占1列
void Column_set(uchar column){
	column = (column-1)*8;
    I2C_Write_Command(0x10|(column>>4));    //设置列地址高位
    I2C_Write_Command(0x00|(column&0x0f));   //设置列地址低位  
}

屏幕显示相关

清屏

可以选择清屏样式,比如全亮/灭,或者其他的图形码,一般只设置亮灭,配合正向显示和反向显示实现清屏

void OLED_fill(uchar color)
{
    uchar page,i;
    for(page=1;page<9;page++) //页循环,页1~8
    { 
	  Page_set(page);
	  Column_set(1);      
	  for(i=0;i<128;i++)    //每页有128列,循环128次
		{
		  I2C_Write_Data(color);
		}
    }
}

指数

主要用于将一长串数字获取到对应的每位数值,要注意范围,x和y都是uint类型,其结果也是uint类型

uint OLED_Pow(uint X, uint Y)
{
    uint Result = 1;
    while (Y--)
    {
        Result *= X;
    }
    return Result;
}

显示字符

这部分代码我对我需要的功能做了适配,主要原因是当时用的STC89C52RC单片机,ROM总共只有8K,比较珍贵,而字库差不多能占一半,所以对字库不需要的字形给删除了,然后就导致字符的顺序和ASCII的顺序不一样,需要对其索引调整一下。
如果你要使用的话也可以像我一样,调整这部分代码保证能根据字符的ASCII对应上字库列表的索引。

void OLED_ShowChar(uchar page, uchar column, uchar ch)
{
	uchar i;
	uchar j;
	if (ch>='a')
		ch += 41 - 'a';
	else if (ch>='A')
		ch += 15 - 'A';
	else{
		switch (ch)//处理个别特殊符号
		{
			case ':' : ch = 11;break;
			case '.' : ch = 10;break;
			case '+' : ch = 12;break;
			case '-' : ch = 13;break;
			case '%' : ch = 14;break;
			default:ch -= '0';break;
		}
	}
	
	for (j = 0;j<2;j++)//两行,循环2次
	{
		Column_set(column);
		Page_set(page + j);
		for (i=8*j;i<8*j+8;i++)
			I2C_Write_Data(font_1608[ch][i]);
	}
}

字符库示例

code font_1608[][16] = {//ASCII码表顺序,行尾注释数字为从空格算起的偏移量
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,/*"0",16*/
0x00,0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,/*"1",17*/
0x00,0x70,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,/*"2",18*/
0x00,0x30,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x18,0x20,0x21,0x21,0x22,0x1C,0x00,/*"3",19*/}

显示数字

由于num参数的类型是uint,所以最大值为65535,则length的最大值是5,这点需要注意

void OLED_ShowNumber(uchar page, uchar column, uint num, uchar length)
{
    uchar i;
    for (i = 0; i < length; i++)
    {
        OLED_ShowChar(page, column + i, num / OLED_Pow(10, length - i - 1) % 10 + '0'); //数字0123456789,最后的'0'把数字转为对应的字符
    }
}

显示英文字符串

主要是把字符串当作数组获取每一个字符,再调用字符显示函数去显示。

void OLED_ShowString(uchar page, uchar column, char *String)
{
    uchar i = 0;
    while(String[i] != '\0')//判断到没到字符串结尾
    {
        OLED_ShowChar(page, column+i, String[i]);
        i++;
    }
}

显示汉字

汉字需要通过取模软件获取字形点位,不多介绍
index : 在汉字字符表中的位置

void OLED_ShowChinese(uint page, uint column,uchar index)
{
    uchar i;
    uchar j;
	for (j=0;j<2;j++)
	{
		Page_set(page+j);
		Column_set(column);
		for (i=0;i<16;i++)
			I2C_Write_Data(chdata[index*2+j][i]);
	}
}

中文字库示例

code chdata[][16] = {
	// 温(0) 土(1)
	{0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00},
	{0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00},/*"温",0*/
	{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00},
	{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00},/*"土",1*/
};

显示中文字符串

同样是调用显示单个汉字的函数构成的。
由于不好字节放字符,所以使用多个索引构成的字符串。

void OLED_ShowChineseString(uchar page, uchar column, char *String)
{
    uchar i = 0;
    while(String[i] != '\0')//判断到没到字符串结尾
    {
        OLED_ShowChinese(page, column+i*2, String[i]-'0');
        i++;
    }
}

字库自己用软件根据需要自己做一个,我就不提供了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值