STM32之OLED学习

文章目录


前言

STM32嵌入式学习已经好久了,一些基础知识总是忘记,正好下半年需要找工作,有时间就把之前学习的东西拾起来看看。

实验环境:STM32F103系列开发板,SSD1306型号OLED、KEIL


提示:以下是本篇文章正文内容,下面案例可供参考

一、OLED

OLED有多种接口方式:6800、8080、IIC、3线SPI和4线SPI,在此先讨论8080并口

OLED关键引脚:

                        CS:OLED片选引脚;

                         WR:向SSD1306写入数据;

                         RD:从SSD1306读取数据;

                         RST:硬复位OLED;

                        D[7:0]:8位双向数据线;

                       DC:命令/数据标志(0:命令;1:数据)。

SSD1306的8080并口写时序

 图1  8080并口的写时序

8080并口写过程:首先根据要写入的数据类型,设置DC为高(数据)/低(命令),然后拉低片选信号CS,选中模块,然后再WR出现上升沿时将数据写入到SSD1306中。

SSD1306的8080并口写时序

 图2  8080并口的读时序

 8080并口读过程:首先根据要写入的数据类型,设置DC为高(数据)/低(命令),然后拉低片选信号CS,选中模块,然后再RD出现上升沿时将数据锁存到D[7:0]。

根据8080的读写过程,控制脚的信号状态所对应的功能如表1所示。

功能RDWRCSDC
写命令H上升沿LL
读状态上升沿HLL
写数据H上升沿LH
读数据上升沿HLH

二、软件设计

 SSD1306常用的指令:

                                   0X81:设置对比度,后面加上一个字节的对比度值;

                                  0XAE/0XAF:0XAE为关闭显示命令;0XAF为开启显示命令;

                                  0X8D:电荷泵设置,后面一字节的BIT2为0则关闭,为1则开启;

                                  0XB0~0XB7:设置页地址,低三位对于GRAM的页地址;

                                  0X00~0X0F:设置列地址低四位;

                                  0X10~0X1F:设置列地址高四位。

OLED与STM32F103系列开发板IO口对应关系:

   CS:PD6        RST:PG15        DC:PD3        WR:PG14        RD:PG13        D[7:0]:PC[7:0]

1.初始化SSD1306

void Oled_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG,
    ENABLE);	 

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_6;	 //PD3:DC   PD6:CS 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOD, &GPIO_InitStructure);	  
 	GPIO_SetBits(GPIOD,GPIO_Pin_3|GPIO_Pin_6);	
 	GPIO_InitStructure.GPIO_Pin =0xFF; 
 	GPIO_Init(GPIOC, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOC,0xFF); 

 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;				 
 	GPIO_Init(GPIOG, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOG,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
    //PG13:RD    	PG14:WR     PG15:RST 				



	OLED_CS=1;
	OLED_RS=1;	 
	
	OLED_RST=0;
	delay_ms(100);
	OLED_RST=1; 
					  
	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); 
	OLED_WR_Byte(0xA1,OLED_CMD); 
	OLED_WR_Byte(0xC0,OLED_CMD); 
	OLED_WR_Byte(0xDA,OLED_CMD); 
	OLED_WR_Byte(0x12,OLED_CMD); 
		 
	OLED_WR_Byte(0x81,OLED_CMD); 
	OLED_WR_Byte(0xEF,OLED_CMD); 
	OLED_WR_Byte(0xD9,OLED_CMD); 
	OLED_WR_Byte(0xf1,OLED_CMD); 
	OLED_WR_Byte(0xDB,OLED_CMD); 
	OLED_WR_Byte(0x30,OLED_CMD); 

	OLED_WR_Byte(0xA4,OLED_CMD); 
	OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式
    						   
	OLED_WR_Byte(0xAF,OLED_CMD); //开启显示 
	OLED_Clear();
}

2.SSD1306基础功能

//开启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(0XAE,OLED_CMD);  //关闭显示
}		   
//更新显存到OLED
void OLED_Refresh_Gram(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][i],OLED_DATA); 
	}   
}
//清屏
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();//更新显存
//向SSD1306写字节
//dat:要写入的字节  cmd:数据/命令标志;
void Oled_WR_Byte(u8 dat,u8 cmd)
{
	DATAOUT(dat);	 //向PC[7:0]写数据/命令
 	OLED_DC=cmd;     // 数据/命令标志
	OLED_CS=0;	     //选中SSD1306
	OLED_WR=0;	     //写入拉低
	OLED_WR=1;       //写入拉高
	OLED_CS=1;	     //片选拉高
	OLED_DC=1;	     // 数据标志
} 	    

 上述的几个函数都是根据SSD1306的命令以及80880并口的读写时序图编写的。

3. OLED功能函数

//画点函数
//x:0~27,y:0~63, t:0(清空)/1(填充)
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
	u8 pos,bx,temp=0;
	if(x>127||y>63)return;//超出OLED分辨率 128*64
	pos=7-y/8;
	bx=y%8;
	temp=1<<(7-bx);
	if(t)OLED_GRAM[x][pos]|=temp;
	else OLED_GRAM[x][pos]&=~temp;	    
}

OLED_GRAM[x][y]中的x代表列数(x:0~127),y代表页数(y:0~8),一共有8页,每页又有8行,一共64行,从高到低对应行数的由小到大。


//OLED填充对角区域
//x1<=x2,y1<=y2, 0<=x<=127,0<=y<=63
//dot:0(清空)/1(填充)
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();//更新显示
}
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<csize;t++)
    {   
		if(size==12)temp=asc2_1206[chr][t]; 	 	
		else if(size==16)temp=asc2_1608[chr][t];	
		else if(size==24)temp=asc2_2412[chr][t];	
		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;
			}
		}  	 
    }          
}
//显示字符串
//x,y:起始点坐标 
//*p:字符串起始地址
//size:字符串长度
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++;
    }  
	
}	 


总结

OLED的8080并口使用需要能够看懂8080并口的读写时序以及学会如何写入字符,然后学会如何写入字符串。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值