序
由于电赛的任务调度需求,我写了这个模式选择菜单,测试基于正点原子的战舰V3开发板,3.5寸电阻屏,对正点原子LCD封装库进行扩展,可自选1到12模式数量,自排版并在触屏时输出模式序号。
LCD_Menu.c
#include "LCD_Menu.h"
#include "key.h"
#include "led.h"
//给模式选项画一个框
//width,height 框左上角起始位置
//H,L 设置框的高,宽
void MODE_Draw_Frame(unsigned int width,unsigned int height,unsigned int H,unsigned int L,unsigned int color)
{
POINT_COLOR=color;
LCD_DrawLine(width, height, width + L, height);
LCD_DrawLine(width, height, width , height + H);
LCD_DrawLine(width, height + H, width + L, height + H);
LCD_DrawLine(width + L, height + H, width + L, height);
}
void MODE_Draw_Name(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p,u8 num)
{
u8 x0=x;
width+=x;
height+=y;
while((*p<='~')&&(*p>=' '))//判断是不是非法字符
{
if(x>=width){x=x0;y+=size;}
if(y>=height)break;//退出
LCD_ShowChar(x,y,*p,size,0);
x+=size/2;
p++;
}
if(num<10)//用于显示模式序号
{
LCD_ShowChar(x,y,num+0x30,size,0);
x+=size/2;
}
else if(num<100)
{
LCD_ShowChar(x,y,num/10+0x30,size,0);
x+=size/2;
LCD_ShowChar(x,y,num%10+0x30,size,0);
x+=size/2;
}
}
//显示模式选择界面
//num:模式数量选择
//colorr:方框颜色选择
//color:字体颜色选择
//name:模式名称 最好为四个字符
void MODE_Draw_ChousePage(unsigned char num,unsigned int colorr,unsigned int color,unsigned char* name)
{
unsigned char i;
if(num<=2)
{
for(i=0;i<num;i++)
{
MODE_Draw_Frame(lcddev.width/2-50,(i+1)*lcddev.height/(num+1+num/3),40,100,colorr);
POINT_COLOR=color;
MODE_Draw_Name(lcddev.width/2-27,(i+1)*lcddev.height/(num+1+num/3)+8,80,24,24,name,i+1);
}
}
else if(num<=6)
{
for(i=0;i<num;i++)
{
MODE_Draw_Frame(lcddev.width/2-50,(i+1)*lcddev.height/(num+num/3),40,100,colorr);
POINT_COLOR=color;
MODE_Draw_Name(lcddev.width/2-27,(i+1)*lcddev.height/(num+num/3)+8,80,24,24,name,i+1);
}
}
else if(num<=12)
{
for(i=0;i<num;i++)
{
if(i%2==0)
{
MODE_Draw_Frame(lcddev.width/4-50,(i/2+1)*lcddev.height/(num/2+num%2+num/6),40,100,colorr);
POINT_COLOR=color;
MODE_Draw_Name(lcddev.width/4-27,(i/2+1)*lcddev.height/(num/2+num%2+num/6)+8,80,24,24,name,i+1);
}
if(i%2==1)
{
MODE_Draw_Frame(3*lcddev.width/4-50,(i/2+1)*lcddev.height/(num/2+num%2+num/6),40,100,colorr);
POINT_COLOR=color;
MODE_Draw_Name(3*lcddev.width/4-27,(i/2+1)*lcddev.height/(num/2+num%2+num/6)+8,80,24,24,name,i+1);
}
}
}
}
//触摸模式选择函数
//num 模式数量
//num 最大数量为12
char MODE_Chouse(unsigned char num)
{
u8 key;
u8 a=0,i=0;
while(1)
{
key=KEY_Scan(0);
tp_dev.scan(0);
if(tp_dev.sta&TP_PRES_DOWN) //´触摸屏被按下
{
if(num<=2)
{
for(i=0;i<num;i++)
if((lcddev.width/2-50)<tp_dev.x[0]
&&tp_dev.x[0]<(lcddev.width/2+50)
&&(i+1)*lcddev.height/(num+1+num/3)<tp_dev.y[0]
&&tp_dev.y[0]<((i+1)*lcddev.height/(num+1+num/3)+40))
return i+1;
}else
if(num<=6)
{
for(i=0;i<num;i++)
if((lcddev.width/2-50)<tp_dev.x[0]
&&tp_dev.x[0]<(lcddev.width/2+50)
&&(i+1)*lcddev.height/(num+num/3)<tp_dev.y[0]
&&tp_dev.y[0]<((i+1)*lcddev.height/(num+num/3)+40))
return i+1;
}else
if(num<=12)
{
for(i=0;i<num;i++)
{
if(i%2==0)
{
if((lcddev.width/4-50)<tp_dev.x[0]
&&tp_dev.x[0]<(lcddev.width/4+50)
&&(i/2+1)*lcddev.height/(num/2+num%2+num/6)<tp_dev.y[0]
&&tp_dev.y[0]<((i/2+1)*lcddev.height/(num/2+num%2+num/6)+40))
return i+1;
}
else if(i%2==1)
{
if((3*lcddev.width/4-50)<tp_dev.x[0]
&&tp_dev.x[0]<(3*lcddev.width/4+50)
&&(i/2+1)*lcddev.height/(num/2+num%2+num/6)<tp_dev.y[0]
&&tp_dev.y[0]<((i/2+1)*lcddev.height/(num/2+num%2+num/6)+40))
return i+1;
}
}
}
else delay_ms(10); //没有按键按下的时候
if(key==KEY0_PRES) //KEY0按下 ,则执行校准程序
{
LCD_Clear(WHITE);//清屏
TP_Adjust(); //屏幕校准
MODE_Draw_ChousePage(num,RED,BLUE,"mode");
}
a++;
if(a%20==0)LED0=!LED0;
}
}
}
//集成执行函数
void MODE_IN(unsigned char num)
{
unsigned char MODE=0;
while(1)
{
MODE_Draw_ChousePage(num,RED,BLUE,"mode");
MODE = MODE_Chouse(num);
LCD_Clear(WHITE);
MODE_Draw_Name(lcddev.width/2,lcddev.height/2,210,24,24," ",MODE);
LCD_ShowString(0,lcddev.height-25,210,24,24,"back");
while(1)
{
tp_dev.scan(0);
if(tp_dev.sta&TP_PRES_DOWN) //´触摸屏被按下
{
if(tp_dev.x[0]<lcddev.width&&tp_dev.y[0]<lcddev.height)
{
if(tp_dev.x[0]<210&&tp_dev.y[0]>lcddev.height-24)
{
LCD_Clear(WHITE);
break;
}
}
}
}
}
}
main.c
#include "24cxx.h"
#include "w25qxx.h"
#include "touch.h"
#include "LCD_Menu.h"
int main(void)
{
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
LED_Init();
LCD_Init();
KEY_Init();
tp_dev.init();
MODE_IN(4);
}
LCD_Menu.h
#ifndef _LCD_Menu_H_
#define _LCD_Menu_H_
#include "lcd.h"
#include "touch.h"
void MODE_Draw_Frame(unsigned int width,unsigned int height,unsigned int H,unsigned int L,unsigned int color);
void MODE_Draw_Name(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p,u8 num);
void MODE_Draw_ChousePage(unsigned char num,unsigned int colorr,unsigned int color,unsigned char* name);
char MODE_Chouse(unsigned char num);
void MODE_IN(unsigned char num);
#endif
注
暂定为第一版本,较为简陋,后续会添加背景,优化名称、排序、数量显示,题目分类选项等。
经测试,模式开始界面启动速度快,对触屏感应灵敏且准确,返回时切换速度快,在执行任务时不会造成影响。
使用时清更改集成函数,为方便调试,集成函数内为无法跳出的死循环,读出子函数返回值后进行模式选择判断即可。