STM32 OLED相关笔记(库函数)

发布者:SereneWanderer最新更新时间:2020-07-06 来源: eefocus关键字:STM32  OLED  库函数 手机看文章 扫描二维码
随时随地手机看文章

参考资料:正点原子STM32不完全手册OLED章节

有机发光二极管(Organic Light-Emitting Diode, OLED)

0.OLED不需要背光源,对比度高,注意:电压为3.3v,支持SPI 8080 6800 和iic

1.基于SSD1302芯片,一般为128*8*8的规格,称为12864

对于SSD1302芯片的操作:


0X81:设置对比度,包含两个字节,第一个0X81为命令,然后发送一个值来设置对比度,设置的值越大,则屏幕越亮(0X00--0XFF)


0XAE,0XAF:为关闭显示和开启显示


0x8D:为电荷泵的命令值,后面包括一个设置值,第二个字节的A2位表示是否开启电荷泵(0为关闭,1为开启)


0XB0--0X87:用于设置页的地址


0X00--0X0F:设置显示时地址的低四位


0X10--0X1F:显示起始列地址的高四位

相关代码:


1.相关IO口的设置和OLED初始化过程


void OLED_Init(void)

{     

GPIO_InitTypeDef  GPIO_InitStructure;//设置IO口的初始化

    

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE );

//使能GPIOB,GPIOC

//模式1:定义为8080并口模式,模式0定义为SPI4线串口模式

//#if #else 是用来调整模式的(8080orSPI)  

#if OLED_MODE==1

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能AFIO时钟

 

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE); //JTAG-DP 失能 + SW-DP使能 

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);      

GPIO_Write(GPIOB,0XFFFF);

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_SetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);//如果每一位决定一个GPIO_Pin,则可以通过或的形式来初始化多个IO

 

#else

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD ; //推挽输出

GPIO_Init(GPIOB, &GPIO_InitStructure);      

GPIO_Write(GPIOB,0X03);

 

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_SetBits(GPIOC, GPIO_Pin_8|GPIO_Pin_9);

#endif   

  //对SSD1306进行操作

//先写入数据进行SSD1306的初始化操作

OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示

OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率

OLED_WR_Byte(80,OLED_CMD);   //[3:0],分频因子;[7:4],震荡频率

OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数

OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64) 

OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移

OLED_WR_Byte(0X00,OLED_CMD); //默认为0

 

OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数.

    

OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置

OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭

OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式

OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;

OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;

OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数

OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置

OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置

 

OLED_WR_Byte(0x81,OLED_CMD); //对比度设置

OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮)

OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期

OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;

OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率

OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;

 

OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)

OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示        

OLED_WR_Byte(0xAF,OLED_CMD); //开启显示  

OLED_Clear();

}  

2.根据时序图进行写入数据的设置


1.时序图:

//8080总线

void OLED_WR_Byte(u8 dat,u8 cmd)

{

DATAOUT(dat);     

  OLED_RS=cmd; //写命令

OLED_CS=0; //拉低片选

OLED_WR=0; //拉低WR位

OLED_WR=1; //升高WR位(已经进行了写入操作)

OLED_CS=1;   //拉高片选(写入一个位结束)

OLED_RS=1; //数据标志

}        

3.更新数据入OLED(采用数组的方式)


//更新显存到LCD

 

void OLED_Refresh_Gram(void)

{

u8 i,n;     

for(i=0;i<8;i++)  

{  

OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)

OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址

OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   

for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA); //将数据写入O_LED的GRAM中

}   

}

4.通过函数将字符和数字显示到OLED模块上


<1>:初始化OLED_Display()//基于SSD1306的操作


//开启OLED显示    

void OLED_Display_On(void)

{

OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令

OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON

OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON

}

//关闭OLED显示     

void OLED_Display_Off(void)

{

OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令

OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF

OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF

}    

<2>:清屏操作


将数组的所有的点设为0x00


void OLED_Clear(void)  

{  

u8 i,n;  

for(i=0;i<8;i++)for(n=0;n<128;n++)OLED_GRAM[n][i]=0X00;  

OLED_Refresh_Gram();//更新显示

}

<3>画点操作


void OLED_DrawPoint(u8 x,u8 y,u8 t)

{

u8 pos,bx,temp=0;

if(x>127||y>63)return;//超出范围了.

pos=7-y/8;

bx=y%8;

temp=1<<(7-bx);

if(t)OLED_GRAM[x][pos]|=temp;

else OLED_GRAM[x][pos]&=~temp;     

}

void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot)  

{  

u8 x,y;  

for(x=x1;x<=x2;x++)

{

for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot);

}     

OLED_Refresh_Gram();//更新显示

}

<4>:显示字符串:


void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)

{          

u8 temp,t,t1;

u8 y0=y;

u8 csize=(size/8+((size%8)?1:0))*(size/2); //得到字体一个字符对应点阵集所占的字节数

chr=chr-' ';//得到偏移后的值  

    for(t=0;t    {   

if(size==12)temp=asc2_1206[chr][t]; //调用1206字体

else if(size==16)temp=asc2_1608[chr][t]; //调用1608字体

else if(size==24)temp=asc2_2412[chr][t]; //调用2412字体

else return; //没有的字库

        for(t1=0;t1<8;t1++)

{

if(temp&0x80)OLED_DrawPoint(x,y,mode);

else OLED_DrawPoint(x,y,!mode);

temp<<=1;

y++;

if((y-y0)==size)

{

y=y0;

x++;

break;

}

}   

    }          

}

//m^n函数

u32 mypow(u8 m,u8 n)

{

u32 result=1;  

while(n--)result*=m;    

return result;

}   

<5>显示数字


void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)

{         

u8 t,temp;

u8 enshow=0;    

for(t=0;t {

temp=(num/mypow(10,len-t-1))%10;

if(enshow==0&&t<(len-1))

{

if(temp==0)

{

OLED_ShowChar(x+(size/2)*t,y,' ',size,1);

continue;

}else enshow=1; 

 

}

OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1); 

}

<6>:显示字符串


void OLED_ShowString(u8 x,u8 y,const u8 *p,u8 size)

{

    while((*p<='~')&&(*p>=' '))//判断是不是非法字符!

    {       

        if(x>(128-(size/2))){x=0;y+=size;}

        if(y>(64-size)){y=x=0;OLED_Clear();}

        OLED_ShowChar(x,y,*p,size,1);  

        x+=size/2;

        p++;

    }  

}


注:对于具体的字符进行操作的时候可以采用字库来解决,上面的代码应该是通用的,基于STM32的OLED进行操作,主函数部分可以根据个人需求进行改变;

关键字:STM32  OLED  库函数 引用地址:STM32 OLED相关笔记(库函数)

上一篇:stm32寄存器版学习笔记10 SPI
下一篇:STM32-24位AD7799驱动之手册代码详解,支持模拟SPI和硬件SPI

推荐阅读最新更新时间:2024-11-05 15:06

分享STM32代码读保护个人解决方案
简介:这个加载代码读保护功能的步骤可能对有些人来说还是比较麻烦的,毕竟产品多的时候,写入之后还要按一下写保护命令,对于产线操作员来说,可能一时疏忽忘记其中一个,就会造成代码的外泄,是不是应该还有更简单的办法一键写入呢,答案是肯定的! 具体做法,就是要在生成HEX文件之前,要多几个步骤 1.首先,加载: C:KeilARMBoardsKeilMCBSTM32Blinky文件夹中的一个STM32F10xOPT.s文件 2.修改下面两个值为1 3.生成HEX文件之前务必进行一下此配置 这样的话,就简单的一个HEX文件就会使你的产品流入市场之后,即便是被抄板成功,也不会是代码流出了 当然,必须保证自己公司的员工不
[单片机]
分享<font color='red'>STM32</font>代码读保护个人解决方案
STM32单片机通用定时器的编程设计
一、STM32通用定时器原理 STM32系列的CPU,有多达8个定时器,其中TIM1和TIM8是能够产生三对PWM互补输出的高级定时器,常用于三相电机的驱动,它们的时钟由APB2的输出产生。其它6个为普通定时器,时钟由APB1的输出产生。 下图是STM32参考手册上时钟分配图中,有关定时器时钟部分的截图: 从图中可以看出,定时器的时钟不是直接来自APB1或APB2,而是来自于输入为APB1或APB2的一个倍频器,图中的蓝色部分。 下面以通用定时器2的时钟说明这个倍频器的作用:当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其它数值(即预分频系数为2、4、8或
[单片机]
<font color='red'>STM32</font>单片机通用定时器的编程设计
STM32学习第一步:点灯
前言 任务需求:使用stm32c8点亮两个led小灯并实现闪烁效果 注:本次任务包含CubeMX+hal库以及单独使用标准库两种写法完成代码构建。并最后通过Proteus仿真测试运行结果 提示:以下是本篇文章正文内容,下面案例可供参考 一、CubeMX生成keil5工程文件 工程配置: 时钟配置: 生成Keil5工程文件:注意:路径及名称不能有中文 hal库完善代码逻辑 注意:前面我们通过cubemx将工程硬件配置完毕,所以这里只需要完善软件逻辑层代码 while (1) { /* USER CODE END WHILE */ HAL_GPIO_WritePin(GPIOB,GPIO_PI
[单片机]
<font color='red'>STM32</font>学习第一步:点灯
STM32全局变量占用程序存储空间吗
全局变量是否占用最终程序的存储空间,这个问题其实早在我们学习C语言的时候就已经告诉我们答案了。我隐约记得初学C语言的时候,书本上告诉我们: 全局自动变量 保存在读写数据段 全局静态变量 保存在读写数据段 全局常量 保存在只读数据段 局部自动变量 保存在栈空间里的 而我们在做单片机程序的时候,由于都是用的C编程,所以数据的存储也是一样的。上面的读写数据段在单片机里就是RW-data段,上面的只读数据段在单片机里就是RO-data,还有一个零初始化数据段ZI-data段(由此可见,RW-data加上ZI-data就是总共要分配的RAM空间大小),最后一个Code段就不用介绍了,大家都明白。 那么究竟一个STM32程序编译链接完
[单片机]
<font color='red'>STM32</font>全局变量占用程序存储空间吗
基于STM32的多路电压测量设计方案
简介:计中使用的ADC是STM32上的12位ADC,能够满足一定的测量精度,对于较高的测量要求,则需要使用更高精确度的ADC.但是使用高精度ADC和DSP芯片,将很大的增加开发成本。 1.引言 近年来,数据采集及其应用受到了人们越来越广泛的关注,数据采集系统也有了迅速的发展,它可以广泛的应用于各种领域。 数据采集技术是信息科学的重要分支之一,数据采集也是从一个或多个信号获取对象信息的过程。数据采集是工业控制等系统中的重要环节,通常采用一些功能相对独立的单片机系统来实现,作为测控系统不可缺少的部分,数据采集的性能特点直接影响到整个系统。 电压的测量最为普遍性,研究设计并提高电压测量精度的方法及仪器具有十分重要的意义。
[单片机]
基于<font color='red'>STM32</font>的多路电压测量设计方案
你的STM32芯片FLASH容量真如ST官方选型手册那样吗?
如果某一个天项目经理提出一个需求,要求在现有STM32产品基础上,内部FLASH增加64K字库,你脑海中首先会想到什么? 1先说点其它 一般对于初学者来说,内部FLASH完全足够,跑一个简单的裸机Demo,或者一个RTOS加上两个任务的Demo,对于现在的MCU完全没有压力。 但是,一旦你接触到实际项目,你会发现很多地方都会开支FLASH,而且有些项目占用FLASH还不小。比如:某种特定算法,加载字库,甚至放两张图片在FLASH里面。 再拿一个IAP应用编程的例子来说:一般对升级这个功能做的好一点的,会有一块区域(备份区域)与应用程序差不多大小的FLASH区域。就是说:为了保证安全,你程序下载保
[单片机]
你的<font color='red'>STM32</font>芯片FLASH容量真如ST官方选型手册那样吗?
STM32_USB之完全双缓存(包括发送和接收) -- 更新中断处理
STM32的USB双缓存接收代码其实已经可以在ST提供的USB示例代码中找到,只要稍加修改,就可以得到将近1MB的数据接收性能。虽然Datasheet中说明USB发送也同样可以使用双缓存,但并没有示例代码,由于为了测试性能,自己做了一个,测试中没有发现问题,虽然对性能的提升不如在USB接收上实现双缓存那么多。 注意: FreeUserBuffer的作用是切换当前的USB缓存。 1.接收双缓冲: EPX_OUT_Callback中,此代码只是在ST的示例程序的基础上稍加修改,并且不是偶写的,而是一个网友测试的: if(GetENDPOINT(ENDP3) & EP_DTOG_TX) { FreeUserBuffer(EN
[单片机]
STM32固件库SYSTEM 文件夹介绍
SYSTEM 文件夹里面的代码,此文件夹里面的代码由 ALIENTEK 提供,包含了几乎每个实验都可能用到的延时函数,位带操作,串口打印代码等。SYSTEM 文件夹下包含了 delay、 sys、 usart 等三个文件夹。分别包含了 delay.c、 sys.c、usart.c 及其头文件 delay.h,sys.h,usart.h。 delay 文件夹代码介绍 delay 文件夹内包含了 delay.c 和 delay.h 两个文件,这两个文件用来实现系统的延时功能,其中包含 3 个函数: void delay_init(u8 SYSCLK); //该函数用来初始化 2 个重要参数:fac_us 以及 fac_ms;同时把
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved