参考资料:正点原子 EMWIN
学习经历
起因:因为贪便宜买了块STM32F103VE的开发板,到货后发现的问题
1.资料不全;导致学习困难度,“挫败度”大大加深;
2.网上查找的资料与板子不对应,对初学者来说困难度变大;
3.视频教程过于庞大,学习过程中若没有动力支持,放弃的可能性很大
参考意见:如果条件允许;1.尽量买资料全(最好有大量资料的,最好是中文的,否则你需要英文能力的支持),技术成熟的,有完整教材的来开始使用;有技术支持,william hill官网
讨论的;所节省下来的时间,往往比所花费的金钱更值得;最好有文档跟视频的;便于快速学习与查找问题
4.代码混乱,无“模块化”,导致无序与混乱;(模块化是一种必然化的需求)
5.版本的差异(固件库),导致不同的版本会有代码上的差异,从而出现错误
学习步骤(学习动力论):
1.实践大于看书,实践比书要简单;前提是你先粗看一遍;
2.初学者,不要去看平台搭建(延后),平台搭建中的大量错误可能挫败积极性;所以第一步先使用已经搭建好的平台,去建立第一个LED灯实验;
3.初学者需要明确目标:所需要的功能;硬件平台中有大量的硬件知识需要学习,知识的前后也有依赖性;导致你找到你希望学习的内容,也必须将前面的知识先学会;如果你没有合理的安排,或是空闲的时间,将导致挫败感;并且前面的依赖性,关联性,导致无法快速学习一个内容的知识(这是需要解决的,但好像没有相应的教材,故学习很累)
单片机对于计算机底层的知识,有利我们更好的理解计算机;现在的个人计算机底层的操作,都已经封装好了,写程序只需要在软件层操作就行;并不需要涉及硬件层,“寄存器”或是“内存映射”等知识(秉火有详细介绍)
基于成本,项目需求等考虑,单片机的种类很多;有带显示屏,触摸的,到ARDUION;有主频1.2G,内存2G的到只有12M,几百KB的;有容易入门到的,如ARDUION简单开发应用的(现已支持STM32,但还不全);到使用ARM处理的LUNUX系统,需要写底层驱动的;需要根据自己的需求进行选择,总体来说STM32的性价比较高,但依现有的资料与技术(注意:STM32一般内存较小,只有几百KB,而外扩也不大,只有几M);学习比较HAO时;如果你使用ARDUION另当别论
学习单片机或嵌入式,一般都是为了对外进行控制操作,使用STM32或是ARM或树莓派,不单单是点LED灯;更希望使用的是他的液晶显示触摸功能;如果是简单的可以自己写就行,如果是比较复杂的,我们自己写也可以,但有现成的更简单的,就是使用EMWIN来完成,只需要几条指令就可以完成;
EMWIN是UCGUI的升级版,不开放源码;源码可以参考UCGUI
EMWIN主要是通过对原来的驱动的调用,来完成更高级的功能,在液晶屏上显示对话框,图片,可以点击操作;他主要通过调用原驱动中的画点,取点函数来隔离化底层的操作,从而使EMWIN更通用化,可以适合更多的平台,开发板
液晶的使用,为了更简便一般使用FMSC接口功能
1.液晶需要按正确的顺序连接开始板
2.开启FMSC功能
3.驱动的编写(你得查看相应的资料DATASHEET,或是厂家已编好的驱动,移植即可)
STM32的使用的主要步骤:
1.开启时钟:
2.设置功能:
3.控制
开启时钟:(他是为了节能而设置的,如可穿戴调备,使用锂电池,导致多了条语句也导致繁琐度增加;
设置功能:是因为他一个引脚可以有多个功能如PWM,UART,SPI
EMWIN屏幕的移植(参考资料:"正点原子EMWIN移植")
前提:需要已有LCD的液晶和触摸驱动,并能正常画点,画线;触摸
下载stm32cubef1:http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1897/PF260820?s_searchtype=partnumber
需要其中的 stm32cubef1STM32Cube_FW_F1_V1.0.0MiddlewaresSTSTemWin下的
(1.CONFIG
(2.INC
(3.LIB
(4.OS
这向个文件
(SOFTWARE里函有GUIBUILDER软件,可用于创建界面
(SIMULATION里函有WINDOWS中仿真所需的工具
1.画点函数_SETPIXELINDEX()与取点函数_GETPIXELINDEX()的完成:所在文件 GUIDRV_TEMPLATE.C
/*********************************************************************
*
* _SetPixelIndex
*
* Purpose:
* Sets the index of the given pixel. The upper layers
* calling this routine make sure that the coordinates are in range, so
* that no check on the parameters needs to be performed.
*/
static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {
ili9320_SetPoint(x, y,PixelIndex); //其它不改只改此一条
}
/*********************************************************************
*
* _GetPixelIndex
*
* Purpose:
* Returns the index of the given pixel. The upper layers
* calling this routine make sure that the coordinates are in range, so
* that no check on the parameters needs to be performed.
*/
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {
unsigned int PixelIndex;
//
// Convert logical into physical coordinates (Dep. on LCDConf.h)
//
#if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
int xPhys, yPhys;
xPhys = LOG2PHYS_X(x, y);
yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
GUI_USE_PARA(pDevice);
GUI_USE_PARA(x);
GUI_USE_PARA(y);
{
PixelIndex =ili9320_GetPoint(x,y); //其它不改只改此一条
}
#if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
#undef xPhys
#undef yPhys
#endif
return PixelIndex;
}
2.LCD_X_CONFIG() 函数的修改:所在文件LCDCONF_FLEXCOLOR_TEMPLATE.C
并删除 LCDWRITEREG,LCDWRITEDATA,LCDWRITEDATAMULTIPLE,LCDREADDATAMULTIPLE
#include "GUI.h"
//#include "ILI93xx.h"
//#include "touch.h"
#include "GUIDRV_Template.h"
#include "GUIDRV_FlexColor.h"
//与触摸屏有关定义,根据实际情况填写
#define TOUCH_AD_LEFT 377
#define TOUCH_AD_RIGHT 3869
#define TOUCH_AD_TOP 3878
#define TOUCH_AD_BOTTOM 235
//屏幕大小
#define XSIZE_PHYS 320 //X轴
#define YSIZE_PHYS 240 //Y轴
#define VXSIZE_PHYS 320
#define VYSIZE_PHYS 240
//配置检查
#ifndef VXSIZE_PHYS
#define VXSIZE_PHYS XSIZE_PHYS
#endif
#ifndef VYSIZE_PHYS
#define VYSIZE_PHYS YSIZE_PHYS
#endif
#ifndef XSIZE_PHYS
#error Physical X size of display is not defined!
#endif
#ifndef YSIZE_PHYS
#error Physical Y size of display is not defined!
#endif
#ifndef GUICC_565
#error Color conversion not defined!
#endif
#ifndef GUIDRV_FLEXCOLOR
#error No display driver defined!
#endif
//配置程序,用于创建显示驱动器件,设置颜色转换程序和显示尺寸
void LCD_X_Config(void) {
GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);
LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
//触摸屏
GUI_TOUCH_SetOrientation(GUI_SWAP_XY);
GUI_TOUCH_Calibrate(GUI_COORD_X,0,240,TOUCH_AD_LEFT ,TOUCH_AD_RIGHT);
GUI_TOUCH_Calibrate(GUI_COORD_Y,0,320,TOUCH_AD_TOP ,TOUCH_AD_BOTTOM);
}
//显示器驱动的回调函数
int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {
int r;
(void) LayerIndex;
(void) pData;
switch (Cmd) {
case LCD_X_INITCONTROLLER: {
//当初始化的时候被调用,主要是设置显示控制器,如果显示控制器在外部初始化则需要用户初始化
// TFTLCD_Init(); //初始化LCD 已经在开始初始化了,所以此处不需要初始化。
return 0;
}
default:
r = -1;
}
return r;
}
3.配置设置GUICONF.H
#ifndef GUICONF_H
#define GUICONF_H
#define GUI_NUM_LAYERS 10 // 显示的最大层数
#define GUI_OS (0) // 使用操作系统
#define GUI_SUPPORT_TOUCH (1) // 支持触摸
#define GUI_DEFAULT_FONT &GUI_Font6x8 //默认字体
#define GUI_SUPPORT_MOUSE (1) //支持鼠标
#define GUI_WINSUPPORT (1) //窗口管理
#define GUI_SUPPORT_MEMDEV (1) //存储设备
#define GUI_SUPPORT_DEVICES (1) //使用设备指针
#endif
4.需要开启CRC(不开启将导致无显示) 在main.C函数中
int main(void)
{
GUI_PID_STATE TouchState;
int xpos,ypos;
delay_init(); //延时函数初始化
LCD24_Init();
Touch24_Init();
// RCC_Configuration1();
// GPIO_Configuration1();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
// NVIC_Configuration1();
uart_init(115200); //串口初始化为115200
TIM3_Int_Init(999,71); //1KHZ 定时器1ms
TIM6_Int_Init(999,719); //10ms中断
mem_init(); //初始化内部内存池
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,ENABLE);//使能CRC时钟,否则STemWin不能使用
WM_SetCreateFlags(WM_CF_MEMDEV);
GUI_Init();
GUI_SetBkColor(GUI_RED);
GUI_Clear();
GUI_FillCircle(30,30,10);
SD_Init();
if (Status == SD_OK)
{
/*----------------- Read CSD/CID MSD registers ------------------*/
Status = SD_GetCardInfo(&SDCardInfo);
GUI_DispStringAt("SD OK",10,10);
}
if (Status == SD_OK)
{
/*----------------- Select Card --------------------------------*/
Status = SD_SelectDeselect((u32) (SDCardInfo.RCA << 16));
GUI_DispStringAt("SD SELECT OK",10,30);
}
if (Status == SD_OK)
{
// Status = SD_EnableWideBusOperation(SDIO_BusWide_4b);
}
/* Set Device Transfer Mode to DMA */
if (Status == SD_OK)
{
// Status = SD_SetDeviceMode(SD_DMA_MODE);//oet
// Status = SD_SetDeviceMode(SD_POLLING_MODE);
Status = SD_SetDeviceMode(SD_INTERRUPT_MODE);
// printf("nTEST OK!n");
GUI_DispStringAt("SD SETDEVICE OK",10,50);
}
disk_initialize(0);
f_mount(0, &fs);
gifdisplay_demo();
GUIDEMO_Main();
//
// GUI_DispStringAt("X1:",10,10);
// GUI_DispDec(Xs_1,4);
// GUI_DispStringAt("X2:",100,10);
// GUI_DispDec(Xs_2,4);
// GUI_DispStringAt("X3:",10,30);
// GUI_DispDec(Xs_3,4);
// GUI_DispStringAt("X4:",100,30);
// GUI_DispDec(Xs_4,4);
//
// GUI_DispStringAt("Y1:",10,60);
// GUI_DispDec(Ys_1,4);
// GUI_DispStringAt("Y2:",100,60);
// GUI_DispDec(Ys_2,4);
// GUI_DispStringAt("Y3:",10,120);
// GUI_DispDec(Ys_3,4);
// GUI_DispStringAt("Y4:",100,120);
// GUI_DispDec(Ys_4,4);
while(1)
{
// GUI_TOUCH_Exec();
// xpos = GUI_TOUCH_X_MeasureX();
// ypos = GUI_TOUCH_X_MeasureY();
//GUI_TOUCH_GetState(&TouchState);
// xpos = GUI_TOUCH_GetxPhys();
// xpos = TouchState.x;
// GUI_DispStringAt("X:",10,10);
// GUI_DispDec(xpos,4);
//
// // ypos = GUI_TOUCH_GetyPhys();
// ypos = TouchState.y;
// GUI_DispStringAt("Y:",20,20);
// GUI_DispDec(ypos,4);
// GUI_DrawPoint(xpos,ypos);
// delay_ms(50);
}
}
常见的错误:
(1.GUI_NUMBYTES 过大,导致编译通不过:所在文件GUICONF.C
(2.画面不显示:GUI_DEVICE_CREATEANDLINK(&GUIDRV_TEMPLATE_API,GUICC_M565,0,0):此处需设为使用自已的驱动&GUIDRV_TEMPLATE_API:所在文件LCDCONF_FLEXCOLOR_TEMPLATE.C
(3.颜色颜色反了:GUICC_565:所在函数LCDCONF_FLEXCOLOR_TEMPLATE.C-》 GUI_DEVICE_CREATEANDLINK
(4.画面不显示GUIBUILDER创建文件不显示;需要在while中添加GUI_DELAY()或是GUI_EXEC()
(5.画面不显示,未开启CRC
触摸屏的移植
1.需要完成GUI_TOUCH_X_ACTIVEATEX(),GUI_TOUCH_X_ACTIVEATEY()此两个可为空;GUI_TOUCH_X_MEASUREX(),GUI_TOUCH_X_MEASUREY();
#include "stm32f10x.h"
#include "SPI_Flash.h"
#define NotSelect_Flash() GPIO_SetBits(GPIOA, GPIO_Pin_4)
extern unsigned char AT45_buffer[];
extern unsigned int Xs_1,Xs_2,Xs_3,Xs_4,Ys_1,Ys_2,Ys_3,Ys_4; //记录触坐标值
extern unsigned char dw,A_TP,b,TP_B; //TP_B存放 校准参数 0和1为XY轴
unsigned char A_TP =0;
extern unsigned short int X,Y;
void GUI_TOUCH_X_ActivateX(void) {
}
void GUI_TOUCH_X_ActivateY(void) {
}
int GUI_TOUCH_X_MeasureX(void)
{
float Y1,hh;
u16 xx;
unsigned char t=0,t1,count=0;
unsigned short int databuffer[10]={5,7,9,3,2,6,4,0,3,1};//数据组
unsigned short temp=0,X=0;
if(TP_B==0)
{
while(count<10)//循环读数10次
{
databuffer[count]=TPReadX();
count++;
}
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t
{
if(databuffer[t]>databuffer[t+1])//升序排列
{
temp=databuffer[t+1];
databuffer[t+1]=databuffer[t];
databuffer[t]=temp;
t1=1;
}
}
}while(t1);
if(A_TP==1||A_TP==2)
{
Y1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Xs_3-Xs_1; //计算出X1,X3距离
hh=(float)xx/280; //计算出X比例因子
xx=(float)((hh*320)-xx)/2; //X方向偏移量
X=(Y1-(Xs_1-xx))/hh; //计算坐标
X=X*12.79;
}
else
{
Y1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Xs_1-Xs_3; //计算出X1,X3距离
hh=(float)xx/280; //计算出X比例因子
xx=(float)((hh*320)-xx)/2; //X方向偏移量
X=320-(Y1-(Xs_3-xx))/hh; //计算坐标
X=X*12.79;
}
}
}
else
{
while(count<10)//循环读数10次
{
databuffer[count]=TPReadY();
count++;
}
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t
{
if(databuffer[t]>databuffer[t+1])//升序排列
{
temp=databuffer[t+1];
databuffer[t+1]=databuffer[t];
databuffer[t]=temp;
t1=1;
}
}
}while(t1);
if(A_TP==1||A_TP==3)
{
Y1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Ys_2-Ys_1; //计算出Y1,Y2距离
hh=(float)xx/280; //计算出X比例
xx=(float)((hh*320)-xx)/2; //Y方向偏移量
X=(Y1-(Ys_1-xx))/hh; //计算坐标
X=X*12.79;
}
else
{
Y1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Ys_1-Ys_2; //计算出Y1,Y2距离
hh=(float)xx/280; //计算出X比例
xx=(float)((hh*320)-xx)/2; //Y方向偏移量
X=320-(Y1-(Ys_2-xx))/hh; //计算坐标
X=X*12.79;
}
}
}
return(X);
}
int GUI_TOUCH_X_MeasureY(void) {
float X1,hh;
u16 xx;
unsigned char t=0,t1,count=0;
unsigned short int databuffer[10]={5,7,9,3,2,6,4,0,3,1};//数据组
unsigned short temp=0,Y=0;
if(TP_B==0)
{
while(count<10) //循环读数10次
{
databuffer[count]=TPReadY();
count++;
}
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t
{
if(databuffer[t]>databuffer[t+1])//升序排列
{
temp=databuffer[t+1];
databuffer[t+1]=databuffer[t];
databuffer[t]=temp;
t1=1;
}
}
}while(t1);
if(A_TP==1||A_TP==3)
{
X1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Ys_2-Ys_1; //计算出Y1,Y2距离
hh=(float)xx/200; //计算出X比例
xx=(float)((hh*240)-xx)/2; //Y方向偏移量
Y=(X1-(Ys_1-xx))/hh; //计算坐标
Y=Y*17.06;
}
else
{
X1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Ys_1-Ys_2; //计算出Y1,Y2距离
hh=(float)xx/200; //计算出X比例
xx=(float)((hh*240)-xx)/2; //Y方向偏移量
Y=240-(X1-(Ys_2-xx))/hh; //计算坐标
Y=Y*17.06;
}
}
}
else
{
while(count<10) //循环读数10次
{
databuffer[count]=TPReadX();
count++;
}
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t
{
if(databuffer[t]>databuffer[t+1])//升序排列
{
temp=databuffer[t+1];
databuffer[t+1]=databuffer[t];
databuffer[t]=temp;
t1=1;
}
}
}while(t1);
if(A_TP==1||A_TP==2)
{
X1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Xs_3-Xs_1; //计算出X1,X3距离
hh=(float)xx/200; //计算出X比例因子
xx=(float)((hh*240)-xx)/2; //X方向偏移量
Y=(X1-(Xs_1-xx))/hh; //计算坐标
Y=Y*17.06;
}
else
{
X1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Xs_1-Xs_3; //计算出X1,X3距离
hh=(float)xx/200; //计算出X比例因子
xx=(float)((hh*240)-xx)/2; //X方向偏移量
Y=240-(X1-(Xs_3-xx))/hh; //计算坐标
Y=Y*17.06;
}
}
}
return(Y);
}
2.LCD_X_CONFIG():所在文件:LCDCONF_FLEXCOLOR_TEMPLATE.C
使用GUI_TOUCH_CALIBRATE()函数,对触摸屏进行设置方向,位置的校正;
//配置程序,用于创建显示驱动器件,设置颜色转换程序和显示尺寸
void LCD_X_Config(void) {
GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);
LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
//触摸屏
GUI_TOUCH_SetOrientation(GUI_SWAP_XY);
GUI_TOUCH_Calibrate(GUI_COORD_X,0,240,TOUCH_AD_LEFT ,TOUCH_AD_RIGHT);
GUI_TOUCH_Calibrate(GUI_COORD_Y,0,320,TOUCH_AD_TOP ,TOUCH_AD_BOTTOM);
}
3.添加两个中断,在每个中断中完成 所在文件 HARDWARETIMER:
OS_TIMEMS++
GUI_TOUCH_EXEC();
#include "timer.h"
//#include "led.h"
#include "GUI.h"
#include "usart.h"
//
//
extern __IO int32_t OS_TimeMS;
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//开启TIM3时钟
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频值
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数模式
TIM_TimeBaseInitStructure.TIM_Period=arr; //自动重装数值
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //设置时钟分割
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//允许更新中断
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3,ENABLE); //使能TIM3
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
OS_TimeMS++;
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
//基本定时器6中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器6!
void TIM6_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE); //定时器6时钟使能
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //设置分频值,10khz的计数频率
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_Period=arr; //自动重装载值 计数到5000为500ms
TIM_TimeBaseInitStructure.TIM_ClockDivision=0; //时钟分割:TDS=Tck_Tim
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM6,TIM_IT_Update|TIM_IT_Trigger,ENABLE); //使能TIM6的更新中断
NVIC_InitStructure.NVIC_IRQChannel=TIM6_IRQn; //TIM6中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //先占优先级1级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能通道
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM6,ENABLE); //定时器6使能
}
void TIM6_IRQHandler(void)
{
if(TIM_GetITStatus(TIM6,TIM_IT_Update)!=RESET)
{
GUI_TOUCH_Exec();
}
TIM_ClearITPendingBit(TIM6,TIM_IT_Update); //清除中断标志位
}
常见问题:
触摸无反应:测试触摸驱动正常,使用GUI_TOUCH_GETXPHYS()无反应:需开头处添加GUI_TOUCH_EXEC()引用
GUI_TOUCH_CALIBRATE()设置后GUI_TOUCH_GETXPHYS()获取值为物理植,对GUI_TOUCH_GETXPHYS()无效;需使用GUI_TOUCH_GETSTATE() 获取效正的值
应用的触摸无反应:需设置OS_TIMEMS++;和GUI_TOUCH_EXEC()中断服务
应用的触摸无反应:使用GUIBUILDER创建的为DIALOG界面,而非WINDOW界面
无操作系统状态下:操作界面也允许点击,触摸,鼠标操作,使用GUIBUILDER时,需使用WINDOW界面,而不是DIALOG否则消息函数无反应,无法点击操作
参考资料:正点原子 EMWIN
学习经历
起因:因为贪便宜买了块STM32F103VE的开发板,到货后发现的问题
1.资料不全;导致学习困难度,“挫败度”大大加深;
2.网上查找的资料与板子不对应,对初学者来说困难度变大;
3.视频教程过于庞大,学习过程中若没有动力支持,放弃的可能性很大
参考意见:如果条件允许;1.尽量买资料全(最好有大量资料的,最好是中文的,否则你需要英文能力的支持),技术成熟的,有完整教材的来开始使用;有技术支持,william hill官网
讨论的;所节省下来的时间,往往比所花费的金钱更值得;最好有文档跟视频的;便于快速学习与查找问题
4.代码混乱,无“模块化”,导致无序与混乱;(模块化是一种必然化的需求)
5.版本的差异(固件库),导致不同的版本会有代码上的差异,从而出现错误
学习步骤(学习动力论):
1.实践大于看书,实践比书要简单;前提是你先粗看一遍;
2.初学者,不要去看平台搭建(延后),平台搭建中的大量错误可能挫败积极性;所以第一步先使用已经搭建好的平台,去建立第一个LED灯实验;
3.初学者需要明确目标:所需要的功能;硬件平台中有大量的硬件知识需要学习,知识的前后也有依赖性;导致你找到你希望学习的内容,也必须将前面的知识先学会;如果你没有合理的安排,或是空闲的时间,将导致挫败感;并且前面的依赖性,关联性,导致无法快速学习一个内容的知识(这是需要解决的,但好像没有相应的教材,故学习很累)
单片机对于计算机底层的知识,有利我们更好的理解计算机;现在的个人计算机底层的操作,都已经封装好了,写程序只需要在软件层操作就行;并不需要涉及硬件层,“寄存器”或是“内存映射”等知识(秉火有详细介绍)
基于成本,项目需求等考虑,单片机的种类很多;有带显示屏,触摸的,到ARDUION;有主频1.2G,内存2G的到只有12M,几百KB的;有容易入门到的,如ARDUION简单开发应用的(现已支持STM32,但还不全);到使用ARM处理的LUNUX系统,需要写底层驱动的;需要根据自己的需求进行选择,总体来说STM32的性价比较高,但依现有的资料与技术(注意:STM32一般内存较小,只有几百KB,而外扩也不大,只有几M);学习比较HAO时;如果你使用ARDUION另当别论
学习单片机或嵌入式,一般都是为了对外进行控制操作,使用STM32或是ARM或树莓派,不单单是点LED灯;更希望使用的是他的液晶显示触摸功能;如果是简单的可以自己写就行,如果是比较复杂的,我们自己写也可以,但有现成的更简单的,就是使用EMWIN来完成,只需要几条指令就可以完成;
EMWIN是UCGUI的升级版,不开放源码;源码可以参考UCGUI
EMWIN主要是通过对原来的驱动的调用,来完成更高级的功能,在液晶屏上显示对话框,图片,可以点击操作;他主要通过调用原驱动中的画点,取点函数来隔离化底层的操作,从而使EMWIN更通用化,可以适合更多的平台,开发板
液晶的使用,为了更简便一般使用FMSC接口功能
1.液晶需要按正确的顺序连接开始板
2.开启FMSC功能
3.驱动的编写(你得查看相应的资料DATASHEET,或是厂家已编好的驱动,移植即可)
STM32的使用的主要步骤:
1.开启时钟:
2.设置功能:
3.控制
开启时钟:(他是为了节能而设置的,如可穿戴调备,使用锂电池,导致多了条语句也导致繁琐度增加;
设置功能:是因为他一个引脚可以有多个功能如PWM,UART,SPI
EMWIN屏幕的移植(参考资料:"正点原子EMWIN移植")
前提:需要已有LCD的液晶和触摸驱动,并能正常画点,画线;触摸
下载stm32cubef1:http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1897/PF260820?s_searchtype=partnumber
需要其中的 stm32cubef1STM32Cube_FW_F1_V1.0.0MiddlewaresSTSTemWin下的
(1.CONFIG
(2.INC
(3.LIB
(4.OS
这向个文件
(SOFTWARE里函有GUIBUILDER软件,可用于创建界面
(SIMULATION里函有WINDOWS中仿真所需的工具
1.画点函数_SETPIXELINDEX()与取点函数_GETPIXELINDEX()的完成:所在文件 GUIDRV_TEMPLATE.C
/*********************************************************************
*
* _SetPixelIndex
*
* Purpose:
* Sets the index of the given pixel. The upper layers
* calling this routine make sure that the coordinates are in range, so
* that no check on the parameters needs to be performed.
*/
static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {
ili9320_SetPoint(x, y,PixelIndex); //其它不改只改此一条
}
/*********************************************************************
*
* _GetPixelIndex
*
* Purpose:
* Returns the index of the given pixel. The upper layers
* calling this routine make sure that the coordinates are in range, so
* that no check on the parameters needs to be performed.
*/
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {
unsigned int PixelIndex;
//
// Convert logical into physical coordinates (Dep. on LCDConf.h)
//
#if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
int xPhys, yPhys;
xPhys = LOG2PHYS_X(x, y);
yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
GUI_USE_PARA(pDevice);
GUI_USE_PARA(x);
GUI_USE_PARA(y);
{
PixelIndex =ili9320_GetPoint(x,y); //其它不改只改此一条
}
#if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
#undef xPhys
#undef yPhys
#endif
return PixelIndex;
}
2.LCD_X_CONFIG() 函数的修改:所在文件LCDCONF_FLEXCOLOR_TEMPLATE.C
并删除 LCDWRITEREG,LCDWRITEDATA,LCDWRITEDATAMULTIPLE,LCDREADDATAMULTIPLE
#include "GUI.h"
//#include "ILI93xx.h"
//#include "touch.h"
#include "GUIDRV_Template.h"
#include "GUIDRV_FlexColor.h"
//与触摸屏有关定义,根据实际情况填写
#define TOUCH_AD_LEFT 377
#define TOUCH_AD_RIGHT 3869
#define TOUCH_AD_TOP 3878
#define TOUCH_AD_BOTTOM 235
//屏幕大小
#define XSIZE_PHYS 320 //X轴
#define YSIZE_PHYS 240 //Y轴
#define VXSIZE_PHYS 320
#define VYSIZE_PHYS 240
//配置检查
#ifndef VXSIZE_PHYS
#define VXSIZE_PHYS XSIZE_PHYS
#endif
#ifndef VYSIZE_PHYS
#define VYSIZE_PHYS YSIZE_PHYS
#endif
#ifndef XSIZE_PHYS
#error Physical X size of display is not defined!
#endif
#ifndef YSIZE_PHYS
#error Physical Y size of display is not defined!
#endif
#ifndef GUICC_565
#error Color conversion not defined!
#endif
#ifndef GUIDRV_FLEXCOLOR
#error No display driver defined!
#endif
//配置程序,用于创建显示驱动器件,设置颜色转换程序和显示尺寸
void LCD_X_Config(void) {
GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);
LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
//触摸屏
GUI_TOUCH_SetOrientation(GUI_SWAP_XY);
GUI_TOUCH_Calibrate(GUI_COORD_X,0,240,TOUCH_AD_LEFT ,TOUCH_AD_RIGHT);
GUI_TOUCH_Calibrate(GUI_COORD_Y,0,320,TOUCH_AD_TOP ,TOUCH_AD_BOTTOM);
}
//显示器驱动的回调函数
int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {
int r;
(void) LayerIndex;
(void) pData;
switch (Cmd) {
case LCD_X_INITCONTROLLER: {
//当初始化的时候被调用,主要是设置显示控制器,如果显示控制器在外部初始化则需要用户初始化
// TFTLCD_Init(); //初始化LCD 已经在开始初始化了,所以此处不需要初始化。
return 0;
}
default:
r = -1;
}
return r;
}
3.配置设置GUICONF.H
#ifndef GUICONF_H
#define GUICONF_H
#define GUI_NUM_LAYERS 10 // 显示的最大层数
#define GUI_OS (0) // 使用操作系统
#define GUI_SUPPORT_TOUCH (1) // 支持触摸
#define GUI_DEFAULT_FONT &GUI_Font6x8 //默认字体
#define GUI_SUPPORT_MOUSE (1) //支持鼠标
#define GUI_WINSUPPORT (1) //窗口管理
#define GUI_SUPPORT_MEMDEV (1) //存储设备
#define GUI_SUPPORT_DEVICES (1) //使用设备指针
#endif
4.需要开启CRC(不开启将导致无显示) 在main.C函数中
int main(void)
{
GUI_PID_STATE TouchState;
int xpos,ypos;
delay_init(); //延时函数初始化
LCD24_Init();
Touch24_Init();
// RCC_Configuration1();
// GPIO_Configuration1();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
// NVIC_Configuration1();
uart_init(115200); //串口初始化为115200
TIM3_Int_Init(999,71); //1KHZ 定时器1ms
TIM6_Int_Init(999,719); //10ms中断
mem_init(); //初始化内部内存池
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,ENABLE);//使能CRC时钟,否则STemWin不能使用
WM_SetCreateFlags(WM_CF_MEMDEV);
GUI_Init();
GUI_SetBkColor(GUI_RED);
GUI_Clear();
GUI_FillCircle(30,30,10);
SD_Init();
if (Status == SD_OK)
{
/*----------------- Read CSD/CID MSD registers ------------------*/
Status = SD_GetCardInfo(&SDCardInfo);
GUI_DispStringAt("SD OK",10,10);
}
if (Status == SD_OK)
{
/*----------------- Select Card --------------------------------*/
Status = SD_SelectDeselect((u32) (SDCardInfo.RCA << 16));
GUI_DispStringAt("SD SELECT OK",10,30);
}
if (Status == SD_OK)
{
// Status = SD_EnableWideBusOperation(SDIO_BusWide_4b);
}
/* Set Device Transfer Mode to DMA */
if (Status == SD_OK)
{
// Status = SD_SetDeviceMode(SD_DMA_MODE);//oet
// Status = SD_SetDeviceMode(SD_POLLING_MODE);
Status = SD_SetDeviceMode(SD_INTERRUPT_MODE);
// printf("nTEST OK!n");
GUI_DispStringAt("SD SETDEVICE OK",10,50);
}
disk_initialize(0);
f_mount(0, &fs);
gifdisplay_demo();
GUIDEMO_Main();
//
// GUI_DispStringAt("X1:",10,10);
// GUI_DispDec(Xs_1,4);
// GUI_DispStringAt("X2:",100,10);
// GUI_DispDec(Xs_2,4);
// GUI_DispStringAt("X3:",10,30);
// GUI_DispDec(Xs_3,4);
// GUI_DispStringAt("X4:",100,30);
// GUI_DispDec(Xs_4,4);
//
// GUI_DispStringAt("Y1:",10,60);
// GUI_DispDec(Ys_1,4);
// GUI_DispStringAt("Y2:",100,60);
// GUI_DispDec(Ys_2,4);
// GUI_DispStringAt("Y3:",10,120);
// GUI_DispDec(Ys_3,4);
// GUI_DispStringAt("Y4:",100,120);
// GUI_DispDec(Ys_4,4);
while(1)
{
// GUI_TOUCH_Exec();
// xpos = GUI_TOUCH_X_MeasureX();
// ypos = GUI_TOUCH_X_MeasureY();
//GUI_TOUCH_GetState(&TouchState);
// xpos = GUI_TOUCH_GetxPhys();
// xpos = TouchState.x;
// GUI_DispStringAt("X:",10,10);
// GUI_DispDec(xpos,4);
//
// // ypos = GUI_TOUCH_GetyPhys();
// ypos = TouchState.y;
// GUI_DispStringAt("Y:",20,20);
// GUI_DispDec(ypos,4);
// GUI_DrawPoint(xpos,ypos);
// delay_ms(50);
}
}
常见的错误:
(1.GUI_NUMBYTES 过大,导致编译通不过:所在文件GUICONF.C
(2.画面不显示:GUI_DEVICE_CREATEANDLINK(&GUIDRV_TEMPLATE_API,GUICC_M565,0,0):此处需设为使用自已的驱动&GUIDRV_TEMPLATE_API:所在文件LCDCONF_FLEXCOLOR_TEMPLATE.C
(3.颜色颜色反了:GUICC_565:所在函数LCDCONF_FLEXCOLOR_TEMPLATE.C-》 GUI_DEVICE_CREATEANDLINK
(4.画面不显示GUIBUILDER创建文件不显示;需要在while中添加GUI_DELAY()或是GUI_EXEC()
(5.画面不显示,未开启CRC
触摸屏的移植
1.需要完成GUI_TOUCH_X_ACTIVEATEX(),GUI_TOUCH_X_ACTIVEATEY()此两个可为空;GUI_TOUCH_X_MEASUREX(),GUI_TOUCH_X_MEASUREY();
#include "stm32f10x.h"
#include "SPI_Flash.h"
#define NotSelect_Flash() GPIO_SetBits(GPIOA, GPIO_Pin_4)
extern unsigned char AT45_buffer[];
extern unsigned int Xs_1,Xs_2,Xs_3,Xs_4,Ys_1,Ys_2,Ys_3,Ys_4; //记录触坐标值
extern unsigned char dw,A_TP,b,TP_B; //TP_B存放 校准参数 0和1为XY轴
unsigned char A_TP =0;
extern unsigned short int X,Y;
void GUI_TOUCH_X_ActivateX(void) {
}
void GUI_TOUCH_X_ActivateY(void) {
}
int GUI_TOUCH_X_MeasureX(void)
{
float Y1,hh;
u16 xx;
unsigned char t=0,t1,count=0;
unsigned short int databuffer[10]={5,7,9,3,2,6,4,0,3,1};//数据组
unsigned short temp=0,X=0;
if(TP_B==0)
{
while(count<10)//循环读数10次
{
databuffer[count]=TPReadX();
count++;
}
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t
{
if(databuffer[t]>databuffer[t+1])//升序排列
{
temp=databuffer[t+1];
databuffer[t+1]=databuffer[t];
databuffer[t]=temp;
t1=1;
}
}
}while(t1);
if(A_TP==1||A_TP==2)
{
Y1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Xs_3-Xs_1; //计算出X1,X3距离
hh=(float)xx/280; //计算出X比例因子
xx=(float)((hh*320)-xx)/2; //X方向偏移量
X=(Y1-(Xs_1-xx))/hh; //计算坐标
X=X*12.79;
}
else
{
Y1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Xs_1-Xs_3; //计算出X1,X3距离
hh=(float)xx/280; //计算出X比例因子
xx=(float)((hh*320)-xx)/2; //X方向偏移量
X=320-(Y1-(Xs_3-xx))/hh; //计算坐标
X=X*12.79;
}
}
}
else
{
while(count<10)//循环读数10次
{
databuffer[count]=TPReadY();
count++;
}
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t
{
if(databuffer[t]>databuffer[t+1])//升序排列
{
temp=databuffer[t+1];
databuffer[t+1]=databuffer[t];
databuffer[t]=temp;
t1=1;
}
}
}while(t1);
if(A_TP==1||A_TP==3)
{
Y1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Ys_2-Ys_1; //计算出Y1,Y2距离
hh=(float)xx/280; //计算出X比例
xx=(float)((hh*320)-xx)/2; //Y方向偏移量
X=(Y1-(Ys_1-xx))/hh; //计算坐标
X=X*12.79;
}
else
{
Y1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Ys_1-Ys_2; //计算出Y1,Y2距离
hh=(float)xx/280; //计算出X比例
xx=(float)((hh*320)-xx)/2; //Y方向偏移量
X=320-(Y1-(Ys_2-xx))/hh; //计算坐标
X=X*12.79;
}
}
}
return(X);
}
int GUI_TOUCH_X_MeasureY(void) {
float X1,hh;
u16 xx;
unsigned char t=0,t1,count=0;
unsigned short int databuffer[10]={5,7,9,3,2,6,4,0,3,1};//数据组
unsigned short temp=0,Y=0;
if(TP_B==0)
{
while(count<10) //循环读数10次
{
databuffer[count]=TPReadY();
count++;
}
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t
{
if(databuffer[t]>databuffer[t+1])//升序排列
{
temp=databuffer[t+1];
databuffer[t+1]=databuffer[t];
databuffer[t]=temp;
t1=1;
}
}
}while(t1);
if(A_TP==1||A_TP==3)
{
X1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Ys_2-Ys_1; //计算出Y1,Y2距离
hh=(float)xx/200; //计算出X比例
xx=(float)((hh*240)-xx)/2; //Y方向偏移量
Y=(X1-(Ys_1-xx))/hh; //计算坐标
Y=Y*17.06;
}
else
{
X1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Ys_1-Ys_2; //计算出Y1,Y2距离
hh=(float)xx/200; //计算出X比例
xx=(float)((hh*240)-xx)/2; //Y方向偏移量
Y=240-(X1-(Ys_2-xx))/hh; //计算坐标
Y=Y*17.06;
}
}
}
else
{
while(count<10) //循环读数10次
{
databuffer[count]=TPReadX();
count++;
}
if(count==10)//一定要读到10次数据,否则丢弃
{
do//将数据X升序排列
{
t1=0;
for(t=0;t
{
if(databuffer[t]>databuffer[t+1])//升序排列
{
temp=databuffer[t+1];
databuffer[t+1]=databuffer[t];
databuffer[t]=temp;
t1=1;
}
}
}while(t1);
if(A_TP==1||A_TP==2)
{
X1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Xs_3-Xs_1; //计算出X1,X3距离
hh=(float)xx/200; //计算出X比例因子
xx=(float)((hh*240)-xx)/2; //X方向偏移量
Y=(X1-(Xs_1-xx))/hh; //计算坐标
Y=Y*17.06;
}
else
{
X1=(databuffer[3]+databuffer[4]+databuffer[5])/3;
xx=Xs_1-Xs_3; //计算出X1,X3距离
hh=(float)xx/200; //计算出X比例因子
xx=(float)((hh*240)-xx)/2; //X方向偏移量
Y=240-(X1-(Xs_3-xx))/hh; //计算坐标
Y=Y*17.06;
}
}
}
return(Y);
}
2.LCD_X_CONFIG():所在文件:LCDCONF_FLEXCOLOR_TEMPLATE.C
使用GUI_TOUCH_CALIBRATE()函数,对触摸屏进行设置方向,位置的校正;
//配置程序,用于创建显示驱动器件,设置颜色转换程序和显示尺寸
void LCD_X_Config(void) {
GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);
LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
//触摸屏
GUI_TOUCH_SetOrientation(GUI_SWAP_XY);
GUI_TOUCH_Calibrate(GUI_COORD_X,0,240,TOUCH_AD_LEFT ,TOUCH_AD_RIGHT);
GUI_TOUCH_Calibrate(GUI_COORD_Y,0,320,TOUCH_AD_TOP ,TOUCH_AD_BOTTOM);
}
3.添加两个中断,在每个中断中完成 所在文件 HARDWARETIMER:
OS_TIMEMS++
GUI_TOUCH_EXEC();
#include "timer.h"
//#include "led.h"
#include "GUI.h"
#include "usart.h"
//
//
extern __IO int32_t OS_TimeMS;
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//开启TIM3时钟
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频值
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数模式
TIM_TimeBaseInitStructure.TIM_Period=arr; //自动重装数值
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //设置时钟分割
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//允许更新中断
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3,ENABLE); //使能TIM3
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
OS_TimeMS++;
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
//基本定时器6中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器6!
void TIM6_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE); //定时器6时钟使能
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //设置分频值,10khz的计数频率
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_Period=arr; //自动重装载值 计数到5000为500ms
TIM_TimeBaseInitStructure.TIM_ClockDivision=0; //时钟分割:TDS=Tck_Tim
TIM_TimeBaseInit(TIM6,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM6,TIM_IT_Update|TIM_IT_Trigger,ENABLE); //使能TIM6的更新中断
NVIC_InitStructure.NVIC_IRQChannel=TIM6_IRQn; //TIM6中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //先占优先级1级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //使能通道
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM6,ENABLE); //定时器6使能
}
void TIM6_IRQHandler(void)
{
if(TIM_GetITStatus(TIM6,TIM_IT_Update)!=RESET)
{
GUI_TOUCH_Exec();
}
TIM_ClearITPendingBit(TIM6,TIM_IT_Update); //清除中断标志位
}
常见问题:
触摸无反应:测试触摸驱动正常,使用GUI_TOUCH_GETXPHYS()无反应:需开头处添加GUI_TOUCH_EXEC()引用
GUI_TOUCH_CALIBRATE()设置后GUI_TOUCH_GETXPHYS()获取值为物理植,对GUI_TOUCH_GETXPHYS()无效;需使用GUI_TOUCH_GETSTATE() 获取效正的值
应用的触摸无反应:需设置OS_TIMEMS++;和GUI_TOUCH_EXEC()中断服务
应用的触摸无反应:使用GUIBUILDER创建的为DIALOG界面,而非WINDOW界面
无操作系统状态下:操作界面也允许点击,触摸,鼠标操作,使用GUIBUILDER时,需使用WINDOW界面,而不是DIALOG否则消息函数无反应,无法点击操作
举报