《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 设计应用 > 基于STM32F103C8T6单片机的LCD显示系统设计
基于STM32F103C8T6单片机的LCD显示系统设计
2014年微型机与应用第20期
杨 伟,肖义平
湖北工业大学 电气与电子工程学院,湖北 武汉 430068
摘要: 基于Keil for ARM集成开发环境,设计了一种以单片机STM32F103C8T6为核心的LCD12864液晶显示系统,可以在屏幕任意位置实现字符显示和图形显示,同时实现了贪吃蛇游戏的功能。该系统操作便捷,界面友好,具有功耗低、速度快、性价比高等优点。
Abstract:
Key words :

  摘  要: 基于Keil for ARM集成开发环境,设计了一种以单片机STM32F103C8T6为核心的LCD12864液晶显示系统,可以在屏幕任意位置实现字符显示和图形显示,同时实现了贪吃蛇游戏的功能。该系统操作便捷,界面友好,具有功耗低、速度快、性价比高等优点。

  关键词: STM32F103C8T6;LCD12864;贪吃蛇游戏

0 引言

  随着社会的不断发展,人们对终端显示器的要求越来越高,体积小、重量轻、功耗低、清晰度高的LCD显示器无疑成为大家心中理想的选择[1]。与传统的CRT相比,基于单片机的LCD显示系统具有硬件结构简单、控制方便、成本低等优点,在现代嵌入式系统中已得到广泛的运用。本文设计了一种基于单片机STM32F103C8T6和LCD12864的液晶显示系统,可以实现字符、图形的显示,并在此基础上设计了一个贪吃蛇游戏实例。

1 系统硬件设计

  LCD显示系统主要由单片机、LCD显示模块、电源模块、4×4矩阵键盘、通信接口电路组成。系统方框图如图1所示。

001.jpg

  系统电源部分可以使用5 V电源端口供电,再通过3.3 V稳压芯片ASM1117-3.3得到单片机与LCD显示模块所需电源。单片机采用ST公司的芯片STM32F103C8T6,4×4矩阵键盘作为系统的输入设备,采用LCD12864液晶显示模块作为系统的显示部分。单片机系统通过处理键盘输入数据后,根据不同的情况对显示屏发出不同的操作指令。通信接口电路主要是由芯片PL2303构成,它的功能主要是将电脑的USB接口转换为串口,同时还将PC的逻辑电平转换为与单片机系统相同的CMOS电平,方便程序的烧写以及与上位机的通信。

  1.1 Keil MDK和单片机STM32F103C8T6简介

  Keil MDK是德国Keil公司为基于Cortex-M、ARM7、ARM9等系列处理器提供的一款集成开发环境,支持程序的编辑、编译、链接以及在线调试等功能,可以自动配置启动代码,简单易学,性能优越,能满足大多数嵌入式应用[2]。

  STM32F103C8T6是一款基于ARM 32位的Cortext M3内核的单片机,2.0~3.6 V的宽电压供电范围,CPU工作频率最大可达72 MHz,具有单周期的乘法指令和硬件除法,以及优先级可编程的中断系统。同时它还具有64 KB的Flash存储器与20 KB的SRAM存储器,另外还集成了非常丰富的片内外设,如看门狗、定时器、GPIO口、DMA控制器、ADC、UART、SPI接口、IIC接口等,具有成本低、速度快、性价比高等优点。

  1.2 液晶LCD12864显示模块

  LCD12864液晶屏的数据接口是串行的,工作电压为2.8~5.5 V,像素为128×64,显示颜色为黑白色,背光颜色为蓝色,不带字库。模块内部采用的控制器为ST7565P,功耗非常低,在省电模式下的工作电流最大仅为5 A,显示模块仅有8个引脚接口,占用主控制器的I/O数量少。LCD12864引脚说明如表1所示。

004.jpg

  1.3 LCD12864与单片机STM32F103C8T6的硬件连接

  单片机STM32F103C8T6与LCD显示模块的硬件连接非常简单,如图2所示。LCD12864引脚编号为1~5的控制端口可以直接与STM32F103C8T6单片机的GPIO口相连,第8引脚是LCD的背光电源端口,通过单片机的一个I/O口控制三极管的导通来控制背光电源的通断,从而节省功耗[3]。

002.jpg

2 系统软件设计

  系统软件设计主要包括LCD初始化、写数据、写命令,以及画点、字符显示等程序设计。液晶显示模块正常工作前,需要对其进行初始化,主要包括复位液晶、确定显示对比度、偏压比等参数,然后才能实现字符、图形以及其他的显示功能。在向液晶显示模块写入数据或者命令时,一定要注意写入的时序,只有严格地按照时序编写驱动程序才能正常工作。设计程序时,为了方便移植,可以将相关引脚的操作用宏封装起来,如将片选引脚拉低的操作可以用宏LCD_CS_0()定义[4-5]。写数据命令的功能函数如下:

  void LCD12864_WriteCommand(uint8 Cmd)

  {……

  LCD_CS_0();//打开片选

  LCD_A0_0();//选择写命令

  LCD_SCLK_0();//时钟线置低

  for(i=0;i<8;i++){

  if(Cmd &0x80)//如果输出为1

  LCD_SI_1();//SI数据线输出为1

  else

  LCD_SI_0();//SI数据线输出为0

  LCD_SCLK_1();//写入数据

  Dat<<=1;

  LCD_SCLK_0();//置低SCLK时钟线

  } LCD_CS_1();//关闭片选

  }

  写数据功能函数void LCD12864_WriteData(uint8 Dat)实现方法与写命令功能函数相同,只是打开片选后,选择的是写数据LCD_A0_1()。

  在设计LCD液晶驱动程序时,最基本的功能就是在屏幕的任意位置显示一个点,然后在此基础上实现更复杂的功能。但是每次写入的数据都包含了8个点的信息,而且该LCD显示模块没有读控制端口,不能通过读数据的命令了解其他7个点的状态,这样就不能达到最终的目的。为了解决这个问题,可以在单片机的内存区开辟一个数据空间,来记录显示器上每个点的显示情况,代码如下:

  static uint8 LCD_RAM[128*8]={0};//开辟显示缓冲区

  void LCD12864_DrawPoint(uint8 x,uint8 y,uint8 Point_Flag)

  {

  if(Point_Flag==0)

  {LCD_RAM[x+128*(7-(y>>3))]&=(~(1<<(7-(y&0x07))));}

  if(Point_Flag==1)

  {LCD_RAM[x+128*(7-(y>>3))]|=(1<<(7-(y&0x07)));}LCD12864_WriteCommand(0xB0+(7-((y>>3)&0x0F)));//写页地址

  LCD12864_WriteCommand(0x10+((x>>4)&0x0F));

  //写列地址,高低字节两次写入

  LCD12864_WriteCommand(0x00+(x&0x0F));

  LCD12864_WriteData(LCD_RAM[x+128*(7-(y>>3))]);

  //写入数据

  }

  因为液晶模块未带字库,在字符显示前,需要将其字模存入单片机的程序存储空间中,然后在任意坐标显示一个点的基础上,实现字符的显示。8×16字符显示的驱动程序如下:

  void LCD12864_PutChar8x16(uint32 Char_x,uint32 Char_y,uint8 c)

  {……

  Temp=Font8x16[c*16+i];//获取字模

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

  {if(Temp&0x80)

  {LCD12864_DrawPoint(Char_x+j,Char_y-i,1);}

  else{LCD12864_DrawPoint(Char_x+j,Char_y-i,0);}

  Temp<<=1;}}}

3 实例设计

  以单片机STM32F103C8T6作为控制核心,在LCD12864驱动程序的基础上,实现了贪吃蛇游戏的功能。贪吃蛇游戏程序主要分为3个子程序模块,即键盘扫描模块、LCD12864驱动模块和贪吃蛇游戏数据处理模块。贪吃蛇程序流程图如图3所示。

003.jpg

  游戏中的食物和蛇可以看作两个不同的对象,它们的属性可以用两个结构体变量来描述,然后根据游戏功能将整个大模块合理地划分为各个子模块,并编写相应的功能函数,供主模块函数调用。在设计程序时,定义蛇的最长长度为15,蛇运动区域的长为20个单位,宽为15个单位,即横坐标的坐标范围为1~20,纵坐标的坐标范围为1~15。贪吃蛇游戏中定义了食物结构体和蛇结构体变量。食物结构体定义为:

  struct{uint8 X;uint8 Y;}Food;

  蛇体的最大长度宏定义为:

  #define SNAKE_LONG_MAX 15

  蛇结构体变量中定义了蛇体长度、蛇的等级和蛇的分数,具体定义为:

  struct{

  uint8 X[SNAKE_LONG_MAX_];

  uint8 Y[SNAKE_LONG_MAX];

  uint8 Long;

  uint8 Level;

  uint16 Score;}Snake;

  显示无符号整形数据功能函数定义为:

  void LCD12864_PutUintNumber(uint32 Num_x,uint32Num_y,uint32 Uint_Num,uint8 Num_N)

  显示或者熄灭一个蛇体单位功能函数定义为:

  void DiaplaySnakePoint(uint8 x,uint8 y,uint8 Point_Stu)

  判断蛇是否死亡的程序如下:

  if((Snake.X[0]<1)||(Snake.X[0]>20)||(Snake.Y[0]<1)||(Snake.Y[0]>15))

  {Game_Fail();}

  for(i=4;i<Snake.Long;i++){if((Snake.X[0]==Snake.X[i])&&(Snake.Y[0]==Snake.Y[i])){Game_Fail();}}

  判断蛇是否吃到食物程序如下:

  if((Snake.X[0]==Food.X)&&(Snake.Y[0]==Food.Y))

  {Snake.Long++;//蛇身长度加1

  Snake.Score+=10;//得分数增加

  LCD12864_PutUintNumber(96,63-48,Snake.Score,4);

  //屏幕上更新分数

  Snake.X[Snake.Long-1]=Snake_End_x;

  Snake.Y[Snake.Long-1]=Snake_End_y;

  DiaplaySnakePoint(Snake_End_x,Snake_End_y,1);

  //蛇体向后增长1个单位

  Put_Food();//放置食物

  }Delayms(3000-300*Snake.Level);//根据蛇体等级延时

  在贪吃蛇游戏的程序设计中,放置食物的程序会涉及如何获取随机数的问题,为了增加游戏的随机性,本次设计不采用伪随机数产生的方法,而是利用单片机的AD采样引脚在悬空的情况下采样,获得的AD值作为随机种子,然后通过一系列的运算来得到随机数,经过实践得知,此种方式得到的随机数更真实,效果很好。食物放置程序如下:

  void Put_Food(void){…..

  AD_Temp=ADC_ConvertedValue;//获取随机种子

  Food.X=(AD_Temp%20)+1;

  //随机获取食物横坐标(1~20)

  Food.Y=(AD_Temp%15)+1;

  //随机获取食物纵坐标(1~15)

  ……

  DiaplaySnakePoint(Food.X,Food.Y,1);//显示食物

  }

4 结论

  STM32F103C8T6是一款高性能的单片机,LCD12864硬件接口简单,所占用单片机的I/O口资源非常少,单片机有足够的硬件资源供其他外设使用,显示系统可以作为其他嵌入式系统的一部分,运用于不同的显示场合;系统的程序设计采用的是C语言,其移植性非常好,模块化的设计思想可以在系统中灵活地扩展其他功能,满足不同的显示要求。

参考文献

  [1] 刘金星,李洪文.基于高速单片机的液晶显示模块控制[J].液晶与显示,2011,26(1):88-91.

  [2] 韩敬海,王蕊.Cortext-M3开发技术与实现[M].西安:西安电子科技大学出版社,2013.

  [3] 陈杨杨,陈梅.基于PIC18F458单片机的LCD显示[J].仪表技术,2005(4):52-53.

  [4] 武俊鹏,张国印,姚爱红,等.基于ARM的嵌入式系统设计实验与实践教程[M].北京:清华大学出版社,2011.

  [5] 石红晓,吴光敏.基于Nios II处理器的TFT-LCD图形显示设计[J].微型机与应用,2010,29(18):37-39.


此内容为AET网站原创,未经授权禁止转载。