3516| 0
|
[高级教程] OLED显示屏 |
一、介绍基本简介 OLED(Organic Light-Emitting Diode,又称有机电激发光显示、有机发光半导体)是有机发光二极管的英文缩写。其是一种利用多层有机薄膜结构产生电致发光的器件,它很容易制作,只需要低的驱动电压,这些特征使得OLED在满足平面显示器的应用上显得非常突出。OLED显示屏比LCD更轻薄、亮度高、功耗低、响应快、清晰度高、柔性好、发光效率高。单色屏幕的像素是一个像素就是一个发光二极管。OLED是”自发光”,像素本身就是光源,所以对比度极高,显示效果很犀利,绝无朦朦胧胧、拖泥带水之感,深受爱好者追捧,可惜当前技术所限制,无法大尺寸化,价格比TFT液晶屏高得多。 几种原理图外形 二、使用实战准备硬件准备
oled.h [mw_shl_code=cpp,false]#ifndef __OLED_H #define __OLED_H #include "sys.h" #include "stdlib.h" //-----------------测试LED端口定义---------------- #define LED_ON GPIO_ResetBits(GPIOB,GPIO_Pin_8) #define LED_OFF GPIO_SetBits(GPIOB,GPIO_Pin_8) //-----------------OLED端口定义---------------- #define OLED_SCLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_5) #define OLED_SCLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_5)//SCL #define OLED_SDIN_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//DIN #define OLED_SDIN_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7) #define OLED_RST_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_0)//RES #define OLED_RST_Set() GPIO_SetBits(GPIOB,GPIO_Pin_0) #define OLED_DC_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_1)//RES #define OLED_CMD 0 //写命令 #define OLED_DATA 1 //写数据 #define u8 unsigned char #define u32 unsigned int void OLED_ClearPoint(u8 x,u8 y); void OLED_ColorTurn(u8 i); void OLED_DisplayTurn(u8 i); void I2C_Start(void); void I2C_Stop(void); void I2C_WaitAck(void); void Send_Byte(u8 dat); void OLED_WR_Byte(u8 dat,u8 mode); void OLED_DisPlay_On(void); void OLED_DisPlay_Off(void); void OLED_Refresh(void); void OLED_Clear(void); void OLED_DrawPoint(u8 x,u8 y); void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2); void OLED_DrawCircle(u8 x,u8 y,u8 r); void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1); void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1); void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1); void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1); void OLED_ScrollDisplay(u8 num,u8 space); void OLED_WR_BP(u8 x,u8 y); void OLED_ShowPicture(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[]); void OLED_Init(void); void yemian(void); #endif [/mw_shl_code] oled.c [mw_shl_code=c,false]#include "oled.h" #include "stdlib.h" #include "oledfont.h" #include "delay.h" u8 OLED_GRAM[144][8]; //反显函数 void OLED_ColorTurn(u8 i) { if(i==0) { OLED_WR_Byte(0xA6,OLED_CMD);//正常显示 } if(i==1) { OLED_WR_Byte(0xA7,OLED_CMD);//反色显示 } } //屏幕旋转180度 void OLED_DisplayTurn(u8 i) { if(i==0) { OLED_WR_Byte(0xC8,OLED_CMD);//正常显示 OLED_WR_Byte(0xA1,OLED_CMD); } if(i==1) { OLED_WR_Byte(0xC0,OLED_CMD);//反转显示 OLED_WR_Byte(0xA0,OLED_CMD); } } //起始信号 void I2C_Start(void) { OLED_SDIN_Set(); OLED_SCLK_Set(); OLED_SDIN_Clr(); OLED_SCLK_Clr(); } //结束信号 void I2C_Stop(void) { OLED_SCLK_Set(); OLED_SDIN_Clr(); OLED_SDIN_Set(); } //等待信号响应 void I2C_WaitAck(void) //测数据信号的电平 { OLED_SCLK_Set(); OLED_SCLK_Clr(); } //写入一个字节 void Send_Byte(u8 dat) { u8 i; for(i=0;i<8;i++) { OLED_SCLK_Clr();//将时钟信号设置为低电平 if(dat&0x80)//将dat的8位从最高位依次写入 { OLED_SDIN_Set(); } else { OLED_SDIN_Clr(); } OLED_SCLK_Set();//将时钟信号设置为高电平 OLED_SCLK_Clr();//将时钟信号设置为低电平 dat<<=1; } } //发送一个字节 //向SSD1306写入一个字节。 //mode:数据/命令标志 0,表示命令;1,表示数据; void OLED_WR_Byte(u8 dat,u8 mode) { I2C_Start(); Send_Byte(0x78); I2C_WaitAck(); if(mode){Send_Byte(0x40);} else{Send_Byte(0x00);} I2C_WaitAck(); Send_Byte(dat); I2C_WaitAck(); I2C_Stop(); } //开启OLED显示 void OLED_DisPlay_On(void) { OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能 OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵 OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕 } //关闭OLED显示 void OLED_DisPlay_Off(void) { OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能 OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵 OLED_WR_Byte(0xAF,OLED_CMD);//关闭屏幕 } //更新显存到OLED void OLED_Refresh(void) { u8 i,n; for(i=0;i<8;i++) { OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址 OLED_WR_Byte(0x00,OLED_CMD); //设置低列起始地址 OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址 for(n=0;n<128;n++) OLED_WR_Byte(OLED_GRAM[n],OLED_DATA); } } //清屏函数 void OLED_Clear(void) { u8 i,n; for(i=0;i<8;i++) { for(n=0;n<128;n++) { OLED_GRAM[n]=0;//清除所有数据 } } OLED_Refresh();//更新显示 } //画点 //x:0~127 //y:0~63 void OLED_DrawPoint(u8 x,u8 y) { u8 i,m,n; i=y/8; m=y%8; n=1<<m; OLED_GRAM[x]|=n; } //清除一个点 //x:0~127 //y:0~63 void OLED_ClearPoint(u8 x,u8 y) { u8 i,m,n; i=y/8; m=y%8; n=1<<m; OLED_GRAM[x]=~OLED_GRAM[x]; OLED_GRAM[x]|=n; OLED_GRAM[x]=~OLED_GRAM[x]; } //画线 //x:0~128 //y:0~64 void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2) { u8 i,k,k1,k2,y0; if((x1<0)||(x2>128)||(y1<0)||(y2>64)||(x1>x2)||(y1>y2))return ; if(x1==x2) //画竖线 { for(i=0;i<(y2-y1);i++) { OLED_DrawPoint(x1,y1+i); } } else if(y1==y2) //画横线 { for(i=0;i<(x2-x1);i++) { OLED_DrawPoint(x1+i,y1); } } else //画斜线 { k1=y2-y1; k2=x2-x1; k=k1*10/k2; for(i=0;i<(x2-x1);i++) { OLED_DrawPoint(x1+i,y1+i*k/10); } } } //x,y:圆心坐标 //r:圆的半径 void OLED_DrawCircle(u8 x,u8 y,u8 r) { int a, b,num; a = 0; b = r; while(2 * b * b >= r * r) { OLED_DrawPoint(x + a, y - b); OLED_DrawPoint(x - a, y - b); OLED_DrawPoint(x - a, y + b); OLED_DrawPoint(x + a, y + b); OLED_DrawPoint(x + b, y + a); OLED_DrawPoint(x + b, y - a); OLED_DrawPoint(x - b, y - a); OLED_DrawPoint(x - b, y + a); a++; num = (a * a + b * b) - r*r;//计算画的点离圆心的距离 if(num > 0) { b--; a--; } } } //在指定位置显示一个字符,包括部分字符 //x:0~127 //y:0~63 //size:选择字体 12/16/24 void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1) { u8 i,m,temp,size2,chr1; u8 y0=y; size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数 chr1=chr-' '; //计算偏移后的值 for(i=0;i<size2;i++) { if(size1==12) {temp=asc2_1206[chr1];} //调用1206字体 else if(size1==16) {temp=asc2_1608[chr1];} //调用1608字体 else if(size1==24) {temp=asc2_2412[chr1];} //调用2412字体 else return; for(m=0;m<8;m++) //写入数据 { if(temp&0x80)OLED_DrawPoint(x,y); else OLED_ClearPoint(x,y); temp<<=1; y++; if((y-y0)==size1) { y=y0; x++; break; } } } } //显示字符串 //x,y:起点坐标 //size1:字体大小 //*chr:字符串起始地址 void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1) { while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符! { OLED_ShowChar(x,y,*chr,size1); x+=size1/2; if(x>128-size1) //换行 { x=0; y+=2; } chr++; } } //m^n u32 OLED_Pow(u8 m,u8 n) { u32 result=1; while(n--) { result*=m; } return result; } 显示2个数字 x,y :起点坐标 len :数字的位数 size:字体大小 void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1) { u8 t,temp; for(t=0;t<len;t++) { temp=(num/OLED_Pow(10,len-t-1))%10; if(temp==0) { OLED_ShowChar(x+(size1/2)*t,y,'0',size1); } else { OLED_ShowChar(x+(size1/2)*t,y,temp+'0',size1); } } } //显示汉字 //x,y:起点坐标 //num:汉字对应的序号 void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1) { u8 i,m,n=0,temp,chr1; u8 x0=x,y0=y; u8 size3=size1/8; while(size3--) { chr1=num*size1/8+n; n++; for(i=0;i<size1;i++) { if(size1==16) {temp=Hzk1[chr1];}//调用16*16字体 else if(size1==24) {temp=Hzk2[chr1];}//调用24*24字体 else if(size1==32) {temp=Hzk3[chr1];}//调用32*32字体 else if(size1==64) {temp=Hzk4[chr1];}//调用64*64字体 else return; for(m=0;m<8;m++) { if(temp&0x01)OLED_DrawPoint(x,y); else OLED_ClearPoint(x,y); temp>>=1; y++; } x++; if((x-x0)==size1) {x=x0;y0=y0+8;} y=y0; } } } //num 显示汉字的个数 //space 每一遍显示的间隔 void OLED_ScrollDisplay(u8 num,u8 space) { u8 i,n,t=0,m=0,r; while(1) { if(m==0) { OLED_ShowChinese(128,24,t,16); //写入一个汉字保存在OLED_GRAM[][]数组中 t++; } if(t==num) { for(r=0;r<16*space;r++) //显示间隔 { for(i=0;i<144;i++) { for(n=0;n<8;n++) { OLED_GRAM[i-1][n]=OLED_GRAM[n]; } } OLED_Refresh(); } t=0; } m++; if(m==16){m=0;} for(i=0;i<144;i++) //实现左移 { for(n=0;n<8;n++) { OLED_GRAM[i-1][n]=OLED_GRAM[n]; } } OLED_Refresh(); } } //配置写入数据的起始位置 void OLED_WR_BP(u8 x,u8 y) { OLED_WR_Byte(0xb0+y,OLED_CMD);//设置行起始地址 OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD); OLED_WR_Byte((x&0x0f)|0x01,OLED_CMD); } //x0,y0:起点坐标 //x1,y1:终点坐标 //BMP[]:要写入的图片数组 void OLED_ShowPicture(u8 x0,u8 y0,u8 x1,u8 y1,u8 BMP[]) { u32 j=0; u8 x=0,y=0; if(y%8==0)y=0; else y+=1; for(y=y0;y<y1;y++) { OLED_WR_BP(x0,y); for(x=x0;x<x1;x++) { OLED_WR_Byte(BMP[j],OLED_DATA); j++; } } } //OLED的初始化 void OLED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能A端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOD3,6 GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7|GPIO_Pin_4); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能A端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOD3,6 GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_8); OLED_RST_Set(); delay_ms(100); OLED_RST_Clr();//复位 delay_ms(200); OLED_RST_Set(); OLED_DC_Clr(); OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel OLED_WR_Byte(0x00,OLED_CMD);//---set low column address OLED_WR_Byte(0x10,OLED_CMD);//---set high column address OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64) OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F) OLED_WR_Byte(0x00,OLED_CMD);//-not offset OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration OLED_WR_Byte(0x12,OLED_CMD); OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02) OLED_WR_Byte(0x02,OLED_CMD);// OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5) OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) OLED_WR_Byte(0xAF,OLED_CMD); OLED_Clear(); } //初始页面 void yemian(void) { OLED_Clear(); OLED_ShowChinese(0,0,7,16);//智 OLED_ShowChinese(18,0,8,16);//能 OLED_ShowChinese(36,0,9,16);//房 OLED_ShowChinese(54,0,10,16);//盗 OLED_ShowChinese(72,0,11,16);//门 OLED_Refresh(); delay_ms(500); } [/mw_shl_code] |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed