文章目录
本文代码是软件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++;
}
}