汉字点阵与OLE屏显

汉字点阵与OLE屏显
一、串口传输文件
串口传输文件是一种通过串行通信接口进行文件传输的方式。在工业自动化、数据采集、仪器仪表等领域,经常需要将数据或文件通过串口发送到其他设备或计算机上。
在进行串口传输文件时,需要注意以下几点:

  1. 确定传输协议:串口传输文件需要制定传输协议,包括数据格式、波特率、校验位、停止位等参数。根据实际需求,可以选择通用的协议如RS-232、RS-485等,也可以自定义协议。
  2. 选择传输模式:串口传输文件可以选择同步或异步模式。同步模式要求发送和接收设备时钟同步,而异步模式则不需要。根据实际需求选择合适的传输模式。
  3. 准备文件:将要传输的文件进行格式转换和处理,以便于通过串口进行传输。通常可以将文件转换为二进制格式,以便于传输。
  4. 发送数据:将文件数据按照传输协议打包成串口可识别的数据帧,然后通过串口发送出去。在发送过程中需要注意数据的完整性和正确性,可以采用校验位等方式进行错误检测和纠正。
  5. 接收数据:接收端接收到数据后,需要按照传输协议对数据进行解析和处理,然后保存为文件。在接收过程中也需要对数据进行完整性和正确性的检测和纠正。
    总之,串口传输文件需要制定好传输协议和选择合适的传输模式,然后对文件进行处理和打包,最后通过串口发送出去。在接收端需要对数据进行解析和处理,并保存为文件。
    在这里插入图片描述
    二、使用opencv显示图片
    汉字点阵介绍
    (一)国标码(交换码)
    国标码
    国标码是一个四位十六进制数,它将一个汉字用两个字节表示,每个字节只有7位,与ASCII码相似。为了避开ASCII字符中的不可显示字符0000 0000 ~ 0001 1111(十六进制为0 ~ 1F,十进制为0 ~ 31)及空格字符0010 0000(十六进制为20,十进制为32)(至于为什么要避开、又为什么只避开ASCII中0~32的不可显示字符和空格字符,后文有解释),国标码(又称为交换码)规定表示汉字的范围为(0010 0001,0010 0001) ~ (0111 1110,0111 1110),十六进制为(21,21) ~ (7E,7E),十进制为(33,33) ~ (126,126)
    举例:“万”字的国标码十进制为:(45+32,82+32) = (77,114)
    (二)汉字机内码
    汉字机内码是计算机内部用于处理和传输汉字的编码,也称为汉字ASCII码或内码。它是将汉字通过特定的算法转换为由0和1符号组成的二进制代码,以便在计算机内部进行存储和传输。汉字机内码的基础是汉字国标码,它是中国国家标准的汉字编码。为了解决汉字机内码与西文机内码之间的二义性问题,大部分汉字系统采用将国标码每个字节高位置1作为汉字机内码。这样既保证了汉字机内码的唯一性,又使其与西文机内码之间具有简单的对应关系。在计算机内部,输入的汉字外码(即键盘输入的编码)首先被转换为机内码,然后才能被存储和处理。这个转换过程由汉字操作系统的“输入码转换模块”完成,与所采用的键盘输入法无关。总之,汉字机内码是计算机处理和传输汉字的重要编码方式,它保证了汉字在计算机内部的唯一性和兼容性。
    举例:“啊”字的汉字机内码则是B0A1H。
    (三)汉字区位码
    汉字区位码是用于汉字编码的一种方法,它把汉字集中分到不同的区位,每个区位包含一定数量的汉字。区位码的编码方式是将汉字分为94个区,每个区对应一个十进制的区码;然后再将每个区中的汉字分为94个位,每个位对应一个十进制的位码。这样,通过区码和位码就可以唯一地确定一个汉字。在计算机内部,汉字区位码被广泛用于汉字的存储和传输,以及汉字输入法的编码。它与汉字机内码不同,汉字机内码是计算机内部用于处理和传输汉字的编码,而汉字区位码则是用于将汉字进行分类和定位的编码。需要注意的是,汉字区位码并不是唯一的编码方式,还有其他一些汉字编码方式,如汉字Unicode码、汉字GBK编码等。这些编码方式都有各自的特点和应用范围。
    GB2312字符集中区位码位置
    (1)01~09区(682个):特殊符号、数字、英文字符、制表符等,包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母等在内的682个全角字符;
    (2)10~15区:空区,留待扩展;
    (3)16~55区(3755个):常用汉字(也称一级汉字),按拼音排序;
    (4)56~87区(3008个):非常用汉字(也称二级汉字),按部首/笔画排序;
    (5)88~94区:空区,留待扩展。
    (四)汉字机内码、国标码和区位码三者关系
    国标码 = 区位码 + 2020H;
    机内码 = 国标码 + 8080H;
    (五)汉字字形储存格式
  6. 点阵字库存储
    点阵字库存储是最常见的汉字字形存储方式之一。它将每个汉字的字形用一系列黑白点阵表示,每个点对应一个二进制位,用来表示该位置的像素点是否为黑色。这种存储方式具有直观、易于理解的特点,被广泛应用于各种计算机系统中。
    点阵字库存储的优点在于其表现形式直观,可以直接观察到汉字的字形效果。此外,由于每个汉字的字形都存储在一张点阵图中,因此可以实现汉字的快速查找和显示。然而,点阵字库存储也存在一些缺点,主要是存储空间较大,对于大量的汉字需要占用大量的计算机存储空间。此外,由于点阵字库存储的字形是固定的,因此无法实现缩放和旋转等操作,这对于一些需要灵活处理汉字的应用场景来说不太适用。
  7. 矢量字库存储
    矢量字库存储是一种基于矢量图形的汉字字形存储方式。它将每个汉字的字形用一系列数学公式(矢量图形)表示,这些公式描述了汉字的轮廓和笔画。矢量字库存储的优点在于其存储空间较小,并且可以方便地进行缩放和旋转等操作。此外,由于矢量字库存储的字形是矢量图形,因此可以在不失真的情况下进行放大或缩小,这对于一些需要打印或显示较大尺寸汉字的应用场景来说非常适用。
    矢量字库存储的缺点在于其表现形式不够直观,需要一定的专业知识才能理解其数学公式所代表的字形。此外,由于矢量字库存储的字形是通过数学公式描述的,因此需要一定的计算资源来进行显示和渲染,这可能会影响一些需要快速显示和打印的应用场景的性能。
    (六)汉字点阵获取
  8. 利用区位码获取汉字点阵
    汉字点阵字库是根据区位码的顺序进行存储的,因此,可以根据区位码获取一个字库的点阵。具体的计算公式如下:
    点阵起始位置 = ((区码- 1)×94 + (位码 – 1)) ×汉字点阵字节数
    获取点阵起始位置后,就可以从这个位置开始,读取出一个汉字的点阵。这种方法比较简单直观,适用于区位码已知的情况。
  9. 利用汉字机内码获取汉字点阵
    汉字的区位码和机内码之间有一定的关系,可以根据机内码来获得区位码,进而获取汉字点阵。具体的计算公式如下:
    区码 = 机内码高位字节 - A0H
    位码 = 机内码低位字节 - AOH
    利用机内码获取汉字点阵的方法需要先根据机内码计算出区位码,然后再根据区位码获取汉字点阵。这种方法适用于机内码已知的情况。
    (七)配置环境:
    在双系统里使用Ubuntu进行操作。如果是刚下载才初始化的话,那就需要先配置基本环境。
    在终端输入以下命令
    sudo apt-get install build-essential
    sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
    sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev
    安装:
    在opencv目录下先创建build文件
    cd opencv
    mkdir build
    在build下进行编译:
    cd build
    sudo cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local …
    再输入以下命令:
    sudo make -j8
    或者
    sudo make -j4
    开始安装:
    sudo make install
    添加路径:
    (1)打开文件:
sudo gedit /etc/ld.so.conf

(2)在文件中添加如下代码:

/usr/loacal/lib

(3)保存关闭,运行下面代码:

sudo ldconfig

配置环境:
(1)打开.bashrc文件:
sudo gedit /etc/bash.bashrc
(2)添加下面两行代码,放到最后面即可:
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
export PKG_CONFIG_PATH
(3)保存退出,终端输入:
source /etc/bash.bashrc
输入以下命令,可以查看所安装opencv的版本
pkg-config opencv --modversion
(八)
打开Ubuntu,具体代码如下:

String image_path="/home/lxj/qianrushi/week10/yuanshen.png";

char* logo_path=(char*)"/home/lxj/qianrushi/week10/logo.txt";

put_text_to_image(20,300,image_path,logo_path);

return 0;

//绘制的起点坐标
Point p;
p.x = x_offset;
p.y = y_offset;
 //存放ascii字膜
char buff[16];           
//打开ascii字库文件
FILE *ASCII;
if ((ASCII = fopen("/home/lxj/qianrushi/week10/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;
}

Point p;
p.x=x_offset;
p.y=y_offset;
FILE *HZK;
char buff[72];//72个字节,用来存放汉字的
if((HZK=fopen("/home/lxj/qianrushi/week10/HZKs2424.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=18;//要打印的字符长度
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个字节来表示
        如赵字
        区位码是5352
        十六进制位3534
        机内码就是d5d4
        d5-af=38(十进制),因为是从汉字啊开始的,所以减去的是af而不是a0,38+15等于53与区码相对应
        d4-a0=52
        */
        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();

三、OLED屏显
(一)SPI(串行外设接口)
1.什么是SPI
SPI协议是一种高速全双工同步串行通信协议,由一个主设备(Master)和一个或多个从设备(Slave)组成。它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,一般需要4根线,也可以使用三根线(单向传输)。SPI协议被广泛应用于ADC、LCD等设备与MCU间,要求通讯速率较高的场合。在物理层上,SPI通讯使用3条总线及片选线,3条总线分别为SCK、MOSI、MISO,片选线为SS。SPI时钟频率相比IIC要高很多,最高可以工作在上百MHZ。
2.SPI接口
在这里插入图片描述
3.SPI总线事务
SPI协议没有定义数据流的结构; 数据的组成完全取决于组件设计者。但是,许多设备遵循相同的基本格式来发送和接收数据,从而允许来自不同供应商的部件之间的互操作性。
二.OLED显示数据
OLED显示汉字是通过汉字取摸软件生成的,将汉字在16*16的像素区域内进行识别并排列,生成对应的c51代码。所以我们这里需要下载一个汉字取摸软件。
运行软件,点击设置,设置以下内容
在这里插入图片描述
开始任务:
任务一:显示自己的学号和姓名
打开工程,点击魔术棒,点击Device,将芯片换为STM32F103C8
在这里插入图片描述
再点击C/C++,将以下位置更改为以下内容
在这里插入图片描述然后进入到gui.c,找到头文件oledfont.h,右键跳转
在这里插入图片描述在取模软件里面复制之前生成的数组,找到GB16函数,复制进去,在前面加上中文。打开test.c文件,找到TEST_MainPage函数,修改内容,最后再打开主函数,修改为以下内容
在这里插入图片描述
连线如下:
然后在进行烧录,得到结果如下:
在这里插入图片描述
任务二:显示AHT20的温度和湿度
为了将几个任务分清楚,并保存好每个任务的文件,这里可以复制上个工程,然后再进行操作
获取字模
在这里插入图片描述
“正”,0x00,0x00,0x7F,0xFC,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x11,0x00,0x11,0xF8,
0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0xFF,0xFE,0x00,0x00,/“正”,0/

    "在",0x02,0x00,0x02,0x00,0x04,0x00,0xFF,0xFE,0x08,0x00,0x08,0x40,0x10,0x40,0x30,0x40,
    0x57,0xFC,0x90,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x1F,0xFE,0x10,0x00,/*"在",1*/
	
    "检",0x10,0x40,0x10,0x40,0x10,0xA0,0x10,0xA0,0xFD,0x10,0x12,0x08,0x35,0xF6,0x38,0x00,
    0x54,0x88,0x50,0x48,0x92,0x48,0x11,0x50,0x11,0x10,0x10,0x20,0x17,0xFE,0x10,0x00,/*"检",2*/
	
    "测",0x00,0x04,0x27,0xC4,0x14,0x44,0x14,0x54,0x85,0x54,0x45,0x54,0x45,0x54,0x15,0x54,
    0x15,0x54,0x25,0x54,0xE5,0x54,0x21,0x04,0x22,0x84,0x22,0x44,0x24,0x14,0x08,0x08,/*"测",3*/
	
    "温",0x00,0x00,0x23,0xF8,0x12,0x08,0x12,0x08,0x83,0xF8,0x42,0x08,0x42,0x08,0x13,0xF8,
    0x10,0x00,0x27,0xFC,0xE4,0xA4,0x24,0xA4,0x24,0xA4,0x24,0xA4,0x2F,0xFE,0x00,0x00,/*"温",4*/
	
    "度",0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x3F,0xFC,0x22,0x20,0x22,0x20,
    0x23,0xE0,0x20,0x00,0x2F,0xF0,0x24,0x10,0x42,0x20,0x41,0xC0,0x86,0x30,0x38,0x0E,/*"度",5*/

添加头文件路径
主要代码如下:

uint8_t AHT20_RD_Byte(void)//从AHT20读取一个字节
{
uint8_t Byte,i,a;
Byte = 0;
SCL_Pin_Output_Low();
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
for(i=0;i<8;i++)
{
SCL_Pin_Output_High();
Delay_5us();
a=0;
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)) a=1;
Byte = (Byte<<1)|a;
SCL_Pin_Output_Low();
Delay_5us();
}
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
return Byte;
}

uint8_t Receive_ACK(void) //看AHT20是否有回复ACK
{
uint16_t CNT;
CNT = 0;
SCL_Pin_Output_Low();
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
while((GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)) && CNT < 100)
CNT++;
if(CNT == 100)
{
return 0;
}
SCL_Pin_Output_Low();
SensorDelay_us(8);
return 1;
}

void Send_ACK(void) //主机回复ACK信号
{
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_Output_Low();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_IN_FLOATING();
SensorDelay_us(8);
}

void Send_NOT_ACK(void) //主机不回复ACK
{
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_Output_High();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
SCL_Pin_Output_Low();
SensorDelay_us(8);
SDA_Pin_Output_Low();
SensorDelay_us(8);
}

void Stop_I2C(void) //一条协议结束
{
SDA_Pin_Output_Low();
SensorDelay_us(8);
SCL_Pin_Output_High();
SensorDelay_us(8);
SDA_Pin_Output_High();
SensorDelay_us(8);
}

uint8_t AHT20_Read_Status(void)//读取AHT20的状态寄存器
{

uint8_t Byte_first;	
I2C_Start();
AHT20_WR_Byte(0x71);
Receive_ACK();
Byte_first = AHT20_RD_Byte();
Send_NOT_ACK();
Stop_I2C();
return Byte_first;
1
2
3
4
5
6
7
8
}

uint8_t AHT20_Read_Cal_Enable(void) //查询cal enable位有没有使能
{
uint8_t val = 0;//ret = 0,
val = AHT20_Read_Status();
if((val & 0x68)==0x08)
return 1;
else return 0;
}

void AHT20_SendAC(void) //向AHT20发送AC命令
{

I2C_Start();
AHT20_WR_Byte(0x70);
Receive_ACK();
AHT20_WR_Byte(0xac);//0xAC采集命令
Receive_ACK();
AHT20_WR_Byte(0x33);
Receive_ACK();
AHT20_WR_Byte(0x00);
Receive_ACK();
Stop_I2C();
1
2
3
4
5
6
7
8
9
10
}

//CRC校验类型:CRC8/MAXIM
//多项式:X8+X5+X4+1
//Poly:0011 0001 0x31
//高位放到后面就变成 1000 1100 0x8c
//C现实代码:
uint8_t Calc_CRC8(uint8_t *message,uint8_t Num)
{
uint8_t i;
uint8_t byte;
uint8_t crc=0xFF;
for(byte=0; byte<Num; byte++)
{
crc^=(message[byte]);
for(i=8;i>0;–i)
{
if(crc&0x80) crc=(crc<<1)^0x31;
else crc=(crc<<1);
}
}
return crc;
}

void AHT20_Read_CTdata(uint32_t *ct) //没有CRC校验,直接读取AHT20的温度和湿度数据
{
volatile uint8_t Byte_1th=0;
volatile uint8_t Byte_2th=0;
volatile uint8_t Byte_3th=0;
volatile uint8_t Byte_4th=0;
volatile uint8_t Byte_5th=0;
volatile uint8_t Byte_6th=0;
uint32_t RetuData = 0;
uint16_t cnt = 0;
AHT20_SendAC();//向AHT10发送AC命令
Delay_1ms(80);//延时80ms左右
cnt = 0;
while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表示为空闲状态,若为1,表示忙状态
{
SensorDelay_us(1508);
if(cnt++>=100)
{
break;
}
}
I2C_Start();
AHT20_WR_Byte(0x71);
Receive_ACK();
Byte_1th = AHT20_RD_Byte();//状态字,查询到状态为0x98,表示为忙状态,bit[7]为1;状态为0x1C,或者0x0C,或者0x08表示为空闲状态,bit[7]为0
Send_ACK();
Byte_2th = AHT20_RD_Byte();//湿度
Send_ACK();
Byte_3th = AHT20_RD_Byte();//湿度
Send_ACK();
Byte_4th = AHT20_RD_Byte();//湿度/温度
Send_ACK();

得到结果
在这里插入图片描述
任务三:上下或左右的滑动显示长字符,比如“Hello,欢迎来到重庆交通大学物联网205实训室!”
在这里插入图片描述

    "迎",0x00,0x00,0x20,0x80,0x13,0x3C,0x12,0x24,0x02,0x24,0x02,0x24,0xF2,0x24,0x12,0x24,
    0x12,0x24,0x12,0xB4,0x13,0x28,0x12,0x20,0x10,0x20,0x28,0x20,0x47,0xFE,0x00,0x00,/*"迎",1*/
	
    "来",0x01,0x00,0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x11,0x10,0x09,0x10,0x09,0x20,
    0xFF,0xFE,0x03,0x80,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,0x01,0x00,/*"来",2*/
	
    "到",0x00,0x04,0xFF,0x84,0x08,0x04,0x10,0x24,0x22,0x24,0x41,0x24,0xFF,0xA4,0x08,0xA4,
    0x08,0x24,0x08,0x24,0x7F,0x24,0x08,0x24,0x08,0x04,0x0F,0x84,0xF8,0x14,0x40,0x08,/*"到",3*/
	
    "交",0x02,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00,0x10,0x10,0x10,0x08,0x20,0x24,
    0x48,0x24,0x04,0x40,0x02,0x80,0x01,0x00,0x02,0x80,0x0C,0x40,0x30,0x30,0xC0,0x0E,/*"交",4*/
	
    "大",0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,
    0x02,0x80,0x02,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x10,0x10,0x20,0x08,0xC0,0x06,/*"大",5*/

按照任务一修改对应的内容即可,以下为修改内容:
在这里插入图片描述
在这里插入图片描述
将main函数里面的while循环删去,添加以下代码:
​ 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); //终止页 2
​ OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
​ OLED_WR_Byte(0xFF,OLED_CMD); //虚拟字节
​ TEST_MainPage();
​ OLED_WR_Byte(0x2F,OLED_CMD); //开启滚动

结果如下:
在这里插入图片描述
总结:
本次实验做得还是比较成功的,也深切地体会了测试温度,显示字幕的过程,让我对于这门课程的了解也更多,当然未来还需要继续进步、学习。

  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值