writeScreen.vs

本文深入探讨了OpenGL ES在图像处理领域的应用,结合OpenCV库实现AR特效与音视频编解码算法,同时介绍了图像色彩空间、视频编解码算法等关键概念。
#version 150 

uniform mat4 mvpMatrix;
in vec4 vVertex;
in vec2 texCoord0;
out vec2 vTexCoord;

void main(void)
{ 
	vTexCoord = texCoord0;
	gl_Position = mvpMatrix * vVertex;
}
首页/嵌入式 如何任意调节屏幕像素尺寸的同时,还能使汉字点阵正确映射到LED屏幕上? stm32 嵌入式硬件 c语言 当前主要问题就是:如何任意调节屏幕像素尺寸的同时,还能使汉字点阵正确映射到LED屏幕上 目前的情况是 在原有的可正确显示汉字的程序上,实现调节屏幕像素的功能,但是发现原有的程序,只能适用于16*64大小的屏幕,我试图找到LED屏幕中关于汉字点阵的的映射逻辑,但是发现输出的日志,有点混乱,找不到对应的逻辑,这一点需要协助解决一下 源代码如下: /* 显示汉字总数 */ #define WORD_NUM 4 /* 每行显示的字节数 */ #define SCAN_NUM (8 * WORD_NUM) u8 Chinese[4][32] = { { 0x00,0x01,0x00,0x01,0x3F,0x01,0x20,0x3F,0xA0,0x20,0x92,0x10,0x54,0x02,0x28,0x02, 0x08,0x02,0x14,0x05,0x24,0x05,0xA2,0x08,0x81,0x08,0x40,0x10,0x20,0x20,0x10,0x40, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, }; uint8_t dispram[128] = {0}; void hub12DataSerialInput(uint8_t data){ uint16_t i; for( i = 0; i < 8; i++){ if(data & 0x80){ HIGH_HUB12_DR; }else{ LOW_HUB12_DR; } LOW_HUB12_CLK; Delay_us(2); HIGH_HUB12_CLK; data = data << 1; } } // 行选择 (1/4扫描) void hub12SelectRows(uint8_t rows){ LOW_HUB12_C; LOW_HUB12_D; switch(rows){ case 0: LOW_HUB12_A; LOW_HUB12_B; break; case 1: HIGH_HUB12_A; LOW_HUB12_B; break; case 2: LOW_HUB12_A; HIGH_HUB12_B; break; case 3: HIGH_HUB12_A; HIGH_HUB12_B; break; default: break; } } // 行选择 (1/4扫描) void hub12Display(uint16_t bright,uint8_t *buffer) { for(u8 s=0; s<4; s++){ // 4个行组(1/4扫描) HIGH_HUB12_OE; hub12SelectRows(s); // Delay_us(20); LOW_HUB12_LAT; for(int i=0; i<SCAN_NUM; i++) { hub12DataSerialInput(buffer[s*SCAN_NUM + i]); //128字节 } HIGH_HUB12_LAT; LOW_HUB12_OE; Delay_us(bright); HIGH_HUB12_OE; } } //高低字节交换,0b10110000 → 0b00001101 u8 SwapByte(u8 data) { data=(data<<4)|(data>>4); data=((data<<2)&0xcc)|((data>>2)&0x33); data=((data<<1)&0xaa)|((data>>1)&0x55); return data; } // 打印buffer内容 void PrintBuffer(const char* name, uint8_t* buffer, uint32_t size) { for(uint32_t i = 0; i < size; i++) { printf("0x%02X ", buffer[i]); if((i + 1) % 16 == 0) { printf("\n"); } } printf("\n"); } // 打印dispram的数据结构 void PrintDispramStructure(void) { printf("\n Dispram 数据结构 \n"); for(uint8_t group = 0; group < 4; group++) { printf("Group %d:\n", group); for(uint8_t scan_line = 0; scan_line < 4; scan_line++) { printf(" Scan Line %d: ", scan_line); uint16_t start_idx = group * SCAN_NUM + scan_line * 8; for(uint8_t i = 0; i < 8; i++) { printf("0x%02X ", dispram[start_idx + i]); } printf("\n"); } } } void WriteScreen(u8 location, u8 *text) { u8 i; // 原始的扫描行组 u8 j; // 显示缓冲区的标号 u8 k; u8 buffer[32]; const u8 row_map[4] = {1,2,3, 0}; //行扫描修正 printf("\n\n=== Writing Hanzi at Location %d ===\n", location); /* 字模处理 */ for(k = 0; k < 32; k++) { buffer[k] = text[31 - k]; //上下左右交换、高低字节交换 buffer[k] = SwapByte(buffer[k]); } /* 写缓冲区 */ for(i = 0; i < 4; i++) // 4组扫描行 (i=0,1,2,3 对应 4/1,4/2,4/3,4/4) { // 通过查找表,获取用于行修正计算的 "new_i" u8 new_i = row_map[i]; for(j = (SCAN_NUM * i); j < SCAN_NUM * (i + 1); j++) { if((j >= ((SCAN_NUM * i) + 8 * location)) && (j <= ((SCAN_NUM * i + 3) + 8 * location)))//0-3列 { // 使用 new_i 来计算行修正项,但 j 的范围仍基于原始的 i dispram[j] = buffer[(7 - 2 * new_i) + 8 * (j - 8 * location - SCAN_NUM * i)]; //右边字节 //printf("Write: dispram[%d] = buffer[%d] = 0x%02X\n", j, (7 - 2 * new_i) + 8 * (j - 8 * location - SCAN_NUM * i), dispram[j]); } if((j >= ((SCAN_NUM * i + 4) + 8 * location)) && (j <= ((SCAN_NUM * i + 7) + 8 * location)))//4-7列 { dispram[j] = buffer[(6 - 2 * new_i) + 8 * (j - 8 * location - SCAN_NUM * i - 4)]; //左边字节 // printf("Write: dispram[%d] = buffer[%d] = 0x%02X\n", j, (6 - 2 * new_i) + 8 * (j - 8 * location - SCAN_NUM * i - 4), dispram[j]); } } } PrintDispramStructure(); } //静态显示汉字 void StaticDisplay(uint8_t font[4][32]) { memset(dispram, 0, sizeof(dispram)); // 清空显存 //locatin,0-3,表示第几个汉字的位置 for(u8 location=0; location<4; location++) { WriteScreen(location, font[location]); } } 程序逻辑为: 给void StaticDisplay(uint8_t font[4][32])传入Chinese汉字点阵数组, 然后调用WriteScreen(location, font[location]);,先将Chinese汉字点阵数组中的字节进行上下左右交换、高低字节交换,映射顺序调整后,存入buffer数组,然后将数组通过,写缓存的映射逻辑,将数据存入dispram。 在main中循序调用hub12Display(200,dispram);将dispram。中的数据写映射到屏幕上 函数PrintDispramStructure();输出的日志如下: ```c UARTinit init Dispram 数据结构 Group 0: Scan Line 0: 0x02 0x28 0x49 0x00 0x08 0xA0 0x08 0x80 Scan Line 1: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Scan Line 2: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Scan Line 3: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Group 1: Scan Line 0: 0x04 0x24 0x2A 0xFC 0x04 0xA0 0x40 0x80 Scan Line 1: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Scan Line 2: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Scan Line 3: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Group 2: Scan Line 0: 0x08 0x45 0x14 0x04 0x02 0x10 0x40 0xFC Scan Line 1: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Scan Line 2: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Scan Line 3: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Group 3: Scan Line 0: 0x81 0x10 0x05 0x00 0x10 0x40 0x04 0x80 Scan Line 1: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Scan Line 2: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Scan Line 3: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Dispram 为屏幕的映射逻辑,应该是一一对应16*64大小的屏幕中的每个像素 从日志中,看不出Chinese数组中的汉字点阵,调整到Dispram 后,有什么规律 我自己写了一个映射逻辑 ```c // 屏幕尺寸配置 #define SCREEN_WIDTH 64 // 屏幕宽度(列数) #define SCREEN_HEIGHT 16 // 屏幕高度(行数) // 扫描方式配置 #define SCAN_MODE 4 // 扫描方式:4=1/4扫描,8=1/8扫描,16=1/16扫描 //一组多少行 #define ROW_NUM_GROUP SCREEN_HEIGHT/SCAN_MODE #define HANZI_WIDTH 16 // 单个汉字宽度 #define HANZI_HEIGHT 16 // 单个汉字高度 //汉字一行的字节量 #define HANZI_SIZE HANZI_WIDTH/8 #define MAX_HANZI_NUM (SCREEN_WIDTH / HANZI_WIDTH) // 最大显示汉字数 #define BYTES_PER_ROW (SCREEN_WIDTH / 8) // 每行字节数 #define BUFFER_SIZE (ROW_NUM_GROUP * BYTES_PER_ROW * SCAN_MODE) // 显存大小 u8 Chinese[4][32] = { { 0x00,0x01,0x00,0x01,0x3F,0x01,0x20,0x3F,0xA0,0x20,0x92,0x10,0x54,0x02,0x28,0x02, 0x08,0x02,0x14,0x05,0x24,0x05,0xA2,0x08,0x81,0x08,0x40,0x10,0x20,0x20,0x10,0x40, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, }; // 动态显存 uint8_t dispram[BUFFER_SIZE] = {0}; void hub12DataSerialInput(uint8_t data){ uint16_t i; for( i = 0; i < 8; i++){ if(data & 0x80){ HIGH_HUB12_DR; }else{ LOW_HUB12_DR; } LOW_HUB12_CLK; Delay_us(2); HIGH_HUB12_CLK; data = data << 1; } } void hub12SelectRows(uint8_t row_address) { switch(SCAN_MODE) { case 4: // 1/4扫描 - 使用A,B两根线 switch(row_address & 0x03) { // 只取低2位 case 0: LOW_HUB12_A; LOW_HUB12_B; break; case 1: HIGH_HUB12_A; LOW_HUB12_B; break; case 2: LOW_HUB12_A; HIGH_HUB12_B; break; case 3: HIGH_HUB12_A; HIGH_HUB12_B; break; } break; case 8: // 1/8扫描 - 使用A,B,C三根线 if (row_address & 0x01) HIGH_HUB12_A; else LOW_HUB12_A; if (row_address & 0x02) HIGH_HUB12_B; else LOW_HUB12_B; if (row_address & 0x04) HIGH_HUB12_C; else LOW_HUB12_C; break; case 16: // 1/16扫描 - 使用A,B,C,D四根线 if (row_address & 0x01) HIGH_HUB12_A; else LOW_HUB12_A; if (row_address & 0x02) HIGH_HUB12_B; else LOW_HUB12_B; if (row_address & 0x04) HIGH_HUB12_C; else LOW_HUB12_C; if (row_address & 0x08) HIGH_HUB12_D; else LOW_HUB12_D; break; } } void hub12Display(uint8_t *buffer) { for(uint8_t group = 0; group < ROW_NUM_GROUP; group++) { HIGH_HUB12_OE; uint8_t row_address = group; hub12SelectRows(row_address); LOW_HUB12_LAT; for(uint16_t i = 0; i < BYTES_PER_ROW * SCAN_MODE; i++) { hub12DataSerialInput(buffer[group * BYTES_PER_ROW * SCAN_MODE + i]); } HIGH_HUB12_LAT; LOW_HUB12_OE; Delay_us(300); } } void PrintDispram(void) { printf("\n=== dispram dump (size=%d) ===\n", BUFFER_SIZE); for (int i = 0; i < BUFFER_SIZE; i++) { if (i % 8 == 0) { printf("\nRow %02d: ", i / 8); } printf("0x%02X ", dispram[i]); } printf("\n==============================\n"); } //高低字节交换,0b10110000 → 0b00001101 u8 SwapByte(u8 data) { data=(data<<4)|(data>>4); data=((data<<2)&0xcc)|((data>>2)&0x33); data=((data<<1)&0xaa)|((data>>1)&0x55); return data; } void WriteHanzi(uint8_t *hanzi_data, uint8_t hanzi_index) { uint8_t buffer[32]; uint16_t dispram_index; //const u8 row_map[4] = {1,2,3, 0}; //行扫描修正 uint8_t start_col_byte = hanzi_index * (HANZI_WIDTH / 8); printf("\n\rstart_col_byte=%d,\n\r",start_col_byte); printf("buffer=\n\r"); for(uint8_t k = 0; k < 32; k++) { buffer[k] = hanzi_data[31 - k]; // 左右反转 buffer[k] = SwapByte(buffer[k]); // 字节反转 printf("0x%2X ",buffer[k]); if(k%8==0) printf("\n\r"); } printf("\n\rdispram=\n\r"); for(uint8_t group = 0; group < ROW_NUM_GROUP; group++) { for(uint8_t scan_line = 0; scan_line < SCAN_MODE; scan_line++) { // 计算当前行在汉字数据中的行号 uint8_t hanzi_row = group * SCAN_MODE + scan_line; // 处理该行的每个字节 for(uint8_t col_byte = 0; col_byte < (HANZI_WIDTH / 8); col_byte++) { // 计算显存中的目标位置 dispram_index = group * BYTES_PER_ROW * SCAN_MODE + scan_line * BYTES_PER_ROW + (start_col_byte + col_byte); //printf("dispram_index=%d,\n\r",dispram_index); // 计算汉字数据中的源位置 uint8_t buf_index = hanzi_row * (HANZI_WIDTH / 8) + col_byte; //printf("buf_index=%d,\n\r",buf_index); if(dispram_index < BUFFER_SIZE && buf_index < 32) { uint8_t hanzi_byte = buffer[buf_index]; dispram[dispram_index] = hanzi_byte; } } } } PrintDispram(); } // 静态显示示例 void StaticDisplayDemo(void) { memset(dispram, 0, BUFFER_SIZE); for(uint8_t i = 0; i < MAX_HANZI_NUM; i++) { WriteHanzi(Chinese[i],i); } } 函数 PrintDispram();输出的日志如下 init start_col_byte=0, buffer= 0x 2 0x 8 0x 4 0x 4 0x 8 0x 2 0x10 0x81 0x10 0x45 0xA0 0x24 0xA0 0x28 0x40 0x10 0x40 0x14 0x40 0x2A 0x 8 0x49 0x 4 0x 5 0xFC 0x 4 0x80 0xFC 0x80 0x 0 0x80 0x 0 dispram= === dispram dump (size=128) === Row 00: 0x02 0x08 0x00 0x00 0x00 0x00 0x00 0x00 Row 01: 0x04 0x04 0x00 0x00 0x00 0x00 0x00 0x00 Row 02: 0x08 0x02 0x00 0x00 0x00 0x00 0x00 0x00 Row 03: 0x10 0x81 0x00 0x00 0x00 0x00 0x00 0x00 Row 04: 0x10 0x45 0x00 0x00 0x00 0x00 0x00 0x00 Row 05: 0xA0 0x24 0x00 0x00 0x00 0x00 0x00 0x00 Row 06: 0xA0 0x28 0x00 0x00 0x00 0x00 0x00 0x00 Row 07: 0x40 0x10 0x00 0x00 0x00 0x00 0x00 0x00 Row 08: 0x40 0x14 0x00 0x00 0x00 0x00 0x00 0x00 Row 09: 0x40 0x2A 0x00 0x00 0x00 0x00 0x00 0x00 Row 10: 0x08 0x49 0x00 0x00 0x00 0x00 0x00 0x00 Row 11: 0x04 0x05 0x00 0x00 0x00 0x00 0x00 0x00 Row 12: 0xFC 0x04 0x00 0x00 0x00 0x00 0x00 0x00 Row 13: 0x80 0xFC 0x00 0x00 0x00 0x00 0x00 0x00 Row 14: 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Row 15: 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ============================== 但是屏幕实际现实的是混乱的,问题点就在于,实际的屏幕映射逻辑是怎样的?如何任意调节屏幕像素尺寸的同时,还能使汉字点阵正确映射到LED屏幕上?
最新发布
10-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值