emwin在SDRAM中绘制图形,直接加载到LCD速度比较块

本文介绍了如何在SDRAM中使用emwin库创建内存设备,通过GUI_MEMDEV_CreateFixed函数分配内存并绘制图形,如GUI_JPEG_Draw加载JPEG图片。然后,通过GUI_MEMDEV_Select和GUI_MEMDEV_WriteAt将内容快速显示到LCD上,实现快速图形绘制和更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GUI_MEMDEV_HandlehMempic ;

hMempic = GUI_MEMDEV_CreateFixed(0, 
                                    0, 

                                    LCD_GetXSize(), 
                                    LCD_GetYSize(), 
                                    GUI_MEMDEV_HASTRANS, 
                                    GUI_MEMDEV_APILIST_16, 
                                    GUICC_M565);
    GUI_MEMDEV_Select(hMempic);
    GUI_JPEG_Draw(_acbkpic,sizeof(_acbkpic), 0, 0);

//再次绘制旋钮一直把剩下得旋钮都绘制完
    GUI_MEMDEV_Select(0);

//使用的时候调用
GUI_MEMDEV_WriteAt(hMempic,0,0);
即可

#include "./SYSTEM/sys/sys.h" #include "./SYSTEM/delay/delay.h" #include "./SYSTEM/usart/usart.h" #include "./BSP/LED/led.h" #include "./BSP/KEY/key.h" #include "./BSP/LCD/lcd.h" #include "./BSP/TOUCH/touch.h" #include "stm32f4xx.h" #include "./BSP/pwm/pwm.h" #include "./BSP/flash/flash.h" #include <string.h> #include "stm32f4xx_hal_flash.h" #include "stm32f4xx_hal_flash_ex.h" #include "system_state.h" // 颜色定义 #define FEEDBACK_COLOR GRAY // 触摸反馈颜色 #define LED_ACTIVE_COLOR BRRED // 光源激活颜色 #define LED_INACTIVE_COLOR RED // 光源未激活颜色 // 定义区域结构体 typedef struct { uint16_t x1, y1, x2, y2; // 区域坐标 const char* label; // 标签 uint16_t default_color; // 初始颜色 uint16_t active_color; // 激活颜色 } TouchArea; // 全局变量 SystemState sys_state = {0, 50, 50, 80, 0}; // 默认状态 TouchArea areas[8]; // 八个区域 int8_t pressed_area_index = -1; // 当前按下的区域的索引 // PWM通道定义 #define LED1_PWM_CHANNEL TIM_CHANNEL_1 #define LED2_PWM_CHANNEL TIM_CHANNEL_2 #define MOTOR_PWM_TIMER htim4 #define MOTOR_FORWARD_CHANNEL TIM_CHANNEL_3 #define MOTOR_REVERSE_CHANNEL TIM_CHANNEL_4 // 初始化触摸区域 void init_touch_areas(void) { uint16_t w = lcddev.width; uint16_t h = lcddev.height; uint16_t margin = 10; uint16_t btn_w = (w - 3 * margin) / 2; uint16_t btn_h = (h - 5 * margin) / 4; // 屏幕亮度控制 areas[0] = (TouchArea){margin, margin, margin + btn_w, margin + btn_h, "亮度+", BLUE, BLUE}; areas[1] = (TouchArea){2*margin + btn_w, margin, w - margin, margin + btn_h, "亮度-", BLUE, BLUE}; // 光源选择 areas[2] = (TouchArea){margin, margin*2 + btn_h, margin + btn_w, margin*2 + 2*btn_h, "上光源", LED_INACTIVE_COLOR, LED_ACTIVE_COLOR}; areas[3] = (TouchArea){2*margin + btn_w, margin*2 + btn_h, w - margin, margin*2 + 2*btn_h, "下光源", LED_INACTIVE_COLOR, LED_ACTIVE_COLOR}; // 光源亮度控制 areas[4] = (TouchArea){margin, margin*3 + 2*btn_h, margin + btn_w, margin*3 + 3*btn_h, "亮度+", GREEN, GREEN}; areas[5] = (TouchArea){2*margin + btn_w, margin*3 + 2*btn_h, w - margin, margin*3 + 3*btn_h, "亮度-", GREEN, GREEN}; // 电机控制(点动) areas[6] = (TouchArea){margin, margin*4 + 3*btn_h, margin + btn_w, margin*4 + 4*btn_h, "开启", YELLOW, YELLOW}; areas[7] = (TouchArea){2*margin + btn_w, margin*4 + 3*btn_h, w - margin, margin*4 + 4*btn_h, "闭合", YELLOW, YELLOW}; } // 检测触摸是否在区域内 uint8_t is_touch_in_area(uint16_t x, uint16_t y, TouchArea area) { return (x >= area.x1 && x <= area.x2 && y >= area.y1 && y <= area.y2); } // 绘制所有区域 void draw_all_areas(void) { // 清屏 lcd_clear(WHITE); // 标题 lcd_show_string(10, 10, 200, 24, 24, "控制系统", BLUE); // 循环绘制所有区域 for(int i = 0; i < 8; i++) { uint16_t color; // 根据光源选择状态确定颜色 if(i == 2 || i == 3) { color = (i == 2 && sys_state.led_selected == 0) || (i == 3 && sys_state.led_selected == 1) ? areas[i].active_color : areas[i].default_color; } else { color = areas[i].default_color; } // 如果区域被按下,使用反馈色 if(i == pressed_area_index) { color = FEEDBACK_COLOR; } // 绘制区域背景 lcd_fill(areas[i].x1, areas[i].y1, areas[i].x2, areas[i].y2, color); // 绘制边框 lcd_draw_rectangle(areas[i].x1, areas[i].y1, areas[i].x2, areas[i].y2, BLACK); // 绘制标签(居中) uint16_t text_x = areas[i].x1 + (areas[i].x2 - areas[i].x1 - 8*strlen(areas[i].label)) / 2; uint16_t text_y = areas[i].y1 + (areas[i].y2 - areas[i].y1 - 16) / 2; lcd_show_string(text_x, text_y, 200, 16, 16, (char*)areas[i].label, BLACK); } // 显示状态信息 char status_buf[100]; sprintf(status_buf, "光源:%d 亮度:%d%% 屏幕:%d%%", sys_state.led_selected + 1, sys_state.led_selected ? sys_state.led2_brightness : sys_state.led1_brightness, sys_state.screen_brightness); lcd_show_string(10, lcddev.height - 30, 300, 16, 16, status_buf, BLACK); } // 应用屏幕亮度设置 void apply_screen_brightness(void) { // 使用TIM2 PWM控制背光LED uint16_t pwm_value = (sys_state.screen_brightness * 1000) / 100; __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pwm_value); } // 应用光源设置 void apply_led_settings(void) { // 设置上光源PWM uint16_t pwm1_value = (sys_state.led1_brightness * 1000) / 100; __HAL_TIM_SET_COMPARE(&htim3, LED1_PWM_CHANNEL, pwm1_value); // 设置下光源PWM uint16_t pwm2_value = (sys_state.led2_brightness * 1000) / 100; __HAL_TIM_SET_COMPARE(&htim3, LED2_PWM_CHANNEL, pwm2_value); // 根据选择点亮/熄灭指示灯 if(sys_state.led_selected == 0) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // 上光源指示亮 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET); // 下光源指示灭 } else { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // 上光源指示灭 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET); // 下光源指示亮 } } // 控制电机(点动模式) void control_motor(uint8_t direction) { // 停止所有电机输出 __HAL_TIM_SET_COMPARE(&MOTOR_PWM_TIMER, MOTOR_FORWARD_CHANNEL, 0); __HAL_TIM_SET_COMPARE(&MOTOR_PWM_TIMER, MOTOR_REVERSE_CHANNEL, 0); // 根据方向控制 if(direction == 1) { // 开启(正转) __HAL_TIM_SET_COMPARE(&MOTOR_PWM_TIMER, MOTOR_FORWARD_CHANNEL, 1000); } else if(direction == 2) { // 闭合(反转) __HAL_TIM_SET_COMPARE(&MOTOR_PWM_TIMER, MOTOR_REVERSE_CHANNEL, 1000); } } // 计算校验和 static uint32_t calculate_checksum(SystemState *state) { return state->led_selected + state->led1_brightness + state->led2_brightness + state->screen_brightness; } // 保存系统状态到Flash void save_system_state(void) { // 计算校验和 sys_state.checksum = calculate_checksum(&sys_state); // 解锁Flash HAL_FLASH_Unlock(); // 擦除扇区 FLASH_EraseInitTypeDef EraseInitStruct; uint32_t SectorError = 0; EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; EraseInitStruct.Sector = FLASH_SECTOR_11; EraseInitStruct.NbSectors = 1; if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { // 错误处理 HAL_FLASH_Lock(); return; } // 写入数据 uint32_t *src = (uint32_t*)&sys_state; uint32_t address = 0x080E0000; uint32_t size = sizeof(SystemState); for (uint32_t i = 0; i < (size + 3) / 4; i++) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *src) != HAL_OK) { // 写入错误 break; } address += 4; src++; } // 锁定Flash HAL_FLASH_Lock(); } // 从Flash加载系统状态 void load_system_state(void) { // 从Flash复制数据 memcpy(&sys_state, (void*)0x080E0000, sizeof(SystemState)); // 验证校验和 uint32_t saved_checksum = sys_state.checksum; sys_state.checksum = 0; // 清零用于计算 if (calculate_checksum(&sys_state) != saved_checksum) { // 校验失败,使用默认值 sys_state.led_selected = 0; sys_state.led1_brightness = 50; sys_state.led2_brightness = 50; sys_state.screen_brightness = 80; } // 恢复校验和 sys_state.checksum = saved_checksum; } int main(void) { // 初始化硬件 HAL_Init(); sys_stm32_clock_init(336, 8, 2, 7); delay_init(168); usart_init(115200); led_init(); key_init(); lcd_init(); tp_dev.init(); PWM_Init(); // 初始化PWM // 加载保存的状态 lcd_show_string(30,50,200,16,16,"Explorer STM32F4",0x8430); lcd_show_string(30,70,200,16,16,"TOUCH TEST",0x8430); lcd_show_string(30,90,200,16,16,"ATOM@ALIENTEK",0x8430); lcd_show_string(30,110,200,16,16,"2017/4/14",0x8430); load_system_state(); // 初始化触摸区域 init_touch_areas(); // 应用初始设置 apply_screen_brightness(); apply_led_settings(); // 绘制界面 draw_all_areas(); // 电机控制状态 uint8_t motor_active = 0; // 0:停止, 1:开启, 2:闭合 uint32_t last_save_time = 0; uint8_t last_touch_state = 0; while(1) { // 扫描触摸屏 tp_dev.scan(0); uint8_t current_touch_state = (tp_dev.sta & TP_PRES_DOWN) ? 1 : 0; // 触摸按下检测 if(current_touch_state && !last_touch_state) { // 新的触摸开始 pressed_area_index = -1; // 查找触摸点所在的第一个区域 for(uint8_t t = 0; t < 10; t++) { if(tp_dev.sta & (1 << t)) { for(int i = 0; i < 8; i++) { if(is_touch_in_area(tp_dev.x[t], tp_dev.y[t], areas[i])) { pressed_area_index = i; draw_all_areas(); // 更新界面显示反馈 break; } } break; // 只处理第一个触摸点 } } } // 触摸释放检测 else if(!current_touch_state && last_touch_state) { // 触摸结束 if(pressed_area_index != -1) { // 执行功能(仅在释放时执行) switch(pressed_area_index) { case 0: // 屏幕亮度+ if(sys_state.screen_brightness < 100) { sys_state.screen_brightness += 5; if(sys_state.screen_brightness > 100) sys_state.screen_brightness = 100; apply_screen_brightness(); } break; case 1: // 屏幕亮度- if(sys_state.screen_brightness > 5) { sys_state.screen_brightness -= 5; apply_screen_brightness(); } break; case 2: // 选择上光源 sys_state.led_selected = 0; apply_led_settings(); break; case 3: // 选择下光源 sys_state.led_selected = 1; apply_led_settings(); break; case 4: // 光源亮度+ if(sys_state.led_selected == 0) { if(sys_state.led1_brightness < 100) { sys_state.led1_brightness += 5; if(sys_state.led1_brightness > 100) sys_state.led1_brightness = 100; } } else { if(sys_state.led2_brightness < 100) { sys_state.led2_brightness += 5; if(sys_state.led2_brightness > 100) sys_state.led2_brightness = 100; } } apply_led_settings(); break; case 5: // 光源亮度- if(sys_state.led_selected == 0) { if(sys_state.led1_brightness > 0) { sys_state.led1_brightness -= 5; // 删除与0的比较(无符号数不会小于0) } } else { if(sys_state.led2_brightness > 0) { sys_state.led2_brightness -= 5; // 删除与0的比较(无符号数不会小于0) } } apply_led_settings(); break; } // 重置按下区域 pressed_area_index = -1; draw_all_areas(); // 更新界面 } } // 更新触摸状态 last_touch_state = current_touch_state; // 电机控制(点动模式,按下时持续控制) uint8_t new_motor_active = 0; if(pressed_area_index == 6) { new_motor_active = 1; // 开启 } else if(pressed_area_index == 7) { new_motor_active = 2; // 闭合 } if(new_motor_active != motor_active) { motor_active = new_motor_active; control_motor(motor_active); } // 每5秒自动保存状态 if(HAL_GetTick() - last_save_time > 5000) { save_system_state(); last_save_time = HAL_GetTick(); } // 按键检测(停止电机) if(key_scan(0) == KEY0_PRES) { motor_active = 0; control_motor(0); if(pressed_area_index == 6 || pressed_area_index == 7) { pressed_area_index = -1; draw_all_areas(); } } delay_ms(10); } } 触摸屏界面设计
最新发布
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值