学习单片机已经有一段时间了,但是很多程序都缺少模块化的思想,之前以为只要把单个的功能封装在一个函数里面就是模块化,但是在公司经过了十多天实习,才真正有了模块化的编程思想,这里将我编写的51单片机控制1602液晶屏的程序共享一下,一是希望没有模块化编程思想的后来者看看,二是希望前辈们给予斧正 。
(补充:以下代码只需要修改.h文件中含有 “选择” 字样的部分,就可以达到复用的效果)
(因为里面用到的宏比较多一点,建议大家利用 source insight工具建一个工程然后查看)
/*################lcd1602.h start ################*/
#ifndef __LCD1602_H__
#define __LCD1602_H__
#include <reg52.h>
#define LCD1602_DATA_PORT P0 /*根据硬件连接选择*/
sbit LCD1602_RW_BIT = P2^5; /*根据硬件连接选择*/
sbit LCD1602_RS_BIT = P2^6; //根据硬件连接选择*/
sbit LCD1602_ENABLE_BIT = P2^7; /*根据硬件连接选择*/
/*
RS RS
0 0 ---->write command to lcd1602
0 1 ---->read lcd1602‘s status
1 0 ---->write data to lcd1602
1 1 ---->read lcd1602‘s data
*/
//LCD1602_RS_BIT select
#define LCD1602_RS_BIT_SELECT_DATA 1
#define LCD1602_RS_BIT_SELECT_COMMAND 0
//LCD1602_RW_BIT selcect
#define LCD1602_RW_BIT_SELECT_READ 1
#define LCD1602_RW_BIT_SELECT_WRITE 0
#define LCD1602_ENABLE_BIT_ENABLE 1
#define LCD1602_ENABLE_BIT_DISABLE 0
#define LCD1602_DISPLAY_DEFAULT_MODE 0x38//display : 16(Column) x 2(Row) , 5 x 7 lattice,8bit data
#define LCD1602_CLEARALL_OPERATION 0x01
/*
0 0 0 0 1 D C B
| | |------cursor blink : 1-->enable ; 0-->disalbe
| |----------cursor display: 1-->enable ; 0-->disable
|-------------lcd1602 dispaly: 1-->enable ; 0-->disalbe
*/
#define LCD1602_CURSOR_AND_DISPLAY_BASE 0x08 /*注意:这里采用“基值 | 光标显示控制 | 光标闪烁控制 | 屏幕显示控制”的方式*/
#define LCD1602_DISPALY_ENABLE 0x04
#define LCD1602_DISPALY_DISABLE 0x00
#define LCD1602_CURSOR_DISPLAY_ENABLE 0x02
#define LCD1602_CURSOR_DISPLAY_DISABLE 0x00
#define LCD1602_CURSOR_BLINK_ENABLE 0x01
#define LCD1602_CURSOR_BLINK_DISABLE 0x00
#define LCD1602_CURSOR_AND_DISPALY_DEFAULT LCD1602_CURSOR_AND_DISPLAY_BASE | LCD1602_CURSOR_BLINK_ENABLE | LCD1602_CURSOR_DISPLAY_ENABLE | LCD1602_DISPALY_ENABLE
/*默认 :屏幕显示 + 光标显示 + 闪烁*/
/*
0 0 0 0 0 1 N S
| |----- S=1:屏幕移动 ; S=0:屏幕不移动
|--------- N=1:读或者写一个字符后地址指针加1,且光标加1
N=0:度或者写一个字符后地址指针减1,且光标减1
当S=1时 :
若N=1,整屏幕左移
N=0,整屏幕右移
以达到光标不移动,而整个屏幕移动的效果
*/
#define LCD1602_CURSOR_AND_POINT_BASE 0x04 /*注意:这里采用“基值 | 屏幕移动控制 | 指针控制”的方式*/
#define LCD1602_POINT_INC 0x02
#define LCD1602_POINT_DEC 0X00
#define LCD1602_SCREEN_MOVE_ENABLE 0x01
#define LCD1602_SCREEN_MOVE_DISABLE 0x00
#define LCD1602_CURSOR_AND_POINT_DEFAULT LCD1602_CURSOR_AND_POINT_BASE | LCD1602_POINT_INC | LCD1602_SCREEN_MOVE_DISABLE
/*默认 : 指针和地址加一 + 屏幕不移动*/
#define LCD1602_ROW0 0
#define LCD1602_ROW1 1
#define LCD1602_ROW0_ADDRESS_START 0X80
#define LCD1602_ROW1_ADDRESS_START 0Xc0
#define LCD1602_ROW_OR_COLUMN_OVERLOW -1
extern unsigned char lcd1602ReadStatus(void);
extern void lcd1602WriteCommand(unsigned char opcode);
extern void lcd1602WriteData(unsigned char dat);
extern char lcd1602AddressWriteData(unsigned char x_position ,unsigned char y_position,unsigned char dat);
extern void lcd1602ClearAll(void);
extern void lcd1602Init(void);
#endif /*__LCD1602_H__*/
/*################lcd1602.h end################*/
/*################ lcd1602.c start################*/
#include "lcd1602.h" /****************************************************************** FuncationName :lcd1602Delay3ms Author :yangrui Date :20140119_16_13 Input :N/A Output :N/A Return :N/A Note :crystal frequecy 12.000MHZ /******************************************************************/ static void lcd1602Delay3ms(void) { unsigned char i, j; i = 36; j = 1; do { while (--j); } while (--i); } /****************************************************************** FuncationName :lcd1602ReadStatus Author :yangrui Date :20140120_13_18 Input :N/A Output :N/A Return :N/A Note :read LCD1602‘s status /******************************************************************/ unsigned char lcd1602ReadStatus(void) { unsigned char temp ; LCD1602_ENABLE_BIT = LCD1602_ENABLE_BIT_DISABLE ; LCD1602_RW_BIT = LCD1602_RW_BIT_SELECT_READ ; /*read*/ LCD1602_RS_BIT = LCD1602_RS_BIT_SELECT_COMMAND ; /*read lcd1602‘s status*/ lcd1602Delay3ms(); LCD1602_DATA_PORT = 0xff; lcd1602Delay3ms(); LCD1602_ENABLE_BIT = LCD1602_ENABLE_BIT_ENABLE ; lcd1602Delay3ms(); temp = LCD1602_DATA_PORT; return temp; } /****************************************************************** FuncationName :lcd1602CheckBusy Author :yangrui Date :20140120_10_50 Input :N/A Output :N/A Return :N/A Note :check bus busy or free, if busy ,wait! /******************************************************************/ static void lcd1602CheckBusy(void) { do{ ; }while(lcd1602ReadStatus()&0x80);/*when LCD1602_DATA_PORT[7] ==1,LCD1602 busy*/ lcd1602Delay3ms(); lcd1602Delay3ms(); lcd1602Delay3ms(); } /****************************************************************** FuncationName :lcd1602WriteCommand Author :yangrui Date :20140119_15_30 Input :opcode(command code) Output :N/A Return :N/A Note :写指令操作, 注意:写地址操作也是本函数完成的,而不是lcd1602WriteData()完成 /******************************************************************/ void lcd1602WriteCommand(unsigned char opcode) { lcd1602CheckBusy(); LCD1602_ENABLE_BIT = LCD1602_ENABLE_BIT_DISABLE ; LCD1602_RW_BIT = LCD1602_RW_BIT_SELECT_WRITE ; /*write*/ LCD1602_RS_BIT = LCD1602_RS_BIT_SELECT_COMMAND ; /*command*/ LCD1602_DATA_PORT = opcode ; lcd1602Delay3ms(); LCD1602_ENABLE_BIT = LCD1602_ENABLE_BIT_ENABLE ; lcd1602Delay3ms(); LCD1602_ENABLE_BIT = LCD1602_ENABLE_BIT_DISABLE ; } /****************************************************************** FuncationName :lcd1602WriteData Author :yangrui Date :20140119_17_30 Input :dat(ready data Tx to lcd1602) Output :N/A Return :N/A Note :写数据操作 /******************************************************************/ void lcd1602WriteData(unsigned char dat) { lcd1602CheckBusy(); LCD1602_ENABLE_BIT = LCD1602_ENABLE_BIT_DISABLE ; LCD1602_RW_BIT = LCD1602_RW_BIT_SELECT_WRITE ; /*write*/ LCD1602_RS_BIT = LCD1602_RS_BIT_SELECT_DATA; /*data*/ LCD1602_DATA_PORT = dat; lcd1602Delay3ms(); LCD1602_ENABLE_BIT = LCD1602_ENABLE_BIT_ENABLE ; lcd1602Delay3ms(); LCD1602_ENABLE_BIT = LCD1602_ENABLE_BIT_DISABLE ; } /****************************************************************** FuncationName :lcd1602ClearAll Author :yangrui Date :20140119_17_30 Input :N/A Output :N/A Return :N/A Note :clear all display /******************************************************************/ void lcd1602ClearAll(void) { lcd1602WriteCommand(LCD1602_CLEARALL_OPERATION); } /****************************************************************** FuncationName :lcd1602Init Author :yangrui Date :20140119_17_30 Input :N/A Output :N/A Return :N/A Note :LCD1602 initialize /******************************************************************/ void lcd1602Init() { lcd1602ClearAll(); lcd1602WriteCommand(LCD1602_DISPLAY_DEFAULT_MODE);/*display : 16(Column) x 2(Row) , 5 x 7 lattice,8bit data*/ lcd1602WriteCommand(LCD1602_CURSOR_AND_DISPALY_DEFAULT);/*默认 :屏幕显示 + 光标显示 + 闪烁*/ lcd1602WriteCommand(LCD1602_CURSOR_AND_POINT_DEFAULT); /*默认 :指针和地址加一 + 屏幕不移动*/ } /****************************************************************** FuncationName :lcd1602AddressWriteData Author :yangrui Date :201401120_11_15 Input :x_position 、y_position 、 dat Output :N/A Return :N/A Note :默认16x2,5x7点阵显示,屏幕不移动,指针加1,情况下的地址数据写操作 x_position 有效范围:0~15 y_position 有效范围:0~1 /******************************************************************/ char lcd1602AddressWriteData(unsigned char x_position ,unsigned char y_position,unsigned char dat) { if( x_position<0 || x_position>15 || y_position<0 || y_position>1 || ((y_position!=LCD1602_ROW0) && (y_position!=LCD1602_ROW1)) ) { return LCD1602_ROW_OR_COLUMN_OVERLOW; } if(y_position == 0) { lcd1602WriteCommand(LCD1602_ROW0_ADDRESS_START + x_position); lcd1602WriteData(dat); } else if(y_position == 1) { lcd1602WriteCommand(LCD1602_ROW1_ADDRESS_START +x_position); lcd1602WriteData(dat); } return 0; }
/*################ lcd1602.c end################*/
/*################main.c end################*/
#include <reg52.h> #include "lcd1602.h" unsigned char author[] = "Author:YangRui" ; unsigned char qq[] = "QQ:279729201" ; unsigned char smile[] = "^_^" ; void main(void) { int i; lcd1602Init(); //Row 0 for(i=0; i<sizeof(author)-1 ; i++) { lcd1602WriteData(author[i]); } lcd1602AddressWriteData(sizeof(author), LCD1602_ROW0, ‘!‘); //Row 1 lcd1602WriteCommand(0xc0); for(i=0; i<sizeof(qq)-1 ; i++) { lcd1602WriteData(qq[i]); } lcd1602WriteCommand(0xc0+sizeof(qq)); for(i=0; i<sizeof(smile)-1 ; i++) { lcd1602WriteData(smile[i]); } while(1) { ; } }
/*################main.c end################*/
(图片有点大,在网页可能无法全部显示,可以右键保存到电脑查看)
希望大家给予指正!!!