實驗板子 ——李想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 Ⅱ,希望能給初學者參考。