经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Linux/Shell » 查看文章
嵌入式Linux—Framebuffer应用编程
来源:cnblogs  作者:Tayoou  时间:2023/2/13 8:44:58  对本文有异议

Framebuffer 应用编程

Frame的意思是帧,buffer的意思是缓冲区。Framebuffer就是一块内存(硬件设备),里面保存着一帧图像。

ioctl()函数解析

ioctl()函数非常强大。不同的驱动程序内部会实现不同的 ioctl() ,可以使用各种 ioctl() 跟驱动程序交互:可以传数据给驱动程序,也可以从驱
动程序中读出数据。

头文件:

  1. #include <sys/ioctl.h>

函数原型:

  1. int ioctl(int fd, unsigned long request, ...);

函数说明:
① fd 表示文件描述符;
② request 表示与驱动程序交互的命令, 用不同的命令控制驱动程序输出我们需要的数据
③ … 表示可变参数 arg, 根据 request 命令,设备驱动程序返回输出的数据。
④ 返回值: 打开成功返回0,失败将返回-1

实现步骤

1.获取framebuffer描述符

  1. fd_fb = open("/dev/fb0", O_RDWR); //可读可写
  2. if(fd_fb == -1) {
  3. printf("can not open /dev/fb0\n");
  4. return -1;
  5. }

2.获取屏幕可变参数

  1. if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)) { //结构体名不是地址,需要取地址。FBIOGET_VSCREENINFO是获取可变参数(fb.h)
  2. printf("can not get var\n");
  3. return -1;
  4. }

3.计算framebuffer空间大小

  1. line_width = var.xres * var.bits_per_pixel / 8;
  2. pixel_width = var.bits_per_pixel / 8;
  3. screen_size = var.xres * var.yres * var.bits_per_pixel / 8; //单位:字节
  4. fb_base = (unsigned char*)mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
  5. if(fb_base == (unsigned char*)-1) {
  6. printf("can not mmap\n");
  7. return -1;
  8. }

4.不同的RGB格式转换

  1. switch(var.bits_per_pixel)
  2. {
  3. case 8:
  4. {
  5. /*代码*/
  6. break;
  7. }
  8. case 16:
  9. {
  10. /* 32位转换为RGB565 */
  11. red = (color >> 16) & 0xff; //保留17-24位
  12. green = (color >> 8) & 0xff; //保留8-16位
  13. blue = (color >> 0) & 0xff; //保留0-8位
  14. color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); //组合为16bit
  15. *add_16 = color; //像素点对应的地址空间赋值
  16. break;
  17. }
  18. case 32:
  19. {
  20. *add_32 = color;
  21. break;
  22. }
  23. default:
  24. printf("can't surport %dbpp\n", var.bits_per_pixel);
  25. break;
  26. }

完整程序如下:

  1. #include <sys/mman.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <unistd.h>
  5. #include <linux/fb.h>
  6. #include <fcntl.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <sys/ioctl.h>
  10. int fd_fb; //文件描述符
  11. int screen_size; //屏幕总字节数(framebuffer的大小)
  12. struct fb_var_screeninfo var;
  13. unsigned char *fb_base;
  14. unsigned int line_width; //行字节
  15. unsigned int pixel_width; //像素字节
  16. void lcd_put_pixel(int x, int y, unsigned int color) {
  17. unsigned char *add_8 = fb_base + y*line_width + x*pixel_width; //像素点对应的内存地址
  18. unsigned short *add_16;
  19. unsigned int *add_32;
  20. unsigned int red, green, blue;
  21. add_16 = (unsigned short*)add_8; //8位转换为16位
  22. add_32 = (unsigned int*) add_8;
  23. switch(var.bits_per_pixel)
  24. {
  25. case 8:
  26. {
  27. /*代码*/
  28. break;
  29. }
  30. case 16:
  31. {
  32. /* 32位转换为RGB565 */
  33. red = (color >> 16) & 0xff; //保留17-24位
  34. green = (color >> 8) & 0xff; //保留8-16位
  35. blue = (color >> 0) & 0xff; //保留0-8位
  36. color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3); //组合为16bit
  37. *add_16 = color; //像素点对应的地址空间赋值
  38. break;
  39. }
  40. case 32:
  41. {
  42. *add_32 = color;
  43. break;
  44. }
  45. default:
  46. printf("can't surport %dbpp\n", var.bits_per_pixel);
  47. break;
  48. }
  49. }
  50. int main(int argc, char **argv)
  51. {
  52. int i;
  53. /* 1.获取framebuffer描述符 */
  54. fd_fb = open("/dev/fb0", O_RDWR); //可读可写
  55. if(fd_fb == -1) {
  56. printf("can not open /dev/fb0\n");
  57. return -1;
  58. }
  59. /* 2.获取屏幕可变参数 */
  60. if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)) { //结构体名不是地址,需要取地址
  61. printf("can not get var\n");
  62. return -1;
  63. }
  64. /* 3.计算framebuffer空间大小 **/
  65. line_width = var.xres * var.bits_per_pixel / 8;
  66. pixel_width = var.bits_per_pixel / 8;
  67. screen_size = var.xres * var.yres * var.bits_per_pixel / 8; //单位:字节
  68. fb_base = (unsigned char*)mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
  69. if(fb_base == (unsigned char*)-1) {
  70. printf("can not mmap\n");
  71. return -1;
  72. }
  73. /* 清屏: 全部设为白色 */
  74. memset(fb_base, 0xff, screen_size);
  75. /* 随便设置出100个为蓝色 */
  76. for (i = 0; i < 100; i++)
  77. lcd_put_pixel(var.xres/2+i, var.yres/2, 0x0000FF);
  78. munmap(fb_base , screen_size);
  79. close(fd_fb);
  80. return 0;
  81. }

原文链接:https://www.cnblogs.com/Tayoou/p/17114400.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号