51单片机驱动1602程序

  • 学习3760次
sbit LCD_RS=P3^4;? ??? ?? // 定义IO口,具体1602的读控制线
sbit LCD_RW=P3^3;? ??? ?? // 定义IO口,具体1602的写控制线
sbit LCD_EN=P2^0;? ??? ?? // 定义IO口,具体1602的使能控制线
sbit Light=P3^7;? ??? ??? ?? // 定义IO口,具体1602的背光控制线(0:开通,1关闭)
sbit D0 = P1^0;?????????? // 定义IO口,P1.0数据口1602LCD的D0口
sbit D1 = P1^1;?????????? // 定义IO口,P1.1数据口1602LCD的D1口
sbit D2 = P1^2;?????????? // 定义IO口,P1.2数据口1602LCD的D2口
sbit D3 = P1^3;?????????? // 定义IO口,P1.3数据口1602LCD的D3口
sbit D4 = P1^4;?????????? // 定义IO口,P1.4数据口1602LCD的D4口
sbit D5 = P1^5;?????????? // 定义IO口,P1.5数据口1602LCD的D5口
sbit D6 = P1^6;?????????? // 定义IO口,P1.6数据口1602LCD的D6口
sbit D7 = P2^1;?????????? // 定义IO口,P2.1数据口1602LCD的D7口?? ?

sbit B_0=B^0;???????????? // 定义变量B的位,方便位操作
sbit B_1=B^1;
sbit B_2=B^2;
sbit B_3=B^3;
sbit B_4=B^4;
sbit B_5=B^5;
sbit B_6=B^6;
sbit B_7=B^7;
 
void main(void)
{?? ?
?? ?P1M0 = 0x00;
?? ?P1M1 = 0x00;?? ??? ?// 配置P1口为准双向口
?? ?P2M0 = 0x00;
?? ?P2M1 = 0x00;?? ??? ?// 配置P2口为准双向口???? ?
?? ?P3M0 = 0x00;
?? ?P3M1 = 0x80;?? ??? ?// 配置P3.7口为强推挽输出(控制背光),其它IO口默认为准双向口(详细配置见STC12C56XXAD数据手册) ??? ?
?? ?Light = 0; ?? ??? ??? ?// 开1602LCD的背光

?? ?lcd_init();?? ??? ??? ?// LCD 初始化
?? ?lcd_write_char(0,0,'A');? ??? ?//在坐标(0,0)处写入A
? ??? ?lcd_write_char(1,0,'B');? ??? ?//在坐标(1,0)处写入B
? ??? ?lcd_write_char(2,0,'C');? ??? ?//在坐标(2,0)处写入C
? ??? ?lcd_write_char(3,0,'D');? ??? ?//在坐标(3,0)处写入D
? ??? ?lcd_write_char(4,0,'E');? ??? ?//在坐标(4,0)处写入E
? ?? ?lcd_write_char(5,0,'F');? ??? ?//在坐标(5,0)处写入F
? ??? ?lcd_write_char(6,0,'G');? ??? ?//在坐标(6,0)处写入G
? ??? ?lcd_write_char(7,0,'H');? ??? ?//在坐标(7,0)处写入H
? ??? ?lcd_write_char(8,0,'I');? ??? ?//在坐标(8,0)处写入I
? ??? ?lcd_write_char(9,0,'J');? ??? ?//在坐标(9,0)处写入J
? ??? ?lcd_write_char(10,0,'K');?? //在坐标(10,0)处写入K
? ??? ?lcd_write_char(11,0,'L');?? //在坐标(11,0)处写入L
? ??? ?lcd_write_char(12,0,'M');?? //在坐标(12,0)处写入M
? ??? ?lcd_write_char(13,0,'N');?? //在坐标(13,0)处写入N
? ??? ?lcd_write_char(14,0,'O');?? //在坐标(14,0)处写入O
? ??? ?lcd_write_char(15,0,'P');?? //在坐标(15,0)处写入P
??? lcd_write_char(0,1,'Q');? ??? ?//在坐标(0,1)处写入Q
??? lcd_write_char(1,1,'R');? ??? ?//在坐标(1,1)处写入R
??? lcd_write_char(2,1,'S');? ??? ?//在坐标(2,1)处写入S
??? lcd_write_char(3,1,'T');? ??? ?//在坐标(3,1)处写入T
??? lcd_write_char(4,1,'U');? ??? ?//在坐标(4,1)处写入U
??? lcd_write_char(5,1,'V');? ??? ?//在坐标(5,1)处写入V
??? lcd_write_char(6,1,'W');? ??? ?//在坐标(6,1)处写入W
??? lcd_write_char(7,1,'X');? ??? ?//在坐标(7,1)处写入X
??? lcd_write_char(8,1,'Y');? ??? ?//在坐标(8,1)处写入Y
??? lcd_write_char(9,1,'Z');? ??? ?//在坐标(9,1)处写入Z? ?
?? ?while(1)?? ??? ??? ?// 进入程序主循环
?? ?{?? ??? ??? ?
?? ??? ?
?? ?} ?? ??? ?
}
void delay1(int ms)?? ?? // 延时子函数,用于模拟时序中高低电平的保持时间,非精确的定时
{
?unsigned char y;
? while(ms--)
?{
? for(y = 0; y<100; y++)
? {
?? _nop_();
?? _nop_();
?? _nop_();
?? _nop_();
? }
?}
}
//================================*/?? 
//?????????????? 1602检测判忙函数?? ??? ??? ??? ?? ??? ? */
//================================*/
bit lcd_busy()?? ??? ??? ?// 读写判断数据的D7读写位,用于判断1602是否忙
?{???????????????????????? ?
??? bit result;
?? ?D7 = 1;?? ??? ?? // 数据口D7置1,为读状态做准备
??? LCD_RS = 0;?? ?? // 选择指令寄存
??? LCD_RW = 1;?? ?? // 选择读控制线
??? LCD_EN = 1;?? ?? // 开使能控制线
??? delayNOP();?? ?? // 时序延时
??? result = D7;? // 读D7的电平
??? LCD_EN = 0;?? ?? // 关使能
??? return(result); // 返回值1:忙,0可以执行操作
?}
//===============================*/?????? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? 
//?????????????? 1602写命令函数?? ??? ??? ??? ??? ????? */
//===============================*/
void lcd_wcmd(uchar cmd)
{???????????????????????? ?
??? while(lcd_busy());?? ?// 判断等待
??? LCD_RS = 0;?? ??? ?// 选择指令寄存
??? LCD_RW = 0;?? ??? ?//选择写
??? LCD_EN = 0;?? ??? ?// 开使能控制线
??? _nop_();?? ??? ?// 时序延时
??? _nop_(); ?? ??? ?// 时序延时
??? B = cmd;?? ??? ?// 把命令字送入B 
?? ?D0 = B_0;?? ???? // 把cmd的0位写入D0
?? ?D1 = B_1;?? ??? ?// 把cmd的1位写入D1
?? ?D2 = B_2;?? ??? ?// 把cmd的2位写入D2
?? ?D3 = B_3;?? ??? ?// 把cmd的3位写入D3
?? ?D4 = B_4;?? ??? ?// 把cmd的4位写入D4
?? ?D5 = B_5;?? ??? ?// 把cmd的5位写入D5
?? ?D6 = B_6;?? ??? ?// 把cmd的6位写入D6
?? ?D7 = B_7;?? ??? ?// 把cmd的7位写入D7
??? delayNOP();?? ??? ?// 时序延时
??? LCD_EN = 1;?? ??? ?// 使能控制线
??? delayNOP();?? ??? ?// 时序延时
??? LCD_EN = 0; ??? ?// 关闭使能控制线
}
//===========================*/?? 
//????????? 1602写数据函数?? ??? ??????? ????? */
//===========================*/
void lcd_wdat(uchar dat)
{???????????????????????? ?
?? while(lcd_busy()); ??? ?// 判断等待
??? LCD_RS = 1;?? ??? ?// 选择数据寄存器
??? LCD_RW = 0;?? ??? ?// 选择写
??? LCD_EN = 0;?? ??? ?// 使能控制线
??? B = dat;?? ??? ?// 把databuf送入B 
?? ?D0 = B_0;?? ??? ?// 把dat的0位写入D0
?? ?D1 = B_1;?? ??? ?// 把dat的1位写入D1
?? ?D2 = B_2;?? ??? ?// 把dat的2位写入D2
?? ?D3 = B_3;?? ??? ?// 把dat的3位写入D3
?? ?D4 = B_4;?? ??? ?// 把dat的4位写入D4
?? ?D5 = B_5;?? ??? ?// 把dat的5位写入D5
?? ?D6 = B_6;?? ??? ?// 把dat的6位写入D6
?? ?D7 = B_7;?? ??? ?// 把dat的7位写入D7
??? delayNOP();?? ??? ?// 时序延时
??? LCD_EN = 1;?? ??? ?// 开使能控制线
??? delayNOP();?? ??? ?// 时序延时
??? LCD_EN = 0; ?? ?// 关使能控制线
}
//=========================*/?? 
//????????? 1602 LCD初始化?? ??? ? ????? */
//=========================*/
void lcd_init()
{ 
??? delay1(15);????????? // 时序延时?????? ?
??? lcd_wcmd(0x38);????? //16*2显示,5*7点阵,8位数据
??? delay1(5);?? ??? ??? ? // 时序延时
??? lcd_wcmd(0x38);??????? ?
??? delay1(5);?? ??? ??? ? // 时序延时
??? lcd_wcmd(0x38);??????? ?
??? delay1(5);?? ??? ??? ? // 时序延时

??? lcd_wcmd(0x0c);????? //显示开,关光标
??? delay1(5);
??? lcd_wcmd(0x06);????? //移动光标
??? delay1(5);
??? lcd_wcmd(0x01);????? //清除LCD的显示内容
??? delay1(5);
}
//====================*/?? 
//??? 设置显示地址???? */
//===================*/
void lcd_write_address(unsigned char x,unsigned char y)
{ ?
?? ?x&=0x0f;?? ??? ??? ???????????????????? //列地址限制在0-15
? ??? ?y&=0x01;?? ??? ??? ???????????????????? //行地址限制在0-1
? ??? ?if(y==0x00)
?? ??? ?lcd_wcmd(x| 0x80);
? ??? ?else??????????????????????????????????? //需要自行查看1602写地址的指令格式
?? ??? ?lcd_wcmd((x +0x40) | 0x80);?? ??? ??? ?//第二行的列地址写入
}
//========================*/?? 
//?? 指定地址写入函数???? */
//=====================*/
void lcd_write_char(unsigned char x,unsigned char y,unsigned char buf)
{ ??? ??? ?
?? ?lcd_write_address(x,y); //写入地址?? ??? ??? ?
??? lcd_wdat(buf);?? ??? ?//写入显示数据?? ?
}

发表评论