部分效果图:
准备工作:
51单片机(BST)+1602显示屏
基础知识:
注:X表示可以是0,也可以是1;
DL 1,
N 1,
F 0,
代码一: 要求显示字母‘a’
#include <reg52.h>
sbit E = P2^5; // enable 数据读写操作控制位 1: 写 0: 读
sbit RW = P1^1; // 读写控制线 0: 写操作, 1: 读操作
sbit RS = P1^0; // 数据和指令选择控制端, 0: 命令状态; 1:数据状态
Write_CMD(unsigned char x){
int i = 1000;
// 设置进入命令状态
RS = 0;
// 写操作
RW = 0;
// 0x01 清屏 0x38 设置 ......等指令内容
P0 = x;
// 打开指令读写操作控制允许
E = 1;
// 等待1秒
while(i--);
// 关闭指令读写操作控制允许
E = 0;
}
Write_DATA(unsigned char x) {
int i = 1000;
// 设置进入数据状态
RS = 1;
// 写操作
RW = 0;
// 数据内容
P0 = x;
// 打开数据读写操作控制允许
E = 1;
// 等待1秒
while(i--);
// 关闭数据读写操作控制允许
E = 0;
}
main(){
// 清屏
Write_CMD(0x01);
// 设置16X2显示,5X7点阵,8位数据接口;
Write_CMD(0x38);
// 开显示,显示光标,光标闪烁;
Write_CMD(0x0f);
// 地址加1,当写入数据的时候光标右移:
Write_CMD(0x06);
// 写入字符a
Write_DATA('a');
while(1);
}
效果结果图:
代码优化一下:
#include <reg52.h>
sbit E = P2^5; // enable 数据读写操作控制位 1: 写 0: 读
sbit RW = P1^1; // 读写控制线 0: 写操作, 1: 读操作
sbit RS = P1^0; // 数据和指令选择控制端, 0: 命令状态; 1:数据状态
void Write_CMD(unsigned char x){
int i = 1000;
// 设置进入命令状态
RS = 0;
// 写操作
RW = 0;
// 0x01 清屏 0x38 设置 ......等指令内容
P0 = x;
// 打开指令读写操作控制允许
E = 1;
// 等待1秒
while(i--);
// 关闭指令读写操作控制允许
E = 0;
}
void Write_DATA(unsigned char x) {
int i = 1000;
// 设置进入数据状态
RS = 1;
// 写操作
RW = 0;
// 数据内容
P0 = x;
// 打开数据读写操作控制允许
E = 1;
// 等待1秒
while(i--);
// 关闭数据读写操作控制允许
E = 0;
}
// 初始化代码
void LCDinit(void){
// 清屏
Write_CMD(0x01);
// 设置16X2显示,5X7点阵,8位数据接口;
Write_CMD(0x38);
// 开显示,显示光标,光标闪烁;
Write_CMD(0x0f);
// 地址加1,当写入数据的时候光标右移:
Write_CMD(0x06);
}
main(){
// 初始化代码
LCDinit();
// 写入字符a
Write_DATA('a');
while(1);
}
例2: 从C7的位置显示字符“W”
#include <reg52.h>
sbit E = P2^5; // enable 数据读写操作控制位 1: 写 0: 读
sbit RW = P1^1; // 读写控制线 0: 写操作, 1: 读操作
sbit RS = P1^0; // 数据和指令选择控制端, 0: 命令状态; 1:数据状态
void Write_CMD(unsigned char x){
int i = 1000;
// 设置进入命令状态
RS = 0;
// 写操作
RW = 0;
// 0x01 清屏 0x38 设置 ......等指令内容
P0 = x;
// 打开指令读写操作控制允许
E = 1;
// 等待1秒
while(i--);
// 关闭指令读写操作控制允许
E = 0;
}
void Write_DATA(unsigned char x) {
int i = 1000;
// 设置进入数据状态
RS = 1;
// 写操作
RW = 0;
// 数据内容
P0 = x;
// 打开数据读写操作控制允许
E = 1;
// 等待1秒
while(i--);
// 关闭数据读写操作控制允许
E = 0;
}
// 初始化代码
void LCDinit(void){
// 清屏
Write_CMD(0x01);
// 设置16X2显示,5X7点阵,8位数据接口;
Write_CMD(0x38);
// 开显示,显示光标,光标闪烁;
Write_CMD(0x0f);
// 地址加1,当写入数据的时候光标右移:
Write_CMD(0x06);
}
main(){
//初始化代码
LCDinit();
// 指令显示从C7位置开始写字母
Write_CMD(0xC7);
// 写入字符W
Write_DATA('W');
while(1);
}
例子三,输出“I Love China !”
#include <reg52.h>
sbit E = P2^5; // enable 数据读写操作控制位 1: 写 0: 读
sbit RW = P1^1; // 读写控制线 0: 写操作, 1: 读操作
sbit RS = P1^0; // 数据和指令选择控制端, 0: 命令状态; 1:数据状态
void Write_CMD(unsigned char x){
int i = 1000;
// 设置进入命令状态
RS = 0;
// 写操作
RW = 0;
// 0x01 清屏 0x38 设置 ......等指令内容
P0 = x;
// 打开指令读写操作控制允许
E = 1;
// 等待1秒
while(i--);
// 关闭指令读写操作控制允许
E = 0;
}
void Write_DATA(unsigned char x) {
int i = 1000;
// 设置进入数据状态
RS = 1;
// 写操作
RW = 0;
// 数据内容
P0 = x;
// 打开数据读写操作控制允许
E = 1;
// 等待1秒
while(i--);
// 关闭数据读写操作控制允许
E = 0;
}
// 初始化代码
void LCDinit(void){
// 清屏
Write_CMD(0x01);
// 设置16X2显示,5X7点阵,8位数据接口;
Write_CMD(0x38);
// 开显示,显示光标,光标闪烁;
Write_CMD(0x0f);
// 地址加1,当写入数据的时候光标右移:
Write_CMD(0x06);
}
main(){
int i;
char a[] = {"I Love China !"};
//初始化代码
LCDinit();
for(i = 0; i < 14; i++){
// 指令显示从C1位置开始写字母
Write_CMD(0xC1 + i);
// 写入字符
Write_DATA(a[i]);
}
while(1);
}
附官方提供的示例代码:
/**********************BST-V51实验开发板例程************************
* 平台:BST-V51 + Keil U3 + STC89C52
* 名称:LCD1602模块实验
* 公司:深圳市XXXX科技有限公司
* 日期:2013-11
* 晶振:11.0592MHZ
* 说明:免费开源,不提供源代码分析.
******************************************************************/
//实验目的:
/*-----------------------------------------------
名称:LCD1602
内容:通过标准程序静态显示字符
引脚定义如下:1-VSS 2-VDD 3-V0 4-RS 5-R/W 6-E 7-14 DB0-DB7 15-BLA 16-BLK
------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>
#include<string.h>
#define uchar unsigned char
sbit RS = P1^0; //定义端口
sbit RW = P1^1;
sbit EN = P2^5;
sbit DU = P2^0;
sbit WE = P2^1;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
/*协议定义*/
bit startBit = 0; //串口接收开始标志位
bit newLineReceived = 0; //串口一帧协议包接收完成
unsigned char inputString[50]; //接收数据协议
/*------------------------------------------------
串口初始化函数
------------------------------------------------*/
void init_com(void)
{
TMOD|=0x20; //设T0为方式1,GATE=1;
SCON=0x50;
TH1=0xFD;
TL1=0xFD;
TR1=1; //开启定时器
//TI=1;
EA=1; //开启总中断
ES=1; //串口中断打开
}
void cmg88()//关数码管,点阵函数
{
DU=1;
P0=0X00;
DU=0;
}
/*------------------------------------------------
uS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*------------------------------------------------
写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com)
{
while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*------------------------------------------------
写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data)
{
while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*------------------------------------------------
清屏函数
------------------------------------------------*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*------------------------------------------------
写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*s)
{
LCD_Write_Data( *s);
s ++;
}
}
/*------------------------------------------------
写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*------------------------------------------------
初始化函数
------------------------------------------------*/
void LCD_Init(void)
{
LCD_Write_Com(0x38); /*显示模式设置*/
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08); /*显示关闭*/
LCD_Write_Com(0x01); /*显示清屏*/
LCD_Write_Com(0x06); /*显示光标移动设置*/
DelayMs(5);
LCD_Write_Com(0x0C); /*显示开及光标设置*/
}
/*------------------------------------------------
主函数
------------------------------------------------*/
void main(void)
{
uchar temp[17] = {0};
cmg88();//关数码管,点阵函数
LCD_Init();
LCD_Clear();//清屏
init_com();
LCD_Write_Char(7,0,'o');
LCD_Write_Char(8,0,'k');
LCD_Write_String(1,1,"I Love TT");
while (1)
{
//开始解析协议 $51,LCD1602,1,0123456789abcdef# 第一行 $51,LCD1602,2,0123456789abcdef# 第二行
while (newLineReceived) //协议数据接收完毕一包
{
//判断是否是51的协议
if(inputString[1] != '5' || inputString[2] != '1')
{
newLineReceived = 0;
memset(inputString, 0x00, sizeof(inputString));
break;
}
//判断是否是1602的协议数据
if(inputString[4] != 'L' || inputString[5] != 'C' || inputString[6] != 'D'
|| inputString[7] != '1'|| inputString[8] != '6'|| inputString[9] != '0'|| inputString[10] != '2')
{
newLineReceived = 0;
memset(inputString, 0x00, sizeof(inputString));
break;
}
//开始取数据 位置12 开始 $51,HS00ff3003#
if(inputString[12] == '0') //清屏
{
LCD_Clear();//清屏
}
if(inputString[12] == '1') //显示第一行
{
memcpy(temp, inputString+14, 16);
LCD_Write_String(0, 0, temp);
}
if(inputString[12] == '2') //显示第二行
{
memcpy(temp, inputString+14, 16);
LCD_Write_String(0, 1, temp);
}
newLineReceived = 0;
memset(inputString, 0x00, sizeof(inputString));
break;
}
}
}
/******************************************************************/
/* 串口中断程序*/
/******************************************************************/
void UART_SER () interrupt 4
{
unsigned char n; //定义临时变量
static int num = 0;
if(RI) //判断是接收中断产生
{
RI = 0; //标志位清零
n = SBUF; //读入缓冲区的值
//control=n;
if(n == '$')
{
startBit = 1;
num = 0;
}
if(startBit == 1)
{
inputString[num] = n;
num++;
}
if (startBit == 1 && n == '#')
{
newLineReceived = 1;
startBit = 0;
num = 0;
}
if(num >= 50)
{
num = 0;
startBit = 0;
newLineReceived = 0;
}
}
}