zoukankan      html  css  js  c++  java
  • 点阵显示


    title: 点阵显示
    date: 2019/2/27 19:32:07
    toc: true

    点阵显示

    linux内核中存在着ASCII的字符点阵文件,这里我们挑选8*16的,也就是8列16行来测试显示英文.

    mark

    汉字的话我们需要自己寻找点阵,这里选取了hzk16,也就是16*16的,这也是为什么我们英文选取8*16的原因,一个中文占据两个英文空间

    具体关于汉字库的使用,参考这里

    gbk转uft8

    linux下默认都是utf-8编码的,终端的输入都是utf-8的,所以这里我们需要将输入的utf8转换为gbk才能使用hzk这个点阵

    PC显示点阵

    这里直接都是使用utf8编码的

    #include <stdio.h>
    #include <stdlib.h>
    
    #include <iconv.h>  
    
    #include <unistd.h>  
    #include <fcntl.h>  
    #include <string.h>  
    #include <sys/stat.h>  
    int code_convert(char *from_charset, char *to_charset, char *inbuf, size_t inlen,  
            char *outbuf, size_t outlen) {  
        iconv_t cd;  
        char **pin = &inbuf;  
        char **pout = &outbuf;  
      
        cd = iconv_open(to_charset, from_charset);  
        if (cd == 0)  
            return -1;  
        memset(outbuf, 0, outlen);  
        if (iconv(cd, pin, &inlen, pout, &outlen) == -1)  
            return -1;  
        iconv_close(cd);  
        *pout = '';  
      
        return 0;  
    }  
      
    int u2g(char *inbuf, size_t inlen, char *outbuf, size_t outlen) {  
        return code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, outlen);  
    }  
      
    int g2u(char *inbuf, size_t inlen, char *outbuf, size_t outlen) {  
        return code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, outlen);  
    }
    
    
    
    int main(void)
    {
        FILE* fphzk = NULL;
        int i, j, k, offset;
        int flag;
        unsigned char buffer[32];
        unsigned char word[5];
    	unsigned char utf[5];
        unsigned char key[8] = {
            0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
        };
        fphzk = fopen("hzk16", "rb");
        if(fphzk == NULL){
            fprintf(stderr, "error hzk16
    ");
            return 1;
        }
        while(1){
            printf("输入要生成字模的汉字(多个):");
            for(;;){
                fgets((char*)utf, 4, stdin);//这里是读取3个字符,然后补上一个结束
    			
    			printf("raw char[] is :");
    			for(i=0;i<10;i++)
    				printf("%x ",(*(utf+i)&0xFF));
    			
    			u2g(utf, 3, word, sizeof(word)); 
    			
    			printf("
     change char[] is :");
    			for(i=0;i<3;i++)
    				printf("%x ",(*(word+i)&0xFF));
    			
                if(*word == '
    ') 
                    break;
                offset = (94*(unsigned int)(word[0]-0xa0-1)+(word[1]-0xa0-1))*32;
                fseek(fphzk, offset, SEEK_SET);
                fread(buffer, 1, 32, fphzk);
                for(k=0; k<16; k++){
                    for(j=0; j<2; j++){
                        for(i=0; i<8; i++){
                            flag = buffer[k*2+j]&key[i];
                            printf("%s", flag?".":" ");
                        }
                    }
                    printf("
    ");
                }
                printf("uchar code key[32] = {");
                for(k=0; k<31; k++){
                    printf("0x%02X,", buffer[k]);
                }
                printf("0x%02X};
    ", buffer[31]);
                printf("
    ");
            }
        }
        fclose(fphzk);
        fphzk = NULL;
        return 0;
    }
    

    mark

    关键函数

    LCD操作相关

    • ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)获取到lcd可变信息:xy分辨率,像素位数
    • ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix),获取固定信息,缓存地址,每行字节数

    内存映射

    • void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

    文件大小查看

    • int fstat(int fd, struct stat *buf);

    怎么查看函数的使用,直接man xxx,然后使用/ fun_name 即可

    编译错误排查

    find -name "fb.h"  #寻找头文件路径,在交叉工具链中搜索
    open 函数中找不到 O_RDWR的宏定义,使用 man 2 open 找到对应头文件
    

    详细代码

    具体代码如下,没什么好分析的了

    #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 4096
    
    
    
    
    // 这里是英文点阵
    
    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
    ", 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
    ");
    		return -1;
    	}
    
    	if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
    	{
    		printf("can't get var
    ");
    		return -1;
    	}
    
    	if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix))
    	{
    		printf("can't get fix
    ");
    		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
    ");
    		return -1;
    	}
    
    	fd_hzk16 = open("HZK16", O_RDONLY);
    	if (fd_hzk16 < 0)
    	{
    		printf("can't open HZK16
    ");
    		return -1;
    	}
    	if(fstat(fd_hzk16, &hzk_stat))
    	{
    		printf("can't get fstat
    ");
    		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
    ");
    		return -1;
    	}
    
    	/* 清屏: 全部设为黑色 */
    	memset(fbmem, 0, screen_size);
    
    	lcd_put_ascii(var.xres/2, var.yres/2, 'A');
    
    	printf("chinese code: %02x %02x
    ", str[0], str[1]);
    	lcd_put_chinese(var.xres/2 + 8,  var.yres/2, str);
    
    	return 0;	
    }
    
    

    内核设置

    内核需要加入对lcd的驱动支持,具体在

      │ Symbol: FB_S3C2410 [=y]                                                                                                    │
      │ Type  : tristate                                                                                                           │
      │ Prompt: S3C2410 LCD framebuffer support                                                                                    │
      │   Defined at drivers/video/Kconfig:2062                                                                                    │
      │   Depends on: HAS_IOMEM [=y] && FB [=y] && ARCH_S3C24XX [=y]                                                               │
      │   Location:                                                                                                                │
      │     -> Device Drivers                                                                                                      │
      │       -> Graphics support                                                                                                  │
      │         -> Support for frame buffer devices (FB [=y])                                                                      │
      │   Selects: FB_CFB_FILLRECT [=y] && FB_CFB_COPYAREA [=y] && FB_CFB_IMAGEBLIT [=y]  
    

    后续

    测试发现,从终端输入到串口,linux读取到的编码是utf-8的,参考这里写个程序输入字符,然后显示到液晶,这里还需要做一个utf8转gbk的函数,实际上这个函数在板子上不行,iconv_open返回成功,下面的转换就返回失败

    
    #include <stdio.h>
    #include <stdlib.h>
    
    #include <iconv.h>  
    
    #include <unistd.h>  
    #include <fcntl.h>  
    #include <string.h>  
    #include <sys/stat.h>  
    int code_convert(char *from_charset, char *to_charset, char *inbuf, size_t inlen,  
            char *outbuf, size_t outlen) {  
        iconv_t cd;  
        char **pin = &inbuf;  
        char **pout = &outbuf;  
      
        cd = iconv_open(to_charset, from_charset);  
        if (cd == 0)  
            return -1;  
        memset(outbuf, 0, outlen);  
        if (iconv(cd, pin, &inlen, pout, &outlen) == -1)    //这里失败了
            return -1;  
        iconv_close(cd);  
        *pout = '';  
      
        return 0;  
    }  
      
    int u2g(char *inbuf, size_t inlen, char *outbuf, size_t outlen) {  
        return code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, outlen);  
    }  
      
    int g2u(char *inbuf, size_t inlen, char *outbuf, size_t outlen) {  
        return code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, outlen);  
    }
    
    
    
    int main(void)
    {
        FILE* fphzk = NULL;
        int i, j, k, offset;
        int flag;
        unsigned char buffer[32];
        unsigned char word[5];
    	unsigned char utf[5];
        unsigned char key[8] = {
            0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
        };
        fphzk = fopen("hzk16", "rb");
        if(fphzk == NULL){
            fprintf(stderr, "error hzk16
    ");
            return 1;
        }
        while(1){
            printf("输入要生成字模的汉字(多个):");
            for(;;){
                fgets((char*)utf, 4, stdin);//这里是读取3个字符,然后补上一个结束
    			
    			printf("raw char[] is :");
    			for(i=0;i<10;i++)
    				printf("%x ",(*(utf+i)&0xFF));
    			
    			u2g(utf, 3, word, sizeof(word)); 
    			
    			printf("
     change char[] is :");
    			for(i=0;i<3;i++)
    				printf("%x ",(*(word+i)&0xFF));
    			
                if(*word == '
    ') 
                    break;
                offset = (94*(unsigned int)(word[0]-0xa0-1)+(word[1]-0xa0-1))*32;
                fseek(fphzk, offset, SEEK_SET);
                fread(buffer, 1, 32, fphzk);
                for(k=0; k<16; k++){
                    for(j=0; j<2; j++){
                        for(i=0; i<8; i++){
                            flag = buffer[k*2+j]&key[i];
                            printf("%s", flag?".":" ");
                        }
                    }
                    printf("
    ");
                }
                printf("uchar code key[32] = {");
                for(k=0; k<31; k++){
                    printf("0x%02X,", buffer[k]);
                }
                printf("0x%02X};
    ", buffer[31]);
                printf("
    ");
            }
        }
        fclose(fphzk);
        fphzk = NULL;
        return 0;
    }
    
  • 相关阅读:
    servlet的配置
    getRequestDispatcher()与sendRedirect()的区别
    request.setAttribute()怎么用的?
    <jsp:useBean>元素使用全解
    jsp中使用javabean简单例子
    2-1
    跟我想的一样,已经连续暴跌三天了。
    我的判断很正确
    我靠算个账发现最近打德扑输了好多钱啊,怀疑PokerStars里是不是有好多机器人作弊骗钱呢???
    1-18
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10492453.html
Copyright © 2011-2022 走看看