首页 > 其他 > 详细

单片机控制2004A液晶屏之模块化编程

时间:2014-02-27 22:12:09      阅读:648      评论:0      收藏:0      [点我收藏+]

学习单片机已经有一段时间了,但是很多程序都缺少模块化的思想,之前以为只要把单个的功能封装在一个函数里面就是模块化,经过了十多天实习,才真正开始有了模块化的编程思想,这里将我编写的STC12C5A60S2单片机控制2004A液晶屏的程序共享一下,一是希望没有模块化编程思想的后来者看看,二是希望前辈们给予斧正。

(补充:以下代码只需要修改.h文件中含有 “选择” 字样的部分,就可以达到复用的效果,只需要注意中文注释部分)

(提示:因为其中的宏较多,建议source insight查看代码)

 

(图片有点大,在网页可能无法全部显示,可以右键选择在新标签页中查看,就可以在新网页看到全部图片)

bubuko.com,布布扣

/*################lcd2004.h start################*/

#ifndef __LCD2004_H__
#define __LCD2004_H__

#include <reg52.h>
#include "common.h"

sbit lcd2004_rs_bit = P2^6;/*根据硬件连接选择*/
sbit lcd2004_rw_bit = P2^5;/*根据硬件连接选择*/
sbit lcd2004_en_bit = P2^7;/*根据硬件连接选择*/

#define LCD2004_DATA_PORT	P0/*根据硬件连接选择*/
/*default type:  
px^0---DB0(LSB)  
px^1---DB1  
px^2---DB2  
px^3---DB3  
px^4---DB4  
px^5---DB5  
px^6---DB6  
px^7---DB7(MSB)  
*/

/*  
    RS          Rw  
    0           0   ---->write command to lcd2004    
    0           1   ---->read  lcd2004‘s  status  
    1           0   ---->write data to lcd2004  
    1           1   ---->read  lcd2004‘s data   
          
*/ 

//lcd2004_rw_bit  select
#define LCD2004_READ_OPERATION		HIGH_LEVEL
#define LCD2004_WRITE_OPERATION		LOW_LEVEL

//lcd2004_rs_bit select
#define LCD2004_DATA_OPERATION		HIGH_LEVEL
#define LCD2004_COMMAND_OPERATION	LOW_LEVEL

//lcd2004_en_bit  select
#define LCD2004_ENABLE	HIGH_LEVEL
#define LCD2004_DISABLE	LOW_LEVEL

  

/*display:16(column)x2(row),5x7 lattice,8bit data interface*/	
#define LCD2004_DEFAULT_DISPALY_MODE	0x38

/*
====================================================
lcd diaplay on/off and cursor display on/off configure
====================================================
/*  
0   0   0   0   1   D   C   B     
                    |   |   |------cursor blink  : 1-->enable ; 0-->disalbe  
                    |   |----------cursor display: 1-->enable ; 0-->disable  
                    |-------------lcd2004 dispaly: 1-->enable ; 0-->disalbe   
      
*/
#define LCD2004_DISPLAY_ENABLE			0X04
#define LCD2004_CURSOR_DISPLAY_ENABLE	0X02
#define LCD2004_CURSOR_BLINK_ENABLE 	0X01

#define LCD2004_DISPLAY_DISABLE			(0X04 & (~(0x01<<2)))
#define LCD2004_CURSOR_DISPLAY_DISABLE	(0X02 & (~(0x01<<1)))
#define LCD2004_CURSOR_BLINK_DISABLE 	(0X01 & (~(0x01<<0)))

/*默认:lcd显示,光标显示,光标闪烁*/			/*根据实际需要选择*/
#define LCD2004_DEFAULT_DISPLAY_AND_CURSOR_MODE 0x08 				 | 										LCD2004_DISPLAY_ENABLE		 | 										LCD2004_CURSOR_DISPLAY_ENABLE| 										LCD2004_CURSOR_BLINK_ENABLE

/*
====================================================
point and cursor address  configure
==================================================== 
0   0   0   0   0   1   N   S  
                        |   |-----  screen move:1-->enable ; 0-->disable 
                        |---------  N=1:读或者写一个字符后地址指针加1,且光标加1  
                                    N=0:度或者写一个字符后地址指针减1,且光标减1  


                        当S=1时 :  
                            若N=1,整屏幕左移  
                              N=0,整屏幕右移   

                            以达到光标不移动,而整个屏幕移动的效果  
*/   	 	
									
#define LCD2004_POINT_AND_CURSOR_PLUS		0X02
#define LCD2004_SCREEN_MOVE_ENABLE			0x01

#define LCD2004_POINT_AND_CURSOR_MINUS		(0X02 & (~(0X01<<1)))
#define LCD2004_SCREEN_MOVE_DISABLE			(0x01 & (~(0X01<<0)))

/*默认:光标和指针加一,屏幕不移动*/			/*根据实际需要选择*/
#define LCD2004_DEFAULT_POINT_AND_POINT_ADDRESS_MODE 0X04				 | 											LCD2004_POINT_AND_CURSOR_PLUS| 											LCD2004_SCREEN_MOVE_DISABLE




#define LCD2004_ROW0	0
#define LCD2004_ROW1	1
#define LCD2004_ROW2	2
#define LCD2004_ROW3	3
#define LCD2004_MIN_ROW LCD2004_ROW0
#define LCD2440_MAX_ROW	LCD2004_ROW3


#define LCD2004_ROW_LENGHT	0X14 //20

#define LCD2004_ROW0_ADDRESS_START (0X80)
#define LCD2004_ROW1_ADDRESS_START (0X80+0X40)
#define LCD2004_ROW2_ADDRESS_START (LCD2004_ROW0_ADDRESS_START+LCD2004_ROW_LENGHT)
#define LCD2004_ROW3_ADDRESS_START (LCD2004_ROW1_ADDRESS_START+LCD2004_ROW_LENGHT)

//instruction:
#define LCD2004_CLEAN_ALL_DISPALY			0x01/*清屏*/
#define LCD2004_CURSOR_RETURN_TO_ORIGIN		0x02/*光标归位*/



//写命令
extern void lcd2004WriteCommand(UB8 commandCode);

//写数据
extern void lcd2004WriteData(UB8 dataCode);

//lcd20041清屏
extern void lcd2004CleanAll(void) ;

//光标归位
extern void lcd2004CursorHoming(void);

//lcd2004初始化
extern void lcd2004Init(void) ;

//lcd2004地址写字节
extern void lcd2004AddressWriteByte(UB8 row,UB8 column,UB8 dataCode) ;

//lcd2004地址写字符串
extern void lcd2004AddressWriteString(UB8 row,UB8 column,UB8 *stringCode);

#endif	/*__LCD2004_H__*/


 

/*################lcd2004.h end################*/

 

/*################lcd2004.c start################*/

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

							申明
							
	经过测试J204A(也称2004A,每行20字符,显示4行)液晶屏和1602液晶屏的
	使用方法几乎是一样的,不过也是有区别的,在1602液晶屏中,用来寄存待显
	示字符代码的DDRAM共有80个字节,而J204A能够一次性显示的字符是80字
	节,这里不是巧合,即J204A只是将LCD1602的DDRAM的80个自己全部显示出
	来而已。
	
	第一行首地址	:0x80
	第二行首地址	:0x80+0x40
	第三行首地址	:0x80+20
	第四行首地址	:0x80+0x40+20

	可以注意到,第一行和第三行、第二行和第四行的地址是分别连续的。 经过
	实验验证,可以得出这样的结论:J204A是将LCD1602的DDRAM的0x00~0x13地址
	的数据映射显示在J204A的第一行,LCD1602的DDRAM的0x14~0x27地址的数据映
	射显示在第三行 ; LCD1602的DDRAM的0x40~0x53地址的数据映射显示在J204A
	的第二行,将LCD1602的DDRAM的0x54~0x67地址的数据映射显示在J204A的第四行。
	
----------------------------------------------------------------------------
	J204A的程序和LCD1602的程序很相似,这里的程序是由LCD1602程序修改而来。
----------------------------------------------------------------------------

	
***************************************************************************/
/***************************************************************************
Module	:lcd2004.c  

Purpose	:Implementation of lcd2004  module.

Version	:0.01							2014/02/13 12:00(OK)

Complier:Keil 8051 C complier V9.01

MCU		:STC12C5A60S2


Author	:yangrui

Email	:yangrui90s@163.com


Modification:
=================
	2014/02/24 23:44
	Reson:
		1.Add function lcd2004AddressWriteString(...)
=================

=================
	2014/02/24 15:00
	Reason:
		1.Add Function delay1msForLcd2004()
		  STC12C5A60S2单片机操作速度快比传统8051快,某些操作延时必须足够。
=================


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

#include <reg52.h>
#include <intrins.h>
#include <string.h>
#include "lcd2004.h"

/******************************************************
Function	:delay1msForLcd2004
Input		:N/A
Output		:N/A
Return		:N/A
Description	:N/A
Note		:crystal frequency is 12MHZ
******************************************************/
static void delay1msForLcd2004(void)
{
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 12;
	j = 168;
	do
	{
		while (--j);
	} while (--i);	
}

/******************************************************
Function	:lcd2004ReadStatus
Input		:N/A
Output		:N/A
Return		:lcd2004 status value
Description	:N/A
Note		:N/A
******************************************************/
static UB8 lcd2004ReadStatus(void)
{
	UB8 statusCode ;

	lcd2004_en_bit = LCD2004_DISABLE ;
	
	lcd2004_rs_bit = LCD2004_COMMAND_OPERATION ;
	lcd2004_rw_bit = LCD2004_READ_OPERATION ;

	LCD2004_DATA_PORT = 0xff ;
	delay1msForLcd2004() ;
	lcd2004_en_bit = LCD2004_ENABLE ;
	delay1msForLcd2004() ;
	statusCode = LCD2004_DATA_PORT ;
	
	lcd2004_en_bit = LCD2004_DISABLE ;

	return statusCode ;
}

/******************************************************
Function	:lcd2004CheckBusy
Input		:N/A
Output		:N/A
Return		:N/A
Description	:check lcd2004 busy or free,if busy,wait !
Note		:when LCD2004_DATA_PORT[7]==1,lcd2004 is busy,
				  LCD2004_DATA_PORT[7]==0,lcd2004 is free.
******************************************************/
static void lcd2004CheckBusy(void)
{
	do{
		;
	}while((lcd2004ReadStatus()) & 0x80);
}

/******************************************************
Function	:lcd2004WriteCommand
Input		:command code
Output		:N/A
Return		:N/A
Description	:write command to lcd2004
Note		:N/A
******************************************************/
void lcd2004WriteCommand(UB8 commandCode)
{
	lcd2004CheckBusy();
	
	lcd2004_en_bit = LCD2004_DISABLE ;
	
	lcd2004_rs_bit = LCD2004_COMMAND_OPERATION ;/*command*/
	lcd2004_rw_bit = LCD2004_WRITE_OPERATION ;	/*write*/

	LCD2004_DATA_PORT = commandCode ;
	delay1msForLcd2004();
	lcd2004_en_bit = LCD2004_ENABLE ;
	delay1msForLcd2004();

	lcd2004_en_bit = LCD2004_DISABLE ;	
}


/******************************************************
Function	:lcd2004WriteData
Input		:data code
Output		:N/A
Return		:void
Description	:write data to lcd2004
Note		:N/A
******************************************************/
void lcd2004WriteData(UB8 dataCode)
{	
	lcd2004CheckBusy() ;
	
	lcd2004_en_bit = LCD2004_DISABLE ;
	
	lcd2004_rs_bit = LCD2004_DATA_OPERATION ;	/*data*/
	lcd2004_rw_bit = LCD2004_WRITE_OPERATION ;	/*write*/

	LCD2004_DATA_PORT = dataCode;
	delay1msForLcd2004();
	lcd2004_en_bit = LCD2004_ENABLE ;
	delay1msForLcd2004();

	lcd2004_en_bit = LCD2004_DISABLE ;	   
}


/******************************************************
Function	:lcd2004CleanAll
Input		:N/A
Output		:N/A
Return		:N/A
Description	:clean lcd2004 display
Note		:清除屏幕显示,光标归位(左上角),地址计数器AC设为0
******************************************************/
void lcd2004CleanAll(void)
{
	lcd2004WriteCommand(LCD2004_CLEAN_ALL_DISPALY);
}

/******************************************************
Function	:lcd2004CursorHoming
Input		:N/A
Output		:N/A
Return		:N/A
Description	:curosr homing to the 0x80 
Note		:光标归位,当屏幕移动显示时,lcd2004显示所有数据后,
			 调用此函数,屏幕显示的所有东西都会归位。光标在第一
			 个位置(0x80)。
******************************************************/
void lcd2004CursorHoming(void)
{
	lcd2004WriteCommand(LCD2004_CURSOR_RETURN_TO_ORIGIN);
}

/******************************************************
Function	:lcd2004Init
Input		:N/A
Output		:N/A
Return		:N/A
Description	:N/A
Note		:N/A
******************************************************/
void lcd2004Init(void)
{
	lcd2004_en_bit = LCD2004_DISABLE ;
	
	lcd2004CleanAll();
	lcd2004WriteCommand(LCD2004_DEFAULT_DISPALY_MODE);
	lcd2004WriteCommand(LCD2004_DEFAULT_DISPLAY_AND_CURSOR_MODE);
	lcd2004WriteCommand(LCD2004_DEFAULT_POINT_AND_POINT_ADDRESS_MODE);

	/*可忽略,在lcd2004CleanAll()中隐含了该功能*/
	lcd2004WriteCommand(LCD2004_ROW0_ADDRESS_START);
	
	lcd2004_en_bit = LCD2004_DISABLE ;
}

/******************************************************
Function	:lcd2004AddressWriteByte
Input		:行位置
			 列位置
			 数据
Output		:N/A
Return		:N/A
Description	:N/A
Note		:N/A
******************************************************/
void lcd2004AddressWriteByte(UB8 row,UB8 column,UB8 dataCode)
{
	
	if(row == LCD2004_ROW0)
	{
		lcd2004WriteCommand(LCD2004_ROW0_ADDRESS_START+column) ;
	}
	else if(row == LCD2004_ROW1)
	{
		lcd2004WriteCommand(LCD2004_ROW1_ADDRESS_START+column) ;
		
	} 
	else if(row == LCD2004_ROW2)
	{
		lcd2004WriteCommand(LCD2004_ROW2_ADDRESS_START+column) ;
	}
	else if(row == LCD2004_ROW3)
	{
		lcd2004WriteCommand(LCD2004_ROW3_ADDRESS_START+column) ;
	}
	
	lcd2004WriteData(dataCode);
}

/******************************************************
Function	:lcd2004AddressWriteString
Input		:首个字符显示的行,列地址,字符串
Output		:N/A
Return		:N/A
Description	:N/A
Note		:这里使用的是strlen,而不是sizeof
******************************************************/
void lcd2004AddressWriteString(UB8 row,UB8 column,UB8 *stringCode)
{
	UB8 length = strlen(stringCode) ;
	
	if(row == LCD2004_ROW0)
	{
		lcd2004WriteCommand(LCD2004_ROW0_ADDRESS_START+column) ;
	}
	else if(row == LCD2004_ROW1)
	{
		lcd2004WriteCommand(LCD2004_ROW1_ADDRESS_START+column) ;
		
	}
	if(row == LCD2004_ROW2)
	{
		lcd2004WriteCommand(LCD2004_ROW2_ADDRESS_START+column) ;
	}
	else if(row == LCD2004_ROW3)
	{
		lcd2004WriteCommand(LCD2004_ROW3_ADDRESS_START+column) ;
		
	}
	while(length--) 
	{
		lcd2004WriteData(*stringCode);
		stringCode++;
	}
}


 

/*################lcd2004.c end################*/

 

测试程序:

/*################main.c start################*/

#include <reg52.h>
#include <string.h>
#include "common.h"
#include "lcd2004.h"

void main(void)
{	
	UB8 i ;
	UB8 author[] = "Author:YangRui" ;

	lcd2004Init();

	for(i=0 ; i<sizeof(author)-1 ; i++)
	{
		lcd2004AddressWriteByte(LCD2004_ROW0,i,author[i]) ;
	}

	lcd2004AddressWriteString(LCD2004_ROW1,0,"QQ:279729207");
	lcd2004AddressWriteString(LCD2004_ROW2,0,"yangrui90s@163.com");
	lcd2004AddressWriteString(LCD2004_ROW3,0,"Data:2014/02/26");
	
	while(1);
}


 

/*################main.c end################*/

 

 

补充:common.h

#ifndef __COMMON_H__
#define __COMMON_H__

typedef unsigned char UB8 ;
typedef unsigned short int UW16 ;
typedef unsigned long UL32 ;

typedef char SB8;
typedef short int SW16 ;
typedef long SL32 ;
	
#define HIGH_LEVEL 1	
#define LOW_LEVEL  0



#endif	/*__COMMON_H__*/


 

单片机控制2004A液晶屏之模块化编程,布布扣,bubuko.com

单片机控制2004A液晶屏之模块化编程

原文:http://blog.csdn.net/yagnruinihao/article/details/19999551

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!