stm32学习笔记---OLED调试工具(理论部分和代码部分)

目录

理论部分

三种常用的程序调试方法

第一种是串口调试

第二种是显示屏调试

第三种是Keil调试模式

其他调试方式

OLED显示屏的介绍

OLED的硬件电路

OLED驱动程序中所包含的驱动函数

OLED_Init();

OLED_Clear();

OLED的显示函数

OLED_ShowChar(1, 1, 'A');

OLED_ShowString(1, 3, "HelloWorld!");

OLED_ShowNum(2, 1, 12345, 5);

OLED_ShowSignedNum(2, 7, -66, 2);

OLED_ShowHexNum(3, 1, 0xAA55, 4);

OLED_ShowBinNum(4, 1, 0xAA55, 16);

代码部分

OLED.c

OLED.h

main.c

Keil调试模式演示


声明:本专栏是本人跟着B站江科大的视频的学习过程中记录下来的笔记,我之所以记录下来是为了方便自己日后复习。如果你也是跟着江科大的视频学习的,可以配套本专栏食用,如有问题可以QQ交流群:963138186

本篇来学习一下OLED调试工具,至于OLED屏幕的原理和代码编写以后再讲,目前只要知道怎么用的就可以了。

理论部分

这就是OLED显示屏:

我们用OLED当一个调试的显示屏,方便我们调试程序。

这个OLED模块和我之前在51单片机专栏里介绍LCD模块的驱动函数基本都是一模一样的。所以上手这个OLED屏幕应该还是比较容易的。

三种常用的程序调试方法

首先我们先来看一下目前常用的程序调试方式。

这里列举了三种常用的程序调试方法:

第一种是串口调试

第一种是串口调试它是通过串口通信将调试信息发送到电脑端,电脑使用串口助手显示调试信息。这种调试方式是非常见的,就是用串口将单片机连接到电脑相当于把电脑的屏幕挂在单片机上方便单片机显示调试信息。

一般我们设计pcb电路板的时候,都会在pcb边上留一个串口通信的硬件,需要调试程序的时候,把单片机连在电脑上,然后就可以在电脑屏幕打印信息了。

调试好之后,就断开串口程序,就能正常工作了。

第二种是显示屏调试

第二种是显示屏调试它是直接将显示屏连接到单片机,将调试信息打印在显示屏上,这个方法就比较直接,单片机没有显示参数的东西,我们就直接接个屏幕上去。这里我们使用的是这种比较小巧的0.96寸OLED显示屏,使用还是非常方便的。

串口调试和显示屏调试也是各有利弊的:

串口的优势是可以借助强大的电脑来调试,电脑端的软件不仅可以显示单独的参数,而且可以显示曲线、图形、图像等,还可以自己做一个软件,来实现一个强大的用户交互界面。串口调试的弊端就是调试的时候需要拖着电脑,而且通常的串口助手只能以信息流的方式呈现数据,就是只能一行一行的打印。如果有很多不断变化的数据要显示,就只能在电脑上刷屏显示,这样用起来就不太方便。

显示屏调试的优势是对于不断变化的数据可以覆盖刷新显示,而且显示屏可以始终接在单片机上,显示方式很直接。还有一般我们做一些稍微复杂的东西,都会需要有一个人机交互的界面,这样就可以直接把显示屏当做产品的一部分,还是比较好用的。显示屏的弊端就是屏幕太小,显示内容有限,没有电脑软件么强大的功能。

所以这两种方法各有各的适用场景,需要根据实际情况选择合适的方法。

第三种是Keil调试模式

第三种是Keil调试模式它是借助keil软件的调试模式,可使用单步运行,设置断点查看寄存器及变量等高级功能。Keil调试模式的功能还是非常强大的。这个在下一节可以给大家具体演示一下。

其他调试方式

当然除了这三种方法之外,还有很多种程序调试的方法:

比如点灯调试法,即如果你不清楚程序是不是执行到了某个位置,就可以在那个位置放一个点灯的代码,如果运行到了灯就亮,没运行到灯就不亮。

还有注释调试法,如果你的程序原来是好的,但是加了某段程序就死了。这时你可以把新加入的程序全部注释掉,恢复到正常运行的状态,然后依次一行一行的解除注释,直到错误出现。或者注释掉一部分来测试另一部分,然后再注释掉另一部分测试这一部分,减少程序运行的部分,来定位出问题的程序在哪里。

另外还有对照法,就是你跟着别人写了一个的程序,感觉它的逻辑没问题。但是别人的可以运行,你的却不能运行,这时就可以对照一下,在他的程序逻辑上逐步替换成你的程序逻辑。这样就比较容易发现错误在什么地方。

总之测试程序的基本思想就是缩小范围、控制变量、对比测试等,测试的方法是多样的。

OLED显示屏的介绍

我们来看一下OLED显示屏的介绍。

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

OLED显示屏的特点:性能优异的新型显示屏,具有功耗低是因为OLED每一个像素都是一个单独的发光二极管每一个像素都是可以自发光的不像LCD样需要有背光所以OLED屏幕会比较省电、相应速度快这个特性可以使OLED有更高的刷新率总线时序快也可以避免阻塞我们的程序、宽视角(因为OLED屏幕是自发光的,所以在任何角度看显示内容都是清晰的。而LCD的话,如果从上面或者下面斜着看这个屏幕,屏幕就会变黑,很难看清上面的内容。OLED屏幕基本上各个视角都可以看清屏幕)、轻薄柔韧(比如现在手机上的折叠屏,柔性屏等用的就是OLED显示屏)等特点。

我们学习用的0.96寸OLED模块:小巧玲珑、占用接口少、简单易用,是电子设计中非常常见的显示屏模块(这个显示屏也算是单片机领域的一个经典显示屏)。当然它不会像我们手机电脑上的屏幕那么强大,这个OLED一般都只有一种颜色,分辨率也比较低。驱动这个OLED只需要几根线和简单的通信协议,占用资源比较少。

供电:3~5.5V,通信协议:I2C/SPI一般用的是I2C的通信协议,七针脚的屏幕一般用的是SPI的通信协议,分辨率:128*64

OLED有几种规格,第一种就是我们学习使用的

总共有四个针脚,像素是白色的。

右边这里还有一种七针脚版本的,需要占用的IO口就多一些。除了有白色像素的版本,还有蓝色像素的版本和黄蓝双色的版本。这个黄蓝双色并不是真正的双色,它是上面四分之一的像素固定是黄色的,下面四分之三的像素固定是蓝色。这种屏幕适合做一个需要显示标题行的界面。上面的黄色显示标题,下面的蓝色显示内容,这样比较好看一些。

OLED的硬件电路

接着我们来看一下OLED的硬件电路。

这个是四针脚版本的OLED电路,

SCL和SDA是I2C的通信引脚,需要接在单片机I2C通信的引脚上。当然我们用的驱动函数模块用的是GPIO口模拟的I2C通信,所以这两个端口就可以接在任意的GPIO口上。

然后右边七针脚版本的OLED电路也是一样

除了VCC和GND引脚,剩下的引脚是SPI通信协议的引脚,如果是GPIO口模拟的通信协议,也是接在任意的GPIO口上就行了。

最后来看一下驱动函数模块都有哪些东西:

OLED驱动程序中所包含的驱动函数

这个表里的就是OLED驱动程序中所包含的驱动函数,

OLED_Init();

这个是OLED初始化函数,在使用OLED之前需要调用一下这个函数,对OLED进行初始化,然后就可以正常使用了。

OLED_Clear();

这个是清屏函数,调用这个函数屏幕就会清空。

然后下面的这些函数就都是OLED的显示函数了:

OLED的显示函数

OLED_ShowChar(1, 1, 'A');

首先,OLED_ShowChar(1, 1, 'A');

显示一个字符,第一个参数指定起始行。第二个参数指定起始列。第三个参数是要显示的字符,比如一行一列显示字符A,在屏幕上一行一列的位置显示一个A。

OLED_ShowString(1, 3, "HelloWorld!");

接着是OLED_ShowString(1, 3, "HelloWorld!");

显示字符串,比如在一行三列显示字符串。helloword感叹号。

OLED_ShowNum(2, 1, 12345, 5);

然后OLED_ShowNum(2, 1, 12345, 5);

这个是显示无符号十进制数字,前两个参数指定起始坐标。第三个参数是要显示的数字,第四个参数是数字的长度。比如二行一列显示数字12345,长度为5。

OLED_ShowSignedNum(2, 7, -66, 2);

剩下的OLED_ShowSignedNum(2, 7, -66, 2);

就是显示有符号十进制数字,在显示的时候会带一个正负号。

OLED_ShowHexNum(3, 1, 0xAA55, 4);

然后OLED_ShowHexNum(3, 1, 0xAA55, 4);

显示十六进制数。

OLED_ShowBinNum(4, 1, 0xAA55, 16);

显示二进制数。

以下是显示的效果

对应OLED屏幕的坐标图:

以下就是开始演示如何使用OLED显示屏的驱动函数模块

代码部分

首先我们还是看一下接线图,

以后我们就一直把这个屏幕拆在这里,需要用的时候随时可以使用,而且放在右下角也不是很占地方。

我们可以在OLED的下面,像这样先插上两根线,

把OLED的GND引到负极供电孔,OLED的VCC引到正极供电孔。另外这个供电孔也会同时接到STM32的PB6和PB7两个引脚,之后我们直接不初始化这两个引脚就行了。STM32的引脚上电后,如果不初始化,默认是浮空输入的模式。在这个模式下引脚不会输出电平,所以不会有什么影响。

当然你也可以不接这两根跳线

直接给PB6口输出低电平,PB7口输出高电平,用GPIO口直接给OLED供电,这个也是没问题的,因为这个OLED功率很小,所以也是可以驱动的。不过这种用GPIO口供电不是很规范。但是要做实际项目的话,最好还是用电源供电。

插好这两个供电跳线之后,

再把OLED插到PB6到PB9这四个口,这样OLED就接好了。

此时OLED的SCL接到PB8,SDA接到PB9。

接好电路后,我们和之前一样复制上一节的工程文件夹,改一下名字

我们把这个文件夹打开

领取链接:链接:https://pan.baidu.com/s/1Z6TlQZn9S30udgyazkr_Hw

提取码:cbr6

里面有两个版本,

我们打开4针脚的版本的文件夹,里面有三个文件,全部复制

然后到OLED显示屏这个工程里来打开hardware文件夹,把它们粘贴到这里来。

之后打开在Keil里面的hardware组添加这个三个文件的操作和之前的操作都是一样的,不再赘述。

我们打开分别看一下这三个文件都是什么东西。

OLED.c

首先OLED.c里面就是函数的主体代码了,里面包括了引脚配置,引脚初始化,I2C通信的基本时序和OLED用户调用的代码等。

这些函数都已经写好了,绝大部分都不需要更改.

我们需要更改的,就只有上面的这两部分代码:

第一部分是引脚配置,这里选择的是你硬件电路上把SCL和SDA这两个引脚接在了哪两个端口上。比如我们这里SCL接在了PB8。

这个地方就是GPIOB,GPIO_Pin_8,

如果你换个端口,比如接在PA6上,这个地方就要改成GPIOB,GPIO_Pin_6。

下面这个SDA的引脚配置也是一样,SDA接在了哪个位置,这里就改成对应的端口。

然后下面这个OLED_I2C_Init函数里也得更改。

这里面就是把SCL和SDA的两个引脚都初始化为开漏输出的模式。

图片更正为:开漏输出模式

对于这个模块来说,这里默认用的是SCL接PB8,SDA接PB9,如果你想修改,先把上面两行引脚配置改一下,再把下面这里的端口初始化改一下,剩下的都不需要修改,就可以直接使用这个OLED驱动函数模块了

图片更正为:开漏输出模式 

OLED.h

接下来OLED.h里面,这里就是外部可调用函数的声明,

最后是OLED_Font.h文件,这里存的是OLED的字库数据。

因为这个OLED显示屏是不带字库的,想要显示字符图形,还得先定义字符的点阵数据。这里就是这些字符的点阵数据,也就是字库。OLED.c文件的显示函数会用到这些数据,我们需要把这个文件复制过来,放到工程里。当然,字库也是不用我们修改的。

接下来我们试用一下。

main.c

在主函数中调用这些函数,请认真看一下以下代码注释

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	
	/*OLED显示*/
	OLED_ShowChar(1, 1, 'A');				//1行1列显示字符A
	
	OLED_ShowString(1, 3, "HelloWorld!");	//1行3列显示字符串HelloWorld!
	
	OLED_ShowNum(2, 1, 12345, 5);			//2行1列显示十进制数字12345,长度为5,
	//注:如果写长度为6,那么它就会在12345前面补0,如果指定的长度比要显示的数字长度小,那它就会把高位的数据切掉
	
	OLED_ShowSignedNum(2, 7, -66, 2);		//2行7列显示有符号十进制数字-66,长度为2
	//注:指定的长度不包括符号位,如果写OLED_ShowSignedNum(2, 7, 12345, 5)显示效果就是+12345
	
	OLED_ShowHexNum(3, 1, 0xAA55, 4);		//3行1列显示十六进制数字0xA5A5,长度为4
	//注:指定长度不包含0x
	
	OLED_ShowBinNum(4, 1, 0xAA55, 16);		//4行1列显示二进制数字0xA5A5,长度为16
	//注:C语言无法直接写出二进制数字,故需要用十六进制表示,但是在显示屏上我们看到的是二进制数:1010101001010101
	
	//OLED_Clear();//调用这个函数就清屏了,OLED上不会显示任何东西了
	//如果你只想要清除掉部分数据,可以用OLED_ShowString在你想要清掉的地方显示空格字符,
	//比如:
	//OLED_ShowString(1, 3, "           ");
	//这样就把OLED_ShowString(1, 3, "HelloWorld!");这句代码之前显示的HelloWorld!给清除掉了
	
	while (1)
	{
		
	}
}

显示效果:

STM32-OLED调试工具

Keil调试模式演示

接下来演示一下keil的调试模式。

这里用我之前介绍的第一个LED闪烁的工程作为例子。

然后工程选项debug这里可以对调试选项进行配置。

这里默认是选择右边的这一项,这个是在硬件上在线仿真需要我们把stlink或者DAP和STM32都连接好。

如果你不想连接硬件,也可以选择左边的使用仿真器这个选项,这样就是电脑模拟STM32的运行了。

我们就使用硬件的在线仿真。

首先,在进入调试模式之前,需要先连接好STM32之后编译一下,确保工程没有问题。

然后点击这里的放大镜里面带一个d的图标进入调试模式。

在这个界面里,主窗口就是我们的C语言程序。

而上面这个窗口就是C语言翻译成的汇编程序。

感兴趣的话可以对照这里看一下每句c语言实际上都执行了哪些操作。

然后左边的这个窗口是寄存器组和状态标志位等信息。

这个是单片机硬件底层很重要的东西,如果你用汇编编程的话,这些东西都是必须要非常清楚的。但如果你用的是C语言,这些东西就不用管的。

之后上面这一部分是程序运行控制的,

第一个是复第二个是全速运行第三个是停止全速运行。

接着后面四个分别是单步运行跳过当前行单步运行跳出当前函数单步运行跳到光标指定行单步运行。

我们可以试一下:

这个黄色箭头指示的就是下一句将要执行的代码

我们当前的程序就是从main函数开始的,我们可以点一下单步运行,它就执行到了下一行,

然后再单步,它就进到了RCC这个函数里面来了,

点击这个跳出函数,它就可以跳到函数外面来了,

指定这一行,

然后点击运行到光标指定行,程序就运行到这个位置了。

我们可以点击程序,左边这里深灰色的区域设置断点。

然后点击全速运行,程序就会一直运行,直到断点停下。如果没有断点的话,再全速运行程序就不会自动停下来了。我们就需要点击这里的停止按钮,这样程序就会停下来了。

然后我们点击RST复位,程序就会回到最开始的地方,

这里我们可以看到现在程序是在启动文件的复位中断函数里,

说明复位后程序是从这里开始执行的,我们点击单步运行后,可以看到程序会跳到SystemInit函数里。

这里继续单步运行,然后跳出函数继续运行,应该就会执行main函数,不过它突然停不下来了,没关系,我们点击停止一下,然后点击复位,然后指定到main函数,点击直接运行到当前行,现在可以看到程序就执行到了这一行然后停下来了

这就是调试模式下控制程序运行的方法,这个方法可以精确追踪我们的程序是如何运行的。

如果你不清楚程序是如何一步步运行的在这个调试模式里,单步运行探索一下。

接着我们来看一下上面的这一堆功能。

第一个是命令窗口,我们点击它可以打开和关闭命令窗口。

第二个是反汇编窗口,可以打开和关闭上面的汇编窗口。

第三个是符号窗口。

点击后右边会出现如图所示窗口,在这里我们可以实时查看程序中所有变量的值,

比如想看一下这个GPIO_InitStructure结构体的值

就可以在这个窗口里找一下,main.c里面,然后main函数这里就可以看到这个变量了。

里面可以看到结构体的三个成员。

如果想看一下结构体值的变化,可以在这里右键。添加到watch1窗口。

在这里就能看到结构体的值了。

比如我们在这里单步运行GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0这一句后,这里就能看到这个变量值的变化了。

然后剩下的这里还有串口显示、逻辑分析仪等等。

这些工具的功能也都是非常强大的,大家可以自行了解一下。

另外我们还可以点击这个外设菜单栏,系统资源,查看这里就可以看到所有的外设寄存器。

比如我们选择GPIOA

右边的这里就会显示GPIOA外设的所有寄存器。

我们这个程序是翻转PA0端口,我们就可以看一下ODR寄存器,这个就是PA0的输出数据寄存器,

接下来我们运行,可以看到这个ODR0是实时显示输出寄存器的变化的。

我们再在面包板上的PA0插上一个LED。可以看到,STM32也是在实施执行程序的。

虽然说这个实时变化会有一些延迟,但不得不说这个在线调试的功能还是非常强大的。

STM32实时执行程序,Keil软件实时显示外设寄存器状态,还能随时控制程序的开始、停止、单步运行。

所以当你以后遇到一个比较难调的程序,比如不清楚程序是如何执行的,或者想要看一大堆变量,却不方便显示的,或者想看一下寄存器是不是配置正确了。都可以考虑一下使用这个keil自带的调试模式。

最后再说明一下,如果你想修改程序的话,是不能直接在这个调试模式下修改的,修改程序得先退出调试模式

点击原来这里可以退出调试模式

重新编译后,再进入调试模式。

我们也可以点这里的帮助,第一项这里可以打开keil软件的官方帮助文档,

这个帮助文档里有对这整个软件最权威最细致的介绍。

如果你对某个功能不熟悉的话,可以在这里找一找。

以上就是本节的全部内容,我们下篇继续。

QQ交流群:963138186

本篇就到这里,下篇继续!欢迎点击下方订阅本专栏↓↓↓

  • 38
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32是一款非常流行的嵌入式微控制器系列,它具有强大的性能和丰富的外设资源。在学习STM32时,掌握如何进行Flash读写是非常重要的。 Flash是一种非易失性存储器,可以用来存储程序代码和数据。在STM32中,Flash存储器通常用来存储应用程序代码。下面是一个简单的Flash读写程序的示例: 1.首先,我们需要包含适用于所使用的STM32型号的头文件。例如,对于STM32F4系列,我们需要包含"stm32f4xx.h"。 2.然后,我们需要定义一个指向Flash存储器的指针变量。例如,可以使用如下代码:`uint32_t* flash_address = (uint32_t*)0x08000000;`其中0x08000000是Flash存储器的起始地址。 3.要读取Flash存储器中的数据,我们可以通过以下代码实现:`data = *flash_address;`其中data是一个变量,用于存储读取到的数据。 4.要写入数据到Flash存储器中,我们可以通过以下代码实现:`*flash_address = data;`其中data是要写入的数据。 需要注意的是,STM32的Flash存储器是有写保护机制的,因此在写入数据之前,我们需要禁用写保护。可以使用以下代码禁用写保护:`FLASH->KEYR = 0x45670123; FLASH->KEYR = 0xCDEF89AB;`然后才能进行数据写入。 另外,为了确保数据的完整性,我们可以使用CRC校验来验证Flash存储器中的程序代码的正确性。可以使用库函数来计算校验和,然后将其与预期的校验和进行比较以进行验证。 综上所述,掌握STM32的Flash读写操作对于嵌入式系统的开发非常重要。上述示例代码可以帮助我们快速进行Flash读写操作,同时注意写保护和数据校验可以提高数据的安全性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vera工程师养成记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值