当前位置: 首页 > java >正文

嵌入式自学第三十一天

(1)framebuf帧缓冲  :linux提供的显示设备驱动的接口。

设备路径 : 设备/dev/fb0

*        分辨率:像素点是w * h。
每个像素点色深 RGB:0-255  红绿蓝各3字节(byte)即可描述色深。
访问的显存默认左上角为坐标原点。

*        xres yres真实分辨率
        xres_vitrual虚拟分辨率:

        一般可访问显存小一些,即虚拟分辨率,真实分辨率就是打开设置查看得到的分辨率。

*        每个像素点色深RGB用三字节描述,即3*8bit,用十六进制就是0x00rrggbb,具体颜色对应16进制可以搜索w3cschool,在里面的htmlyanse查看。

*        文件解压:tar -xvf 压缩包.tar.xz

*        ctrl alt f3文字终端,没有图形界面。
ctrl alt f1图形界面,伪终端即图形界面打开的终端。
ctrl alt鼠标出现
直接操作硬件运行时sudo ./out

*        简单的操作像素点,比如画直线等,可以通过简单的循环控制xy坐标就能实现,但汉字图像等需要的像素点坐标就比较复杂了。

*        文字可以通过字模工具获取要操作的像素点坐标数组,也可以通过字库进行操作,最原始的图像是位图,文件信息中前54字节是头信息,包含图像的大小等参数,剩下的就是连续了BGRBGR像素点数据,我们可以循环取三字节,再倒序就得到RGB参数了,然后输出。

(2)利用帧缓存点亮第一个点。

*        步骤:open打开设备-》ioctl获取屏幕信息-》mmap映射:获得显存 -》draw根据坐标操作像素点 -》unmap显存回收

#include <stdio.h>   
#include <stdlib.h>   
#include <string.h>   
#include <unistd.h>   
#include <fcntl.h>   
#include <sys/ioctl.h>   
#include <sys/mman.h>   
#include <linux/fb.h>   
#include <math.h>
   
// 颜色定义   
#define RGB888_FMT 32   
#define RGB565_FMT 16   
#define WHITE     0x00FFFFFF   
#define BLACK     0x00000000   
#define RED       0x00FF0000   
#define GREEN     0x0000FF00   
#define BLUE      0x000000FF   
#define YELLOW    0x00FFFF00   
#define PURPLE    0x00FF00FF   
#define CYAN      0x0000FFFF
   
// 全局变量   
struct fb_var_screeninfo vinf;   
void *pmem = NULL;
   
// 函数声明   
int init_fb(char *devname);   
void draw_point(int x, int y, unsigned int col);   
void draw_h_line(int x, int y, int len, unsigned int col);   
void draw_v_line(int x, int y, int len, unsigned int col);   
void draw_x_line(int x1, int y1, int x2, int y2, unsigned int col);   
void draw_rect(int x, int y, int w, int h, unsigned int col);   
void draw_circle(int x0, int y0, int r, unsigned int col);   
void draw_bmp(int x, int y, char *picname, int w, int h);   
void draw_word(int x, int y, unsigned char *word, int w, int h, unsigned int col);
   
// 初始化帧缓冲设备   
int init_fb(char *devname)   
{
    //1. 打开显示设备
    int fd = open(devname, O_RDWR);    
    if (-1 == fd)
    {
        perror("fail open fb");
        return -1;
    }
    
    //2、获取显示设备参数(分辨率、位深度等)
    int ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinf);
    if (-1 ==ret)
    {
        perror("fail ioctl");
        return -1;
    }
    
    //3, 建立显存和用户空间的映射关系
    size_t len = vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8;
    pmem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if ((void *)-1 == pmem)
    {
        perror("fail mmap");
        return -1;
    }
    
    return fd;   
}
   
// 绘制单个像素点   
void draw_point(int x, int y, unsigned int col)   
{
    if (x >= vinf.xres || y >= vinf.yres)
    {
        return ; // 超出屏幕范围则不绘制
    }
    if (vinf.bits_per_pixel == RGB888_FMT) // 32位色模式
    {
        unsigned int *p = pmem;
        *(p + y * vinf.xres_virtual + x) = col;
    }
    else if (vinf.bits_per_pixel == RGB565_FMT) // 16位色模式
    {
        unsigned short *p  = pmem;    
        *(p + y * vinf.xres_virtual + x) = col;
    }   
}
   
// 绘制水平线   
void draw_h_line(int x, int y, int len, unsigned int col)   
{
    for (int i = x; i < x+len; i++)
    {
        draw_point(i, y, col); // 连续绘制水平方向的点
    }   
}
   
// 绘制垂直线   
void draw_v_line(int x, int y, int len, unsigned int col)   
{
    for (int i = y; i < y+len; i++)
    {
        draw_point(x, i, col); // 连续绘制垂直方向的点
    }   
}
   
// 绘制斜线(使用直线方程y=kx+b)   
void draw_x_line(int x1, int y1, int x2, int y2, unsigned int col)   
{
    if (x1 == x2) // 垂直线特殊情况处理
    {
        if (y2 > y1)
        {
            draw_v_line(x1, y1, y2-y1, col);
        }
        else
        {
            draw_v_line(x2, y2, y1-y2, col);            
        }
    }

    // 计算直线斜率和截距
    double k = (double)(y2-y1)/(double)(x2-x1);
    double b = y1 - k*x1;
   
    // 根据x坐标计算y值并绘制
    for (int x = (x1 > x2 ? x2 : x1); x <= (x1 > x2 ? x1 : x2); x++)
    {
        int y = x * k + b;
        draw_point(x, y, col);
    }   
}
   
// 绘制矩形   
void draw_rect(int x, int y, int w, int h, unsigned int col)   
{
    draw_h_line(x, y, w, col);        // 上边
    draw_h_line(x, y+h-1, w, col);    // 下边
    draw_v_line(x, y, h, col);        // 左边
    draw_v_line(x+w-1, y, h, col);    // 右边   
}
   
// 绘制圆形(使用三角函数参数方程)   
void draw_circle(int x0, int y0, int r, unsigned int col)   
{
    for (double si = 0; si <= 360; si+=0.01) // 0-360度循环
    {
        // 计算圆周上的点坐标
        int x = r * cos(2 * 3.14159/360 *si) + x0;
        int y = r * sin(2 * 3.14159/360 *si) + y0;
        // 绘制点及其相邻点使线条更粗
        draw_point(x, y, col);
        draw_point(x-1, y, col);
        draw_point(x+1, y, col);
        draw_point(x, y-1, col);
        draw_point(x, y+1, col);
    }   
}
   
// 绘制BMP图片   
void draw_bmp(int x, int y, char *picname, int w, int h)   
{
    int fd = open(picname, O_RDONLY);
    lseek(fd, 54, SEEK_SET); // 跳过BMP文件头
    
    unsigned char *buff = malloc(w*h*3); // 分配缓冲区
    read(fd, buff, w*h*3); // 读取像素数据
    
    // BMP是倒序存储的,所以从下往上绘制
    for (int j = h-1; j >= 0; j--)
    {
        for (int i = 0; i < w; i++)
        {
            // 读取BGR分量(注意BMP存储顺序是BGR)
            unsigned char b = *buff++; 
            unsigned char g = *buff++;
            unsigned char r = *buff++;
            
            // 根据显示设备位深处理颜色
            if (vinf.bits_per_pixel == RGB888_FMT)
            {
                unsigned int col = (r << 16) | (g << 8) | b;
                draw_point(i+x, j+y, col);
            }
            else if (vinf.bits_per_pixel == RGB565_FMT)
            {
                unsigned short col = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
                draw_point(i+x, j+y, col);
            }
        }
    }
    free(buff);
    close(fd);   
}
   
// 汉字点阵数据结构   
typedef struct {
    unsigned char word[32]; // 16x16点阵,每个汉字32字节   
} HZ_DOT;
   
// 绘制单个汉字(使用点阵数据)   
void draw_word(int x, int y, unsigned char *word, int w, int h, unsigned int col)   
{
    for (int j = 0; j < h; j++) // 行循环
    {
        for (int i = 0; i < w; i++) // 列循环
        {
            unsigned char tmp = word[i+j*w]; // 获取点阵数据的一个字节
            for (int k = 0; k < 8; k++) // 每个字节8位
            {
                if (tmp & 0x80) // 最高位为1表示需要绘制
                {
                    draw_point(i*8+k+x, j+y, col);
                }
                tmp = tmp << 1; // 检查下一位
            }
        }
    }   
}
   
// UTF-8字符信息结构体   
typedef struct {
    int width;
    int height;
    unsigned char *dot;   
} UTF8_INFO;
   
// 绘制UTF-8字符串   
int draw_utf8_str(UTF8_INFO *info, int arg_x, int arg_y, char* zi, unsigned int col, unsigned int col1)   
{
    char* temp = zi;
    unsigned int x = arg_x;
    unsigned int y = arg_y;

    while(*temp != '\0') // 遍历字符串直到结束
    {
        // 绘制单个UTF-8字符
        int ret = draw_utf8(info, x, y, temp, col, col1);
        x += info->width; // 移动到下一个字符位置
        
        // 处理换行
        if(x > vinf.xres)
        {
            x = 0;
            y += info->height;
            if(y > vinf.yres)
            {
                y = 0; // 超出屏幕底部则回到顶部
            }
        }
        temp += ret; // 移动到下一个UTF-8字符
    }
    return 0;   
}
   
int main(int argc, char *argv[])   
{
    // 初始化帧缓冲
    int fd = init_fb("/dev/fb0");
    if(fd < 0)
    {
        printf("Frame buffer initialization failed!\n");
        return -1;
    }
    
    // 清屏为黑色
    memset(pmem, 0, vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8);
    
    // 绘制测试图形
    draw_rect(100, 100, 200, 150, RED);
    draw_circle(300, 200, 50, BLUE);
    draw_x_line(50, 50, 400, 300, GREEN);
    
    // 关闭设备
    munmap(pmem, vinf.xres_virtual * vinf.yres_virtual * vinf.bits_per_pixel/8);
    close(fd);
    
    return 0;   
}
 

http://www.xdnf.cn/news/9899.html

相关文章:

  • 反范式设计应用场景解析
  • 【飞控】ChibiOS与NuttX
  • 【C++】ldd常见命令
  • st倍增(st表)
  • 运行apt install为何卡顿 (by quqi99)
  • Nginx版本平滑迁移方案
  • @ModelAttribute、@RequestBody、@RequestParam、@PathVariable 注解对比
  • 农村土地承包经营权二轮延包—归户表
  • day13 leetcode-hot100-22(链表1)
  • cf2059B
  • 【模板-指南】
  • 12:遨博机器人开发
  • 软考-系统架构设计师-第七章 软件工程基础知识
  • 学生管理系统V2.0
  • PCA主成分分析与Python应用
  • View的工作流程——measure
  • Linux实操篇-进程管理
  • 防火墙ASPF(针对应用层包过滤技术) FTP(主动模式)
  • 为什么我开始用 Data.olllo 做数据处理了?
  • langchain框架-对比分析chain的三种实现方式
  • 【二】10.L并发与竞争机制
  • HOW - 简历和求职面试宝典(三)
  • Python多版本共存指南:使用虚拟环境实现不同Python版本的灵活切换
  • 【CBAP50技术手册】#29 Mind Mapping(思维导图):BA(业务分析师)的“思维引擎”
  • Debian:自由操作系统的精神图腾与技术基石
  • Python 基于卷积神经网络手写数字识别
  • (二)视觉——工业镜头(以海康威视为例)
  • 罗马-华为
  • CC攻击的种类与特点解析
  • ElementUI表单验证指南