91294|2

321

帖子

1

TA的资源

一粒金砂(高级)

楼主
 

一个单片机软件工程师如何写简单的计算机软件 [复制链接]

从事单片机开发有些年头,受益于LCD的成本不断降低我们的产品终于也用上了彩色LCD。经过最近一年的摸索我总结出了一套不同于常规的单片机彩屏控制方法,现把它分享出来希望可以得到高人的进一步完善或加强。
GUI我还没来得及研究,操作系统也是。所以我的方法比较低端,谈不上高大上。唯一能值得说道的也就是用上了FATFS文件系统来存储图片文件,单片机在取用图片的时候还算方便简洁,最关键是为了方便后期图片文件调整。另外本方法只适用于RGB565格式的bmp位图。
我的这个方法始于一个执念:怎样让单片机直接打开标准图片文件,从而在图片格式上实现电脑与单片机“统一度量衡”。考虑到单片机的算力和刷屏速度不可与电脑同日而语,这个统一的格式必须一边倒的偏袒单片机。那么有没有这样一种符合要求的图片格式呢?确实有,只是这种格式似乎早已被常用的图片处理软件所摒弃,很难找到它的踪迹。它的名字叫16-BPP-BF-565,采用十六位颜色编码其中红色和蓝色各占5位,绿色占用6位。这种编码格式刚好和我用的LCD屏格式吻合,颜色编码问题解决了还有一个图像扫描顺序的问题需要解决:在电脑上的图片一般的扫描顺序都是:从图片的左下角开始从左到右从下至上一行一行存储图片的像素数据 


但是这种扫描顺序却不适用于我用的LCD屏,LCD屏的扫描顺序是:从图片的左上角开始从左到右从上至下一行一行写入像素数据  对于这个问题要如何统一呢?其实16-BPP-BF-565对于扫描顺序是有定义的:在图片文件起始的偏移0x16位置,长度4个字节,表示图片的垂直方向像素数(图片高度)。

当这个数为正数时即表示扫描顺序为从下至上,为负数则为从上至下扫描(高度为其绝对值)。至此统一度量衡已经是水到渠成了。

BMP格式之16bpp-BF-565.zip (13.58 KB, 下载次数: 0)

关于16-BPP-BF-565详情请点击此链接16-BPP-BF-565

另外再分享一个我用Visual Studio写的将普通的BMP位图文件(BMP888)转为BMP565(扫描顺序也转为从上至下)的工具软件

BMP888to565CN.zip (6.28 KB, 下载次数: 0)

使用方法:将此文件解压后得到“BMP888To565.exe”可执行文件,将这个可执行文件放在你要转换的BMP888图片文件同一路径下,双击运行此可执行文件即可在同路径下创建BMP565文件夹并将转换后的原图片同名文件放置其中非常方便。接下来今天的重点来了,会单片机编程的往往都不会电脑编程,一直以来我都认为电脑编程和单片机编程之间有一道难以逾越的鸿沟,对于一个懒癌晚期的我来说是一辈子都难以跨越的。现在好了我发现只要掌握几个库函数的使用只有单片机C基础的人也可以使用电脑编程来服务于自己的不时之需。下面我把我写的“BMP888To565”源代码分享出来大家一起来围观一下:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <windows.h>
#include <direct.h>
#include <wingdi.h>
#include "main.h"


int main()
{
	int res = 0,file_count = 0;
	int32_t buf32; long Handle = 0;
	uint8_t array_buffer[0x42] = { 0 };
	FILE* fps = 0;
	struct _wfinddata_t FileInfo; TCHAR lpFileName[MAX_PATH];
	GetModuleFileName(NULL, lpFileName, MAX_PATH);
	uint16_t path_end = 0;
	for (; path_end < MAX_PATH - 6; path_end++)if (lpFileName[path_end] == L'\0')break;
	for (; path_end != 0; path_end--)if (lpFileName[path_end - 1] == L'\\')break;
	for (uint16_t i = 0; i < 6; i++)lpFileName[path_end + i] = *(L"*.BMP\0" + i);
	Handle = _wfindfirst(lpFileName, &FileInfo);
	DO_NEXT:
	if (Handle == -1L)
	{
		//_findclose(Handle);
		printf_s("There Is No Matching File!\n");
		fps = 0;
	}
	else
	{
		if (FileInfo.attrib != 0x20 || FileInfo.size == 0)goto JMP1;
		size_t s_len = wcslen(FileInfo.name);
		wprintf_s(L"CONVERTIONG:%ws\n",FileInfo.name);
		memcpy_s(lpFileName + path_end, s_len*2, FileInfo.name, s_len*2);
		if (path_end + s_len < MAX_PATH)
		{
			lpFileName[path_end + s_len] = L'\0';
			_wfopen_s(&fps, lpFileName, L"rb");
		}
		else fps = 0 , printf_s("Source Path Is Too Long!\n");
	}
	if (fps!=NULL)
	{
		fread(array_buffer, 1, 0x36, fps);
		if (*(uint16_t*)(&array_buffer[bfType]) != ('M' << 8 | 'B'))
		{
			printf_s("Not A BMP File!\n");
			res = 1;
		}
		else if (*(uint32_t*)(&array_buffer[bfSize]) > 10UL*1024UL*1024UL)
		{
			printf_s("File Size Over Flow!\n");
			res = 2;
		}
		else if (*(uint32_t*)(&array_buffer[biWidth]) > 4096UL)
		{
			printf_s("Width is out of range!\n");
			res = 3;
		}
		else if (*(uint32_t*)(&array_buffer[biBitCount]) != 24UL)
		{
			printf_s("Not A BMP888 File!\n");
			res = 4;
		}
		else
		{
			FILE* fpd = 0;uint32_t width32 = *(uint32_t*)(&array_buffer[biWidth]);
			uint8_t* data_buffer = (uint8_t*)malloc(10UL * 1024UL * 1024UL);
			uint8_t* put_cache = (uint8_t*)malloc(10UL * 1024UL * 1024UL);//scanf_s("%s", FileNameString, FILENAME_MAX);
			size_t s_len = wcslen(FileInfo.name);
			for (uint16_t i = 0; i < path_end + 8; i++)lpFileName[i] = i < path_end ? lpFileName[i] : *(L"BMP565\\" + i - path_end);
			if (_waccess(lpFileName, 0) != 0 && _wmkdir(lpFileName) != 0)printf_s("Path Creating Faild!\n");
			memcpy_s(lpFileName + path_end + 7, s_len*2, FileInfo.name, s_len*2);
			if (path_end + 7 + s_len < MAX_PATH)
			{
				lpFileName[path_end + 7 + s_len] = L'\0';
				_wfopen_s(&fpd, lpFileName, L"wb");
			}
			else fpd = 0, printf_s("Dest. Path Is Too Long!\n");
			if (fpd != NULL && data_buffer != 0 && put_cache != 0)
			{
				int32_t height32 = 0;
				uint32_t BitMapSize = *(uint32_t*)(&array_buffer[biSizeImage]);
				printf_s("File Checking Passed! \n Converting...\n");
				buf32 = *(uint32_t*)(&array_buffer[bfOffBits]);
				*(uint32_t*)(&array_buffer[bfOffBits]) = 0x42;
				height32 = *(int32_t*)(&array_buffer[biHeight]);
				fseek(fps, buf32, SEEK_SET);
				if (BitMapSize == fread(data_buffer, 1, BitMapSize, fps))
				{
					uint16_t* put_ptr16 = (uint16_t*)(put_cache + 0x42);
					if (height32 > 0)
					{
						*(int32_t*)(&array_buffer[biHeight]) = 0 - height32;
						*(uint32_t*)(&array_buffer[bfSize]) = 0x42 + width32 * height32 * 2;
						*(uint32_t*)(&array_buffer[biSizeImage]) = width32 * height32 * 2;
						for (uint32_t i = height32; i != 0; i--)
						{
							for (uint32_t j = 0; j < width32; j++)
							{
								buf32 = *(uint32_t*)&data_buffer[((i - 1) * width32 + j) * 3] & 0x00FFFFFF;
								*put_ptr16++ = (buf32 >> 8 & 0xF800) | (buf32 >> 5 & 0x07E0) | (buf32 >> 3 & 0x001F);
							}
						}
					}
					else 
					{
						height32 = 0 - height32;
						*(uint32_t*)(&array_buffer[bfSize]) = 0x42 + width32 * height32 * 2;
						*(uint32_t*)(&array_buffer[biSizeImage]) = width32 * height32 * 2;
						for (uint32_t i = 0; i < width32 * height32 / 2; i++)
						{
							*put_ptr16++ = (data_buffer[i * 6 + 2] << 8 & 0xF800) | (data_buffer[i * 6 + 1] << 3 & 0x07E0) | (data_buffer[i * 6 + 0] >> 3 & 0x001F);
							*put_ptr16++ = (data_buffer[i * 6 + 5] << 8 & 0xF800) | (data_buffer[i * 6 + 4] << 3 & 0x07E0) | (data_buffer[i * 6 + 3] >> 3 & 0x001F);
						}
					}
					*(uint16_t*)(&array_buffer[biBitCount]) = 16;
					*(uint32_t*)(&array_buffer[biCompression]) = BI_BITFIELDS;
					*(uint32_t*)(&array_buffer[RedMask]) = 0x0000F800;
					*(uint32_t*)(&array_buffer[GreenMask]) = 0x000007E0;
					*(uint32_t*)(&array_buffer[BlueMask]) = 0x0000001F;
					memcpy(put_cache, array_buffer, 0x42);
					fwrite(put_cache, 2, 0x42/2 + width32 * height32, fpd);
					printf_s("%u. File Converting Completed!\n", ++file_count);
				}
				else printf_s("Bit Map Size Don't Match The File Size!\n");
				fclose(fpd);
			}
			else printf_s("Dest. File Pointer Is Null!\n");
			free(data_buffer); free(put_cache);
		}
		fclose(fps);
	}
	else printf_s("Source File Pointer Is Null!\n");
	JMP1:
	if (_wfindnext(Handle, &FileInfo) == 0)goto DO_NEXT;
	printf_s("Totle Files:%d\n", file_count);
	_findclose(Handle);
	system("pause");
	return res;
}

另外还有几个main.h头文件的宏定义:


#include <stdint.h>

#define bfType		0x0000
#define bfSize		0x0002
#define bfOffBits	0x000a
#define biWidth		0x0012
#define biHeight	0x0016
#define biBitCount	0x001c
#define biCompression	0x001e
/*
#define BI_RGB		0UL//No Compression
#define BI_RLE8		1UL//RLE,Only for 8bits BMP
#define BI_RLE4		2UL//RLE,Only for 4bits BMP
#define BI_BITFIELDS 3UL//Bit Fields,For 16/32bits BMP
#define BI_JPEG		4UL//Conmain JPEG,Only For Printer
#define BI_PNG		5UL//Conmain PNG,Only For Printer
*/
#define biSizeImage		0x0022UL
#define RedMask		0x0036UL
#define GreenMask		0x003aUL
#define BlueMask		0x003eUL

都是用单片机编程很常见的C语言写的,怎么样是不是很简单为表诚意再附上Visual Studio工程包 BMP888to565CN.zip (538.39 KB, 下载次数: 7)

此帖出自单片机论坛

最新回复

565挺常见呀,我记得有个工具就是bitmap2lcd的  详情 回复 发表于 2021-7-2 12:51
点赞 关注
个人签名模电临时工
 

回复
举报

7504

帖子

2

TA的资源

五彩晶圆(高级)

沙发
 

565挺常见呀,我记得有个工具就是bitmap2lcd的

此帖出自单片机论坛

点评

你这个工具我没用过,我用过Image2LCD,LCD厂商打包资料都用这个软件转,但是只能转成565的bin二进制文件  详情 回复 发表于 2021-7-6 14:42
 
 

回复

321

帖子

1

TA的资源

一粒金砂(高级)

板凳
 
freebsder 发表于 2021-7-2 12:51 565挺常见呀,我记得有个工具就是bitmap2lcd的

你这个工具我没用过,我用过Image2LCD,LCD厂商打包资料都用这个软件转,但是只能转成565的bin二进制文件

此帖出自单片机论坛
 
个人签名模电临时工
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表