STM32学习笔记——TFT2.4彩屏显示字符和汉字

本文转自:http://blog.sina.com.cn/s/blog_6cd2030b01019ovi.html

STM32学习笔记——TFT2.4彩屏显示字符和汉字  

 

利用彩屏显示汉字、字符和字符串,需要先完成彩屏的驱动程序,然后在驱动程序的基础上再编写应用程序。

 

彩屏的驱动程序如果写好的话,就可以一直使用了,精力主要集中在应用程序的编写就可以了,但是移植的话,要移植驱动程序。其实移植也只是改变那些很底层的靠近处理器的那部分代码。

 

代码如下,注释比较详细,看懂了基本就可以了。

 

驱动程序的头文件LCD_driver.h如下:

 

 

 

#define uchar unsigned char

#define uint unsigned int

 

 

 

#define Bus_16        //16位数据模式,如果使用8位模式,请注释此语句,如果使用16位模式,请打开此句

#define  LCD_DataPortH P1     //8位数据口,8位模式下只使用高8位 

#define  LCD_DataPortL P0     //8位数据口,8位模式下低8位可以不接线

 

 

 

#define LCD_WR    GPIO_Pin_2 //WR  引脚定义 P2^5

#define LCD_RS    GPIO_Pin_1 //RS  引脚定义 P2^6

#define LCD_CS    GPIO_Pin_0 //CS  引脚定义 P2^7

#define LCD_RST   GPIO_Pin_11     //RST 引脚定义 P3^3

#define LCD_RD    GPIO_Pin_8 //RD  引脚定义 P3^2

 

 

#define  LCD_SIZE_X240 //彩屏的分辨率为240*320

#define  LCD_SIZE_Y320

 

extern  uint colors[];

 

void LCD_Init(void); //LCD初始化函数

void LCD_ShowString(uint x,uint y,uint For_color,uint Bk_color,char *p);//写字符串函数

void LCD_ShowChar(uint x,uint y,uint For_color,uint Bk_color, char ch);//写字符函数

void ChineseChar(uint x,uint y,int size,uint For_color,uint Bk_color ,char c); //写汉字函数

void delayms(int count) ;

//void LCD_Writ_Bus(char VH,char VL);//8位模式下的总线写函数

void LCD_Writ_Bus( uint VH, uint VL);  //16位模式下的总线写函数

void LCD_Write_COM(char VH,char VL);   //写命令函数

void LCD_Write_DATA(char VH,char VL);  //写数据函数

void Pant(char VH,char VL);  //涂满彩屏函数

void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2);  //设置地址范围函数

 

 

驱动程序Lcd.c文件如下:

 

 

 

#include "stm32f10x_lib.h"

#include"LCD_driver.h"

#include"chinese.h"

#include"char.h"

 

 

 

#define    LCD_rest(x) GPIO_SetBits(GPIOA, LCD_RST):   GPIO_ResetBits(GPIOA, LCD_RST) //自己定义位操作函数

#define    LCD_rd(x)   GPIO_SetBits(GPIOA, LCD_RD)   GPIO_ResetBits(GPIOA, LCD_RD)

#define    LCD_rs(x)   GPIO_SetBits(GPIOB, LCD_RS)   GPIO_ResetBits(GPIOB, LCD_RS)

#define    LCD_wr(x)   GPIO_SetBits(GPIOB, LCD_WR)   GPIO_ResetBits(GPIOB, LCD_WR)

#define    LCD_cs(x)   GPIO_SetBits(GPIOB, LCD_CS)   GPIO_ResetBits(GPIOB, LCD_CS)

 

 

uint colors[]=

{

  0xf800,0x07e0,0x001f,0xffe0,0x0000,0x07ff,0xf81f,0xffff  //颜色数据  16位的

};

 

 

 

 

void LCD_Init(void)     //lcd初始化

{

 

    LCD_rest(1);

    delayms(5);

LCD_rest(0);

delayms(5);

LCD_rest(1);

delayms(5);

 

LCD_cs(0);  //打开片选使能

//

LCD_Write_COM(0x00,0xE5); LCD_Write_DATA(0x78,0xF0); // set SRAM internal timing

LCD_Write_COM(0x00,0x01); LCD_Write_DATA(0x01,0x00); // set SS and SM bit

LCD_Write_COM(0x00,0x02); LCD_Write_DATA(0x07,0x00); // set line inversion

LCD_Write_COM(0x00,0x03); LCD_Write_DATA(0x10,0x30); // set GRAM write direction and BGR=1.

LCD_Write_COM(0x00,0x04); LCD_Write_DATA(0x00,0x00); // Resize register

LCD_Write_COM(0x00,0x08); LCD_Write_DATA(0x02,0x07); // set the back porch and front porch

LCD_Write_COM(0x00,0x09); LCD_Write_DATA(0x00,0x00); // set non-display area refresh cycle ISC[3:0]

LCD_Write_COM(0x00,0x0A); LCD_Write_DATA(0x00,0x00); // FMARK function

LCD_Write_COM(0x00,0x0C); LCD_Write_DATA(0x00,0x00); // RGB interface setting

LCD_Write_COM(0x00,0x0D); LCD_Write_DATA(0x00,0x00); // Frame marker Position

LCD_Write_COM(0x00,0x0F); LCD_Write_DATA(0x00,0x00); // RGB interface polarity

//

LCD_Write_COM(0x00,0x10); LCD_Write_DATA(0x00,0x00); // SAP, BT[3:0], AP, DSTB, SLP, STB

LCD_Write_COM(0x00,0x11); LCD_Write_DATA(0x00,0x07); // DC1[2:0], DC0[2:0], VC[2:0]

LCD_Write_COM(0x00,0x12); LCD_Write_DATA(0x00,0x00); // VREG1OUT voltage

LCD_Write_COM(0x00,0x13); LCD_Write_DATA(0x00,0x00); // VDV[4:0] for VCOM amplitude

LCD_Write_COM(0x00,0x07); LCD_Write_DATA(0x00,0x01);

delayms(50); // Dis-charge capacitor power voltage

LCD_Write_COM(0x00,0x10); LCD_Write_DATA(0x10,0x90); // 1490//SAP, BT[3:0], AP, DSTB, SLP, STB

LCD_Write_COM(0x00,0x11); LCD_Write_DATA(0x02,0x27); // DC1[2:0], DC0[2:0], VC[2:0]

delayms(50); // Delay 50ms

LCD_Write_COM(0x00,0x12); LCD_Write_DATA(0x00,0x1F); //001C// Internal reference voltage= Vci;

delayms(50); // Delay 50ms

LCD_Write_COM(0x00,0x13); LCD_Write_DATA(0x15,0x00); //0x1000//1400   Set VDV[4:0] for VCOM amplitude  1A00

LCD_Write_COM(0x00,0x29); LCD_Write_DATA(0x00,0x27); //0x0012 //001a  Set VCM[5:0] for VCOMH  //0x0025  0034

LCD_Write_COM(0x00,0x2B); LCD_Write_DATA(0x00,0x0D); // Set Frame Rate   000C

delayms(50); // Delay 50ms

LCD_Write_COM(0x00,0x20); LCD_Write_DATA(0x00,0x00); // GRAM horizontal Address

LCD_Write_COM(0x00,0x21); LCD_Write_DATA(0x00,0x00); // GRAM Vertical Address

// ----------- Adjust the Gamma Curve ----------//

LCD_Write_COM(0x00,0x30); LCD_Write_DATA(0x00,0x00);

LCD_Write_COM(0x00,0x31); LCD_Write_DATA(0x07,0x07);

LCD_Write_COM(0x00,0x32); LCD_Write_DATA(0x03,0x07);

LCD_Write_COM(0x00,0x35); LCD_Write_DATA(0x02,0x00);

LCD_Write_COM(0x00,0x36); LCD_Write_DATA(0x00,0x08);//0207

LCD_Write_COM(0x00,0x37); LCD_Write_DATA(0x00,0x04);//0306

LCD_Write_COM(0x00,0x38); LCD_Write_DATA(0x00,0x00);//0102

LCD_Write_COM(0x00,0x39); LCD_Write_DATA(0x07,0x07);//0707

LCD_Write_COM(0x00,0x3C); LCD_Write_DATA(0x00,0x02);//0702

LCD_Write_COM(0x00,0x3D); LCD_Write_DATA(0x1D,0x04);//1604

 

//------------------ Set GRAM area ---------------//

LCD_Write_COM(0x00,0x50); LCD_Write_DATA(0x00,0x00); // Horizontal GRAM Start Address

LCD_Write_COM(0x00,0x51); LCD_Write_DATA(0x00,0xEF); // Horizontal GRAM End Address

LCD_Write_COM(0x00,0x52); LCD_Write_DATA(0x00,0x00); // Vertical GRAM Start Address

LCD_Write_COM(0x00,0x53); LCD_Write_DATA(0x01,0x3F); // Vertical GRAM Start Address

LCD_Write_COM(0x00,0x60); LCD_Write_DATA(0xA7,0x00); // Gate Scan Line

LCD_Write_COM(0x00,0x61); LCD_Write_DATA(0x00,0x01); // NDL,VLE, REV

LCD_Write_COM(0x00,0x6A); LCD_Write_DATA(0x00,0x00); // set scrolling line

//-------------- Partial Display Control ---------//

LCD_Write_COM(0x00,0x80); LCD_Write_DATA(0x00,0x00);

LCD_Write_COM(0x00,0x81); LCD_Write_DATA(0x00,0x00);

LCD_Write_COM(0x00,0x82); LCD_Write_DATA(0x00,0x00);

LCD_Write_COM(0x00,0x83); LCD_Write_DATA(0x00,0x00);

LCD_Write_COM(0x00,0x84); LCD_Write_DATA(0x00,0x00);

LCD_Write_COM(0x00,0x85); LCD_Write_DATA(0x00,0x00);

//-------------- Panel Control -------------------//

LCD_Write_COM(0x00,0x90); LCD_Write_DATA(0x00,0x10);

LCD_Write_COM(0x00,0x92); LCD_Write_DATA(0x06,0x00);

LCD_Write_COM(0x00,0x07); LCD_Write_DATA(0x01,0x33); // 262K color and display ON

 

LCD_cs(1);  //关闭片选使能

 

 

 

 

 

 

void delayms(int count)  // 

{

        int i,j;

        for(i=0;i<count;i++)

                for(j=0;j<100;j++);

}

 

#ifdef  Bus_16    //条件编译-16位数据模式 

 

//并行写入数据把数据分为高8VH和低8VL  

void LCD_Writ_Bus(uint VH uint VL)   //并行数据写入函数

{

  //LCD_DataPortH=VH;   //高位P1

//屏蔽高8 将数据送到PA0-PA7

GPIOA->BSRR VH 0x00ff;   

    GPIOA->BRR  (~VH) 0x00ff;

   //GPIO_SetBits(GPIOA,  VH 0x00ff);

   //GPIO_ResetBits(GPIOA, (~ VH 0x00ff));

 

    //LCD_DataPortL=VL;  //低位P0

//屏蔽低8 将数据送到PB8-PB15

GPIOB->BSRR (VL)<<8 0xff00;   

    GPIOB->BRR  ((~VL)<<8) 0xff00;

 

LCD_wr(0);

LCD_wr(1);

}

#else //条件编译-8位数据模式 

void LCD_Writ_Bus(char VH,char VL)   //并行数据写入函数

{

     //LCD_DataPortH=VH;  //八位模式都用P0口送数据

     //LCD_wr(0);

//LCD_wr(1);

//LCD_DataPortH=VL; //八位模式都用P0口送数据

//LCD_wr(0);

//LCD_wr(1);

}

#endif

 

 

//参数VHVL分别为要写入命令的高8位和低8

void LCD_Write_COM(char VH,char VL) //发送命令

{

    LCD_rs(0);

LCD_Writ_Bus(VH,VL);

}

 

//参数VHVL分别为要写入数据的高8位和低8

void LCD_Write_DATA(char VH,char VL)//发送数据

{

    LCD_rs(1);

LCD_Writ_Bus(VH,VL);

}

 

 

void Pant(char VH,char VL)     //涂满全屏函数

{

int i,j;

 

LCD_cs(0);  //打开片选使能

 

Address_set(0,0,239,319); //设置地址范围为全屏

 

    for(i=0;i<320;i++)

 {

  for (j=0;j<240;j++)

   {

         LCD_Write_DATA(VH,VL);

    }

 

  }

     LCD_cs(1);  //关闭片选使能

}

 

 

void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)  //设置地址范围函数

{

LCD_Write_COM(0x00,0x20);LCD_Write_DATA(x1>>8,x1);  //设置X坐标位置

    LCD_Write_COM(0x00,0x21);LCD_Write_DATA(y1>>8,y1);    //设置Y坐标位置

 

    LCD_Write_COM(0x00,0x50);LCD_Write_DATA(x1>>8,x1);   //开始X

LCD_Write_COM(0x00,0x52);LCD_Write_DATA(y1>>8,y1);  //开始Y

    LCD_Write_COM(0x00,0x51);LCD_Write_DATA(x2>>8,x2);   //结束X

LCD_Write_COM(0x00,0x53);LCD_Write_DATA(y2>>8,y2);   //结束Y

 

    LCD_Write_COM(0x00,0x22); 

}

 

 

 

void ChineseChar(uint x,uint y,int size,uint For_color,uint Bk_color ,char c)

{

   int e=0,i,j;

   int  ed;

   

   uint  ncols;

   uint  nrows;

   uint  nbytes;

 

   uchar *pfont;   //指向指定大小的汉字数据存储的数组的指针

   uchar *pchar;   //指向指定数组中指定要显示的汉字的数据的指针

   uchar *fonttable[]={(uchar *)hz16,(uchar *)hz24 (uchar *)hz32};     //汉字的三种大小,16位,24位,32

   //其中hz16hz24hz32为三个数组,分别存储宋体12,宋体18和宋体24的汉字的数据 

   //每个数组中的数据可能包含相同大小字体的多个汉字  

 

   pfont=(uchar *)fonttable[size]; //指向指定大小的汉字的数组

 

   if(size==0)

   {

     ncols =16-1;

     nrows =16-1;

     nbytes =32; //每个字取模的字节数=(16*16)/8

   }

   else

   if(size==1)

   {

     ncols =24-1;

     nrows =24-1;

     nbytes =72;  //每个字取模的字节数=(24*24)/8

   }

   else

   if(size==2)

   {

     ncols =32-1;

     nrows =32-1;

     nbytes =132;   //每个字取模的字节数=(32*32)/8

   }

   

   pchar=pfont (nbytes*(c-1)); //指定要显示指定数组中的第c个汉字

   //每个数组中的数据可能包含相同大小字体的多个汉字

 

   Address_set(x,  y, x+nrows,y+ncols); //设置汉字显示的范围

   

   for(i=0;i<nbytes;i++)   //每个汉字含有nbytes个字节,所以要循环nbytes

   {

     ed=*pchar++;  //ed取出指定要显示的字节的数据

 if(size==0)  //???

 {

       if(i%2==0) //???

        e=8;

       else

        e=4;  //???

 }

 else

 e=8;

     

     for(j=0;j<e;j++)

     {

  if((ed>>j)&0x01)   //判断是汉字还是背景,然后分别写入不同的颜色

      

       

   LCD_Write_DATA(For_color>>8 For_color  );  //textcolor

  }

     else

     {

       LCD_Write_DATA( Bk_color>>8  Bk_color);  //backcolor

 }

}

  }

}

 

 

 

 

void LCD_ShowChar(uint x,uint y,uint For_color,uint Bk_color, char ch)

      

   uchar temp Bytes;

   uchar pos,t;

   uint  CHAR_W,CHAR_H; //一个字符的大小

 

   

   //CHAR_W 8;         //8*16

   //CHAR_H 16;

 

     CHAR_W 16;         //16*24  字符的大小为16*24

     CHAR_H 24;

 

   if(x>(LCD_SIZE_X-CHAR_W)||y>(LCD_SIZE_Y-CHAR_H))  //如果指定的字符显示的位置超过了彩屏的分辨率,则返回

   return;

   

   Address_set(x, y, x+CHAR_W-1, y+CHAR_H-1); //设置字符显示的地址范围

   ch ch-32;                       //按照ASCII编码顺序得到相应字母的编码

  

   Bytes (CHAR_W*CHAR_H)/8; //每个字母取模字节数  一个字节为8位,也即是8个像素点是一个字节

   for(pos=0;pos<Bytes;pos++) //一个字节一个字节的写入,知道这个字符的全部字节数写完

   {

     // temp= Font8x16[ch][pos];  //8*16的字体

 

  temp= Font16x24[ch][pos]; //字体的大小为16*24

      

      for(t=0;t<8;t++)  //一个字节为8位,所以要循环8次写入,一次只能写入一个像素点

           

     //判断哪里是显示字符的地方,哪里是背景,然后分别写入不同的颜色就可以了           

    if(temp&0x80)  //如果是显示字符的地方

      LCD_Write_DATA(For_color>>8 For_color  );  //textcolor

    else  //否则就是背景的地方

      LCD_Write_DATA(Bk_color>>8 Bk_color );  //backcolor

        temp<<=1;  //右移一位

      }

  

   }

 

 

 

void LCD_ShowString(uint x,uint y,uint For_color,uint Bk_color,char *p)

        

   while(*p!='\0')//判断是否到了字符串尾

         

     LCD_ShowChar(x,y,For_color,Bk_color,*p);

    // x+=8;   //8是字体的宽度

 x+=16;   //16是字体的宽度

     p++; //指针后移一位

   }

}

 

 

 

主程序main.c

在主程序中完成对系统的初始化配置,利用彩屏的驱动程序完成相应的显示等功能,程序如下:

 

 

 

 

#include "stm32f10x_lib.h"

#include "LCD_driver.h"

 

 

#define    LCD_cs(x)   GPIO_SetBits(GPIOB, LCD_CS)   GPIO_ResetBits(GPIOB, LCD_CS)//自己定义的位函数  CS位的操作

//打开或关闭片选使能 LCD_cs(0);  //打开片选使能     LCD_cs(1);  //关闭片选使能

 

 

 

GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化的结构体变量

ErrorStatus HSEStartUpStatus;   //定义错误状态变量,是枚举类型

 

 

void RCC_Configuration(void);

void NVIC_Configuration(void);

void Delay(vu32 nCount);

 

 

 

int main(void)

{

#ifdef DEBUG

  debug();

#endif

 

   RCC_Configuration();      //系统时钟配置函数   

 

   NVIC_Configuration();     //NVIC配置函数

 

    //启动GPIO模块时钟 使能APB2

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA RCC_APB2Periph_GPIOB RCC_APB2Periph_AFIO, ENABLE);

 

    //把调试设置普通IO口  禁止SWJ

  GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);  

                            

  GPIO_InitStructure.GPIO_Pin GPIO_Pin_All; //所有GPIO为同一类型端口  选中所有的IO

  GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //推挽输出

  GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //输出的最大频率为50HZ

  GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA端口

  GPIO_Init(GPIOB, &GPIO_InitStructure);   //初始化GPIOB端口

 

   GPIO_Write(GPIOA,0xffff);  //GPIOA 16个端口全部置为高电平

   GPIO_Write(GPIOB,0xffff);  //GPIOB 16个端口全部置为高电平

 

   LCD_Init(); //彩屏初始化

   Pant(colors[5]>>8 colors[5] );   //把全屏涂成color[5]颜色

 

   LCD_cs(0);  //打开片选使能

 

   //下面是要显示的内容

 

   ChineseChar(14+46,10,2,colors[2],colors[7],1);

   ChineseChar(46+46,10,2,colors[2],colors[7],2);

   ChineseChar(78+46,10,2,colors[2],colors[7],3);

   ChineseChar(110+46,10,2,colors[2],colors[7],4);

 

   LCD_ShowString(12,60,colors[0],colors[7],"-");

 

   ChineseChar(20,60,1,colors[0],colors[7],1);//

   ChineseChar(44,60,1,colors[0],colors[7],2);//

   ChineseChar(68,60,1,colors[0],colors[7],3);//

   ChineseChar(92,60,1,colors[0],colors[7],4);//

   ChineseChar(116,60,1,colors[0],colors[7],5);//

   ChineseChar(140,60,1,colors[0],colors[7],6);//

   ChineseChar(164,60,1,colors[0],colors[7],7);//

   ChineseChar(188,60,1,colors[0],colors[7],8);//

   ChineseChar(212,60,1,colors[0],colors[7],9);//界 

  

    ChineseChar(0,120,1,colors[4],colors[7],10);//

ChineseChar(24,120,1,colors[4],colors[7],11); //

ChineseChar(48,120,1,colors[6],colors[7],12); //

ChineseChar(72,120,1,colors[6],colors[7],13); //

ChineseChar(96,120,1,colors[2],colors[7],14); //

ChineseChar(120,120,1,colors[2],colors[7],15); //

// LCD_ShowString(92,120,colors[4],colors[7],":");

       

    LCD_ShowString(0,240,colors[2],colors[7],"abcdefJhiJKLMNOP"); 

    LCD_ShowString(0,265,colors[2],colors[7],"pqrstuvwxyz!@#$"); 

    LCD_ShowString(0,290,colors[2],colors[7],"<>CDEF^&*()/,[]"); 

 

   LCD_cs(1);//关闭片选使能

 

   while(1);

    

}

 

 

 

void RCC_Configuration(void)

  

 //复位RCC外部设备寄存器到默认值

  RCC_DeInit();

 

  //打开外部高速晶振

  RCC_HSEConfig(RCC_HSE_ON);

 

   //等待外部高速时钟准备好

  HSEStartUpStatus RCC_WaitForHSEStartUp();

 

  if(HSEStartUpStatus == SUCCESS)   //外部高速时钟已经准别好

  {     

    //开启FLASH的预取功能

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

 

    //FLASH延迟2个周期

    FLASH_SetLatency(FLASH_Latency_2);

 

  //配置AHB(HCLK)时钟=SYSCLK

    RCC_HCLKConfig(RCC_SYSCLK_Div1);  

  

   //配置APB2(PCLK2)=AHB时钟

    RCC_PCLK2Config(RCC_HCLK_Div1); 

 

    //配置APB1(PCLK1)=AHB 1/2时钟

    RCC_PCLK1Config(RCC_HCLK_Div2);

 

     //配置PLL时钟 == 外部高速晶体时钟*9  PLLCLK 8MHz 72 MHz 

    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

 

    //使能PLL时钟

    RCC_PLLCmd(ENABLE);

 

   //等待PLL时钟就绪

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

    {

    }

 

  //配置系统时钟 PLL时钟

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

 

   //检查PLL时钟是否作为系统时钟

    while(RCC_GetSYSCLKSource() != 0x08)

    {

    }

  }

}

 

 

void NVIC_Configuration(void)

{

#ifdef  VECT_TAB_RAM  

   

  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 

#else  

   

  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   

#endif

}

 

 

void Delay(vu32 nCount)

{

  for(; nCount != 0; nCount--);

}

 

 

 

#ifdef  DEBUG

 

void assert_failed(u8* file, u32 line)

  

 

  

  while (1)

  {

  }

}

#endif

 

存储字符、字符串和汉字的头文件没有贴上。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值