linux应用项目(一)数码相框(2)数码相框之字符编码与字符的点阵显示
一、字符编码
为更好的存储和展示,于是出现了字符编码。下面来看一下字符编码的发展过程。分为三个阶段:
阶段1:ASCII码
欧美人发明,用一个字节来标志。也就是常说的ASCII码,由于英语中只有26个英文字母,以及常用符号,可以很简单的编码出来。Ox41:A;0x61:a。
阶段2:国家编码GB2312(GBK)
我们国家有上千的汉子,所以编码要比较多一些,用两个字节来表示一个汉字。对于内地采用GB2312编码(GBK);big5(繁体字)等等。
D6DO:中。
阶段3:世界统一unicode码
世界需要一个统一的标准,于是出现了unicode,常见的utf-8;utf-16等
显示文字
文字编码方式
源文件用不同的编码方式编写,会导致执行结果不一样。
怎么解决?编译程序时,要指定字符集
man gcc , /charset
-finput-charset=charset 表示源文件的编码方式, 默认以UTF-8来解析
-fexec-charset=charset 表示可执行程序里的字时候以什么编码方式来表示,默认是UTF-8
gcc -o a a.c
gcc -finput-charset=GBK-fexec-charset=UTF-8 -o utf-8_2 ansi.c
ASCII默认国标存储汉字
默认utf8保存就不会有这个问题。
二、点阵显示
1、实现思路:
(1)打开lcd设备:
(2)得到lcd信息
Fbmen.c中有很多ioctl获得可变信息和固定信息
(3)显存占据多少字节
(4)LCD提供mmap
显存fb内存映射:
fbmem= (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED,fd_fb, 0);
screen_size:大小
PROT_READ | PROT_WRITE, MAP_SHARED:可读可写
if(fbmem == (unsigned char *)-1)
{
printf("can'tmmap\n");
return-1;
}
(5)显示A+中
unsignedchar str[] = "中";
lcd_put_ascii(var.xres/2, var.yres/2, 'A');
printf("chinesecode: %02x %02x\n", str[0], str[1]);
lcd_put_chinese(var.xres/2 + 8, var.yres/2, str);
return0;
(6)void lcd_put_ascii(int x, int y, unsignedchar c)
void lcd_put_pixel(int x, int y, unsigned int color)
(7)打开汉字库
fd_hzk16= open("HZK16", O_RDONLY);
if(fd_hzk16 < 0)
{
printf("can'topen HZK16\n");
return-1;
}
struct stat hzk_stat;
if(fstat(fd_hzk16,&hzk_stat))
{
printf("can'tget fstat\n");
return-1;
}
hzkmem= (unsigned char *)mmap(NULL , hzk_stat.st_size, PROT_READ, MAP_SHARED,fd_hzk16, 0);
if(hzkmem == (unsigned char *)-1)
{
printf("can'tmmap for hzk16\n");
return-1;
}
(8)void lcd_put_chinese(int x, int y, unsignedchar *str)
(9)编译
有缺少头文件的错误,修改后成功
拷贝至开发板
(10)内核修改
1.配置、修改内核支持把lcd.c编译进去
cp /work/drivers_and_test_new/10th_lcd/lcd.c drivers/video/
修改drivers/video/Makefile
#obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
obj-$(CONFIG_FB_S3C2410) += lcd.o
2.make menuconfig
支持lcd编译进内核
(11)测试
应用程序挂载到单板
内核配置编译lcd进内核
修改lcd驱动
从新内核启动
nfs 32000000 192.168.1.100:/work/nfs_root/uImage; bootm 32000000
三、代码
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>#define FONTDATAMAX 4096static const unsigned char fontdata_8x16[FONTDATAMAX] = {...
}int fd_fb;
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
int screen_size;
unsigned char *fbmem;
unsigned int line_width;
unsigned int pixel_width;int fd_hzk16;
struct stat hzk_stat;
unsigned char *hzkmem;/* color : 0x00RRGGBB */
void lcd_put_pixel(int x, int y, unsigned int color)
{unsigned char *pen_8 = fbmem+y*line_width+x*pixel_width;unsigned short *pen_16; unsigned int *pen_32; unsigned int red, green, blue; pen_16 = (unsigned short *)pen_8;pen_32 = (unsigned int *)pen_8;switch (var.bits_per_pixel){case 8:{*pen_8 = color;break;}case 16:{/* 565 */red = (color >> 16) & 0xff;green = (color >> 8) & 0xff;blue = (color >> 0) & 0xff;color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);*pen_16 = color;break;}case 32:{*pen_32 = color;break;}default:{printf("can't surport %dbpp\n", var.bits_per_pixel);break;}}
}void lcd_put_ascii(int x, int y, unsigned char c)
{unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];int i, b;unsigned char byte;for (i = 0; i < 16; i++){byte = dots[i];for (b = 7; b >= 0; b--){if (byte & (1<<b)){/* show */lcd_put_pixel(x+7-b, y+i, 0xffffff); /* 白 */}else{/* hide */lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */}}}
}void lcd_put_chinese(int x, int y, unsigned char *str)
{unsigned int area = str[0] - 0xA1;unsigned int where = str[1] - 0xA1;unsigned char *dots = hzkmem + (area * 94 + where)*32;unsigned char byte;int i, j, b;for (i = 0; i < 16; i++)for (j = 0; j < 2; j++){byte = dots[i*2 + j];for (b = 7; b >=0; b--){if (byte & (1<<b)){/* show */lcd_put_pixel(x+j*8+7-b, y+i, 0xffffff); /* 白 */}else{/* hide */lcd_put_pixel(x+j*8+7-b, y+i, 0); /* 黑 */}}}}int main(int argc, char **argv)
{unsigned char str[] = "中";fd_fb = open("/dev/fb0", O_RDWR);if (fd_fb < 0){printf("can't open /dev/fb0\n");return -1;}if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){printf("can't get var\n");return -1;}if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix)){printf("can't get fix\n");return -1;}line_width = var.xres * var.bits_per_pixel / 8;pixel_width = var.bits_per_pixel / 8;screen_size = var.xres * var.yres * var.bits_per_pixel / 8;fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);if (fbmem == (unsigned char *)-1){printf("can't mmap\n");return -1;}fd_hzk16 = open("HZK16", O_RDONLY);if (fd_hzk16 < 0){printf("can't open HZK16\n");return -1;}if(fstat(fd_hzk16, &hzk_stat)){printf("can't get fstat\n");return -1;}hzkmem = (unsigned char *)mmap(NULL , hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);if (hzkmem == (unsigned char *)-1){printf("can't mmap for hzk16\n");return -1;}/* 清屏: 全部设为黑色 */memset(fbmem, 0, screen_size);lcd_put_ascii(var.xres/2, var.yres/2, 'A');printf("chinese code: %02x %02x\n", str[0], str[1]);lcd_put_chinese(var.xres/2 + 8, var.yres/2, str);return 0;
}
(2)LCD驱动程序代码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/platform_device.h>
#include <linux/clk.h>#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/div64.h>#include <asm/mach/map.h>
//#include <asm/arch/regs-lcd.h>
//#include <asm/arch/regs-gpio.h>
//#include <asm/arch/fb.h>static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,unsigned int green, unsigned int blue,unsigned int transp, struct fb_info *info);struct lcd_regs {unsigned long lcdcon1;unsigned long lcdcon2;unsigned long lcdcon3;unsigned long lcdcon4;unsigned long lcdcon5;unsigned long lcdsaddr1;unsigned long lcdsaddr2;unsigned long lcdsaddr3;unsigned long redlut;unsigned long greenlut;unsigned long bluelut;unsigned long reserved[9];unsigned long dithmode;unsigned long tpal;unsigned long lcdintpnd;unsigned long lcdsrcpnd;unsigned long lcdintmsk;unsigned long lpcsel;
};static struct fb_ops s3c_lcdfb_ops = {.owner = THIS_MODULE,.fb_setcolreg = s3c_lcdfb_setcolreg,.fb_fillrect = cfb_fillrect,.fb_copyarea = cfb_copyarea,.fb_imageblit = cfb_imageblit,
};static struct fb_info *s3c_lcd;
static volatile unsigned long *gpbcon;
static volatile unsigned long *gpbdat;
static volatile unsigned long *gpccon;
static volatile unsigned long *gpdcon;
static volatile unsigned long *gpgcon;
static volatile struct lcd_regs* lcd_regs;
static u32 pseudo_palette[16];/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{chan &= 0xffff;chan >>= 16 - bf->length;return chan << bf->offset;
}static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,unsigned int green, unsigned int blue,unsigned int transp, struct fb_info *info)
{unsigned int val;if (regno > 16)return 1;/* 用red,green,blue三原色构造出val */val = chan_to_field(red, &info->var.red);val |= chan_to_field(green, &info->var.green);val |= chan_to_field(blue, &info->var.blue);//((u32 *)(info->pseudo_palette))[regno] = val;pseudo_palette[regno] = val;return 0;
}static int lcd_init(void)
{/* 1. 分配一个fb_info */s3c_lcd = framebuffer_alloc(0, NULL);/* 2. 设置 *//* 2.1 设置固定的参数 */strcpy(s3c_lcd->fix.id, "mylcd");s3c_lcd->fix.smem_len = 480*272*16/8;s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS;s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR; /* TFT */s3c_lcd->fix.line_length = 480*2;/* 2.2 设置可变的参数 */s3c_lcd->var.xres = 480;s3c_lcd->var.yres = 272;s3c_lcd->var.xres_virtual = 480;s3c_lcd->var.yres_virtual = 272;s3c_lcd->var.bits_per_pixel = 16;/* RGB:565 */s3c_lcd->var.red.offset = 11;s3c_lcd->var.red.length = 5;s3c_lcd->var.green.offset = 5;s3c_lcd->var.green.length = 6;s3c_lcd->var.blue.offset = 0;s3c_lcd->var.blue.length = 5;s3c_lcd->var.activate = FB_ACTIVATE_NOW;/* 2.3 设置操作函数 */s3c_lcd->fbops = &s3c_lcdfb_ops;/* 2.4 其他的设置 */s3c_lcd->pseudo_palette = pseudo_palette;//s3c_lcd->screen_base = ; /* 显存的虚拟地址 */ s3c_lcd->screen_size = 480*272*16/8;/* 3. 硬件相关的操作 *//* 3.1 配置GPIO用于LCD */gpbcon = ioremap(0x56000010, 8);gpbdat = gpbcon+1;gpccon = ioremap(0x56000020, 4);gpdcon = ioremap(0x56000030, 4);gpgcon = ioremap(0x56000060, 4);*gpccon = 0xaaaaaaaa; /* GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND */*gpdcon = 0xaaaaaaaa; /* GPIO管脚用于VD[23:8] */*gpbcon &= ~(3); /* GPB0设置为输出引脚 */*gpbcon |= 1;*gpbdat &= ~1; /* 输出低电平 */*gpgcon |= (3<<8); /* GPG4用作LCD_PWREN *//* 3.2 根据LCD手册设置LCD控制器, 比如VCLK的频率等 */lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));/* bit[17:8]: VCLK = HCLK / [(CLKVAL+1) x 2], LCD手册P14* 10MHz(100ns) = 100MHz / [(CLKVAL+1) x 2]* CLKVAL = 4* bit[6:5]: 0b11, TFT LCD* bit[4:1]: 0b1100, 16 bpp for TFT* bit[0] : 0 = Disable the video output and the LCD control signal.*/lcd_regs->lcdcon1 = (4<<8) | (3<<5) | (0x0c<<1);#if 1/* 垂直方向的时间参数* bit[31:24]: VBPD, VSYNC之后再过多长时间才能发出第1行数据* LCD手册 T0-T2-T1=4* VBPD=3* bit[23:14]: 多少行, 320, 所以LINEVAL=320-1=319* bit[13:6] : VFPD, 发出最后一行数据之后,再过多长时间才发出VSYNC* LCD手册T2-T5=322-320=2, 所以VFPD=2-1=1* bit[5:0] : VSPW, VSYNC信号的脉冲宽度, LCD手册T1=1, 所以VSPW=1-1=0*/lcd_regs->lcdcon2 = (1<<24) | (271<<14) | (1<<6) | (9);/* 水平方向的时间参数* bit[25:19]: HBPD, VSYNC之后再过多长时间才能发出第1行数据* LCD手册 T6-T7-T8=17* HBPD=16* bit[18:8]: 多少列, 240, 所以HOZVAL=240-1=239* bit[7:0] : HFPD, 发出最后一行里最后一个象素数据之后,再过多长时间才发出HSYNC* LCD手册T8-T11=251-240=11, 所以HFPD=11-1=10*/lcd_regs->lcdcon3 = (1<<19) | (479<<8) | (1);/* 水平方向的同步信号* bit[7:0] : HSPW, HSYNC信号的脉冲宽度, LCD手册T7=5, 所以HSPW=5-1=4*/ lcd_regs->lcdcon4 = 40;#else
lcd_regs->lcdcon2 = S3C2410_LCDCON2_VBPD(5) | \S3C2410_LCDCON2_LINEVAL(319) | \S3C2410_LCDCON2_VFPD(3) | \S3C2410_LCDCON2_VSPW(1);lcd_regs->lcdcon3 = S3C2410_LCDCON3_HBPD(10) | \S3C2410_LCDCON3_HOZVAL(239) | \S3C2410_LCDCON3_HFPD(1);lcd_regs->lcdcon4 = S3C2410_LCDCON4_MVAL(13) | \S3C2410_LCDCON4_HSPW(0);#endif/* 信号的极性 * bit[11]: 1=565 format* bit[10]: 0 = The video data is fetched at VCLK falling edge* bit[9] : 1 = HSYNC信号要反转,即低电平有效 * bit[8] : 1 = VSYNC信号要反转,即低电平有效 * bit[6] : 0 = VDEN不用反转* bit[3] : 0 = PWREN输出0* bit[1] : 0 = BSWP* bit[0] : 1 = HWSWP 2440手册P413*/lcd_regs->lcdcon5 = (1<<11) | (0<<10) | (1<<9) | (1<<8) | (1<<0);/* 3.3 分配显存(framebuffer), 并把地址告诉LCD控制器 */s3c_lcd->screen_base = dma_alloc_writecombine(NULL, s3c_lcd->fix.smem_len, &s3c_lcd->fix.smem_start, GFP_KERNEL);lcd_regs->lcdsaddr1 = (s3c_lcd->fix.smem_start >> 1) & ~(3<<30);lcd_regs->lcdsaddr2 = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1) & 0x1fffff;lcd_regs->lcdsaddr3 = (480*16/16); /* 一行的长度(单位: 2字节) */ //s3c_lcd->fix.smem_start = xxx; /* 显存的物理地址 *//* 启动LCD */lcd_regs->lcdcon1 |= (1<<0); /* 使能LCD控制器 */lcd_regs->lcdcon5 |= (1<<3); /* 使能LCD本身 */*gpbdat |= 1; /* 输出高电平, 使能背光 */ /* 4. 注册 */register_framebuffer(s3c_lcd);return 0;
}static void lcd_exit(void)
{unregister_framebuffer(s3c_lcd);lcd_regs->lcdcon1 &= ~(1<<0); /* 关闭LCD本身 */*gpbdat &= ~1; /* 关闭背光 */dma_free_writecombine(NULL, s3c_lcd->fix.smem_len, s3c_lcd->screen_base, s3c_lcd->fix.smem_start);iounmap(lcd_regs);iounmap(gpbcon);iounmap(gpccon);iounmap(gpdcon);iounmap(gpgcon);framebuffer_release(s3c_lcd);
}module_init(lcd_init);
module_exit(lcd_exit);MODULE_LICENSE("GPL");
参考资料:
FreeType 字体引擎分析与指南
http://wenku.baidu.com/view/2d24be10cc7931b765ce155b.html
HZK16应用示例
http://wenku.baidu.com/view/0774d20c52ea551810a68768.html
点阵字库HZK12 HZK16 HZK24 ASC12 ASC16 简介 及 使用方法
http://blog.csdn.net/hongjiujing/article/details/6649618
汉字拼音、五笔、GB2312、GBK、Unicode、BIG5编码速查
http://ipseeker.cn/tools/pywb.php
在线汉字编码查询,一次查询多个汉字输入法编码及内码——快典网.htm
http://bm.kdd.cc/
BIG5编码表
http://wenku.baidu.com/view/9bb3ae01b52acfc789ebc970.html
UNICODE编码表
http://wenku.baidu.com/view/7c667f563c1ec5da50e27069.html
GB2312简体中文编码表
http://wenku.baidu.com/view/0ef57bfb04a1b0717fd5dd1a.html
hzk16的介绍以及简单的使用方法
http://hi.baidu.com/hrman/blog/item/4616bc2675ce13128a82a193.html
linux应用项目(一)数码相框(2)数码相框之字符编码与字符的点阵显示相关推荐
- linux相框应用程序,linux应用项目(一)数码相框(1)数码相框之系统框架
项目说明: 数码相框项目:看着简单 涉及到的内容是很多的. 项目流程: 弄清需求 设计框架 编写代码 测试 发展方向: 专家(某个问题专研深刻) 系统(设计框架功能) 弄清需求: (1) 上电, ...
- linux应用项目(一)数码相框(3)数码相框之电子书
一.整体思路 这一节我们重点学习框架,就是编程的思想.架构很重要.采用分层的思想,面向对象的编程思想. 1.怎样在LCD上显示一个文件 2.如何组织代码 分层的结构 main--draw--XXX_m ...
- [电子书]项目储备一: 字符编码与LCD显示单个字母/汉字
[电子书]项目储备一: 字符编码与LCD显示单个字母/汉字 1 字符编码 2 LCD显示单个字母/汉字 2.1 编程思路 2.2 代码实现 2.3 编译.测试与bug 3 总结与下文预告 1 字符编码 ...
- linux下字符编码转换
2019独角兽企业重金招聘Python工程师标准>>> 关于字符编码: 字符编码笔记:ASCII,Unicode和UTF-8: http://www.ruanyifeng.com/b ...
- 数码相框_在LCD上显示英文字母、汉字的点阵显示(2)
数码相框_在LCD上显示英文字母.汉字的点阵显示 主要内容: 写应用程序,使LCD显示汉字和字符 原理: 在SDRAM内存里划出一块空间为FrameBuffer显存,LCD控制器会从FrameBuff ...
- clion浏览linux代码,手把手教你使用 Clion 开发 Linux C++ 项目
手把手教你使用 Clion 开发 Linux C++ 项目 关于CLion CLion是一款专为开发C及C++所设计的跨平台IDE.它是以IntelliJ为基础设计的,包含了许多智能功能来提高开发人员 ...
- linux基本项目环境搭建
文章目录 linux基本项目环境搭建 java环境搭建 获取java源码包 解压 配置环境变量 使配置文件生效 验证 nginx安装 下载(java也可用此方法下载) 解压 配置(configure) ...
- 嵌入式 linux 启动脚本 编写,[9构建嵌入式linux系统项目-启动脚本的编写.ppt
[9构建嵌入式linux系统项目-启动脚本的编写 启动脚本 教学回顾 shell语法 管道.重定向 变量 结构性语句 教学内容 启动脚本的写法 教学要求 熟悉掌握启动脚本的写法 shell 函数 在s ...
- C语言到嵌入式Linux开发项目指导
C语言到嵌入式Linux开发项目指导 第一阶段C语言 1.常量与变量,数据类型,数据类型转换,数据输入与输出: 2.C语言运算符,C语言操作符,C语言表达式,表达式优先级: 3.C语言流程控制,分支, ...
- 关于Linux开源项目基础组件make编译流程
关于Linux开源项目基础组件make编译流程 非常多Linux开源项目都会用到编译出可运行文件的make.这个是有一套流程的. 首先,GNU构建系统:https://en.wikipedia. ...
最新文章
- 中国地址住址五级以下
- mysql noinstall_windows mysql noinstall
- java amr 转 mp3_JAVA 音频转换AMR 转MP3,OS,Linux cent os 7
- 为什么报表里面记录的创建时间 比我们电脑客户端的世界时间 隔8个小时?这个是什么原因?...
- 未来已来 -只是尚未流行
- python如何输入多组数据_Python 中如何实现多组的输入输出
- 厉害!这位80后连发2篇Science!身处普通高校,告诉你科研不决取于平台
- python pip下载本地依赖包,并在离线环境中安装,并解决报错ERROR: Could not find a version that satisfies the requirement报错
- socket的java实现_Socket之Java实现普通版本
- asp.net ajax updatepanel中textbox 乱码问题 解决方案
- Jasper报表导出pdf中文不显示——Font simsun is not available to the JVM. See the Javadoc for more det,已解决
- 红米5 Plus刷开发版/小米手机刷开发版
- 使用PS将图片自然从清晰到模糊过渡
- Android显示人民币双横线的¥符号
- Freebase上的SPARQL查询
- 科恒khs202温控器使用说明书_WS203数字显示温控器使用说明书
- C语言常见问题(3):Although the value stored to ‘ret‘ is used in the enclosing expression
- 基于SpringBoot+Vue的酒店管理系统(免费获取源码+项目介绍+运行介绍+运行截图+论文)
- 小米市场魅力所在?你读懂小米了么?
- Python绘制3D图形:Axes3D