完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、PC串口通信
1. 连线设置 注意将一个串口的TXD连接另一个串口的RXD,接电源和接地连一起即可。 2.打开调试助手 2.1 加载图片 2.2 设置波特率为115200 2.3 点击发送文件 预计时间为15s,但是在实际测试过程中用了21s 3.将波特率设为2000000 可见此时预测时间为0.6s,可是实际的传输时间为11s。 4. 结果分析 因为传输时延=文件大小/波特率,因为随着波特率的升高,丢包率会更高,因此实际时间与预测时间差别很大。 二、点阵汉字读取与打印 1. 点阵汉字知识点 1.1 汉字编码
0331,则它在 03 区 3l 位。
高位字节 = 区码 + 20H + 80H(或区码 + A0H) 低位字节 = 位码 + 20H + 80H(或位码 + AOH) 由于汉字的区码与位码的取值范围的十六进制数均为 01H~5EH(即十进制的 01~94),所以汉字的高位字节与低位字节的取值范围则为 A1H~FEH(即十进制的 161~254)。 例如,汉字“啊”的区位码为 1601,区码和位码分别用十六进制表示即为 1001H,它的机内码的高位字节为 B0H,低位字节为 A1H,机内码就是 B0A1H。 1.2 点阵字库结构
字都是由一个矩形的点阵组成,0 代表没有,1 代表有点,将 0 和 1 分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有 12 * 12, 14 * 14, 16 * 16 三 种字库。 字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期 UCDOS 库),纵向矩阵一 般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库 矩阵做成纵向,省得在显示时还要做矩阵转换。我们接下去所描述的都是指横向矩阵字库。
为了解决这个问题,有些点阵字库会将 14 * 14 和 12 * 12 的字库按 16*14和16 * 12 来存储,即,每行还是按两个字节来存储,但是 14 * 14 的字库,每两个字节的最后两位是没有使用,12 * 12 的字节,每两字节的最后 4 位是没有 使用,这个根据不同的字库会有不同的处理方式,所以在使用字库时要注意这个 问题,特别是 14 * 14 的字库。 1.3 汉字点阵获取
获取一个字库的点阵,它的计算公式如下: 点阵起始位置 = ((区码- 1)*94 + (位码 – 1)) * 汉字点阵字节数 获取点阵起始位置后,我们就可以从这个位置开始,读取出一个汉字的点阵。
机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H) 机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH) 反过来说,我们也可以根据机内码来获得区位码: 区码 = 机内码高位字节 - A0H 位码 = 机内码低位字节 - AOH 将这个公式与获取汉字点阵的公式进行合并计就可以得到汉字的点阵位置。 2. 编程实现 2.1 创建文本文档 创建文本文档并保存为ANSI格式
链接:https://pan.baidu.com/s/1R6t4u8KrAAuf0GCRRpivEQ 提取码:qwer 可以看到宋健鑫对应的编码为CB CE BD A1 F6 CE 2.2 打开Ubuntu
#include #include"opencv2/opencv.hpp" #include #include #include 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="test.png"; char* logo_path="logo1.txt"; put_text_to_image(700,700,image_path,logo_path); 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.***", "rb")) == NULL){ printf("Can't open ascii.***,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 & (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] = true; /*为1的存入新的字膜中*/ } else { mat[j * 8 + k] = false; } } for (i = 0; i < 24; i++) { p.x = x_offset; for (j = 0; j < 24; j++) { if (mat[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 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个字节来表示 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(); } 将需要的文本文档,汉字库,ASCII字库,拖进ubuntu的 Asci0816.***和HZKf2424.hz可以用FONTSHOW查看 链接:https://pan.baidu.com/s/13HoayHz_QBeq5m3B05ddIg 提取码:qwer 利用g++命令,编译生成执行文件 g++ addtext.cpp -o test `pkg-config --cflags --libs opencv`输入 ./test运行程序 2.3 运行结果 三、总结 通过对点阵汉字的学习,明白了除了ASCII能编码英文之外,中文也能够进行编码,不过需要两位,为了与ASCII不冲突,引入了区位码和机内码。opencv的作用就是根据点阵图利用circle函数画实心圆代替像素点来绘字和字符。 |
|
|
|
只有小组成员才能发言,加入小组>>
3309 浏览 9 评论
2988 浏览 16 评论
3490 浏览 1 评论
9050 浏览 16 评论
4085 浏览 18 评论
1171浏览 3评论
602浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
594浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2332浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1894浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-20 17:18 , Processed in 1.123685 second(s), Total 81, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号