嵌入式实验:汉字点阵的字模读取与显示

【嵌入式】点阵汉字的字模读取与显示 汉字点阵原理点阵的介绍点阵是一种将图像或字符分解为由点组成的矩阵的显示方式。每个点被视为一个像素,可以通过控制每个像素的状态(亮或暗)来显示出图像或字符。在点阵显示中,通常使用一个二维矩阵来表示图像或字符,每个元素代表一个像素。矩阵的行和列分别对应于显示屏的行和列。通过设置每个像素的状态,可以在显示屏上呈现出各种图像和字符。例如,一个8x8的点阵矩阵可以表示一个由64个像素组成的图像或字符。图像或字符的每个像素通过设置为亮(通常用1表示)或暗(通常用0表示)来决定其显示状态。 阅读详情

文章目录

电脑间串口连接传输文件

题目要求:

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

首先进行usb转ttl模块,注意:(TXD接RXD,RXD接TXD)

其次,点开串口调试助手,并且“打开串口,选择:打开文件,进行需要传输的文件(这里我选择了一张图片,方便进行接受和演示文件。

首先选择波特率为:115200,点击发送文件:

在这里插入图片描述

这里是显示的接受文件:

在这里插入图片描述

最后选择:保存数据

在这里插入图片描述

找到保存的.dat文件,并重命名为.jpg文件。

显示如下:

实验总结:实际传输时间会大于传输时间

嵌入式实验:汉字点阵的字模读取与显示

1、题目要求:

学习理解汉字的机内码、区位码编码规则和字形数据存储格式。

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

2、汉字点阵字库原理:

区位码:

在国标GD2312-80中规定,所有国标汉字及符号都分配在一个94行、94列的方阵中,方阵的每一行称为一个“区”,每一列称为一个“列”,而一共有94个“区”,而每个“区”都有94个列,一共是94×94个汉字

区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号

机内码:

机内码指的是:计算机中表示一个汉字的编码。

机内码与区位码有所区别

因为:直接使用区位码作为机内码,会与基本ASCII码混淆,所以为了避免混淆

因此:现在区码和位码上分别加上20H,并在此基础上再加80H(H是16进制)

然后经过处理:用一个机内码表示一个汉字需要占用两个字节,分别称为“高位字节”和“低位字节”,这两个字节的机内码按如下规则:

高位字节 = 区码 + 20H + 80H(或区码 + A0H)
低位字节 = 位码 + 20H + 80H(或位码 + AOH)

由于汉字的区码与位码的取值范围的十六进制数均为 01H-5EH(即十进制的 01-94),所以汉字的高位字节与低位字节的取值范围则为 A1H-FEH(即十进制的 161-254)。

点阵字库储存:

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

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

利用汉字机内码获取汉字:

汉字的区位码和机内码的关系如下:

机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H)
机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH)
反过来说,我们也可以根据机内码来获得区位码:

区码 = 机内码高位字节 - A0H
位码 = 机内码低位字节 - AOH
这样,算出区位码之后,我们就可以用它在汉字库里面寻址找字模了。具体方式:

该汉字的偏移地址 =(区码-1)×94×一个字占用的字节数 + 位码×一个字占用的字节数

在Ubuntu下使用C/C++调用opencv显示图片及文字

创建一个word.cpp文件,在文件夹下打开终端,输入以下命令

gedit word.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="bird.jpg";//图片的名字
    char* logo_path="logo.txt";//汉字文件的名字
    put_text_to_image(200,350,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();
}
编译运行:

保存好word.cpp文件

编译指令

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

运行效果:

在这里插入图片描述

题目要求:

理解OLED屏显和汉字点阵编码原理,使用STM32F103的SPI或IIC接口实现以下功能:1) 显示自己的学号和姓名; 2) 显示AHT20的温度和湿度;3) 上下或左右的滑动显示长字符,比如“Hello,欢迎来到重庆交通大学物联网205实训室!”或者一段歌词或诗词(最好使用硬件刷屏模式)。

1)、SPI介绍:

SPI(Serial Peripheral interface)是串行外围设备接口,SPI 接口主要应用在 EEPROM,FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信号解码器之间。

SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为 PCB 的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,STM32 也有 SPI 接口。

SPI 主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。

2)、OLED介绍:

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

我们使用的是ALINETEK 的 OLED 显示模块,该模块不需要高压(5V)供电,否则可能会烧坏模块

img

汉字取模:

在这里插入图片描述

汉字的字型可由其点阵数据来表示。每个字型的点阵数据为 16×16(横行点数×纵列 点数),共 256 个二进制位,32 个字节。 汉字 16 点阵字型数据的 32 个字节排列次序是以 0 字节开始到 31 字节结束,均用十 六进制表示,其记录格式如下:

代码撰写:

test.c文件:

void TEST_MainPage(void)
{	
//	GUI_ShowString(28,0,"abc",16,1);//英文姓名
	GUI_ShowCHinese(28,20,"李奇",1);//中文姓名
	GUI_ShowString(4,48,"12345678910",16,1);//数字详细
	delay_ms(1500);		
	delay_ms(1500);
}

oledfont.h文件:

const typFNT_GB16 cfont16[] = 
{
	"系",0x00,0xF8,0x3F,0x00,0x04,0x00,0x08,0x20,0x10,0x40,0x3F,0x80,0x01,0x00,0x06,0x10,
	0x18,0x08,0x7F,0xFC,0x01,0x04,0x09,0x20,0x11,0x10,0x21,0x08,0x45,0x04,0x02,0x00,/*"系",0*/
	"统",0x10,0x40,0x10,0x20,0x20,0x20,0x23,0xFE,0x48,0x40,0xF8,0x88,0x11,0x04,0x23,0xFE,
	0x40,0x92,0xF8,0x90,0x40,0x90,0x00,0x90,0x19,0x12,0xE1,0x12,0x42,0x0E,0x04,0x00,/*"统",1*/
	"设",0x00,0x00,0x21,0xF0,0x11,0x10,0x11,0x10,0x01,0x10,0x02,0x0E,0xF4,0x00,0x13,0xF8,
	0x11,0x08,0x11,0x10,0x10,0x90,0x14,0xA0,0x18,0x40,0x10,0xA0,0x03,0x18,0x0C,0x06,/*"设",2*/
	"置",0x7F,0xFC,0x44,0x44,0x7F,0xFC,0x01,0x00,0x7F,0xFC,0x01,0x00,0x1F,0xF0,0x10,0x10,
	0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0xFF,0xFE,0x00,0x00,/*"置",3*/
};

mian.c文件:

int main(void)
{	
	delay_init();	    	       //延时函数初始化	  
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0);             //清屏(全黑)
	while(1) 
	{	
		TEST_MainPage();         //界面显示
	}
}

xFC,0x01,0x00,0x1F,0xF0,0x10,0x10,
0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0xFF,0xFE,0x00,0x00,/“置”,3/
};


mian.c文件:

int main(void)
{
delay_init(); //延时函数初始化
OLED_Init(); //初始化OLED
OLED_Clear(0); //清屏(全黑)
while(1)
{
TEST_MainPage(); //界面显示
}
}


点阵汉字的字模读取与显示 我们用之前的方法一个IO口只能控制一个led,如果需要用更少的IO口控制更多的led怎么办?于是,就有了点阵。例如:8X8点阵共由64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置1电平,某一列置0电平,则相应的二极管就亮;如要将第一个点点亮,则1脚接高电平a脚接低电平,则第一个点就亮了。实物图借助取模软件,即可将我们所需要的文字或字母,以点阵的形式呈现出来。我们知道英文字母数量比较少,我们只要用一个字节(8位)就足以表达。但是汉字非常多。要怎么表达呢? 阅读详情

相关推荐

[嵌入式]汉字字模点阵

一、汉字编码 1、区位码 在国标 GD2312—80 中规定,所有的国标汉字及符号分配在一个 94 行、94 列的方阵中,方阵的每一行称为一个“区”,编号为 01 区到 94 区,每一列称为一个“位”,编号为01 位到 94 位,方阵中的每一个汉字和符号所在的区号和位号组合在一起形成的四个阿拉伯数字就是它们的“区位码”。区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号,反过来说,任何一个汉字或符号也都对应着一个唯一的区位码。汉字“母”字的区位码是 3624,表明它在方阵的

weixin_47593895的博客 2063

C++在图片上叠加汉字

这里写目录标题一、汉字点阵字库原理1. 汉字编码1.1 区位码1.2 机内码2. 点阵字库结构2.1 点阵字库存储2.2 16*16 点阵字库2.3 14\*14 与 12\*12 点阵字库3. 汉字点阵获取3.1 利用区位码获取汉字3.2 利用汉字机内码获取汉字 一、汉字点阵字库原理 1. 汉字编码 1.1 区位码 在国标GD2312—80中规定,所有的国标汉字及符号分配在一个 94 行、94 列的方阵中,方阵的每一行称为一个“区”,编号为 01 区到 94 区,每一列称为一个“位”,编号为01 位

Baker的博客 2995

串口传输文件与点阵汉字的字模读取与显示

一、串口传输文件 1.实验内容 串口传输文件的练习。将两台笔记本电脑,借助 usb转rs232 模块和杜邦线,建立起串口连接。然后用串口助手等工具软件(带文件传输功能)将一台笔记本上的一个大文件(图片、视频和压缩包软件)传输到另外一台电脑,预算文件大小、波特率和传输时间三者之间的关系,并对比实际传输时间。 2.实验过程 ①将串口连接好接入一台电脑上 ②打开串口调试助手,选择一张图片导入,并将其波特率设置为115200 ③再打开一个串口调试助手,调整好端口号,点击打开串口,再点击发送文件 如图为传

m0_61878156的博客 459

如何实现一个点阵字库 - 原理篇

在计算机发明之初仅实现了点阵字库,那时显示的仅有一些数字字母,数量相对于象形文字是极低的,在物联网开发中经常会遇到显示的需求,如室外的LED点阵大屏、墨水屏、单色屏等等场景,对于不太复杂显示一般不会使用GUI库,在没有GUI库的情况如何显示动态显示汉字这类象形文字呢?在嵌入式中一般做法是去外挂一个字库芯片,在这里面存储了大部分用到会或者不会的字符的点阵数据,这个类芯片的字体和字号都是固定的,够显示的字符数量有效,整个交互只能围绕这几种字号展开设计;除此之外我们还可以逆向方式使用已有的矢量字体去生成点阵字库。

老Z先生的博客 2618

16点阵字库字模提取软件:专业工具指南

本文还有配套的精品资源,点击获取 简介:16点阵字库字模提取软件是一种专门用于处理汉字点阵字库的专业工具,能够将字符图形化为点阵格式以在显示设备上精确显示。通过将每个字符由16行16列像素点组成的字模读取、分析、预览、导出,并可能进行编辑,以简化点阵字库管理并优化显示效果,尤其适用于资源有限的嵌入式系统、电子显示屏和移动设备。 1. 点阵字库简介 点阵字库是...

weixin_36151775的博客 1867

构建液晶屏显示的汉字字模库

繁体字模起源于传统的汉字书写系统,它保持了汉字的历史形态和艺术美感。在繁体字模的构成中,笔画和结构的复杂度较高,相较于简体字模来说,更能体现汉字的书写韵律和传统美学。繁体字模的主要特点可以概括为以下几点:笔画复杂:繁体字模保留了较多的原始笔画,尤其是那些在简体字中被省略或合并的部分。设计优美:由于保留了更多传统元素,繁体字模往往在视觉上更为美观,更有艺术感。适用性广泛:繁体字模被广泛用于繁体中文的显示,特别在港台地区,对于保持中华文化的传承具有重要作用。

weixin_42506884的博客 1098

【嵌入式14】点阵汉字的字模读取与显示

本文主要介绍了汉字点阵的原理,理解了汉字的机内码、区位码编码规则和字形数据存储格式,并在Linux环境下调用opencv库编程,用汉字点阵实现读入txt文本实现显示。

噗噗的罐子博客 4290

构建14X14 汉字点阵字库:技术解析与应用

本文还有配套的精品资源,点击获取 简介:本文详细介绍了汉字点阵字库的原理和应用,特别是在资源受限环境下的应用。首先解释了点阵字库通过14X14像素矩阵表示汉字的技术,接着探讨了汉字编码与点阵数据的关系,字模提取技术以及Hzk14.bin文件格式。此外,文章还分析了点阵字库在早期电子设备、嵌入式系统等场景中的应用,以及随着技术进步,更高分辨率字库和矢量字体的发展。 ...

weixin_29867767的博客 1550

点阵汉字的字模读取与显示【嵌入式】

这里写目录标题一级目录二级目录三级目录 一级目录 二级目录 三级目录

wanerXR的博客 672

16*16点阵 显示汉字

这是一个16*16点阵,用4个ARK410788K8*8点阵拼起来的,用74HC5952片,74HC154一片 ,是显示“黑龙江科技学院 厚德博学强吾兴邦 计算机06-2班 林君霞”汉字并上移的程序。

嵌入式GUI显示驱动配置实战:从emWin硬件接口到SPI屏驱动优化

在嵌入式系统开发中,显示驱动是连接GUI库与物理屏幕的核心底层模块,其本质是CPU与显示控制器之间的数据“翻译”与“传输”系统。其工作原理是通过实现特定的硬件抽象层接口,将GUI生成的图形数据转换为屏幕能识别的时序和协议。这项技术的核心价值在于,它允许开发者在资源受限的MCU上,通过适配不同的硬件接口,以最小的硬件开销实现稳定的图形输出。其典型应用场景包括智能家居面板、工业HMI、可穿戴设备等嵌入式图形界面开发。本文将深入解析emWin GUI库的驱动框架,重点探讨如何针对SPI、I2C等串行接口进行高效的

weixin_29159711的博客 342

【嵌入式】在Ubuntu系统下通过OpenCV实现点阵汉字的字模读取与显示

介绍汉字点阵的原理,理解汉字的机内码、区位码编码规则和字形数据存储格式,通过OpenCV在Ubuntu系统下显示点阵汉字一、汉字点阵原理1.汉字点阵原理1.点阵2.汉字编码3.点阵字库存储2.汉字点阵获取二、实验要求与过程1.实验题目2.创建文件、源码3.创建文本文件4.编译5.结果三、总结参考文献 一、汉字点阵原理 1.汉字点阵原理 1.点阵 我们用之前的方法一个IO口只能控制一个led,如果需要用更少的IO口控制更多的led怎么办?于是,就有了点阵。 例如:8X8点阵共由64个发光二极管组成,且每个发光

yaositong的博客 469

Cesium生态盘点:超图、火星3D等15个二次开发框架对比

本文深入解析Cesium生态中的15个二次开发框架,包括超图、火星3D等主流选择,帮助开发者根据项目需求进行精准选型。从性能表现、功能完备性、开发友好度等维度进行对比,特别适合需要处理地理空间数据和构建三维可视化的JavaScript开发者。

weixin_28197941的博客 497
上一篇: 1. 学习I2C总线通信协议,使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出
下一篇: 第十二周实验——嵌入式PTOS多任务程序设计
whynotsolve
博客等级 码龄4年 202粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值