stm32-OLED屏+RTC实现简易实时时钟(上篇)

这篇具有很好参考价值的文章主要介绍了stm32-OLED屏+RTC实现简易实时时钟(上篇)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

oled屏选择ssd1306,使用RTC实现简易实时时钟

OLED部分

1、MCU接口选择

SSD1306单片机接口由8个数据引脚和5个控制引脚组成。通过BS[2:0]引脚上的硬件选择可以设置不同的MCU模式

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 通过控制BS[2:0]引脚可以设置MCU与OLED屏的通信方式。因为我使用的是正点原子的开发板,所以我用了适配的接口8080。即BS0=0;BS1=1;BS2=2;

2、单片机并行8080接口

并行接口由8个双向数据引脚(D[7:0])、RD、WR、D/C和CS组成。D/ C中的LOW表示COMMAND读/写,HIGH表示DATA读/写。RS输入的上升沿作为数据读锁存信号,而cs#保持低电平。在 RD 的上升沿, 使数据锁存到数据线(D[7:0])上;在 WR 的上升沿,使数据写入到 SSD1306 里面。

CS:OLED 片选信号。
WR:向 OLED 写入数据。
RD:从 OLED 读取数据。
D[7:0]:8 位双向数据线。
RST(RES):硬复位 OLED。
DC:命令/数据标志(0,读写命令;1,读写数据)

8080接口读时序过程:

首先将CS拉低,表示设备被选中;WR设置为高,RD设置为低,表示读取数据;然后在RD的上升沿将数据从总线上读取出来。

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 8080接口写时序过程:

首先将CS拉低,表示设备被选中;WR设置为低,RD设置为高,表示写数据;然后在WR的上升沿将数据写入总线。

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 SSD1306 的 8080 接口方式下,控制脚的信号状态所对应的功能如表

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 

3、命令编译器

该模块决定输入的数据是被解释为数据还是命令,如果D/C为高则写入的是数据,如果D/C为低则写入的是命令/

4、复位电路

当RET输入为LOW时,芯片初始化为以下状态。

1.显示关闭
2. 128 × 64显示模式
3.正常段和显示数据列地址和行地址的映射(SEG0映射到地址00h, COM0映射到地址00h)
4. 在串行接口中清除移位寄存器数据
5. 显示起始行设置在显示RAM地址0处
6. 列地址计数器设置为0
7. COM输出的正常扫描方向
8. 对比度控制寄存器设置为7Fh
9. 正常显示模式(相当于A4h命令)

5、图形显示数据(GDDRAM)即显存

GDDRAM是位映射静态RAM,保存要显示的位模式。RAM的大小为128 × 64位,RAM分为8个页面,从PAGE0到PAGE7,用于单色128x64点阵显示,如图

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 因为我们每次是通过控制128x64点阵里的每一个点的状态(0/1)来控制OLED屏显示图形;这就要求我们在想要显示图形的时候就应该把每一个点的状态都提前想好,否则我们写入的数据会覆盖之前的数据。所以我们采用的办法是在 STM32 的内部建立一个 OLED 的 GRAM(共 128*8 个字节),在每次修改的时候,只是修改 STM32 上的 GRAM(实际上就是 SRAM),在修改完了之后,一次性把 STM32 上的 GRAM 写入到 OLED 的 GRAM。

6、SSD1306命令

这里列举一些SSD1306的一些常用的命令(参考原子哥的开发指南)

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 第一个命令为 0X81,用于设置对比度的,这个命令包含了两个字节,第一个 0X81 为命令,
随后发送的一个字节为要设置的对比度的值。这个值设置得越大屏幕就越亮。

第二个命令为 0XAE/0XAF。0XAE 为关闭显示命令;0XAF 为开启显示命令。

第三个命令我也不知干啥的,反正开就行了

第四个命令为 0XB0~B7,该命令用于设置页地址,其低三位的值对应着 GRAM 的页地址。(三位表示0-7足够了)

第五个指令为 0X00~0X0F,该指令用于设置显示时的起始列地址低四位。

第六个指令为 0X10~0X1F,该指令用于设置显示时的起始列地址高四位。(五六命令要一起使用)

7、内存寻址模式

在SSD1306中有3种不同的内存寻址模式:页寻址模式、水平寻址模式和垂直寻址模式。该命令将内存寻址方式设置为上述三种模式之一

1、页寻址模式(A[1:0]=10xb)在页寻址模式下,读取/写入显示RAM后,列地址指针自动增加1。如果列地址指针到达列结束地址,则将列地址指针重置为列开始地址,不修改页面地址指针。用户必须设置新的页面和列地址,以便访问下一页RAM内容。

定义RAM的起始访问指针位置:

  • 通过命令B0h设置目标显示位置的页面起始地址为B7h。
  • 通过命令00h~0Fh设置指针的下起始列地址。
  • 通过命令10h~1Fh设置指针上起始列地址

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

2、水平寻址模式

水平寻址模式(A[1:0]=00b)在水平寻址模式下,读/写显示RAM后,列地址指针自动增加1。当列地址指针到达列结束地址时,列地址指针重置为列开始地址,页面地址指针加1 

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

3、垂直寻址方式

A[1:0]=01b

在垂直寻址模式下,读/写显示RAM后,页地址指针自动增加1。当页地址指针到达页结束地址时,将页地址指针重置为页起始地址,列地址指针加1。

 

需要以下步骤来定义RAM访问指针的位置:

通过命令21h设置目标显示位置的列起始地址和列结束地址。

通过命令22h设置目标显示位置的页面起始和结束地址。

注释:在程序中我使用的是页寻址模式,只有在发送0X20命令(设置内存地址模式)之后再写入0x10命令才能成功设置成页寻址模式。

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 8、代码实战

 1、设置STM32与OLED模块相连接的IO

GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG, ENABLE);	 //使能PC,D,G端口时钟

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_6;	 //PD3,PD6推挽输出   PD3=DC 
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
 	GPIO_Init(GPIOD, &GPIO_InitStructure);	  //初始化GPIOD3,6
 	GPIO_SetBits(GPIOD,GPIO_Pin_3|GPIO_Pin_6);	//PD3,PD6 输出高

 #if OLED_MODE==1   //8080模式
 
 	GPIO_InitStructure.GPIO_Pin =0xFF; //PC0~7 OUT推挽输出
 	GPIO_Init(GPIOC, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOC,0xFF); //PC0~7输出高

 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;				 //PG13,14,15 OUT推挽输出
 	GPIO_Init(GPIOG, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOG,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);						 //PG13,14,15 OUT  输出高  

对应的引脚都设置成推挽输出(这样既可以输出高电平也可输出低电平)

PD3=DC ; PG13=RD ; PC0=D0 ; PC2=D2 ; PC4=D4; PC6=D6;  PB4=悬空
PD6=CS ; PG14=RW ; PG15=RST PC1=D1;  PC3=D3 ;PC5=D5;  PC7=D7;

2、初始化OLED屏幕

OLED_CS=1;
	OLED_RS=1;	   //DC位 DC=1表示写数据
	
	OLED_RST=0;   //RST=0复位,在每次初始化OLED屏幕之前都应该复位
	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(0x10,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;  必须紧贴着0x20
	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();

这里不需要知道太多,参考驱动IC的初始化代码就行了(这里我也没深入了解)

3、将数据显示在OLED屏幕上

此代码主要参考正点原子的历程,我在此部分将介绍一些我对这部分代码的理解

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 这里如果是采用页寻址的话,应该是128行8列的数组,应该是原子哥描述有问题。

//画点 
//x:0~127
//y:0~63
//t:1 填充 0,清空				   
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
	u8 pos,bx,temp=0;
	if(x>127||y>63)return;//超出范围了.
	pos=7-y/8;   // 当y=0-7 pos=7  当y=8-15 pos=6         y=1 pos=7
	bx=y%8;      //当y=0-7  bx=0-7   当y=8-15 bx=0-7      bx=1
 	temp=1<<(7-bx);   //                                   temp=1<<(7-1)=1<<6   
	if(t)
	{
		OLED_GRAM[x][pos]|=temp;                            //OLED_GRAM[X][1]=OLED_GRAM[X][1]| temp;  非0
	}
	else 
	{
		OLED_GRAM[x][pos]&=~temp;	                          //OLED_GRAM[X][1]=OLED_GRAM[X][1]| temp;  等于0
	}  
}

画点函数,就是点亮OLED128 × 64位其中一个点,后续的显示字符,显示数字函数都是在此函数的基础上改进的。其中x表示点的列数,y表示点的行数;其中POS用来表示显示的页数(0-7页),因为每一页有8行,也就是8位,所以使用bx来控制位的偏移,这样就可以精确到每一位。

//向SSD1306写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 cmd)
{
	DATAOUT(dat);	   //GPIO_Write()输出   此处为什么要在片选拉低之前就写值
 	OLED_RS=cmd;    //DC位  DC=0表示命令  DC=1表示数据
	OLED_CS=0;	   
	OLED_WR=0;       //WR位
	OLED_WR=1;        //在WR的上升沿将数据写入到SSD1306中
	OLED_CS=1;	   
	OLED_RS=1;	    DC位  DC=0表示命令  DC=1表示数据
} 	    	  

写数据或者命令函数,其中DATAOUT(dat)写的是一个字节也就是8位,也就是D0-D7。

stm32oled屏显示时间,stm32,实时音视频,嵌入式硬件

 结语

因为时间有限,本人是在闲暇之余整理的稳定,目前实验已经做完,时间有限只能先写到这了,后续明天会补充,时间不早了,大家早点休息。实验效果已经上传置B站,大家可以去我的页面看是点灯实验室呀的个人空间-是点灯实验室呀个人主页-哔哩哔哩视频文章来源地址https://www.toymoban.com/news/detail-797020.html

到了这里,关于stm32-OLED屏+RTC实现简易实时时钟(上篇)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32】RTC(实时时钟)

    本质:计数器 RTC中断是外部中断(EXTI) 当VDD掉电的时候,Vbat可以通过电源---实时计时 STM32的RTC外设(Real Time Clock),实质是一个   掉电   后还继续运行的定时器。从定时器的角度来说,相对于通用定时器TIM外设,它十分简单, 只有很纯粹的计时和触发中断的功能 ;但从

    2024年02月03日
    浏览(40)
  • STM32——RTC实时时钟

    Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间 底层使用秒计数器可以节省硬件设计电路,

    2024年01月23日
    浏览(32)
  • STM32--RTC实时时钟

    Unix 时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒 。 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量。 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间。 GMT : GMT(Greenwich Mean Time), 格林威治平时(也称格林

    2024年02月10日
    浏览(37)
  • STM32-RTC实时时钟详解

    RTC的本质很简单,就是一个时钟经过精确分频最后得到的一个1Hz的时钟,也可以说是计数器,其他大部分功能都是基于这个计数器设计的数字逻辑。 本文讲的RTC是基于STM32F030来讲的,相比与F1系列的RTC来说,M0的将很多原本需要软件实现的功能硬件化了,使用起来更加便利。

    2024年02月04日
    浏览(34)
  • 【STM32学习】实时时钟 —— RTC

    STM32RTC实时时钟实验讲解,从入门到放弃 【STM32】RTC休眠唤醒(停机模式)、独立看门狗开启状态下 关于STM32使用RTC唤醒停止模式的设置 RTC(Real Time Clock):实时时钟,是指可以像时钟一样输出实际时间的电子设备,一般会是集成电路,因此也称为时钟芯片。总之,RTC只是个能靠电

    2024年02月01日
    浏览(36)
  • STM32-实时时钟RTC-2

                                     

    2024年01月20日
    浏览(37)
  • STM32基础10--实时时钟(RTC)

     目录 前言 RTC框图 STM32实时时钟电路 功能需要 STM32CubeMx配置RTC 配置RCC 配置RTC 配置时间,闹钟,唤醒 开启中断 设置中断优先级 功能代码实现 STM32Cude生成RTC初始化 自定义触发闹钟次数变量  重写周期唤醒回调函数 重写闹钟中断函数         在做51单片机项目时,如果需

    2023年04月11日
    浏览(26)
  • STM32学习笔记(十二)丨RTC实时时钟

    ​  本次课程采用单片机型号为STM32F103C8T6。 ​  课程链接:江协科技 STM32入门教程   往期笔记链接:   STM32学习笔记(一)丨建立工程丨GPIO 通用输入输出   STM32学习笔记(二)丨STM32程序调试丨OLED的使用   STM32学习笔记(三)丨中断系统丨EXTI外部中断   

    2024年02月16日
    浏览(37)
  • STM32中的RTC实时时钟和配套闹钟设置

    主要初始化函数,以及设置闹钟函数,闹钟中断函数 RTC.c RTC.h main.c

    2024年04月23日
    浏览(33)
  • 【STM32】读写BKP备份寄存器&RTC实时时钟

    目录 BKP BKP简介 BKP基本结构 BKP测试代码 RTC RTC简介 RTC框图 RTC基本结构 硬件电路 RTC操作注意事项 接线图 初始化 使用BKP解决只初始化一次时间  初始化参考代码 RTC设置时间 RTC读取时间 完整代码 MyRTC.c MyRTC.h main.c BKP(Backup Registers)备份寄存器 BKP可用于存储用户应用程序数据

    2024年04月22日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包