文章目录
- 初始化代码
- SSD1305初始化代码
- SSD1315初始化代码(来源于商家赠送)
- 起动,停止,应答
- 启动
- 停止
- 应答
- 发送数据和命令
- 发送一个字节
- 发送1字节命令
- 发送1字节数据
- 设置行列位置
- 设置行起始位置
- 设置列起始位置
- 屏幕显示相关
- 清屏
- 指数
- 显示字符
- 显示数字
- 显示英文字符串
- 显示汉字
- 显示中文字符串
- 字库自己用软件根据需要自己做一个,我就不提供了。
本文代码是软件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~63I2C_Write_Command(0x00); //无偏移I2C_Write_Command(0x40); //设置起始行I2C_Write_Command(0xa1); //列地址127映射到SEG0I2C_Write_Command(0xC8); //--set COM scan directionI2C_Write_Command(0xda); //--set com pins hardware configurationI2C_Write_Command(0x02);I2C_Write_Command(0x81); //设置对比度I2C_Write_Command(0x7f);I2C_Write_Command(0xA4); //输出跟随RAMI2C_Write_Command(0xa6); //正常显示,不翻转A6/A7I2C_Write_Command(0xd5); //--set display clock divide ratio/oscillator frequencyI2C_Write_Command(0x80); //--set divide ratioI2C_Write_Command(0x8d); //--set chare pump enable/disableI2C_Write_Command(0x14); //--set(0x10) disableI2C_Write_Command(0xaf); //开启显示
SSD1315初始化代码(来源于商家赠送)
I2C_Write_Command(0xae); //--turn off oled panelI2C_Write_Command(0x00); //--set low column address
I2C_Write_Command(0x10); //--set high column addressI2C_Write_Command(0x40); //--set start line addressI2C_Write_Command(0xb0); //--set page addressI2C_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 displayI2C_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 dutyI2C_Write_Command(0xd3); //--set display offset
I2C_Write_Command(0x00); //--not offsetI2C_Write_Command(0xd5); //--set display clock divide ratio/oscillator frequency
I2C_Write_Command(0x80); //--set divide ratioI2C_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 Commandfor(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(); // 启动I2CI2C_SendByte(0x00); // 接下来发送的字节视为命令I2C_Ack(); // 应答I2C_SendByte(Data); // 写入1字节命令I2C_Ack(); // 应答I2C_Stop(); // I2C停止
}
发送1字节数据
void I2C_Write_Data(uchar Data)
{I2C_Start(); // 启动I2CI2C_SendByte(0x40); // 接下来发送的数据存入RAMI2C_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++;}
}