简介 OLED:Organic Light-Emitting Diode,即有机发光二极管,又称为有机电激光显示(Organic Electroluminesence Display,OELD)。
OLED 由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。
第一步初始化硬件iic
?/** ? * @brief ?I2C_Configuration,初始化硬件IIC引脚 ? * @param ?无 ? * @retval 无 ? */
void I2C_Configuration(void) { ?? ?I2C_InitTypeDef ?I2C_InitStructure; ?? ?GPIO_InitTypeDef ?GPIO_InitStructure;?
?? ?/*I2C1外设时钟使能 */ ?? ?OLED_I2C_CLK_INIT(OLED_I2C_CLK,ENABLE); ?? ? ?? ?/*I2C1外设GPIO时钟使能 */ ?? ?RCC_APB2PeriphClockCmd(OLED_I2C_SCL_GPIO_CLK | OLED_I2C_SDA_GPIO_CLK,ENABLE);
?? ? /* I2C_SCL、I2C_SDA*/ ? GPIO_InitStructure.GPIO_Pin = OLED_I2C_SCL_PIN; ? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;?? ? ? ? ? // 开漏输出 ? GPIO_Init(OLED_I2C_SCL_GPIO_PORT, &GPIO_InitStructure); ?? ? ? GPIO_InitStructure.GPIO_Pin = OLED_I2C_SDA_PIN; ? GPIO_Init(OLED_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);?? ? ?? ? ?? ? ?? ?/* I2C 配置 */ ? I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;?? ? ? I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;?? ?/* 高电平数据稳定,低电平数据变化 SCL 时钟线的占空比 */ ? I2C_InitStructure.I2C_OwnAddress1 =OLED_ADDRESS; ? ?//主机的I2C地址 ? I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;?? ? ? I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;?? ?/* I2C的寻址模式 */ ? I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 通信速率 */ ?? ? I2C_Init(OLED_I2C, &I2C_InitStructure);?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* I2C1 初始化 */ ?? ?I2C_Cmd(OLED_I2C, ENABLE); ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 使能 I2C1 */ ?? ? }
第二步进行写操作,分别为写数据和写命令
?/** ? * @brief ?I2C_WriteByte,向OLED寄存器地址写一个byte的数据 ? * @param ?addr:寄存器地址 ?? ?*?? ??? ??? ??? ??? ?data:要写入的数据 ? * @retval 无 ? */
void I2C_WriteByte(uint8_t addr,uint8_t data) { ? while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); ?? ? ?? ?I2C_GenerateSTART(I2C1, ENABLE);//开启I2C1 ?? ?while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/
?? ?I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//器件地址 -- 默认0x78 ?? ?while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
?? ?I2C_SendData(I2C1, addr);//寄存器地址 ?? ?while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
?? ?I2C_SendData(I2C1, data);//发送数据 ?? ?while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); ?? ? ?? ?I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C1总线 }
?/** ? * @brief ?WriteCmd,向OLED写入命令 ? * @param ?I2C_Command:命令代码 ? * @retval 无 ? */
void WriteCmd(unsigned char I2C_Command)//写命令 { ?? ?I2C_WriteByte(0x00, I2C_Command);//为什么要从0x00开始,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????????//因为寄存器写入命令的地址在0x00,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????//同理下面写数据一样,只是地址不同 }
?/** ? * @brief ?WriteDat,向OLED写入数据 ? * @param ?I2C_Data:数据 ? * @retval 无 ? */ void WriteDat(unsigned char I2C_Data)//写数据 { ?? ?I2C_WriteByte(0x40, I2C_Data); }
第三步对oled进行初始化
/** ? * @brief ?OLED_Init,初始化OLED ? * @param ?无 ? * @retval 无 ? */ void OLED_Init(void) { ?? ?Delay_s(1);?? ??? ?// 1s,这里的延时很重要,上电后延时,没有错误的冗余设计 ?? ? ?? ?WriteCmd(0xAE); //display off ?? ?WriteCmd(0x20);?? ?//Set Memory Addressing Mode?? ? ?? ?WriteCmd(0x10);?? ?//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid ?? ?WriteCmd(0xb0);?? ?//Set Page Start Address for Page Addressing Mode,0-7 ?? ?WriteCmd(0xc8);?? ?//Set COM Output Scan Direction ?? ?WriteCmd(0x00); //---set low column address ?? ?WriteCmd(0x10); //---set high column address ?? ?WriteCmd(0x40); //--set start line address ?? ?WriteCmd(0x81); //--set contrast control register ?? ?WriteCmd(0xff); //亮度调节 0x00~0xff ?? ?WriteCmd(0xa1); //--set segment re-map 0 to 127 ?? ?WriteCmd(0xa6); //--set normal display ?? ?WriteCmd(0xa8); //--set multiplex ratio(1 to 64) ?? ?WriteCmd(0x3F); // ?? ?WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content ?? ?WriteCmd(0xd3); //-set display offset ?? ?WriteCmd(0x00); //-not offset ?? ?WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency ?? ?WriteCmd(0xf0); //--set divide ratio ?? ?WriteCmd(0xd9); //--set pre-charge period ?? ?WriteCmd(0x22); // ?? ?WriteCmd(0xda); //--set com pins hardware configuration ?? ?WriteCmd(0x12); ?? ?WriteCmd(0xdb); //--set vcomh ?? ?WriteCmd(0x20); //0x20,0.77xVcc ?? ?WriteCmd(0x8d); //--set DC-DC enable ?? ?WriteCmd(0x14); // ?? ?WriteCmd(0xaf); //--turn on oled panel }
第四步剩下的就是一些函数
/** ? * @brief ?OLED_SetPos,设置光标 ? * @param ?x,光标x位置 ?? ?*?? ??? ??? ??? ??? ?y,光标y位置 ? * @retval 无 ? */ void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标 {? ?? ?WriteCmd(0xb0+y); ?? ?WriteCmd(((x&0xf0)>>4)|0x10); ?? ?WriteCmd((x&0x0f)|0x01); }
?/** ? * @brief ?OLED_Fill,填充整个屏幕 ? * @param ?fill_Data:要填充的数据 ?? ?* @retval 无 ? */ void OLED_Fill(unsigned char fill_Data)//全屏填充 { ?? ?unsigned char m,n; ?? ?for(m=0;m<8;m++) ?? ?{ ?? ??? ?WriteCmd(0xb0+m);?? ??? ?//page0-page1 ?? ??? ?WriteCmd(0x00);?? ??? ?//low column start address ?? ??? ?WriteCmd(0x10);?? ??? ?//high column start address ?? ??? ?for(n=0;n<128;n++) ?? ??? ??? ?{ ?? ??? ??? ??? ?WriteDat(fill_Data); ?? ??? ??? ?} ?? ?} }
?/** ? * @brief ?OLED_CLS,清屏 ? * @param ?无 ?? ?* @retval 无 ? */ void OLED_CLS(void)//清屏 { ?? ?OLED_Fill(0x00); }
?/** ? * @brief ?OLED_ON,将OLED从休眠中唤醒 ? * @param ?无 ?? ?* @retval 无 ? */ void OLED_ON(void) { ?? ?WriteCmd(0X8D); ?//设置电荷泵 ?? ?WriteCmd(0X14); ?//开启电荷泵 ?? ?WriteCmd(0XAF); ?//OLED唤醒 }
?/** ? * @brief ?OLED_OFF,让OLED休眠 -- 休眠模式下,OLED功耗不到10uA ? * @param ?无 ?? ?* @retval 无 ? */ void OLED_OFF(void) { ?? ?WriteCmd(0X8D); ?//设置电荷泵 ?? ?WriteCmd(0X10); ?//关闭电荷泵 ?? ?WriteCmd(0XAE); ?//OLED休眠 }
?/** ? * @brief ?OLED_ShowStr,显示codetab.h中的ASCII字符,有6*8和8*16可选择 ? * @param ?x,y : 起始点坐标(x:0~127, y:0~7); ?? ?*?? ??? ??? ??? ??? ?ch[] :- 要显示的字符串;? ?? ?*?? ??? ??? ??? ??? ?TextSize : 字符大小(1:6*8 ; 2:8*16) ?? ?* @retval 无 ? */ void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize) { ?? ?unsigned char c = 0,i = 0,j = 0; ?? ?switch(TextSize) ?? ?{ ?? ??? ?case 1: ?? ??? ?{ ?? ??? ??? ?while(ch[j] != '\0') ?? ??? ??? ?{ ?? ??? ??? ??? ?c = ch[j] - 32; ?? ??? ??? ??? ?if(x > 126) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?x = 0; ?? ??? ??? ??? ??? ?y++; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?OLED_SetPos(x,y); ?? ??? ??? ??? ?for(i=0;i<6;i++) ?? ??? ??? ??? ??? ?WriteDat(F6x8[c][i]); ?? ??? ??? ??? ?x += 6; ?? ??? ??? ??? ?j++; ?? ??? ??? ?} ?? ??? ?}break; ?? ??? ?case 2: ?? ??? ?{ ?? ??? ??? ?while(ch[j] != '\0') ?? ??? ??? ?{ ?? ??? ??? ??? ?c = ch[j] - 32; ?? ??? ??? ??? ?if(x > 120) ?? ??? ??? ??? ?{ ?? ??? ??? ??? ??? ?x = 0; ?? ??? ??? ??? ??? ?y++; ?? ??? ??? ??? ?} ?? ??? ??? ??? ?OLED_SetPos(x,y); ?? ??? ??? ??? ?for(i=0;i<8;i++) ?? ??? ??? ??? ??? ?WriteDat(F8X16[c*16+i]); ?? ??? ??? ??? ?OLED_SetPos(x,y+1); ?? ??? ??? ??? ?for(i=0;i<8;i++) ?? ??? ??? ??? ??? ?WriteDat(F8X16[c*16+i+8]); ?? ??? ??? ??? ?x += 8; ?? ??? ??? ??? ?j++; ?? ??? ??? ?} ?? ??? ?}break; ?? ?} }
?/** ? * @brief ?OLED_ShowCN,显示codetab.h中的汉字,16*16点阵 ? * @param ?x,y: 起始点坐标(x:0~127, y:0~7);? ?? ?*?? ??? ??? ??? ??? ?N:汉字在codetab.h中的索引 ?? ?* @retval 无 ? */ void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N) { ?? ?unsigned char wm=0; ?? ?unsigned int ?adder=32*N; ?? ?OLED_SetPos(x , y); ?? ?for(wm = 0;wm < 16;wm++) ?? ?{ ?? ??? ?WriteDat(F16x16[adder]);
?? ??? ?adder += 1; ?? ?}
?? ?OLED_SetPos(x,y + 1); ?? ?for(wm = 0;wm < 16;wm++) ?? ?{ ?? ??? ?WriteDat(F16x16[adder]);
?? ??? ?adder += 1; ?? ?} }
?/** ? * @brief ?OLED_DrawBMP,显示BMP位图 ? * @param ?x0,y0 :起始点坐标(x0:0~127, y0:0~7); ?? ?*?? ??? ??? ??? ??? ?x1,y1 : 起点对角线(结束点)的坐标(x1:1~128,y1:1~8) ?? ?* @retval 无 ? */ void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]) { ?? ?unsigned int j=0; ?? ?unsigned char x,y;
? if(y1%8==0) ?? ??? ?y = y1/8; ? else ?? ??? ?y = y1/8 + 1; ?? ?for(y=y0;y<y1;y++) ?? ?{ ?? ??? ?OLED_SetPos(x0,y); ? ? for(x=x0;x<x1;x++) ?? ??? ?{ ?? ??? ??? ?WriteDat(BMP[j++]); ?? ??? ?} ?? ?} }
第五步在main文件夹调用
#include "stm32f10x.h" #include "bsp_i2c_gpio.h" #include "OLED_I2C.h" #include "./systick/bsp_SysTick.h"
extern const unsigned char BMP1[];//图片,可通过取子模软件获得
?/** ? * @brief ?主函数 ? * @param ?无 ? * @retval 无 ? */ int main(void) { ? ? unsigned char i;?? ? ?? ? ?SysTick_Init(); ? ? ? ?/*初始化延迟函数*/ ?? ?I2C_Configuration();? /*I2C总线的GPIO初始化*/ ?? ? ?OLED_Init();?? ??? ??? ??? ??? ? /* OLED初始化 */? ? ? ?? ??? ?while(1) ?? ?{ ?? ??? ?OLED_Fill(0xFF);//全屏点亮 ?? ??? ?Delay_s(2); ?? ??? ? ?? ??? ?OLED_Fill(0x00);//全屏灭 ?? ??? ?Delay_s(2); ?? ??? ? ?? ??? ?for(i=0;i<4;i++) ?? ??? ?{ ?? ??? ??? ?OLED_ShowCN(22+i*16,0,i);?? ??? ??? ??? ??? ??? ??? ??? ??? ?//测试显示中文 ?? ??? ?} ?? ??? ?Delay_s(2); ?? ??? ?OLED_ShowStr(0,3,(unsigned char*)"Wildfire Tech",1);?? ??? ??? ??? ?//测试6*8字符 ?? ??? ?OLED_ShowStr(0,4,(unsigned char*)"Hello wildfire",2);?? ??? ??? ??? ?//测试8*16字符 ?? ??? ?Delay_s(200); ?? ??? ?OLED_CLS();//清屏 ?? ??? ?OLED_OFF();//测试OLED休眠 ?? ??? ?Delay_s(2); ?? ??? ?OLED_ON();//测试OLED休眠后唤醒 ?? ??? ?OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//测试BMP位图显示 ?? ??? ?Delay_s(20); ?? ?} }
完整的工程
链接:https://pan.baidu.com/s/1qfQssnGvzuBUjW5S4WqR7w?pwd=dg48? 提取码:dg48
|