#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);
}
}
触摸屏界面设计
最新发布