前言: 很长一段时间内用OLED的机会都很少,即使用了也是参考的大牛的代码,最近迫不得已又仔细研究了一遍。记下来省的忘记。 手头上用到的是0.61寸的OLED分辨率是96*16,也就是横向有96个点,纵向有16个点,贴上这个的尺寸图 我并没有看太多的资料,网上的资料也非常多,大多数是将SSD1306的,这里就简单通俗的记录一下,拿这个96*16的为例子,SSD把纵向(y方向)做了分页处理,每8个像素点作为一组(8个像素点=8个bit=一个字节),那么对于y方向有16个点的那就是分成两页了,从0开始就是0和1。对于其他分辨率的也一样,向上加就对了。在驱动的时候最常规的方法是从左到右,从上到下。值得注意的是不同型号可能取模的方式不一样,有点高位在前也有的低位在前,我现在用的是低位在前,这个手册里面还是有说的。下面附上取模的软件和配置选项: 软件用的是:PCtoLCD2002 取模配置如下: 效果图: 最后附上详细的代码(理论上支持所有的SSD1306控制器)我在12832也试过没有问题,需要自行修改宏定义,代码都有详细的中文注释: #include 'fy_oled12832.h'#include 'fy_oledfont.h' #define OLED_IIC_SCL_PIN GPIO_PIN_4#define OLED_IIC_SCL_L() GPIO_WriteLow(OLED_IIC_SCL_PORT,OLED_IIC_SCL_PIN) //SCLIIC接口的时钟信号#define OLED_IIC_SCL_H() GPIO_WriteHigh(OLED_IIC_SCL_PORT,OLED_IIC_SCL_PIN)//PB4#define OLED_IIC_SDA_PORT GPIOB#define OLED_IIC_SDA_PIN GPIO_PIN_5#define OLED_IIC_SDA_L() GPIO_WriteLow(OLED_IIC_SDA_PORT,OLED_IIC_SDA_PIN) //SDA IIC接口的数据信号#define OLED_IIC_SDA_H() GPIO_WriteHigh(OLED_IIC_SDA_PORT,OLED_IIC_SDA_PIN)//PB5 /*96*16像素 x[0-95]y[0-15]注意:y方向分成了两页 每页8个像素点 刚好是一个字节*/ #define Max_x 96#define Max_y 2 #define OLED_IIC_SCL_PORT GPIOB #define OLED_CMD 0X00 //写命令#define OLED_DATA 0X40 //写数据static void Oled_IIC_Configuration(void){ GPIO_Init(OLED_IIC_SCL_PORT,OLED_IIC_SCL_PIN,GPIO_MODE_OUT_PP_LOW_FAST);//设置PB4为推挽输出 GPIO_Init(OLED_IIC_SDA_PORT,OLED_IIC_SDA_PIN,GPIO_MODE_OUT_PP_LOW_FAST);//设置PB5为推挽输出 }//IIC Startstatic void Oled_IIC_Start(void){ OLED_IIC_SCL_H(); OLED_IIC_SDA_H(); OLED_IIC_SDA_L(); OLED_IIC_SCL_L();}//IIC Stopstatic void Oled_IIC_Stop(void){ OLED_IIC_SCL_L(); OLED_IIC_SDA_L(); OLED_IIC_SDA_H(); OLED_IIC_SCL_H() ;}// IIC Send bytestatic void Oled_IIC_SendByte(u8 dat){ u8 i; for(i=0;i<8;i++) { OLED_IIC_SCL_L(); if(dat & 0x80) OLED_IIC_SDA_H(); else OLED_IIC_SDA_L(); dat<<=1; OLED_IIC_SCL_H(); } OLED_IIC_SCL_L(); OLED_IIC_SCL_H();}//OLED写一个字节 //dat:写入的字节 //cmd:命令或者数据void Oled_WriteByte(u8 dat,u8 cmd){ Oled_IIC_Start(); Oled_IIC_SendByte(0x78); Oled_IIC_SendByte(cmd); Oled_IIC_SendByte(dat); Oled_IIC_Stop();}//坐标设置void Oled_SetPos(u8 x, u8 y) { Oled_WriteByte(0xb0+y,OLED_CMD); Oled_WriteByte(((x&0xf0)>>4)|0x10,OLED_CMD); Oled_WriteByte((x&0x0f),OLED_CMD); } //清屏 void Oled_Clear(void) { u8 i,n; for(i=0;i<Max_y;i++) //有多少个页 { Oled_WriteByte (0xb0+i,OLED_CMD); //设置页地址(0~1) Oled_WriteByte (0x00,OLED_CMD); //设置显示位置—列低地址 Oled_WriteByte (0x10,OLED_CMD); //设置显示位置—列高地址 for(n=0;n<Max_x;n++) Oled_WriteByte(0,OLED_DATA); //每页有多少列 } //更新显示}//在指定位置显示一个字符void Oled_ShowChar(u8 x,u8 y,u8 chr){ u8 c=0,i=0; c=chr-' ';//得到偏移后的值 if(x>Max_x-1) { x=0; y++; if(y>Max_y-1) return; }//这里的y代表的页地址 6*8的字符所以页加一 Oled_SetPos(x,y); for(i=0;i<6;i++)//6*8的字符 点阵占6列没列8个像素点(一个字节),也就是一页的6列 Oled_WriteByte(F6x8[c][i],OLED_DATA);}//显示一个字符号串void Oled_ShowString(u8 x,u8 y,u8 *chr){ u8 j=0; if(y>Max_y-1) return; while (chr[j]!='\0') { Oled_ShowChar(x,y,chr[j]); x+=6;//6*8的字符 点阵占6列所以加6 if(x>Max_x-6){x=0;y++;} j++; }}//显示汉字 16*16的汉字void Oled_ShowCHinese(u8 x,u8 y,u8 no){ u8 t; Oled_SetPos(x,y); for(t=0;t<16;t++)//先写第一页 { Oled_WriteByte(Hzk[2*no][t],OLED_DATA); } Oled_SetPos(x,y+1); for(t=0;t<16;t++)//再写第二页 { Oled_WriteByte(Hzk[2*no+1][t],OLED_DATA); } }//初始化SSD1306 void Oled_Configuration(void){ Oled_IIC_Configuration(); Delay_ms(100); Oled_WriteByte(0xAE,OLED_CMD);//--display off Oled_WriteByte(0x00,OLED_CMD);//---set low column address Oled_WriteByte(0x10,OLED_CMD);//---set high column address Oled_WriteByte(0x40,OLED_CMD);//--set start line address Oled_WriteByte(0xB0,OLED_CMD);//--set page address Oled_WriteByte(0x81,OLED_CMD); // contract control Oled_WriteByte(0xFF,OLED_CMD);//--128 Oled_WriteByte(0xA1,OLED_CMD);//set segment remap Oled_WriteByte(0xA6,OLED_CMD);//--normal / reverse Oled_WriteByte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64) Oled_WriteByte(0x0F,OLED_CMD);//--1/16 duty Oled_WriteByte(0xC8,OLED_CMD);//Com scan direction Oled_WriteByte(0xD3,OLED_CMD);//-set display offset Oled_WriteByte(0x00,OLED_CMD);// Oled_WriteByte(0xD5,OLED_CMD);//set osc division Oled_WriteByte(0x80,OLED_CMD);// Oled_WriteByte(0xD9,OLED_CMD);//set pre-charge period Oled_WriteByte(0x22,OLED_CMD);// Oled_WriteByte(0xDA,OLED_CMD);//set COM pins Oled_WriteByte(0x02,OLED_CMD);// Oled_WriteByte(0xDB,OLED_CMD);//set vcomh Oled_WriteByte(0x40,OLED_CMD);// Oled_WriteByte(0x8D,OLED_CMD);//set charge pump enable Oled_WriteByte(0x14,OLED_CMD);// Oled_WriteByte(0xAF,OLED_CMD);//--turn on oled panel} void Oled_TEST(void){ Delay_ms(200); //延时200ms Oled_Configuration(); //OLED初始化 Delay_ms(200); //延时200ms Oled_Clear(); //清屏 Delay_ms(200); //延时200ms while (1) { Oled_Clear();//清屏 Oled_ShowString(0,0,'012345678ABCDEFGQWERTYUIOO');//显示数字 Delay_ms(2000); Oled_Clear(); //清屏 Oled_ShowCHinese(8,0,0); //显示汉字“火” Oled_ShowCHinese(24,0,1); //显示汉字“星” Oled_ShowCHinese(40,0,2); //显示汉字“科” Oled_ShowCHinese(56,0,3); //显示汉字“技” Delay_ms(2000); } } 字库:
测试例程: void Oled_TEST(void){ Delay_ms(200); //延时200ms Oled_Configuration(); //OLED初始化 Delay_ms(200); //延时200ms Oled_Clear(); //清屏 Delay_ms(200); //延时200ms while (1) { Oled_Clear();//清屏 Oled_ShowString(0,0,'012345678ABCDEFGQWERTYUIOO');//显示字符 Delay_ms(2000); Oled_Clear(); //清屏 Oled_ShowCHinese(8,0,0); //显示汉字“火” Oled_ShowCHinese(24,0,1); //显示汉字“星” Oled_ShowCHinese(40,0,2); //显示汉字“科” Oled_ShowCHinese(56,0,3); //显示汉字“技” Delay_ms(2000); } } 至此完毕! By Urien 2017年11月12日 13:30:22 |
|
来自: goodwangLib > 《OLED》