操作像素的程序分析与基于Framebuffer的字符显示-RZMPU工业控制教程连载(14)

瑞萨MCU小百科 2024-09-19 12:00


7.3

操作像素的程序分析

本节源码位于如下目录:


7.3.1 打开文件


代码如下:

73 fd_fb = open("/dev/fb0", O_RDWR);74 if (fd_fb < 0)75 {76 printf("can't open /dev/fb0\n");77 return -1;78 }


7.3.2 获取LCD参数


LCD驱动程序给APP提供2类参数:可变的参数fb_var_screeninfo、固定的参数fb_fix_screeninfo。编写应用程序时主要关心可变参数,它的结构体定义如下(#include):

图7.6 fb_var_screeninfo


可以使用以下代码获取fb_var_screeninfo:

左右滑动查看完整内容

12 static struct fb_var_screeninfo var; /* Current var */……79 if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))80 {81 printf("can't get var\n");82 return -1;83 }


注意到ioctl里用的参数是:FBIOGET_VSCREENINFO,它表示get varscreen info,获得屏幕的可变信息;当然也可以使用FBIOPUT_VSCREENINFO来调整这些参数,但是很少用到。


对于固定的参数fb_fix_screeninfo,在应用编程中很少用到。它的结构体定义如下:

图7.7 fb_fix_screeninfo


可以使用ioctl FBIOGET_FSCREENINFO来读出这些信息,但是很少用到。


7.3.3 映射Framebuffer


要映射一块内存,需要知道它的地址──这由驱动程序来设置,需要知道它的大小──这由应用程序决定。代码如下:

左右滑动查看完整内容

85 line_width = var.xres * var.bits_per_pixel / 8;86 pixel_width = var.bits_per_pixel / 8;87 screen_size = var.xres * var.yres * var.bits_per_pixel / 8;88 fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);89 if (fb_base == (unsigned char *)-1)90 {91 printf("can't mmap\n");92 return -1;93 }


第88行中,screen_size是整个Framebuffer的大小;PROT_READ | PROT_WRITE表示该区域可读、可写;MAP_SHARED表示该区域是共享的,APP写入数据时,会直达驱动程序,这个参数的更深刻理解可以参考后面驱动基础中讲到的mmap知识。


7.3.4 描点函数


能够在LCD上描绘指定像素后,就可以写字、画图,描点函数是基础。代码如下:

左右滑动查看完整内容

28 void lcd_put_pixel(int x, int y, unsigned int color)29 {30 unsigned char *pen_8 = fb_base+y*line_width+x*pixel_width;31 unsigned short *pen_16;32 unsigned int *pen_32;3334 unsigned int red, green, blue;3536 pen_16 = (unsigned short *)pen_8;37 pen_32 = (unsigned int *)pen_8;3839 switch (var.bits_per_pixel)40 {41 case 8:42 {43 *pen_8 = color;44 break;45 }46 case 16:47 {48 /* 565 */49 red = (color >> 16) & 0xff;50 green = (color >> 8) & 0xff;51 blue = (color >> 0) & 0xff;52 color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);53 *pen_16 = color;54 break;55 }RemiPiSoftware Development Manual56 case 32:57 {58 *pen_32 = color;59 break;60 }61 default:62 {63 printf("can't surport %dbpp\n",var.bits_per_pixel);64 break;65 }66 }67 }


第28行中传入的color表示颜色,它的格式永远是0x00RRGGBB,即RGB888。当LCD是16bpp时,要把color变量中的R、G、B抽出来再合并成RGB565格式。


第30行计算(x,y)坐标上像素对应的Framebuffer地址。


第43行,对于8bpp,color就不再表示RBG三原色了,这涉及调色板的概念,color是调色板的值。


第49~51行,先从color变量中把R、G、B抽出来。


第52行,把red、green、blue这三种8位颜色值,根据RGB565的格式,只保留red中的高5位、green中的高6位、blue中的高5位,组合成一个新的16位颜色值。


第53行,把新的16位颜色值写入Framebuffer。


第58行,对于32bpp,颜色格式跟color参数一致,可以直接写入Framebuffer。


7.3.5 上机实验


本程序的main函数,在最后只是简单地画了几个点:

左右滑动查看完整内容

95 /* 清屏: 全部设为白色 */96 memset(fbmem, 0xff, screen_size);9798 /* 随便设置出 100 个为红色 */99 for (i = 0; i < 100; i++)100 lcd_put_pixel(var.xres/2+i, var.yres/2, 0xFF0000);


编译:

左右滑动查看完整内容

source /opt/remi-sdk/environment-setup-aarch64-poky-linux$CC show_pixel.c -o show_pixel


假设设置开发板的IP为:192.168.5.9,上传程序到开发板上。

左右滑动查看完整内容

scp ./show_pixel root@192.168.5.9:/mnt/


测试:进入/mnt目录运行程序(在运行程序前,请确保已经接好HMDI显示屏):

root@myir-remi-1g:~# cd /mnt/root@myir-remi-1g:/mnt# lsshow_pixelroot@myir-remi-1g:/mnt# ./show_pixel


运行程序后,可以看到HDMI显示屏上会显示白色的背景和红色的横线。


7.4

基于Framebuffer的字符显示

要在LCD中显示一个ASCII字符,即英文字母这些字符,首先是要找到字符对应的点阵。在Linux内核源码中有这个文件:lib\fonts\font_8x16.c,里面以数组形式保存各个字符的点阵,比如:

图7.8 LCD的ASCII点阵


数组里的数字是如何表示点阵的?以字符A为例,如图7.9所示:

图7.9 字符A的点阵


上图左侧有16行数值,每行1个字节。每一个节对应右侧一行中8个像素:像素从右边数起,bit0对应第0个像素,bit1对应第1个像素,……,bit7对应第7个像素。某位的值为1时,表示对应的像素要被点亮;值为0时表示对应的像素要熄灭。


所以要显示某个字符时,根据它的ASCII码在fontdata_8x16数组中找到它的点阵,然后取出这16个字节去描画16行像素。


比如字符A的ASCII值是0x41,那么从fontdata_8x16[0x41*16]开始取其点阵数据。


下载所有源码后,本节源码位于如下目录:


核心函数是void lcd_put_ascii(int x, int y, unsigned char c),它在LCD的(x,y)位置处显示字符c,代码如下图所示:

图7.10 显示字符函数


7.4.1 获取点阵


对于字符c,char c,它的点阵获取方法如下:

左右滑动查看完整内容

4693 unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];


7.4.2 描点


根据“图7.9 字符A的点阵”,我们分析下如何利用点阵在LCD上显示一个英文字母。


因为有十六行,所以首先要有一个循环16次的大循环,然后每一行里有8位,那么在每一个大循环里也需要一个循环8次的小循环。小循环里的判断单行的描点情况,如果是1,就填充白色,如果是0就填充黑色,如此一来,就可以显示出黑色底,白色轮廓的英文字母。


左右滑动查看完整内容

4697 for (i = 0; i < 16; i++)4698 {4699 byte = dots[i];4700 for (b = 7; b >= 0; b--)4701 {4702 if (byte & (1<4703 {4704 /* show */4705 lcd_put_pixel(x+7-b, y+i, 0xffffff); /* 白 */4706 }4707 else4708 {4709 /* hide */4710 lcd_put_pixel(x+7-b, y+i, 0); /* 黑 */4711 }4712 }4713 }


7.4.3 main函数


main函数中首先要打开LCD设备,获取Framebuffer参数,实现lcd_put_pixel函数;然后调用lcd_put_ascii即可绘制字符。


代码如下:

左右滑动查看完整内容

4716 int main(int argc, char **argv)4717 {4718 fd_fb = open("/dev/fb0", O_RDWR);4719 if (fd_fb < 0)4720 {4721 printf("can't open /dev/fb0\n");4722 return -1;4723 }4724 if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))4725 {4726 printf("can't get var\n");4727 return -1;4728 }47294730 line_width = var.xres * var.bits_per_pixel / 8;4731 pixel_width = var.bits_per_pixel / 8;4732 screen_size = var.xres * var.yres * var.bits_per_pixel / 8;4733 fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);4734 if (fbmem == (unsigned char *)-1)4735 {4736 printf("can't mmap\n");4737 return -1;4738 }47394740 /* 清屏: 全部设为黑色 */4741 memset(fbmem, 0, screen_size);47424743 lcd_put_ascii(var.xres/2, var.yres/2, 'A'); /*在屏幕中间显示 8*16 的字母 A*/47444745 munmap(fbmem , screen_size);4746 close(fd_fb);47474748 return 0;4749 }4750


7.4.4 编译c文件show_ascii.c


编译命令如下:

左右滑动查看完整内容

source /opt/remi-sdk/environment-setup-aarch64-poky-linux$CC show_ascii.c -o show_ascii


假设设置开发板的IP为:192.168.5.9,上传程序到开发板上。

左右滑动查看完整内容

scp ./show_ascii root@192.168.5.9:/mnt/


7.4.5 上机实验


测试:进入/mnt目录运行程序:

root@myir-remi-1g:~# cd /mnt/root@myir-remi-1g:/mnt# lsshow_ascii


如果实验成功,我们将看到HDMI显示屏幕中间会显示出一个白色的字母‘A’。


需要技术支持?

如您在使用瑞萨MCU/MPU产品中有任何问题,可识别下方二维码或复制网址到浏览器中打开,进入瑞萨技术论坛寻找答案或获取在线技术支持。

https://community-ja.renesas.com/zh/forums-groups/mcu-mpu/



未完待续


推荐阅读

Linux I2C设备访问方法 - RZ MPU工业控制教程连载(9)

用户态接口应用与编写APP - RZ MPU工业控制教程连载(10)

Linux SPI协议介绍与访问方法 - RZ MPU工业控制教程连载(11)

更多精彩,敬请关注


评论
  • 职场是人生的重要战场,既是谋生之地,也是实现个人价值的平台。然而,有些思维方式却会悄无声息地拖住你的后腿,让你原地踏步甚至退步。今天,我们就来聊聊职场中最忌讳的五种思维方式,看看自己有没有中招。1. 固步自封的思维在职场中,最可怕的事情莫过于自满于现状,拒绝学习和改变。世界在不断变化,行业的趋势、技术的革新都在要求我们与时俱进。如果你总觉得自己的方法最优,或者害怕尝试新事物,那就很容易被淘汰。与其等待机会找上门,不如主动出击,保持学习和探索的心态。加入优思学院,可以帮助你快速提升自己,与行业前沿
    优思学院 2025-01-09 15:48 96浏览
  • 在当前人工智能(AI)与物联网(IoT)的快速发展趋势下,各行各业的数字转型与自动化进程正以惊人的速度持续进行。如今企业在设计与营运技术系统时所面临的挑战不仅是技术本身,更包含硬件设施、第三方软件及配件等复杂的外部因素。然而这些系统往往讲究更精密的设计与高稳定性,哪怕是任何一个小小的问题,都可能对整体业务运作造成严重影响。 POS应用环境与客户需求以本次分享的客户个案为例,该客户是一家全球领先的信息技术服务与数字解决方案提供商,遭遇到一个由他们所开发的POS机(Point of Sal
    百佳泰测试实验室 2025-01-09 17:35 96浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 110浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 82浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 97浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 79浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 92浏览
  • HDMI 2.2 规格将至,开启视听新境界2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新HDMI规范为规模庞大的 HDMI 生态系统带来更多选择,为创建、分发和体验理想的终端用户效果提供更先进的解决方案。新技术为电视、电影和游戏工作室等内容制作商在当前和未来提供更高质量的选择,同时实现多种分发平台。96Gbps的更高带宽和新一代 HDMI 固定比率速率传输(Fixed Rate Link)技术为各种设备应用提供更优质的音频和视频。终端用户显示器能以最
    百佳泰测试实验室 2025-01-09 17:33 106浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 112浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 91浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦