一、串口传输文件
1.串口连接
(1)首先下载串口调试助手:
链接:https://pan.baidu.com/s/1T-7cHCwenyQCfyJSyRusKg? 提取码:jack
(2)使用两台电脑连接:使用借助 usb转rs232 模块和杜邦线,建立起串口连接,连线为GND接GND,电源接电源,TDX和RDX反接
(3)传输:
?打开图中的第一个软件
在发送电脑里:选择你需要打开的文件,选择完毕之后,点击打开串口,以及调整波特率,然后直接点击发送文件即可
?在接受电脑:从接收完毕之后点击图中的保存数据,即可看到数据保存成功
?
我这里保存的文件打开之后是这样的
?
?3.预算文件大小、波特率和传输时间三者之间的关系,对比实际传输时间。
115200波特率下:
600000波特率下面
?可以看见在不同波特率下面传输时间是不同的,但这里实际传输速率要慢得多(忘记整秒表了,但是在软件下面在传输的时候是有时间的)
总结一下就是:理论来说,传输时间=文件大小/波特率,但这里要注意计算时文件大小的单位换算。同时当发送速率提升时,发送所需的时间也会缩短,但时间并不像理论那样缩短,是因为当速率上升时,丢包率也会上升,重传导致时间增加。总的来说还是原理还是比较了解了,但细致过程还没那么清晰。
二、在Ubuntu下用C/C++(或python) 调用opencv库编程显示一张图片,并打开一个名为"logo.txt"的文本文件
1、汉字点阵原理
所谓一个字的点阵. 其实就是指这个汉字用多少个象素点来描述. 每个象素点显示为什么颜色, 通常情况下, HZK16采用的是1616点阵, 即256个象素点描述一个汉字. 这些点的颜色分为两种, 一种是前景色, 一种是显示为背景色 1、汉字编码 ①区位码:区位码的前两位是它的区号,后两位是它的位号。用区位码就可以唯一地确定一个汉字或符号。 ②机内码:汉字的机内码是指在计算机中表示一个汉字的编码。 2、点阵字库结构 ①点阵字库存储:字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期 UCDOS 字库),纵向矩阵一般是因为有某些液晶是采用纵向扫描显示法, ②1616点阵字库:对于 1616 的矩阵来说,它所需要的位数共是 1616=256 个位,每个字 节为 8 位,因此,每个汉字都需要用 256/8=32 个字节来表示。 例如: ③1414和1212点阵字库:对于 1414 和 1212 的字库,理论上计算,它们所需要的点阵分别为(1414/8)=25, (1212/8)=18 个字节,由于它们每一行都不是 8 的整位数,所以有些点阵字库会将 1414 和 1212 的字库按 1614和 1612 来存储,即,每行还是按两个字节来存储。 3、汉字点阵获取 ① 利用区位码:*点阵起始位置 = ((区码- 1)94 + (位码 – 1)) * 汉字点阵字节数 ②利用机内码: 机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H) 机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH) 区码 = 机内码高位字节 - A0H 位码 = 机内码低位字节 - AOH ?
2.使用opcv让汉字点阵呈现在图片上
1.首先得在同一目录下准备几个文件:在下面标识出来了,一个是图片:1.png,一个是需要输入的汉字(自己找一个文本写就行),另外两个我放一个链接下载就行:链接:https://pan.baidu.com/s/1pxprO_PD3y0b-6g9P2bqzA? 提取码:jack
?
?2.打开终端进入你保存文件的位置(cd 路径名),编写程序(gedit 文件名.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;
void PaintSChinese(Mat& image, int x_offset, int y_offset, unsigned long offset);
void PaintSAscii(Mat& image,int x_offset, int y_offset, unsigned long offset);
void putTextToImage(int x_offset,int y_offset,String imagePath ,char* txtPath);
int main(){
String image_path="1.png";
char* logo_path=(char*)"logo.txt";
putTextToImage(20,300,image_path,logo_path);
return 0;
}
void putTextToImage(int x_offset,int y_offset,String imagePath ,char* txtPath)
{
//通过图片路径获取图片
Mat img = imread(imagePath);
unsigned char qh, wh;
unsigned long offset;
//用于存放从记事本读取的十六进制
char hexcode[30];
//打开包含名字的txt文件,转为十六进制,存入hexcode中
FILE* filetxt;
if ((filetxt = fopen(txtPath, "rb")) == NULL){
printf("Can't open txtfile,Please check the path!");
//getch();
exit(0);
}
fseek(filetxt, 0, SEEK_SET); /*将文件指针移动到偏移量的位置*/
fread(hexcode, 19, 1, filetxt);
int x = x_offset, y = y_offset;//x,y:在图片上绘文字的起始的坐标
for (int m = 0; m < 19; )
if (hexcode[m] == 0x23) /* 当读取到‘#’号时结束 */
break;
//判断高阶两个十六进制数,大于或等于b0(汉字第一个是b0a1)的都应该从汉字字库中找
else if (hexcode[m] > 0xffffffaf)
{
qh = hexcode[m] - 0xaf; /*计算区码*/
wh = hexcode[m+1] - 0xa0; /*计算位码*/
offset = (94 * (qh - 1) + (wh - 1)) * 72L;/*计算该汉字在字库中偏移量*/
PaintSChinese(img, x , y , offset);
m = m + 2; //一个汉字占两个char,所以加2
x += 24; //一个汉字在图片上占24个像素点,所以水平坐标每次+24
}
else
{
wh = hexcode[m];
offset = wh * 16L; //计算其他英文字符的偏移量
PaintSAscii(img, x, y, offset);
m++; //一个char
//原本应该8*16,但是和24*24比小了点,所以改为16*32,原本的一个像素点现在用四个像素点绘画
x += 16;
}
cv::imshow("image", img);
cv::waitKey();
}
void PaintSChinese(Mat& image, int x_offset, int y_offset, unsigned long offset){
//实际在图片上绘制的像素点坐标
Point p;
p.x = x_offset;
p.y = y_offset;
//打开DZKs1516汉字库文件
FILE *HZK;
char buff[72]; //存放汉字字膜
if ((HZK = fopen("HZKf2424.hz", "rb")) == NULL){
printf("Can't openHZKf2424.hz,Please check the path!");
//getch();
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 PaintSAscii(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 Asci0816.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;
}
}
3.再次打开终端:进入刚刚你保存文件的路径,输入命令g++ lan.cpp` pkg-config --cflags --libs?opencv?-o main`(记得改自己刚刚编写的程序名),最后编译./文件名?
4.成果展示
三、实验总结
主要借鉴了很多大佬的知识,所以显得很简单?
四、参考资料
|