第10周作业--汉字点阵与OLED屏显

目录

前言

一、任务要求

二、任务一:串口传输文件

​编辑

三、任务二:点阵字型显示

1、点阵字库原理

2、实验步骤

1)前期准备

2)代码及文本编写

3)编译运行

四、任务三:OLED屏显

1、了解SPI

2、了解OLED

3、前期准备

4、显示自己的学号和姓名

1)代码修改

2)编译

3)实物连接

4)烧录

5、显示AHT20的温度和湿度

1)前期准备

2)文字生成

3)代码修改

4)编译烧录

​编辑

​编辑

5)实际效果及实物连接图

6、左右的滑动显示长字符

参考资料:

总结


前言

        本文记录学校嵌入式开发课程的第十周作业,学习OLED相关的知识并能运用其与Ubuntu系统结合,在屏幕上显示文字。


一、任务要求

1、串口传输文件的练习。将两台笔记本电脑,借助 usb转rs232 模块和杜邦线,建立起串口连接。然后用串口助手等工具软件(带文件传输功能)将一台笔记本上的一个大文件(图片、视频和压缩包软件)传输到另外一台电脑,预算文件大小、波特率和传输时间三者之间的关系,并对比实际传输时间。

2、学习理解汉字的机内码、区位码编码规则和字形数据存储格式。在Ubuntu下用C/C++(或python) 调用opencv库编程显示一张图片,并打开一个名为"logo.txt"的文本文件(其中只有一行文本文件,包括你自己的名字和学号),按照名字和学号去读取汉字24*24点阵字形字库(压缩包中的文件HZKf2424.hz)中对应字符的字形数据,将名字和学号叠加显示在此图片右下位置。

3、理解OLED屏显和汉字点阵编码原理,使用STM32F103的SPI或IIC接口实现以下功能:

        1) 显示自己的学号和姓名; 

        2) 显示AHT20的温度和湿度;

        3) 上下或左右的滑动显示长字符,比如“Hello,欢迎来到物联网实训室!”或者一段歌词或诗词(最好使用硬件刷屏模式)。

二、任务一:串口传输文件

1、硬件连接:准备两台电脑,若干杜邦线,和两块USB转TTL模块,将USB转TTL模块的RXD与TXD相连接,并分别接在两台电脑上,此时基本连接完成。

2、打开串口调试助手,选择好文件,两台电脑均设置波特率为2000000,点击发送文件,等待发送完毕后,如下图。

3、发现另外一台电脑接收完毕后,点击下方保存数据。

4、在保存路径中,将DAT文件修改后缀名为JPG,并保存。

即可查看传输的文件:

三、任务二:点阵字型显示

1、点阵字库原理

显示原理

        点阵字库是把每一个汉字都分成16×16或24×24个点,然后用每个点的虚实来表示汉字的轮廓,常用来作为显示字库使用,这类点阵字库汉字最大的缺点是不能放大,一旦放大后就会发现文字边缘的锯齿。

        所有的汉字或者英文都是下面的原理,

  由左至右,每8个点占用一个字节,不足8个字节的占用一个字节,而且从位向位排列。

  生成的字库说明:(以12×12例子)

  一个汉字占用字节数:12÷8=1····4也就是占用了2×12=24个字节。

  编码排序A0A0→A0FE A1A0→A2FE依次排列。

  以12×12字库的“我”为例:“我”的编码为CED2,所以在汉字排在CEH-AOH=2EH区的D2H-A0H=32H个。所以在12×12字库的起始位置就是[{FE-A0}*2EH+32H]*24=104976开始的24个字节就是我的点阵模。

  其他的类推即可。

  英文点阵也是如此推理。

与字符字模:

        在dos终端模式下是不可以显示中文汉字的,只能显示英文。

  汉字与英文的区别是:

  1. 汉字字库中,任何字符均用2个字节编码,即区码和位码,在英文字库中,所有字符均用单字节编码。

  2. 16点阵汉字字库(16*16)用32个字节存储一个字符的字模,16点阵英文字库(8*16)用16个字节存储单个字符的字模。

  在DOS终端模式下用的是16点阵英文字库,如果要让DOS终端中显示中文,可以改写终端模式下的16点阵英文字库,使其显示的不是原有的英文字符,而是汉字字符,当然也可以加入自造点阵图形图像。原理为:

  我们输入AB,正常显示的是AB,但如果改变AB的字模,用汉字的字模代替,这样输入AB字符,并不显示AB,而是显示一个汉字。将一个汉字从中间劈为两半,左面部分顶替A的字模,右面部分顶替B的字模。

  dos所用字库,文件头结构很简单,如默认的8*16英文字库,文件头长度为4,跳过这四个字节就是字模数据;也有没有文件头的,从个字节开始就是字模数据。

汉字编码

        1)区位码
        在国标GD2312-80中规定,所有的国标汉字及符号分配在一个94行、94列的方阵中,方阵的每一行称为一个"区",编号为01区到94区,每一列称为一个"位",编号为01位到94位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿拉伯数字就是它们的"区位码"。区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一的区位码。汉字"母"字的区位码是3624,表明它在方阵的36区24位,问号"?"的区位码为0331,则它在03区3位。
        2)机内码
        汉字的机内码是指在计算机中表示一个汉字的编码。机内码与区位码稍有区别。如上所述,汉字区位码的区码和位码的取值均在1~94之间,如直接用区位码作为机内码,就会与基本ASCII码混淆。为了避免机内码与基本ASCII码的冲突,需要避开基本ASCII 码中的控制码(O0H~1FH),还需与基本ASCII码中的字符相区别。为了实现这两点,可以先在区码和位码分别加上20H,在此基础上再加80H(此处"H"表示前两位数字为十六进制数)。经过这些处理,用机内码表示一个汉字需要占两个字节,分别称为高位字节和低位字节,这两位字节的机内码按如下规则表示:
                   高位字节=区码+20H + 80H(或区码+AOH)

                   低位字节=位码+20H + 80H(或位码+AOH)
        由于汉字的区码与位码的取值范围的十六进制数均为01H~5EH(即十进制的01~94),所以汉字的高位字节与低位字节的取值范围则为A1H~FEH(即十进制的161~254)。
        例如,汉字"啊"的区位码为1601,区码和位码分别用十六进制表示即为1001H,它的机内码的高位字节为BOH,低位字节为A1H,机内码就是B0A1H。

结构

        1)点阵字库存储

        在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0代表没有,1代表有点,将0和1分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有12*12, 14*14, 16*16三种字库。

  字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期UCDOS字库),纵向矩阵一般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库矩阵做成纵向,省得在显示时还要做矩阵转换。我们接下去所描述的都是指横向矩阵字库。

  2)16*16点阵字库

  对于16*16的矩阵来说,它所需要的位数共是16*16=256个位,每个字节为8位,因此,每个汉字都需要用256/8=32个字节来表示。

  即每两个字节代表一行的16个点,共需要16行,显示汉字时,只需一次性读取32个字节,并将每两个字节为一行打印出来,即可形成一个汉字。

  点阵结构如下图所示:

  字节 第二字节

  0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7

  0

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  14

  15

  3)14*14与12*12点阵字库

  对于14*14和12*12的字库,理论上计算,它们所需要的点阵分别为(14*14/8)=25, (12*12/8)=18个字节,但是,如果按这种方式来存储,那么取点阵和显示时,由于它们每一行都不是8的整位数,因此,就会涉到点阵的计算处理问题,会增加程序的复杂度,降低程序的效率。

  为了解决这个问题,有些点阵字库会将14*14和12*12的字库按16*14和16*12来存储,即,每行还是按两个字节来存储,但是14*14的字库,每两个字节的两位是没有使用,12*12的字节,每两字节的4位是没有使用,这个根据不同的字库会有不同的处理方式,所以在使用字库时要注意这个问题,特别是14*14的字库。

点阵字库存储

        在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0代表没有,1代表有点,将0和1分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有1212, 1414, 16*16三种字库。

字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期UCDOS字库),纵向矩阵一般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库矩阵做成纵向,省得在显示时还要做矩阵转换。我们接下去所描述的都是指横向矩阵字库。

2、实验步骤

1)前期准备

        下载汉字点阵库及显示工具:

        在Ubuntu环境下安装opencv

        这里玻珠给出安装参考链接:【精选】Ubuntu系统安装opencv详细操作及具体应用_ubuntu opencv_加菲猫不爱吃猫粮的博客-CSDN博客

        在Ubuntu系统中建立文件夹asic,并将实验文件放进去,具体如下:

        PS:图片自行准备。 

2)代码及文本编写

        (1)文本编写

        打开logo.txt,输入一行文本,即自己的名字和学号,用来在图片上显示。这里注意,文本保存编码方式要选择ANSI,否则后续显示会乱码。

        (2)代码编写

        由于需要在asic文件夹下进行操作,在Ubuntu中打开终端后输入:

    cd asic

        进入asic文件夹。

        用vim编辑器,创建asic.cpp文件:

        并在asic.cpp文件中输入如下代码:

#include<iostream>
#include<opencv/cv.h>
#include"opencv2/opencv.hpp"
#include<opencv/cxcore.h>
#include<opencv/highgui.h>
#include<math.h>

using namespace cv;
using namespace std;

void paint_chinese(Mat& image,int x_offset,int y_offset,unsigned long offset);
void paint_ascii(Mat& image,int x_offset,int y_offset,unsigned long offset);
void put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path);

int main(){
    String image_path="mao.jpg";//图片的名字
    char* logo_path="logo.txt";//汉字文件的名字
    put_text_to_image(350,800,image_path,logo_path);//change txt place
    return 0;
}

void paint_ascii(Mat& image,int x_offset,int y_offset,unsigned long offset){
    //绘制的起点坐标
	Point p;
	p.x = x_offset;
	p.y = y_offset;
	 //存放ascii字膜
	char buff[16];           
	//打开ascii字库文件
	FILE *ASCII;

	if ((ASCII = fopen("Asci0816.zf", "rb")) == NULL){
		printf("Can't open ascii.zf,Please check the path!");
		//getch();
		exit(0);
	}

	fseek(ASCII, offset, SEEK_SET);
	fread(buff, 16, 1, ASCII);

	int i, j;
	Point p1 = p;
	for (i = 0; i<16; i++)                  //十六个char
	{
		p.x = x_offset;
		for (j = 0; j < 8; j++)              //一个char八个bit
		{
			p1 = p;
			if (buff[i] & (0x80 >> j))    /*测试当前位是否为1*/
			{
				/*
					由于原本ascii字膜是8*16的,不够大,
					所以原本的一个像素点用4个像素点替换,
					替换后就有16*32个像素点
					ps:感觉这样写代码多余了,但目前暂时只想到了这种方法
				*/
				circle(image, p1, 0, Scalar(0, 0, 255), -1);
				p1.x++;
				circle(image, p1, 0, Scalar(0, 0, 255), -1);
				p1.y++;
				circle(image, p1, 0, Scalar(0, 0, 255), -1);
				p1.x--;
			   circle(image, p1, 0, Scalar(0, 0, 255), -1);
			}						
            p.x+=2;            //原来的一个像素点变为四个像素点,所以x和y都应该+2
		}
		p.y+=2;
	}
}
void paint_chinese(Mat& image,int x_offset,int y_offset,unsigned long offset){//在图片上画汉字
    Point p;
    p.x=x_offset;
    p.y=y_offset;
    FILE *HZK;
    char buff[72];//72个字节,用来存放汉字的

    if((HZK=fopen("HZKf2424.hz","rb"))==NULL){
        printf("Can't open HZKf2424.hz,Please check the path!");
        exit(0);//退出
    }
    fseek(HZK, offset, SEEK_SET);/*将文件指针移动到偏移量的位置*/
    fread(buff, 72, 1, HZK);/*从偏移量的位置读取72个字节,每个汉字占72个字节*/
    bool mat[24][24];//定义一个新的矩阵存放转置后的文字字膜
    int i,j,k;
    for (i = 0; i<24; i++)                 /*24x24点阵汉字,一共有24行*/
	{
        	for (j = 0; j<3; j++)                /*横向有3个字节,循环判断每个字节的*/
			for (k = 0; k<8; k++)              /*每个字节有8位,循环判断每位是否为1*/
				if (buff[i * 3 + j] & (0x80 >> k))    /*测试当前位是否为1*/
				{
					mat[j * 8 + k][i] = true;          /*为1的存入新的字膜中*/
				}
				else {
					mat[j * 8 + k][i] = false;
				}
	}
	
    for (i = 0; i < 24; i++)
	{
		p.x = x_offset;
		for (j = 0; j < 24; j++)
		{		
			if (mat[i][j])
				circle(image, p, 1, Scalar(255, 0, 0), -1);	  //写(替换)像素点
			p.x++;                                                //右移一个像素点
		}
		p.y++;                                                    //下移一个像素点
	}
}

void put_text_to_image(int x_offset,int y_offset,String image_path,char* logo_path){//将汉字弄上图片
//x和y就是第一个字在图片上的起始坐标
    //通过图片路径获取图片
    Mat image=imread(image_path);
    int length=19;//要打印的字符长度(打印多少字节长度就为多少,根据自己的情况调整)
    unsigned char qh,wh;//定义区号,位号
    unsigned long offset;//偏移量
    unsigned char hexcode[30];//用于存放记事本读取的十六进制,记得要用无符号
    FILE* file_logo;

    if ((file_logo = fopen(logo_path, "rb")) == NULL){
		printf("Can't open txtfile,Please check the path!");
		//getch();
		exit(0);
	}

    fseek(file_logo, 0, SEEK_SET);
    fread(hexcode, length, 1, file_logo);
    int x =x_offset,y = y_offset;//x,y:在图片上绘制文字的起始坐标

    for(int m=0;m<length;){
        if(hexcode[m]==0x23){
            break;//读到#号时结束
        }
        else if(hexcode[m]>0xaf){
            qh=hexcode[m]-0xaf;//使用的字库里是以汉字啊开头,而不是以汉字符号开头
            wh=hexcode[m+1] - 0xa0;//计算位码
            offset=(94*(qh-1)+(wh-1))*72L;
            paint_chinese(image,x,y,offset);
            /*
            计算在汉字库中的偏移量
            对于每个汉字,使用24*24的点阵来表示的
            一行有三个字节,一共24行,所以需要72个字节来表示
            */

            m=m+2;//一个汉字的机内码占两个字节,
            x+=24;//一个汉字为24*24个像素点,由于是水平放置,所以是向右移动24个像素点
        }

        else{
        //当读取的字符为ASCII码时
        wh=hexcode[m];
        offset=wh*16l;//计算英文字符的偏移量
        paint_ascii(image,x,y,offset);
        m++;//英文字符在文件里表示只占一个字节,所以往后移一位就行了
        x+=16;
        }

    }

    cv::imshow("image", image);
    cv::waitKey();
}

        考虑到代码与实际情况需匹配,所以根据每个人的文件命名不同对部分代码要做修改,具体如下:

        图片的名字需要修改;并且根据每个图片尺寸不同,需修改文本显示的位置,使其按照题目要求出现在右下角,我这里设置的为“350,800”,当然也可以在后续显示的时候再进行调整。

        找到put_text_to_image函数,修改打印的字符长度,这也是根据实际情况来修改的,汉字算两个长度,数字算一个长度,我这里例子就需要打印19个。 

        修改完毕后,按下esc键,输入“:wq”即保存退出。

3)编译运行

        编译指令如下:

    g++ asic.cpp -o asic `pkg-config --cflags --libs opencv`

        注意这里的引号是从键盘左上角数字1的左边键入的。

        输入“ls”查看文件夹下包含的文件,出现该文件即成功。

        输入“./asic”,运行程序,成功在图片右下角显示自己的名字和学号。

四、任务三:OLED屏显

1、了解SPI

(1)SPI定义

        SPI(Serial Peripheral Interface)就是串行外围设备接口。是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚。SPI 是一个环形总线结构,由 ss(cs)、sck、sdi、sdo 构成,时序主要是在 sck 的控制下,两个双向移位寄存器进行数据交换。
        上升沿发送、下降沿接收、高位先发送。
        上升沿到来的时候,sdo 上的电平将被发送到从设备的寄存器中。
        下降沿到来的时候,sdi 上的电平将被接收到主设备的寄存器中。
(2)SPI时序

        上图中的时序只是 SPI 其中一种通讯模式,SPI 一共有四种通讯模式,它们的主要区别是总线空闲时 SCK 的时钟状态以及数据采样时刻。为方便说明,在此引入“时钟极性 CPOL”和“时钟相位 CPHA”的概念。
        时钟极性 CPOL 是指 SPI 通讯设备处于空闲状态时,SCK 信号线的电平信号(即 SPI 通讯开始前、 NSS 线为高电平时 SCK 的状态)。CPOL=0 时, SCK 在空闲状态时为低电平,CPOL=1 时,则相反。
        时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时,MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的“奇数边沿”被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿”采样。

(3)SPI的连接方式

SS( Slave Select):从设备选择信号线,常称为片选信号线。
SCK (Serial Clock):时钟信号线,用于通讯数据同步。
MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。
MISO(Master Input,,Slave Output):主设备输入/从设备输出引脚。

2、了解OLED

        OLED即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED 由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。

        在本次实验中采用的是七针OLED板,具体接线情况如下表所示。

3、前期准备

OLED模块配套资料包下载链接:

0.96寸SPI_OLED模块配套资料包

汉字生成软件下载链接:

【资源下载】PCtoLCD2002 下载 资源分享 OLED取模软件_pctolcd2002下载-CSDN博v

4、显示自己的学号和姓名

1)代码修改

在下载好的模板文件里找到Demo:

选择STM32文件:

找到文件名为“0.96inch_OLED_Demo_STM32F103RCT6_Software_4-wire_SPI”的文件:

在该文件夹下打开project文件:

打开keil5文件:

打开main.c文件,根据实验,仅需要一个函数,所以将其他函数注释掉:

打开test.c文件,找到刚刚主函数中的对应的函数,对其进行修改,即添加需要在屏幕上显示的内容:

根据如下路径,找到OLEDFONT.h文件:

找到该函数:

这里需要打开PCtoLCD即汉字生成软件,上面有下载链接:

点击设置:

按照下图进行配置,然后点击确定保存:

在文本框内输入需要生成的文字,点击生成字模,下面就会出现对应的代码:

将代码复制过来,并按照上面的格式进行微调:

2)编译

进行编译,发现没有错误

3)实物连接

OLED板和STM32板连接可参考下图,STM32与USB转TTL接口可参考我之前的文章,方便大家参考,还是直接拍照贴上来了:

4)烧录

将USB与电脑连接后,打开烧录软件进行烧录:

烧录成功后,显示屏上就会出现如下文字:

5、显示AHT20的温度和湿度

1)前期准备

将OLED数据显示代码添加到之前的AHT20温湿度传感器数据采集工程的USER文件夹下:

2)文字生成

同样在PCtoLCD2002中生成文字显示代码:

将代码添加到OLEDFONT.h文件中:

3)代码修改

修改温湿度显示代码:

void read_AHT20(void)
{
	uint8_t   i;
	for(i=0; i<6; i++)
	{
		readByte[i]=0;
	}

	//-------------
	I2C_Start();

	I2C_WriteByte(0x71);
	ack_status = Receive_ACK();
	readByte[0]= I2C_ReadByte();
	Send_ACK();

	readByte[1]= I2C_ReadByte();
	Send_ACK();

	readByte[2]= I2C_ReadByte();
	Send_ACK();

	readByte[3]= I2C_ReadByte();
	Send_ACK();

	readByte[4]= I2C_ReadByte();
	Send_ACK();

	readByte[5]= I2C_ReadByte();
	SendNot_Ack();
	//Send_ACK();

	I2C_Stop();

	//--------------
	if( (readByte[0] & 0x68) == 0x08 )
	{
		H1 = readByte[1];
		H1 = (H1<<8) | readByte[2];
		H1 = (H1<<8) | readByte[3];
		H1 = H1>>4;

		H1 = (H1*1000)/1024/1024;

		T1 = readByte[3];
		T1 = T1 & 0x0000000F;
		T1 = (T1<<8) | readByte[4];
		T1 = (T1<<8) | readByte[5];

		T1 = (T1*2000)/1024/1024 - 500;

		AHT20_OutData[0] = (H1>>8) & 0x000000FF;
		AHT20_OutData[1] = H1 & 0x000000FF;

		AHT20_OutData[2] = (T1>>8) & 0x000000FF;
		AHT20_OutData[3] = T1 & 0x000000FF;
	}
	else
	{
		AHT20_OutData[0] = 0xFF;
		AHT20_OutData[1] = 0xFF;

		AHT20_OutData[2] = 0xFF;
		AHT20_OutData[3] = 0xFF;
		printf("lyy");

	}
	printf("\r\n");
	
	printf("温度:%d%d.%d",T1/100,(T1/10)%10,T1%10);
	printf("湿度:%d%d.%d",H1/100,(H1/10)%10,H1%10);
	printf("\r\n");
	t=T1/10;
	t1=T1%10;
	a=(float)(t+t1*0.1);
	h=H1/10;
	h1=H1%10;
	b=(float)(h+h1*0.1);
	sprintf(strTemp,"%.1f",a);   //调用Sprintf函数把DHT11的温度数据格式化到字符串数组变量strTemp中  
  sprintf(strHumi,"%.1f",b);    //调用Sprintf函数把DHT11的湿度数据格式化到字符串数组变量strHumi中  
	//printf(strTemp);
	//printf("/r/n");
	GUI_ShowCHinese(16,00,16,"温湿度显示",1);
	GUI_ShowCHinese(16,20,16,"温度",1);
	GUI_ShowString(53,20,strTemp,16,1);
	GUI_ShowCHinese(16,38,16,"湿度",1);
	GUI_ShowString(53,38,strHumi,16,1);
	delay_ms(1500);		
	delay_ms(1500);
	delay_ms(1500);
	delay_ms(1500);
	
}

修改主函数:

代码如下:

#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"

int main(void)
{	
	delay_init();	    	       //延时函数初始化    	  
	uart_init(115200);	 
	IIC_Init();
		  
	NVIC_Configuration(); 	   //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 	
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0); 
	while(1)
	{
		//printf("温度湿度显示");
		read_AHT20_once();
		OLED_Clear(0); 
		delay_ms(1500);
  }
}

4)编译烧录

修改完后进行编译,发现无错误,生成hex文件:

打开烧录软件,找到上一步生成的hex文件,进行烧录:

5)实际效果及实物连接图

烧录后的效果如下图,可以看到温湿度在改变:

实物连接其实就是在原来连接的基础上将温湿度传感器通过面包板与STM32模块连接起来,端口具体连接可以参考上一篇文章,这里为了方便参考也是直接把图放出来:

6、左右的滑动显示长字符

这一步的程序可以沿用显示名字和学号的代码,只需要对主函数进行修改:

int main(void)
{	
	delay_init();	    	       //延时函数初始化	  
	NVIC_Configuration(); 	   //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 	
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0);             //清屏(全黑)
	OLED_WR_Byte(0x2E,OLED_CMD);        //关闭滚动
    OLED_WR_Byte(0x27,OLED_CMD);        //水平向左或者右滚动 26/27
    OLED_WR_Byte(0x00,OLED_CMD);        //虚拟字节
	OLED_WR_Byte(0x00,OLED_CMD);        //起始页 0
	OLED_WR_Byte(0x07,OLED_CMD);        //滚动时间间隔
	OLED_WR_Byte(0x07,OLED_CMD);        //终止页 7
	OLED_WR_Byte(0x00,OLED_CMD);        //虚拟字节
	OLED_WR_Byte(0xFF,OLED_CMD);        //虚拟字节
	TEST_MainPage();
	OLED_WR_Byte(0x2F,OLED_CMD);        //开启滚动
	while(1) 
	{}
}

然后进行编译,无错误:

实物连接也与第一个的连接相同,就不多展示了。然后进行烧录,可以看到成功烧录:

实际效果图如下:

参考资料:

0.96inch SPI OLED Module - LCD wiki

【精选】基于SPI通信方式的OLED显示_oled spi 时序-CSDN博客

【精选】【嵌入式16】STM32+OLED屏显应用实例_基于stm32智能实现播放音乐,同时oled上显示播放音乐-CSDN博客


总结

        以上就是本次实验的全部内容,通过本次实验我学会了在Ubuntu系统下完成opencv的安装,以及在图片中添加文字,在此过程中我遇到了汉字会出现乱码的问题,经过询问同学发现是文本文档的编码方式选错了,修改过后也是成功完成任务;对OLED的原理及其使用方法也有了一定的了解,同时也锻炼了我的线路连接能力,动手实操能力。本次实验受益良多,也学到了很多知识,希望读者也能从中有所收获。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在STM32控制OLED示时,可以使用以下函数来实现: 1. `OLED_Init()`函数用于初始化OLED幕。 2. `OLED_Clear()`函数用于清除幕上的内容。 3. `OLED_ShowChar()`函数用于在指定位置示一个字符。 4. `OLED_ShowNum()`函数用于在指定位置示一个数字。 5. `OLED_ShowString()`函数用于在指定位置示一个字符串。 此外,还可以使用`OLED_DrawPoint()`函数来在指定位置绘制一个点,使用`OLED_Fill()`函数来填充一个矩形区域,使用`OLED_Refresh_Gram()`函数来刷新示。 在控制OLED示时,需要使用SPI接口来与幕进行通信。可以使用`OLED_WR_Byte()`函数来向SSD1306写入一个字节的数据或命令。其中,`dat`参数表示要写入的数据,`cmd`参数表示数据或命令的标志,0表示命令,1表示数据。 综上所述,你可以使用以上提到的函数来控制STM32控制OLED幕的示。 #### 引用[.reference_title] - *1* [使用STM32实现OLED](https://blog.csdn.net/qq_52362275/article/details/127573490)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [基于stm32的oled示](https://blog.csdn.net/ababababa23/article/details/126438483)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值