STM32移植uCGUI+触摸屏显示,没有加入uCOS Ⅱ

实验板子 ——李想STM32开发板   

开发工具—— keil uVision5.0 for MDK

本次终极任务为显示示波器的GUI界面,此文章只是简单总结移植uCGUI+触摸屏,之后会加入视窗管理器及uCOSⅡ。

下面说说移植步骤,会穿插一些个人简单的理解,为像我一样的新手提供方便。

步骤分为三大步:

一、移植uCGUI  

二、显示汉字    

三、移植触摸屏

一、移植uCGUI

1、建立工程模版。

个人会先建立一个工程模板,里边只包含系统的一些文件,主函数是while(1);的循环。每次项目用到就直接复制,添加文件即可。(假设大家都知道在工程中正确添加.c与.h文件的方法)工程目录如下:

                                     

CMSIS——CM3中断相关及启动的文件

delay——延时相关的文件(大多数工程都需要。因此放在顶层目录了)

library——ST提供的各种库文件分为inc和src两个文件夹

MDK-ARM——编译产生的中间文件即输出文件

my_driver——自己的驱动文件主要是彩屏驱动文件、个人字库文件和其他工程需要的文件,如spi、iic相关文件

USER——main.c及其它未添加的库文件

2、添加彩屏驱动。

每个人的开发板配套的彩屏及驱动芯片都不一定一样,要根据自己的情况,保证在没移植uCGUI之前情况下,彩屏能够正常显示任意能显示的图案,(不一定要显示汉字)。此处使用李想stm32教程STM32 理想智芯科技(库函数)里的ILI93xx.c文件,将其头文件LCD.h改名为ILI93xx.h文件。并将STM32 理想智芯科技(库函数)里的mian文件替换到工程,删除修改不必要的头文件,删除主函数的全部内容。

主要应包含三个函数:

1)彩屏初始化文件 LCD_MyInit() ;由原来ILI93xx.c里的LCD_Init()更改名称而来;

2)画点函数,原函数LCD_DrawPoint();因为要横屏显示更改为如下模式:竖屏保留原来的函数

void LCD_DrawPoint(u16 x,u16 y,u16 color)
{

LCD_WriteReg(0x004e,239-y); 
LCD_WriteReg(0x004f,x); 
LCD_WR_REG(0x22); //LCD_WriteCMD(GRAMWR);

LCD_WR_DATA(color);
}

3)读点函数,返回设定坐标点的颜色值。即ILI93xx.c文件里的LCD_ReadPoint();

三、下载uCGUI的源码。

本次使用的是3.98的版本,uCGUI的文件目录如下。可以只移植自己需要的文件,怕麻烦或者工程最后会用到的文件也可以全部添加进去。

              

将uCGUI源码中的config及GUI文件夹复制到工程目录,添加需要的.c文件以及.h文件的目录。完成如下:

4、配置uCGUI文件

1)打开config下的LCDConf.h,全部注释,改为如下内容(显示为横屏模式)

#ifndef LCDCONF_H
#define LCDCONF_H

/*********************************************************************
*
*                   General configuration of LCD
*
**********************************************************************
*/

#define LCD_XSIZE (320) /* X-resolution of LCD, Logical coor. *///竖屏改为240
#define LCD_YSIZE (240) /* Y-resolution of LCD, Logical coor. *///竖屏改为320


#define LCD_BITSPERPIXEL (16) //16位色
#define LCD_CONTROLLER (-1) //缺省驱动(即采用自己的驱动函数)
#define LCD_FIXEDPALETTE (565) //调色板565格式
#define LCD_SWAP_RB (1) //红蓝反色交换
#define LCD_INIT_CONTROLLER()     LCD_MyInit() ; //LCD_MyInit();为你自己的彩屏初始化函数4

2)修改GUIConf.h文件

#ifndef GUICONF_H
#define GUICONF_H

#define GUI_OS (0) /* Compile with multitasking support */ //操作系统的支持
#define GUI_SUPPORT_TOUCH (1) /* Support a touch screen (req. win-manager) */ // 触摸屏
#define GUI_SUPPORT_MOUSE (1)//鼠标
#define GUI_SUPPORT_UNICODE (1) /* Support mixed ASCII/UNICODE strings */ //UNICODE支持,显示汉字

#define GUI_DEFAULT_FONT &GUI_Font6x8 //GUI默认字体
#define GUI_ALLOC_SIZE 5000 /* Size of dynamic memory ... For WM and memory devices*///动态内存

/*********************************************************************
*
* Configuration of available packages
*/

#define GUI_WINSUPPORT 1 /* Window manager package available */ //´窗口控件支持
#define GUI_SUPPORT_MEMDEV 1 /* Memory devices available */ //内存设备支持
#define GUI_SUPPORT_AA 0 /* Anti aliasing available */ //抗锯齿形。打开刷新速率会差

#endif /* Avoid multiple inclusion */

3)替换uCGUI函数体:

因为uCGUI的显示是基于点的显示,即uCGUI会调用你自己驱动的画点操作完成图案的显示,因此需要将为我们的三个主要的驱动函数复制到uCGUI的内部。

I、打开LCDDriver下的LCDDummy.c文件将LCD_L0_SetPixelIndex的函数体该为LCD_DrawPoint(x,y,PixelIndex);

II、将LCD_L0_GetPixelIndex的函数体该为return LCD_ReadPoint(x,y);并且包含ILI93xx.h

III、修改主函数

RCC_Configuration();
GPIO_Configuration();
delay_init(72);
GUI_Init();
GUI_SetBkColor(GUI_BLUE);
GUI_SetColor(GUI_RED);
GUI_DispStringAt("Hello My World! ",150,150);

5、编译下载,即可横屏显示。

二、显示汉字

汉字的显示需要字库文件,标准字库文件太大,很多字体都用不到,会浪费很大的内存空间。因此一般选择定制自己的字库。一个小软件ucgui_font.exe。

1、打开软件,之后选择字体,选择你所需要的字体格式,确定,在文本框输入自己定义的字体名称,不能含中文,指定范围导出GBK码,输入你需要显示的汉字字符,确定等待完成。之后文件夹会多一个文件。比如将字体名称定义为My_Font,包含“汉字显示测试”几个文字,会产生一个My_Font.c的文件,将文件复制到工程目录,添加进Font目录。

2、复制extern GUI_FLASH const GUI_FONT GUI_FontHZ_My_Font;

改为extern const GUI_FONT GUI_FontHZ_My_Font;

3、修改主函数

RCC_Configuration();
GPIO_Configuration();
delay_init(72);
GUI_Init();
GUI_SetBkColor(GUI_BLUE);
GUI_SetColor(GUI_RED);
GUI_DispStringAt("Hello My World! ",150,150);
GUI_SetFont(&GUI_FontHZ_My_Font);
GUI_DispStringAt("汉字显示测试",50,50);

4、编译下载,显示成功

三、移植触摸屏

1、将智芯一号触摸屏测试程序中的LIXIANG文件夹下的按需要添加到工程,如:

                      

2、修改配置及驱动文件

1)因为原工程为寄存器版本,现在为库函数版本,将所有的头文件stm32f10x_lib.h改为stm32f10x.h

2)将sys.c文件下

MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)

函数最后一句IPR改为IP即NVIC->IP[IPRADDR]|=temp<<IPROFFSET;//设置响应优先级可抢占优先级

在touch.c文件中,将 MY_NVIC_Init(2,0,EXTI1_IRQChannel,2);改为MY_NVIC_Init(2,0,EXTI1_IRQn,2);

3)因为横屏驱动,将touch.c文件下Drow_Touch_Point(u8 x,u16 y);改为Drow_Touch_Point(u16 x,u8 y);并且

修改相应的声明,Draw_Big_Point(u8 x,u16 y)函数同理,并且这两个函数的函数体可以改为使用uCGUI画,比如将LCD_DrawLine(x-12,y,x+13,y);//横线      

 改为LCD_L0_DrawHLine(x-12,y,x+13);//横线

4)因为没有移植ucosⅡ,不支持任务,需要靠GUI_TOUCH_Exec() 这个函数是定时刷新,驱动函数获取坐标值重绘窗口。即设置完窗口,并不会马上生效,必须重绘才能显示。

因此在定时器中断EXTI1_IRQHandler中加入GUI_TOUCH_Exec();实现坐标获取。

5)横屏显示,LCD坐标的系数及偏移需要重新设置,并且实际检测中,右上角触屏不灵敏,校准出现失败,因此将较准点改到屏幕中间部分在Touch_Adjust中

将屏幕上现实的四个点坐标改为  (50,50),(270,50),(50,190),(270,190)

并且将

Pen_Point.xfac=(float)200/(pos_temp[1][0]-pos_temp[0][0]);
Pen_Point.xoff=(240-Pen_Point.xfac*(pos_temp[1][0]+pos_temp[0][0]))/2;
Pen_Point.yfac=(float)280/(pos_temp[2][1]-pos_temp[0][1]);
Pen_Point.yoff=(320-Pen_Point.yfac*(pos_temp[2][1]+pos_temp[0][1]))/2;

 改为

Pen_Point.xfac=(float)220/(pos_temp[1][0]-pos_temp[0][0]);
Pen_Point.xoff=(320-Pen_Point.xfac*(pos_temp[1][0]+pos_temp[0][0]))/2;
Pen_Point.yfac=(float)140/(pos_temp[2][1]-pos_temp[0][1]);
Pen_Point.yoff=(240-Pen_Point.yfac*(pos_temp[2][1]+pos_temp[0][1]))/2;

6)在GUI_X_Touch.c改为如下程序:

#include "GUI.h"
#include "GUI_X.h"
#include "touch.h"

void GUI_TOUCH_X_ActivateX(void) {

}

void GUI_TOUCH_X_ActivateY(void) {
}
/***************************************

*******************************************/
int GUI_TOUCH_X_MeasureX(void) {

u16 x,y;
Read_ADS2(&x,&y);
return x;
}

int GUI_TOUCH_X_MeasureY(void) {
u16 x,y;
Read_ADS2(&x,&y);
return y;
}

7)main文件改为

#include "stm32f10x.h"
#include <stdio.h>
#include "delay.h"
#include "ILI93xx.h"
#include "gui.h"
#include "touch.h"
#include "24cxx.h"

//const unsigned char my_space[]="自定义汉字库";
/*************************************************
函数名称:  void RCC_Configuration(void)
函数功能: 复位及时钟配置
参数:无
返回:无

**************************************************/
void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus; 
RCC_DeInit(); 
RCC_HSEConfig(RCC_HSE_ON); 
HSEStartUpStatus = RCC_WaitForHSEStartUp(); 
if(HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2); 

RCC_HCLKConfig(RCC_SYSCLK_Div1); 
RCC_PCLK2Config(RCC_HCLK_Div1); 
RCC_PCLK1Config(RCC_HCLK_Div2);

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); 
RCC_PLLCmd(ENABLE); 

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) 
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource() != 0x08) 
{
}
}

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, ENABLE);  

}

/*************************************************

函数名称: void GPIO_Configuration(void)
函数功能:GPIO配置
参数:无
返回:无
**************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure; 


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP ;
GPIO_Init(GPIOE, &GPIO_InitStructure);
}

/*************************************************

函数名称: void GPIO_Configuration_key(void)
函数功能:按键配置
参数:无
返回:无
**************************************************/

void GPIO_Configuration_key(void)
{
GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;
GPIO_Init(GPIOD, &GPIO_InitStructure); /* PC6 */
}

void Load_Drow_Dialog(void)
{
LCD_Clear(WHITE);//清屏,白色  
GUI_SetFont(&GUI_FontHZ_My_Font);
GUI_SetColor(GUI_RED);
GUI_DispStringAt( "清除",0,0); //需要添加汉字字库
// POINT_COLOR=RED;//设置画笔颜色
}


/*************************************************
函数名称: int main(void)
函数功能: main主函数
参数:无
返回:无
**************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
delay_init(72);
GUI_Init();
Touch_Init();
delay_ms(1500);
Load_Drow_Dialog();

GPIO_Configuration_key();
while(1)
{
if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_7) == Bit_RESET)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_7) == Bit_RESET)
{
Touch_Adjust(); //屏幕校准
Save_Adjdata();
Load_Drow_Dialog();
}
while((GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_7) == Bit_RESET));
}
else if(Pen_Point.Key_Sta==Key_Down)//触摸屏被按下
{
Pen_Int_Set(0);//关中断
do
{
Convert_Pos();
Pen_Point.Key_Sta=Key_Up;
if(Pen_Point.X0<40&&Pen_Point.Y0<20)Load_Drow_Dialog();//清除
else
{
Draw_Big_Point(Pen_Point.X0,Pen_Point.Y0);//画图 
GPIOC->ODR|=1<<1; //pc1上拉   
}
}while(PEN==0);//若PEN一直有效,则一直执行
Pen_Int_Set(1);//开启中断
}else delay_ms(10);

}
}

7)编译下载,触摸屏能用了。

  后续会加入视窗管理及ucos Ⅱ,希望能给初学者参考。

原文地址:https://www.cnblogs.com/soloman/p/3959511.html