4. 绘制像素点
任务目标
在LCD屏幕上指定坐标(x, y)绘制一个像素点,并验证写入的颜色值正确。本案例基于Linux Framebuffer驱动接口,通过mmap映射显存后直接操作像素地址,实现单点绘制。
环境与依赖
- Linux系统(含
/dev/fb0设备节点) - LCD驱动已启用Framebuffer(分辨率如800×480,32位色)
- 编译依赖:
linux/fb.h(内核头文件)、libc
核心实现
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#define FB_DEV "/dev/fb0"
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "用法: %s <x> <y> <颜色值(0xRRGGBB)>\n", argv[0]);
return 1;
}
int x = atoi(argv[1]);
int y = atoi(argv[2]);
unsigned int color = (unsigned int)strtoul(argv[3], NULL, 0);
int fb_fd = open(FB_DEV, O_RDWR);
if (fb_fd < 0) { perror("open"); return 1; }
struct fb_var_screeninfo vinfo;
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
perror("ioctl"); close(fb_fd); return 1;
}
// 计算显存大小并映射
size_t screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
unsigned char *fbp = mmap(NULL, screensize, PROT_READ | PROT_WRITE,
MAP_SHARED, fb_fd, 0);
if (fbp == MAP_FAILED) { perror("mmap"); close(fb_fd); return 1; }
// 坐标边界检查
if (x < 0 || x >= (int)vinfo.xres || y < 0 || y >= (int)vinfo.yres) {
fprintf(stderr, "坐标超出范围 (0~%u, 0~%u)\n", vinfo.xres-1, vinfo.yres-1);
munmap(fbp, screensize); close(fb_fd); return 1;
}
// 计算像素偏移(32位色:每像素4字节)
long offset = (x + y * vinfo.xres) * (vinfo.bits_per_pixel / 8);
unsigned int *pixel = (unsigned int *)(fbp + offset);
// 写入颜色(RGB888 → 内存布局需匹配驱动格式)
*pixel = color;
// 验证:读回并比较
unsigned int readback = *pixel;
munmap(fbp, screensize);
close(fb_fd);
if (readback == color) {
printf("像素点(%d,%d)写入成功,颜色值 0x%06X 验证通过\n", x, y, color);
return 0;
} else {
printf("验证失败:写入 0x%06X,读回 0x%06X\n", color, readback);
return 1;
}
}
编译与运行
# 编译
gcc -o draw_pixel draw_pixel.c
# 在(100, 200)处绘制红色像素
./draw_pixel 100 200 0xFF0000
# 在(400, 300)处绘制绿色像素
./draw_pixel 400 300 0x00FF00
验证方法
- 程序输出:若显示“写入成功,颜色值验证通过”,说明像素写入与读回一致。
- 视觉确认:在LCD屏幕上对应坐标应出现一个单色亮点(若背景为黑色则更明显)。
- 边界测试:尝试
./draw_pixel 0 0 0xFFFFFF(左上角白点)和超出分辨率的值,程序应正确报错。
注意事项
- 若LCD驱动使用16位色(RGB565),需将
color转换为对应格式,且每像素字节数为2。 - 部分驱动要求先设置
FBIOGET_FSCREENINFO获取固定信息,但本案例仅需可变信息即可完成单点绘制。 - 若屏幕内容被其他进程刷新覆盖,视觉验证可能不明显,以程序读回验证为准。