C51 LCD1602 VB上位机实现简单通信

合集下载

VB编写的简单的上位机

VB编写的简单的上位机

一个简单的用VB编写的上位机程序自己想做一个简单上位机,却发现相关的资料很少,于是在做出来之后把自己的这样一个简单程序上传,给新入门的朋友一个借鉴学习的资料。

窗口布局用到的MSComm控件的基本属性(必用)CommPort:设置或返回串口通信的串口号(COM口)设置格式是:mPort[=value],其中object为控件名,如MSComm1;value的合法值是整形的数据,例如1,2……比如mPort=1(默认值),表示我们将用COM1口进行通信COM口可以通过鼠标右击“我的电脑(计算机)”图标,在弹出的快捷菜单中选择“管理”,弹出如下图左边的对话框左键点击“设备管理器”可以看到上图右边对话框左键点击设备管理器可以看到如上图右边视图其中的就是当前连接到计算机的可用串口了Settings:以字符串的形式设置或返回串口通信参数。

设置格式:mPort[=value]其中object为控件名,如MSComm1;Value需为一字符串,由四个设置值组成其格式为:“波特率,奇偶校验,数据位,停止位”Portopen:设置或返回串口状态,若其已经打开,则返回TRUE,否则返回FALSE 设置格式:object.Portopen[=value]其中object为控件名,如MSComm1;value为一逻辑值,若为TRUE,则打开,否则关闭注意:如果串口不是打开(关闭),而对它进行关闭(打开)将会出错RThreshold:该属性为一阀值。

当接收缓冲区中字符数达到该值时,MSComm 控件设置Commevent属性为ComEvReceive,并产生OnComm事件。

用户可在OnComm事件处理程序中进行相应处理。

若Rthreshold属性设置为0,则不产生OnComm事件。

例如用户希望接收缓冲区中达到一个字符就接收一个字符,可将Rthreshold设置为1。

这样接收缓冲区中接收到一个字符,就产生一次OnComm事件。

上位机制作过程单片机51vb上位机超简单

上位机制作过程单片机51vb上位机超简单
上位机制作过程单片机51vb上位机 超简单
• 1602控制
上位机用途
• 上位机是一台可以发出特定操控命令的计 算机,通过操作预先设定好的命令,将命 令传递给下位机,通过下位机来控制设备 完成各项操作(应用最多的地方如:工业、 水利、供电部门、交通等方面)。上位机 都有特定的编程,有专门的开发系统,或 以上是已经规定好任务,只能按特定的任 务进行操作。简单说上位机就是命令的下 达者,而下位机则是命令的执行者。
口。
• Private Sub Command2_Click() • 这个是点击按钮2所触发的事件代码函数入
口。
代码如下
成功和下位机通讯
谢谢观赏
比如上位机控制在工厂中的应用
首先打开vb软件
• 弹出新建工程对话框,点击标准exe
• 出现如下
设置属性窗口
• caption:标题 • font:字体大小和风格
• 新建两个按钮,改一下caption:打开串口 和发送数据如下图所示
点击左边按钮框新建一个text1,如下图所示
添加串口控件,在工程-部件中找到Microsoft comm control 6.0,如下图所示,点击打钩,并确定。
在右边控件Байду номын сангаас出现一个电话的控件,并把下图箭头所示的控 件添加到窗口中。
对代码进行编写
• 首先,双击窗口进入代码编辑框,如下图 所示:
• Private Sub Form_Load() • 这个函数是窗口运行时初始化一些控件。
• Private Sub Command1_Click() • 这个是点击按钮1所触发的事件代码函数入

上位机VB实现与三菱PLC的串行通讯

上位机VB实现与三菱PLC的串行通讯

上位机VB实现与三菱PLC的串行通讯上位机VB实现与三菱PLC的串行通讯1. 通行原理与方法上位机要能够通过PLC监控下层设备的状态,就要实现上位机与PLC间的通信,一般工业控制中都是采用RS232C实现。

上位机首先向PLC发送查询数据的指令(实际上是查询PLC中端子的状态和DM 区的值等),PLC接收了上位的指令后,进行校验(FCS校验码),看其是否正确,如果正确,则向上位机传送数据(包含首尾校验字节)。

否则,PLC拒绝向上位机传送数据。

上位接收到PLC传送的数据,也要判断正确与否,如果正确,则接收,否则,拒绝接收。

由于CPM1A没有提供串行通信口,我们利用其提供的外设端口实现通信。

PLC与计算机之间的连接是通过OMRON提供的专用电缆CQM1-CIF01来实现的,其硬件连接图如图1所示。

(见附图)2. PLC与计算机间的通信规约计算机与PLC间的通信是以“帧”为单位进行的,并且在通信的过程中,计算机具有更高的优先级。

首先,计算机向PLC发出命令帧,然后,PLC作出响应,向计算机发送回响应帧。

其中命令帧和响应帧的格式如下:(1) 命令帧格式。

为了方便计算机和PLC的通讯,CPM1A对在计算机连接通信中交换的命令和响应规定了相应的格式。

当计算机发送一个命令时,命令数据主准备格式如图2所示。

(见附图)其中@放在首位,表示以@开始,设备号为上位机识别所连接的PLC的设备号。

识别码为命令代码,用来设置用户希望上位机完成的操作,FCS为帧检验代码,一旦通信出错,通过计算FCS可以及时发现。

结束符为“*”和CR回车符,表示命令结束。

(2) 响应帧格式。

由PLC发出的对应于命令格式的响应帧格式如图3所示。

(见附图)其中,异常码可以确定计算机发送的命令是否正确执行。

其它的与正文中的含义相同。

正文仅在有读出数据时有返回。

3. 通信程序的设计为了充分利用计算机数据处理的强大功能,我们可以采用计算机有优先权的方式,在计算机上编写程序来实现计算机与PLC的通信,计算机向PLC发出命令发起通信,PLC自动返回响应。

基于VB实现PLC与上位机之间的通信

基于VB实现PLC与上位机之间的通信

基于VB实现PLC与上位机之间的通信康微微;鞠振河【摘要】Centering on the THSMS-C type network programmable controller in the Experimental Center of school of automation,this paper realized the communication between Siemens S7-200 PLC and the host computer based on VB6 . 0 . The objectives are to enhance the real-time monitoring function and to improve the experimental performance of PLC control system. On the one hand,the controlled interface of man-machine is designed by VB6. 0,which can in-put parameters in need and display real-time output results. And the serial communication ActiveX controller MSComm is provided by VB6 . 0 ,using the free port communication protocol to achieve communications between PLC and PC,then PC stores and processes the experiment data timely. This paper applies experiments to prove the correct-ness of the study. The results show that the design will get good monitoring and control function,which has advantages such as economy,reliability,flexibility,real-time performance and so on.%利用THSMS-C网络型可编程控制器实验台进行VB6.0与S7-200西门子系列PLC控制实验的调试,改善了系统在监控过程中的实时同步性。

基于51单片机的病床呼叫系统 (4)

基于51单片机的病床呼叫系统 (4)

2019届本科毕业设计基于51单片机的病床呼叫系统姓名:马梦园学院:电子电气工程学院专业:电子信息工程学号:150312002指导教师:李莉2019年1月20日目录摘要 (II)Abstract (III)引言 (1)1 系统方案设计 (1)1.1 系统整体方案设计 (1)1.2 主控制器方案 (1)1.3 显示模块方案 (1)1.4 报警模块方案 (1)1.5 无线通信方案 (2)2 系统硬件设计 (2)2.1 主控制器设计 (2)2.1.1 概述 (2)2.1.2 晶振电路 (2)2.1.3 复位电路 (2)2.2 主机显示电路 (3)2.3 主机报警电路 (3)2.4 从机按键电路 (3)2.5 无线通信电路 (4)3 系统软件设计 (4)3.1 主机系统软件设计 (4)3.2 显示软件设计 (4)3.3 无线通信子程序设计 (5)3.4 按键扫描子程序设计 (5)4 组装和测试 (5)4.1 系统组装 (5)4.2液晶显示上电测试 (7)4.3系统报警上电测试 (7)4.4无线通信上电测试 (7)5 结语 (7)参考文献 (8)致谢 (9)附录 (10)基于51单片机的病床呼叫系统摘要此项目为基于51单片机的病床呼叫系统,系统选取STC89C52控制器作为主控芯片。

系统包括一个主板(接收信号)也就是下图中的主机,发送板(发送呼叫信号)也就是下图中的从机,从机设计4个按键,为4个病床报警按键。

通过无线模块实现通信。

当病房中有病床按键按下后,通过无线模块通知主机,主机显示病床号信息,并且进行声音报警提示,如果主机的按键按下,则取消报警。

显示电路选取液晶LCD1602显示。

无线通信选择NRF24L01。

选择C语言进行软件设计,应用Keil软件进行程序设计编写。

最终实现病床呼叫系统,完成病床远程呼叫报警。

关键词: STC89C52;声音报警;无线通信;液晶显示;病床呼叫Hospital-bed Alarming System Based on 51MicrocontrollerAbstractThis project is a hospital -bed alarming based on 51 microcontroller The system selects STC89C52 controller as the main control chip. The system consists of a motherboard (receiving signal) which is the host in the following picture. The sending board (sending call signal) is the slave in the following picture. The slave has four keys and four alarm keys for the sickbed. Communication is realized through wireless module. When the key of the hospital bed is pressed in the ward, the host is notified by the wireless module. The host displays the information of the hospital bed number and gives a sound alarm. If the key of the host is pressed, the alarm will be cancelled. LCD 1602 is selected as the display circuit. NRF24L01 is chosenfor wireless communication. C language is chosen for software design and Keil software is used for programming. Finally, the hospital bed call system is realized, and the remote call and alarm of the hospital bed are completed.Keywords:STC89C52; audible alarm ;wireless communication; liquid crystal display; hospital-bed alarming引言随着科学技术的日益发展和不断进步,流体流量和流体流速的精确控制被运用在越来越多的场合。

C51LCD1602VB上位机实现简单通信.

C51LCD1602VB上位机实现简单通信.

设计基本原理主要功能:上位机和下位机连接好后握手,如果成功,上位机就可以发字符串让下位机的LCD显示出来,如果没有握手就不显示上位机发来的内容.下位机设计:主程序首先初始化串口和LCD,然后进入一个死循环,这个循环往LCD写dataArray这个数组中的数据,因此只要改变了这个数组中的第0-31位的内容就相当于改变了屏幕上显示的内容. 当串口发来消息的时候,执行中断号为4(串口中断)的服务子程序.这时候还不能让上位机往下位机传字符串,因此需要判断是否已经握手,判断的标志就是dispEn (display enable),如果等于0说明还没有握手,就把用户发来的数据当成是控制字control,如果是等于1说明之前已经握过手了,就把用户发来的数据放到dataArray中.最后判断控制字是否是握手,如果control等于0x00是就握手信号,然后回复0x01.然后把dispEn=1,最后把控制字control改掉(因为下一次中断可能已经不是握手信号了)上位机设计:由于已经把端口号写在vb程序中了,所以要改端口号的话要进vb的代码中把mPort = 4 中的4 改为自己需要的串行端口号.然后运行程序,打开端口,此时没有和下位机握手,所以输入数据后单击发送是没有反应的,所以需要先单击握手按钮,向传哭发送0x00,然后延时800毫秒等待回复,然后接收数据,如果回复的是0x01那就表明握手成功,如果没有回复那就是握手失败.用户点击发送信息,上位机把字符串拆分成字符来发送一次发送一个字符,每个字符发送延时30毫秒避免因为连续发送而造成的乱码.a)原理框图b)硬件电路原理图AT89C521~8:I/OP1口(P1.0~P1.7);9:复位脚(RST/Vpd);10~17:I/OP3口(P3.0=RXD,P3.1=TXD,P3.2=-INT0,P3.3=-INT1,P3.4=T0,P3.5=T1,P3.6=-WR,P3.7=-RD)主要是此引脚;18、19:晶振(18=XTAL2,19=XTAL1);20:地(Vss);21~28:I/OP2口(P2.0~P2.7);29:-PSEN;30:ALE/-PROG;31:-EA/Vpp32~39:I/OP0口(P0.7~P0.0);40:+5V电源。

基于51单片机的温度测试系统 VB上位机

基于51单片机的温度测试系统 VB上位机

简介:这是我学完51单片机的第一个作品,单片机型号为89c52,时钟芯片用的是DS1302,温度传感器用的是DS18B20,USB供电,掉电后时钟芯片继续工作,且已经设置好的温度上下限和闹钟数据不会丢失。

上位机是用VB语言写的,只是一个模型,从上位机上可以观察当前温度值以及温度上下限,以后会更加完善其功能。

下面是下位机程序和上位机程序,程序比较长,而且下位机程序的键盘部分写得有点麻烦。

下位机程序:/***************************************************************************************作者:江苏科技大学电子信息科学与技术二班吴亚迪注:此程序可以实现万年历闹钟温度测定温度超过上下限发出警报断电后时钟不停,且已设好的温度上下限和闹钟数据不会丢失****************************************************************************************/#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]="20 / / DAY- ";uchar code table1[]=" : : ";uchar code table2[]="0123456789";uchar code table3[]=" alarm clock ";sbit ds_clk=P3^6;sbit ds_io=P3^7;sbit ds_rst=P1^4;sbit lcdrs=P1^0;sbit lcdrw=P1^1;sbit lcden=P1^2;sbit scl=P3^2;sbit sda=P3^3;sbit ACC_7=ACC^7;sbit P34=P3^4;bit alarm=0;//闹钟标志位bit stop_alarm=0;//停止闹钟标志位uchar i,j;uchar th,tl; //温度上下限uint th1,th2,tl1,tl2;uchar min,hour,sec; //闹钟时分秒uint min1,min2,hour1,hour2,sec1,sec2;void delay(uint i){uint j;for(;i>0;i--)for(j=0;j<110;j++);}/***********************************************************************************************DS1302部分**************************************************************************************************/ char s,s1,s2; //时钟秒char m,m1,m2; //分char h,h1,h2; //时char day; //星期char date,date1,date2;//日期char mon,mon1,mon2; //月char year,year1,year2;//年void write_ds(uchar add,uchar date ) //向ds1302指定地址写数据{uchar i,temp;ds_rst=0;ds_clk=0;ds_rst= 1;for ( i=8; i>0; i-- ){ds_clk = 0;temp = add;ds_io= temp&0x01;add >>= 1;ds_clk = 1;}for ( i=8; i>0; i-- ){ds_clk = 0;temp = date;ds_io =temp&0x01;date >>= 1;ds_clk = 1;}ds_rst= 0;}uchar read_ds(uchar add ) //ds1302指定地址读数据{unsigned char i,temp,date1;ds_rst=0;ds_clk=0;ds_rst= 1;for ( i=8; i>0; i-- ){ds_clk = 0;temp = add;ds_io=temp&0x01;add >>= 1;ds_clk = 1;}for ( i=8; i>0; i-- ) //这里要注意{ACC_7=ds_io;ds_clk = 1;ACC>>=1;ds_clk = 0;}ds_rst=0;date1=ACC;return date1;}void init_ds() //初始化ds1302{write_ds(0x8e,0x00); //关闭写保护write_ds(0x80,0x22); //初始化秒write_ds(0x82,0x59); //分write_ds(0x84,0x23); //时write_ds(0x86,0x21); //日write_ds(0x88,0x05); //月write_ds(0x8a,0x06); //星期write_ds(0x8c,0x11); //年write_ds(0x8e,0x80); //开写保护}void read_all() //读s,m,h,date,mon,year,day{s=read_ds(0x81);s1=s/16;s2=s%16;m=read_ds(0x83);m1=m/16;m2=m%16;h=read_ds(0x85);h1=h/16;h2=h%16;date=read_ds(0x87);date1=date/16;date2=date%16;mon=read_ds(0x89);mon1=mon/16;mon2=mon%16;day=read_ds(0x8b);year=read_ds(0x8d);year1=year/16;year2=year%16;}/***********************************************************************************************1602部分**************************************************************************************************/ void write_com(uchar com) //写命令{lcdrs=0;lcden=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date)//写数据{lcdrs=1;lcden=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void init_1602() //初始化1602{lcdrw=0;write_com(0x01);write_com(0x38);write_com(0x0f);write_com(0x06);for(i=0;i<16;i++){write_date(table[i]);delay(10);}write_com(0x80+0x40);for(i=0;i<16;i++){write_date(table1[i]);delay(10);}write_com(0x80+0x40+0x0e);write_date(0xdf);delay(10);write_date('c');}/***********************************************************************************************EEPROM部分**************************************************************************************************/void delay1(){ ; ; }void init()//初始化总线{sda=1;delay1();scl=1;delay1();}void start()//开始函数{sda=1;delay1();scl=1;delay1();sda=0;delay1();}void stop()//停止函数{sda=0;delay1();scl=1;delay1();sda=1;delay1();}void respons()//应答{uchar i;sda=1;delay1();scl=1;while(sda==1&&i<250) i++;scl=0;delay1();}void write_byterom(uchar date)//向eeprom中写一字节数据{uchar i;for(i=0;i<8;i++){date=date<<1;scl=0;delay1();sda=CY;delay1();scl=1;delay1();}scl=0;delay1();}uchar read_byterom()//从eeprom中读一字节数据{uchar i,temp;scl=0;delay1();for(i=0;i<8;i++){scl=1;delay1();temp<<=1;temp|=sda;scl=0;delay1();}return temp;}void write_add(uchar add,uchar date)//指定地址写数据{start();write_byterom(0xa0);respons();write_byterom(add);respons();write_byterom(date);respons();stop();}uchar read_add(uchar add)//指定地址读数据{uchar temp;start();write_byterom(0xa0);respons();write_byterom(add);respons();start();write_byterom(0xa1);respons();temp=read_byterom();stop();return temp;}/***********************************************************************************************ds18b20部分**************************************************************************************************/ sbit DQ=P3^5;void delay2(uchar i){while(i--);}void init_ds18b20()//初始化ds18b20{uchar i;DQ=1;delay2(8);DQ=0;delay2(80);DQ=1;while(DQ==1&&i<255) i++;delay2(35);delay2(20);}void write_byte(uchar dat)//向ds18b20中写一字节{uchar i;for(i=0;i<8;i++){DQ=1;delay2(1);DQ=0;delay2(1);DQ=dat&0x01;delay2(5);DQ=1;dat>>=1;delay2(4);}}uchar read_byte()//从ds18b20中读一字节{uchar i,dat=0;for(i=0;i<8;i++){DQ=1;delay2(1);DQ=0;dat>>=1;DQ=1;if(DQ)dat=dat|0X80;delay2(4);}return dat;}uchar read_temp() //读温度函数{uchar a,b,c;init_ds18b20();write_byte(0xcc);write_byte(0x44);init_ds18b20();write_byte(0xcc);write_byte(0xbe);a=read_byte();b=read_byte();c=(b<<4)|(a>>4);return c;}uchar read_th()//读上限函数{uchar a,b,c;init_ds18b20();write_byte(0xcc);write_byte(0x44);init_ds18b20();write_byte(0xcc);write_byte(0xbe);a=read_byte();b=read_byte();c=read_byte();return c;}uchar read_tl()//读下限函数{uchar a,b,c;init_ds18b20();write_byte(0xcc);write_byte(0x44);init_ds18b20();write_byte(0xcc);write_byte(0xbe);a=read_byte();b=read_byte();a=read_byte();c=read_byte();return c;}/***********************************************************************************************键盘部分(P2^0~P2^3)**************************************************************************************************/void keyscan(){uchar temp,num1,num2;temp=P2;temp&=0x0f;if(temp!=0x0f) //消抖{delay(5);if(temp!=0x0f){temp=P2;temp&=0x0f;if(temp==0x0e){num1=1;write_ds(0x8e,0x00);write_ds(0x80,s|0x80);//禁止写保护while(temp==0x0e)//松手检测{temp=P2;temp&=0x0f;}while(1){temp=P2;temp&=0x0f;if(temp==0x0e){delay(5);temp=P2;temp&=0x0f;if(temp==0x0e){num1++;}}while(temp==0x0e)//松手检测{temp=P2;temp&=0x0f;}if(num1==1){write_com(0x80+0x40+0x08); write_com(0x0f);//光标闪烁temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测 {temp=P2;temp&=0x0f;}s=read_ds(0x81);s1=s/16;s2=s%16;s2+=1;if(s2==10){s1+=1;}if(s1==6) s1=0;write_com(0x80+0x40+0x07);write_date(table2[s1]);write_date(table2[s2]);write_ds(0x80,s1*16+s2);//向ds1302中写入秒 }}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测{temp=P2;temp&=0x0f;}s=read_ds(0x81);//读ds1302秒s1=s/16;s2=s%16;s2-=1;if(s2==-1){s2=9;s1-=1;}if(s1==-1) s1=5;write_com(0x80+0x40+0x07);write_date(table2[s1]);write_date(table2[s2]);write_ds(0x80,s1*16+s2);}}}if(num1==2){write_com(0x80+0x40+0x05);write_com(0x0f);temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测{temp=P2;temp&=0x0f;}m=read_ds(0x83);//从ds1302中读分m1=m/16;m2=m%16;m2+=1;if(m2==10){m2=0;m1+=1;}if(m1==6) m1=0;write_com(0x80+0x40+0x04);write_date(table2[m1]);write_date(table2[m2]);write_ds(0x82,m1*16+m2);//向ds1302中写入分 }}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测{temp=P2;temp&=0x0f;}m=read_ds(0x83);m1=m/16;m2=m%16;m2-=1;{m2=9;m1-=1;}if(m1==-1) m1=5;write_com(0x80+0x40+0x04);write_date(table2[m1]);write_date(table2[m2]);write_ds(0x82,m1*16+m2);}}}if(num1==3){write_com(0x80+0x40+0x02);write_com(0x0f);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测{temp=P2;temp&=0x0f;}h=read_ds(0x85);//从ds1302中读时 h1=h/16;h2=h%16;h2+=1;if(h2==10){h2=0;h1+=1;}if(h2==4&&h1==2){h2=0;h1=0;}write_com(0x80+0x40+0x01);write_date(table2[h1]);write_date(table2[h2]);write_ds(0x84,h1*16+h2);//向ds1302中写入时 }}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测{temp=P2;temp&=0x0f;}h=read_ds(0x85);h1=h/16;h2=h%16;h2-=1;if(h2==-1){h2=9;h1-=1;}if(h2==9&&h1==-1){h2=3;h1=2;}write_com(0x80+0x40+0x01);write_date(table2[h1]);write_date(table2[h2]);write_ds(0x84,h1*16+h2);}}}if(num1==4){write_com(0x80+0x0f);write_com(0x0f);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测{temp=P2;temp&=0x0f;}day=read_ds(0x8b);//从ds1302中读星期day+=1;if(day==8){day=1;}write_com(0x80+0x0f);write_date(table2[day]);write_ds(0x8a,day);//向ds1302中写入星期 }}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测{temp=P2;temp&=0x0f;}day=read_ds(0x8b);day-=1;if(day==0){day=7;}write_com(0x80+0x0f);write_date(table2[day]);write_ds(0x8a,day);}}}if(num1==5){write_com(0x80+0x09);write_com(0x0f);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测{temp=P2;temp&=0x0f;}date=read_ds(0x87);//从ds1302中读日期date1=date/16;date2=date%16;date2+=1;if(date2==10){date2=0;date1+=1;}if(date2==2&&date1==3){date2=0;date1=0;}if(date1==0&&date2==0){date1=0;date2=1;}write_com(0x80+0x08);write_date(table2[date1]);write_date(table2[date2]);write_ds(0x86,date1*16+date2);//向ds1302中写入日期 }}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测{temp=P2;temp&=0x0f;}date=read_ds(0x87);date1=date/16;date2=date%16;date2-=1;if(date2==-1){date2=9;date1-=1;}if(date2==9&&date1==-1){date2=1;date1=3;}if(date1==0&&date2==0){date1=3;date2=1;}write_com(0x80+0x08);write_date(table2[date1]);write_date(table2[date2]);write_ds(0x86,date1*16+date2); }}}if(num1==6){write_com(0x80+0x06);write_com(0x0f);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测{temp=P2;temp&=0x0f;}mon=read_ds(0x89);//从ds1302中读月mon1=mon/16;mon2=mon%16;mon2+=1;if(mon2==10){mon2=0;mon1+=1;}if(mon2==3&&mon1==1){mon2=0;mon1=0;}if(mon1==0&&mon2==0){mon1=0;mon2=1;}write_com(0x80+0x05);write_date(table2[mon1]);write_date(table2[mon2]);write_ds(0x88,mon1*16+mon2);//向ds1302中写入月 }}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测{temp=P2;temp&=0x0f;}mon=read_ds(0x89);mon1=mon/16;mon2=mon%16;mon2-=1;if(mon2==-1){mon2=9;mon1-=1;}if(mon2==9&&mon1==-1){mon2=2;mon1=1;}if(mon1==0&&mon2==0){mon1=1;mon2=2;}write_com(0x80+0x05);write_date(table2[mon1]);write_date(table2[mon2]);write_ds(0x88,mon1*16+mon2); }}}if(num1==7){write_com(0x80+0x03);write_com(0x0f);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测{temp=P2;temp&=0x0f;}year=read_ds(0x8d);//从ds1302中读年year1=year/16;year2=year%16;year2+=1;if(year2==10){year2=0;year1+=1;}if(year1==9){year1=0;}write_com(0x80+0x02);write_date(table2[year1]);write_date(table2[year2]);write_ds(0x8c,year1*16+year2);//向ds1302中写入年 }}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测{temp=P2;temp&=0x0f;}year=read_ds(0x8d);year1=year/16;year2=year%16;year2-=1;if(year2==-1){year2=9;year1-=1;}if(year1==-1){year1=7;}write_com(0x80+0x02);write_date(table2[year1]);write_date(table2[year2]);write_ds(0x8c,year1*16+year2); }}}if(num1==8) //修改上限{write_com(0x80+0x40+0x0d); write_com(0x0f);delay(10);write_com(0x80+0x40+0x09); write_com(0x0e);write_date('T');write_date('H');write_com(0x80+0x40+0x0d); write_com(0x0f);th=read_th();write_com(0x80+0x40+0x0b);if(th>=100){write_date('-');th=~th+1;}else write_date(' ');th1=th/10;th2=th%10;write_date(table2[th1]);write_date(table2[th2]);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测{temp=P2;temp&=0x0f;}tl=read_tl();th=read_th();th+=1;if(th==100){th=157;}if(th==256){th=0;}init_ds18b20(); //写上下限 write_byte(0xcc);write_byte(0x4e);write_byte(th);write_byte(tl);}}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测 {temp=P2;temp&=0x0f;}th=read_th();tl=read_tl();th-=1;if(th==256){th=255;}if(th==156){th=99;}init_ds18b20(); //写上下限write_byte(0xcc);write_byte(0x4e);write_byte(th);write_byte(tl);}}}if(num1==9) //修改下限{write_com(0x80+0x40+0x0d); write_com(0x0f);delay(10);write_com(0x80+0x40+0x09); write_com(0x0e);write_date('T');write_date('L');write_com(0x80+0x40+0x0d); write_com(0x0f);tl=read_tl();write_com(0x80+0x40+0x0b); if(tl>=100){write_date('-');tl=~tl+1;}else write_date(' ');tl1=tl/10;tl2=tl%10;write_date(table2[tl1]);write_date(table2[tl2]);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测 {temp=P2;temp&=0x0f;}tl=read_tl();th=read_th();tl+=1;if(tl==100){tl=157;}if(tl==256){tl=0;}init_ds18b20(); //写上下限 write_byte(0xcc);write_byte(0x4e);write_byte(th);write_byte(tl);}}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测 {temp=P2;temp&=0x0f;}th=read_th();tl=read_tl();tl-=1;if(tl==256){tl=255;}if(tl==156){tl=99;}init_ds18b20(); //写上下限write_byte(0xcc);write_byte(0x4e);write_byte(th);write_byte(tl);}}}if(num1==10){write_com(0x80+0x40+0x09); write_com(0x0e);write_date(' ');write_date(' ');write_date(' ');init_ds18b20(); //拷贝上下限write_byte(0xcc);write_byte(0x48);num1=0;write_ds(0x80,s&0x7f);write_ds(0x8e,0x80);//开启写保护 break;}}}if(temp==0x07)//闹钟设定{delay(5);if(temp==0x07){while(temp==0x07){temp=P2;temp&=0x0f;}if(alarm==1){P34=1;alarm=0;stop_alarm=1;}else{num2=1;while(1){temp=P2;temp&=0x0f;if(temp==0x07){delay(5);temp=P2;temp&=0x0f;if(temp==0x07){num2++;}}while(temp==0x07)//松手检测{temp=P2;temp&=0x0f;}if(num2==1)//按下第一次显示上次设定的时间 {write_com(0x80);for(i=0;i<16;i++){write_date(table3[i]);delay(10);}write_com(0x80+0x40+0x0c);write_date(' ');write_date(' ');write_date(' ');write_date(' ');hour=read_add(1);hour1=hour/10;hour2=hour%10;min=read_add(7);min1=min/10;min2=min%10;sec=read_add(4);sec1=sec/10;sec2=sec%10;write_com(0x80+0x40+0x01); write_date(table2[hour1]);write_date(table2[hour2]);write_com(0x80+0x40+0x04); write_date(table2[min1]);write_date(table2[min2]);write_com(0x80+0x40+0x07); write_date(table2[sec1]);write_date(table2[sec2]);}if(num2==2)//按下第二次设定秒 {write_com(0x80+0x40+0x08); write_com(0x0f);delay(100);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测 {temp=P2;temp&=0x0f;}sec++;if(sec==60) sec=0;}}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测 {temp=P2;temp&=0x0f;}sec--;if(sec==255) sec=59;}}}sec1=sec/10;sec2=sec%10;write_com(0x80+0x40+0x07); write_date(table2[sec1]);write_date(table2[sec2]);if(num2==3)//按下第三次设定分 {write_com(0x80+0x40+0x05); write_com(0x0f);delay(100);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测 {temp=P2;temp&=0x0f;}min++;if(min==60) min=0;}}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测 {temp=P2;temp&=0x0f;}min--;if(min==255) min=59;}}}min1=min/10;min2=min%10;write_com(0x80+0x40+0x04); write_date(table2[min1]);write_date(table2[min2]);if(num2==4)//按下第四次设定时 {write_com(0x80+0x40+0x02); write_com(0x0f);delay(100);temp=P2;temp&=0x0f;if(temp==0x0d){delay(5);if(temp==0x0d){while(temp==0x0d)//松手检测 {temp=P2;temp&=0x0f;}hour++;if(hour==24) hour=0;}}else if(temp==0x0b){delay(5);if(temp==0x0b){while(temp==0x0b)//松手检测{temp=P2;temp&=0x0f;}hour--;if(hour==255) hour=23;}}}hour1=hour/10;hour2=hour%10;write_com(0x80+0x40+0x01);write_date(table2[hour1]);write_date(table2[hour2]);if(num2==5) //按下第五次向eeprom中写入时分(秒省略),并退出循环 {write_add(7,min);delay(10);write_add(1,hour);write_com(0x80);for(i=0;i<16;i++){write_date(table[i]);delay(10);}write_com(0x80+0x40+0x0e);write_date(0xdf);write_date('c');break;}}}}}}}}/***********************************************************************************************主函数部分**************************************************************************************************/ void main(){uchar temp;init();init_1602();init_ds();temp=read_temp();delay(100);while(1)//循环检测{read_all();keyscan();write_com(0x80+0x40+0x01);write_date(table2[h1]);write_date(table2[h2]);write_com(0x80+0x40+0x04);write_date(table2[m1]);write_date(table2[m2]);write_com(0x80+0x40+0x07);write_date(table2[s1]);write_date(table2[s2]);write_com(0x80+0x02);write_date(table2[year1]);write_date(table2[year2]);write_com(0x80+0x05);write_date(table2[mon1]);write_date(table2[mon2]);write_com(0x80+0x08);write_date(table2[date1]);write_date(table2[date2]);write_com(0x80+0x0f);write_date(table2[day]);temp=read_temp();th=read_th();tl=read_tl();//*********************************************************************************温度上限先检测及报警write_com(0x80+0x40+0x0b);if(temp<128) //查看温度是否超过上下限{if((th>128)||(th<128&&temp>=th)||(tl<128&&temp<=tl)){P34=0;delay(1000);P34=1;}}if(temp>128) //temp>128时温度取反后加一,查看温度是否超过上下限{if((th>128&&temp>=th)||(tl>128&&temp<=tl)||(tl<128)){P34=0;delay(1000);P34=1;}write_date('-');temp=~temp+1;}else write_date(' ');write_date(table2[temp/10]);write_date(table2[temp%10]);min=read_add(7);delay(5);hour=read_add(1);delay(5);//***********************************************************************************闹钟检测及报警if((min==m1*10+m2)&&stop_alarm){}else if((min==m1*10+m2)&&(hour==h1*10+h2)&&(!stop_alarm)) //闹钟{alarm=1;}if((min!=m1*10+m2)&&stop_alarm){stop_alarm=0;}if(alarm==1){P34=0;delay(30);P34=1;delay(100);P34=0;delay(30);P34=1;delay(100);P34=0;delay(30);P34=1;delay(100);P34=0;delay(30);P34=1;delay(100);}//*************************************************************************************************** }}上位机程序(VB语言):Option ExplicitDim i%Dim buf$Private Sub Form_Load()mPort = 2MSComm1.PortOpen = TrueMSComm1.RThreshold = 1MSComm1.InBufferCount = 0MSComm1.InputMode = comInputModeTextText1.FontSize = 10End SubPrivate Sub MSComm1_OnComm() Select Case mEvent Case comEvReceivebuf = Trim(Str(Asc(MSComm1.Input))) i = i + 1If i = 1 ThenText1.Text = bufEnd IfIf i = 2 ThenText2.Text = bufEnd IfIf i = 3 Theni = 0Text3.Text = bufEnd IfEnd SelectEnd Sub上位机运行图片:。

89C51 PS2键盘控制LCD1602显示(已通过硬件实..

89C51 PS2键盘控制LCD1602显示(已通过硬件实..

实验二十:LCD1602+PS2键盘输入实验一.实验目的:熟悉PS2协议。

二.实验原理图:键盘与单片机的连接LCD1602连接图华南理工大学无线电爱好者协会F D R 工作室三.硬件连线图:四.实验原理:PS/2通信协议是键盘与其他硬件通信时的一种半双工通信协议,键盘通过Data 线向外发送数据,数据时钟由键盘产生,在协议中数据的传送格式为短帧格式,一般为11位,各位的含义如下图所示:Start D0 D1 D2 D3 D4D5D6 D7 Parity StopStart :起始位,总为‘0’(低电平)D0~D7:8位数据位(低位在前,高位在后) Parity :奇偶校验位(为奇校验) Stop :停止位,总为‘1’(高电平)键盘向外发送数据的时序图如下图所示:键盘首先检查Clock 线和Data 线是否同时为高电平时,若是,则键盘产生Clock 信号,并将待发的数据按照数据帧的格式逐位放在数据线上,数据线在时钟的高电平期间改变状态,时钟的下降沿将数据锁定到数据线上,此时外界就可以到数据线上读取数据。

键盘同步时钟的最大频率为33KHZ ,一般情况下使用10~20KHZ 的频率。

本实验主要是接收由键盘Data 线发送过来的11位串行数据。

用的是11位移位寄存器的基本原理。

实现将由键盘发送过来的键盘扫描码转换成ASCII 码,并在LCD1602液晶上显示出来。

五.实验代码:华南理工大学无线电爱好者协会F D R 工作室//===========================ps2.h 头文件=============================// #ifndef PS2_H #define PS2_Hsbit keydata=P3^3; sbit clk=P3^2;unsigned char times=0; unsigned char i=0;unsigned char keycode=0,ps2_key; //ps2_key 用于存放接收到的键码static unsigned char BF=0; //标识是否有字符被收到unsigned char code noshift[80][2]= {1 , 8,// { f9 } 3 , 4,// { f5 } 4 , 2,// { f3 } 5 , 0,// { f1 } 6 , 1,// { f2 } 7 ,11,// { f12 } 9 , 9,// { f10 } 13 ,25,// { tab } 20 ,27,// { ctrl } 17 ,28,// { alt } 41 ,29,// { space } 31 ,30,// { win } 12 , 3,// { f4 } 11 , 5,// { f6 } 10 , 7,// { f8 } 14 ,96,// { ` } 22 ,49,// { 1 } 28 ,97,// { a } 30 ,50,// { 2 } 33 ,99,// { c } 38 ,51,// { 3 } 37 ,52,// { 4 } 46 ,53,// {5 }47 ,31,// { winright} 54 ,54,// { 6 } 61 ,55,// { 7 } 62 ,56,// { 8 } 50 ,98,// { b } 35 ,100,// { d } 36 ,101,// { e } 43 ,102,// { f } 52 ,103,// { g } 51 ,104,// { h } 59 ,106,// { j } 58 ,109,// { m } 49 ,110,// { n } 21 ,113,// { q } 45 ,114,// { r }华南理工大学无线电爱好者协会F D R 工作室44 ,116,// { t } 60 ,117,// { u } 42 ,118,// { v } 29 ,119,// { w } 34 ,120,// { x } 53 ,121,// { y } 26 ,122,// { z } 65 ,44,// { , } 66 ,107,// { k } 67 ,105,// { i } 68 ,111,// { o } 69 ,48,// { 0 } 70 ,57,// { 9 } 73 ,46,// { . } 74 ,47,// { / } 75 ,108,// { l } 76 ,59,// { ; } 77 ,112,// { p } 78 ,45,// { - } 82 ,39,// { ' } 85 ,61,// { = } 84 ,91,// { [ } 91 ,93,// { ] } 88 ,26,// { caps } 93 ,92,// { \ } 90 ,32,// { enter } 120,10,// { f11 } 102,12,// { back } 224,13,// { home } 105,14,// { end } 125,15,// { pageup } 122,16,// { pagedown } 117,17,// { up } 114,18,// { down } 107,19,// { left } 116,20,// { right } 113,21,// { del } 112,22,// { insert } 225,23,// { pause } 118,24,// { esc } 131, 6,// { f7 } };unsigned char code addshift[47][2]= {14,126, // { ~ } 22, 33, // { ! } 30, 64, // { @ } 38, 35, // { # } 37, 36, // { $ } 46, 37, // { % } 54, 94, // { ^ }华南理工大学无线电爱好者协会F D R 工作室62, 42, // { * } 70, 40, // { ( } 69, 41, // { ) } 78, 95, // { _ } 85, 43, // { + } 93,124, // { | } 84,123, // { { } 91,125, // { } } 76, 58, // { : } 82, 34, // { " } 65, 60, // { < } 73, 62, // { > } 74, 63, // { ? } 28 ,65,// { a } 50 ,66,// { b } 33 ,67,// { c } 35 ,68,// { d } 36 ,69,// { e } 43 ,70,// { f } 52 ,71,// { g } 51 ,72,// { h } 67 ,73,// { i } 59 ,74,// { j } 66 ,75,// { k } 75 ,76,// { l } 58 ,77,// { m } 49 ,78,// { n } 68 ,79,// { o } 77 ,80,// { p } 21 ,81,// { q } 45 ,82,// { r } 27 ,83,// { s } 44 ,84,// { t } 60 ,85,// { u } 42 ,86,// { v } 29 ,87,// { w } 34 ,88,// { x } 53 ,89,// { y } 26 ,90,// { z } };unsigned char getchar(unsigned char k) //转换键码为ASCII 码 { unsigned char j; if(!i)for(j=0;j<80;j++) {if(noshift[j][0]==k){ps2_key=noshift[j][1];return 1;} } elsefor(j=0;j<47;j++)华南理工大学无线电爱好者协会F D R 工作室{if(addshift[j][0]==k){ps2_key=addshift[j][1];return 1;} } return 0; }void Keyboard_out(void) interrupt 0 {if(times<9) {keycode=keycode>>1; //因键盘数据是低>>高,结合上一句所以右移一位if(keydata) keycode=keycode | 0x80; //当键盘数据线为1时为1到最高位 }times++; if(times>10) {times=0;if(keycode==0xe0 || keycode==0xf0){}//return;} else if((keycode==18 || keycode==89) && i==0) {i=1;} else if((keycode==18 || keycode==89) && i==1) {i=0;} else {EX0=0;BF=1;} //关中断等显示完后再开中断 //当中断11次后表示一帧数据收完,清变量准备下一次接收 //(注:如这里不用BF 和关中断直接调Decode() //则所Decode 中所调用的所有函数要声明为再入函数)} // while(!clk); //等待PS/2CLK 拉高 }#endif//=========================1602液晶头文键=================// #ifndef LCD1602_4_H #define LCD1602_4_H#include <reg52.h> #include <intrins.h>#define MSB 0x80 //读忙位 #define HIGH 1 #define LOW 0//*****************************************#define DATA_MODE 0x28 //LCD 模式设置,0x28位四位数据线模式 #define OPEN_SCREEN 0x0f //打开LCD 显示,有光标;0x0c 没有光标 #define DISPLAY_ADDRESS 0x80 //写地址指令#define CLEARSCREEN LCD_en_com(0x01) //清屏华南理工大学无线电爱好者协会F D R 工作室//***********//LCD1602的接线//***************************** #define LCDIO P0 //LCD1602的高四位接在P0口的高四位sbit LCD1602_RS=P0^0; //RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

lcd1602的用法

lcd1602的用法

LCD1602的用法一、简介LCD1602是一款常用的液晶显示模块,它具有16x2的字符显示能力,可以显示基本的英文、数字和符号。

通过与微处理器或单片机等控制器的连接,可以实现各种数据和信息的显示。

二、硬件连接1. 电源:LCD1602模块需要5V电压供电,可以使用USB转RS232接口或直接连接5V电源。

2. 数据线:LCD1602模块需要连接数据线才能与控制器通信。

常见的连接方式是使用4条数据线:RS、RW、E。

其中RS线控制亮灭,RW线控制光标,E线控制开关。

3. 地线:通常需要连接一个公共地线,以使电路稳定。

三、软件实现以下是一个简单的示例代码,使用C语言和LCD1602模块实现显示字符串的功能:```c#include <reg52.h> // 包含8051单片机寄存器定义#include <lcd1602.h> // 包含LCD1602驱动库文件// 声明LCD1602结构体变量LCD1602 lcd;void main() {// 初始化LCD1602模块lcd_init(&lcd);lcd_clear(&lcd); // 清空屏幕// 显示字符串"Hello, world!"lcd_puts(&lcd, "Hello, world!");// 等待一段时间,以便观察显示效果delay(500);}```四、常用命令LCD1602模块支持一些常用的命令,如光标移动、清屏、显示文本等。

具体命令可以参考LCD1602驱动库文档。

五、注意事项1. LCD1602模块的字符宽高比为4:5,因此需要调整显示的字符大小以适应屏幕。

2. 需要根据具体的应用场景和硬件配置选择合适的LCD1602模块和驱动库。

不同的模块和库可能存在差异,需要参考相应的文档进行操作。

3. 在实际应用中,需要考虑与其他设备的接口和控制方式,确保数据传输的正确性和稳定性。

单片机控制的lcd1602字符液晶滚动电路功能说明

单片机控制的lcd1602字符液晶滚动电路功能说明

单片机控制的lcd1602字符液晶滚动电路功能说明功能说明:单片机控制的LCD1602字符液晶滚动电路该电路是由单片机控制的LCD1602字符液晶显示屏的滚动功能。

通过单片机的程序控制,可以实现字符的滚动显示,从而达到信息展示的目的。

具体功能说明如下:1. 显示屏控制:该电路使用LCD1602字符液晶显示屏作为显示器,通过单片机的控制,可以控制显示屏上的字符显示。

显示屏具有2行16列的字符显示区域。

2. 滚动显示:通过单片机的程序控制,可以实现字符的滚动显示。

滚动显示可以从左向右或者从右向左进行,可以设置滚动速度和滚动内容。

3. 单片机控制:该电路使用单片机作为控制核心,通过单片机的GPIO口控制显示屏的数据和控制信号。

单片机可以根据用户的需求,通过编程实现不同的滚动效果。

4. 滚动速度调节:用户可以通过调节单片机程序中的延时参数,来控制滚动速度。

延时时间越短,滚动速度越快;延时时间越长,滚动速度越慢。

5. 滚动内容设置:用户可以通过编程将需要滚动显示的内容存储在单片机的内存中,然后通过单片机控制,将内容逐个字符地显示在LCD1602字符液晶显示屏上。

6. 滚动方向选择:用户可以通过编程设置滚动的方向,可以选择从左向右滚动或者从右向左滚动。

7. 硬件连接:该电路需要将单片机的GPIO口与LCD1602字符液晶显示屏的数据和控制信号引脚连接起来,通过连接线进行数据传输和控制。

总结:该电路通过单片机控制LCD1602字符液晶显示屏的滚动功能,可以实现字符的滚动显示,从而达到信息展示的目的。

用户可以通过编程设置滚动速度、滚动内容和滚动方向,灵活控制滚动效果。

这种电路在信息展示、广告宣传等领域有着广泛的应用。

LCD1602单片机的应用原理

LCD1602单片机的应用原理

LCD1602单片机的应用原理1. 介绍LCD1602是一种常见的字符型液晶显示器,广泛应用于单片机嵌入式系统中。

LCD1602能够在有限的字符显示区域内同时显示多个字符,通过单片机的控制,实现字符的显示和变化。

本文将介绍LCD1602的应用原理,包括LCD和单片机之间的连接方法、LCD的工作原理以及控制LCD1602显示字符的方法。

2. 连接方法要使用LCD1602显示字符,需要将其与单片机连接起来。

连接方法如下:•将LCD1602的VDD引脚连接到5V电源•将LCD1602的VSS引脚连接到地线•将LCD1602的VO引脚连接到一个可变电位器,用于调整对比度•将LCD1602的RS引脚连接到单片机的某个IO口•将LCD1602的RW引脚连接到地线•将LCD1602的E引脚连接到单片机的某个IO口•将LCD1602的D0-D7引脚连接到单片机的相应IO口以上是最基本的连接方法,具体连接方式可以根据单片机的型号和LCD1602的引脚分配图进行调整。

3. LCD的工作原理LCD1602是一种被动矩阵液晶显示器,其工作原理如下:•LCD1602由多个液晶单元组成,每个液晶单元由一对平行的玻璃片夹持,夹入其中的是液晶材料。

•液晶材料分为两种类型:向列为正的液晶和向列为负的液晶。

它们在电场作用下会有不同的取向。

•LCD1602的显示原理是通过控制液晶材料的取向来达到显示字符的目的。

当电场作用在液晶上时,液晶将改变自身的取向,使通过液晶的光线发生折射,从而显示出字符。

•LCD1602的液晶单元按照2行16列进行排列,每个液晶单元可以显示一个字符。

通过改变电场的作用方式,可以控制不同位置的液晶单元显示不同的字符。

4. 控制LCD1602显示字符的方法要控制LCD1602显示字符,需要在单片机中编写相应的代码,通过控制IO口的状态来控制LCD1602的显示。

下面是一个示例的控制LCD1602显示字符的方法:1.初始化LCD1602:设置IO口方向并发送初始化命令和参数,将LCD1602设置为显示模式,并设置显示模式等相关参数。

lcd1602使用手册,LCD1602的使用详解

lcd1602使用手册,LCD1602的使用详解

lcd1602 使用手册,LCD1602 的使用详解LCD1602 是很多单片机爱好者较早接触的字符型液晶显示器,它的主控芯片是HD44780 或者其它兼容芯片。

刚开始接触它的大多是单片机的初学者。

由于对它的不了解,不能随心所欲地对它进行驱动。

经过一段时间的学习,我对它的驱动有了一点点心得,今天把它记录在这里,以备以后查阅。

一般来说,LCD1602 有16 条引脚,据说还有14 条引脚的,与16 脚的相比缺少了背光电源A(15 脚)和地线K(16 脚)。

我手里这块LCD1602 的型号是HJ1602A,是绘晶科技公司的产品,它有16 条引脚。

LCD1602 的基本操作1. 读状态:输入RS=0,RW=1,E=高脉冲。

输出:D0D7 为状态字。

2. 读数据:输入RS=1,RW=1,E=高脉冲。

输出:D0D7 为数据。

3. 写命令:输入RS=0,RW=0,E=低脉冲。

输出:无。

(写完置E= 高脉冲)4. 写数据:输入RS=1,RW=0,E=低脉冲。

输出:无。

分析时序图(1)写操作(单片机至HD44780)首先要对寄存器的选择和读、写操作选择进行配置。

RS 是寄存器选择,RS = 1 对数据进行操作;RS = 0 对指令进行操作。

接着对读写操作选择进行配置,RW = 0 写操作。

打开使能端,输入使能信号E = 1。

数据总线,对DB0~DB7 赋值,进行数据的传输【注】如果先打开使能,再进行其他配置的话,有可能传输的数据不是自己想要的。

(2)读操作(HD44780 至单片机)显示模块的指令集,根据自己的显示需要进行相应的配置显示的位置设置DDRAM显示在第一行某一列的数据可以写命令:0x80 | 0x**,显示在第二行某一列的数据可以写命令:0x80 | 0x40 | 0x** = 0xC0 | 0x**,0x80 是因为在设置DDRAM 地址时,DB7 固定是为1 的。

LCD1602 写入自己的字符及显示汉字1、由于LCD 是外部设备,处理速度比CPU 速度慢,向LCD 写入命令到完成功能需要一定的时间,在这个过程中,LCD 处于忙状态,不能向LCD 写入新的内容。

lcd1602介绍及其工作原理

lcd1602介绍及其工作原理

lcd1602介绍及其工作原理下载提示:该文档是本店铺精心编制而成的,希望大家下载后,能够帮助大家解决实际问题。

文档下载后可定制修改,请根据实际需要进行调整和使用,谢谢!本店铺为大家提供各种类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by this editor. I hope that after you download it, it can help you solve practical problems. The document can be customized and modified after downloading, please adjust and use it according to actual needs, thank you! In addition, this shop provides you with various types of practical materials, such as educational essays, diary appreciation, sentence excerpts, ancient poems, classic articles, topic composition, work summary, word parsing, copy excerpts, other materials and so on, want to know different data formats and writing methods, please pay attention!LCD1602介绍及其工作原理LCD1602是一款常见的液晶显示器模块,广泛应用于各种电子设备中。

51单片机驱动LCD1602程序设计(C语言)

51单片机驱动LCD1602程序设计(C语言)

4.显示开关控制指令
功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情况如下: 位名 D C B 设置 0=显示功能关 0=无光标 0=光标闪烁 1=显示功能开 1=有光标 1=光标不闪烁
5.设定显示屏或光标移动方向指令
功能:使光标移位或使整个显示屏幕移位。参数设定的情况如下: S/C 0 0 1 1 0 1 0 1 R/L 设定情况 光标左移 1 格,且 AC 值减 1 光标右移 1 格,且 AC 值加 1 显示器上字符全部左移一格,但光标不动 显示器上字符全部右移一格,但光标不动
10.数据写入 DDRAM 或 CGRAM 指令一览
功能:<1> 将字符码写入 DDRAM,以使液晶显示屏显示出相对应的字符; <2> 将使用者自己设计的图形存入 CGRAM。
11.从 CGRAM 或 DDRAM 读出数据的指令一览
功能:读取 DDRAM 或 CGRAM 中的内容。
基本操作时序:
读状态
从上图可以看出,“A”字的对应上面高位代码为 0100,对应左边低位代码为 0001,合起来就 是 01000001,也就是 41H。可见它的代码与我们 PC 中的字符代码是基本一致的。因此我们在向 DDRAM 写 C51 字符代码程序时甚至可以直接用 P1='A'这样的方法。 PC 在编译时就把“A”先转为 41H 代码了。 字符代码 0x00~0x0F 为用户自定义的字符图形 RAM(对于 5X8 点阵的字符,可以存放 8 组, 5X10 点阵的字符,存放 4 组),就是 CGRAM 了。后面我会详细说的。 0x20~0x7F 为标准的 ASCII 码, 0xA0~0xFF 为日文字符和希腊文字符, 其余字符码(0x10~ 0x1F 及 0x80~0x9F)没有定义。

上位机串口发送至单片机1602液晶

上位机串口发送至单片机1602液晶
*/voidlcd_wcmd(ucharcmd){//while(lcd_busy());LCD_RS=0;LCD_WR=0;
LCD_EN=0;_nop_();_nop_();P0=cmd;delayNOP();LCD_EN=1;delayNOP();
LCD_EN = 0;}tips:感谢大家的阅读,本文由我司收集整编。仅供参阅!
delay1(uintms)
{uchark;while(ms--){for(k=0;k
/******************************************************************//*
*//*检查LCD忙状态*//*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
uchardataRXDdata[]={0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20 };uchar temp,buf,m,count;
/*******************************************************************//
**//*写指令数据到LCD*//*RS=L,RW=L,E=高脉冲,D0-D7=指令码。*//*
*//******************************************************************
*
单片机接收到数据后发送TX-MCU给主机。**主机发送其它数据给单片机,
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

设计基本原理主要功能:上位机和下位机连接好后握手,如果成功,上位机就可以发字符串让下位机的LCD 显示出来,如果没有握手就不显示上位机发来的内容.下位机设计:主程序首先初始化串口和LCD,然后进入一个死循环,这个循环往LCD写dataArray这个数组中的数据,因此只要改变了这个数组中的第0-31位的内容就相当于改变了屏幕上显示的内容. 当串口发来消息的时候,执行中断号为4(串口中断)的服务子程序.这时候还不能让上位机往下位机传字符串,因此需要判断是否已经握手,判断的标志就是dispEn (display enable),如果等于0说明还没有握手,就把用户发来的数据当成是控制字control,如果是等于1说明之前已经握过手了,就把用户发来的数据放到dataArray中.最后判断控制字是否是握手,如果control等于0x00是就握手信号,然后回复0x01.然后把dispEn=1,最后把控制字control改掉(因为下一次中断可能已经不是握手信号了)上位机设计:由于已经把端口号写在vb程序中了,所以要改端口号的话要进vb的代码中把mPort = 4 中的4 改为自己需要的串行端口号.然后运行程序,打开端口,此时没有和下位机握手,所以输入数据后单击发送是没有反应的,所以需要先单击握手按钮,向传哭发送0x00,然后延时800毫秒等待回复,然后接收数据,如果回复的是0x01那就表明握手成功,如果没有回复那就是握手失败.用户点击发送信息,上位机把字符串拆分成字符来发送一次发送一个字符,每个字符发送延时30毫秒避免因为连续发送而造成的乱码.a) 原理框图b) 硬件电路原理图AT89C521~8:I/OP1口(P1.0~P1.7);9:复位脚(RST/Vpd);10~17:I/OP3口(P3.0=RXD,P3.1=TXD,P3.2=-INT0,P3.3=-INT1,P3.4=T0,P3.5=T1,P3.6=-WR,P3.7=-RD)主要是此引脚;18、19:晶振(18=XTAL2,19=XTAL1);20:地(Vss);21~28:I/OP2口(P2.0~P2.7);29:-PSEN;30:ALE/-PROG;31:-EA/Vpp32~39:I/OP0口(P0.7~P0.0);40:+5V电源。

MAX232第一部分是电荷泵电路。

由1、2、3、4、5、6脚和4只电容构成。

功能是产生+5v和-5v两个电源,提供给RS-232串口电平的需要。

第二部分是数据转换通道。

由7、8、9、10、11、12、13、14脚构成两个数据通道。

其中13脚(R1IN)、12脚(R1OUT)、11脚(T1IN)、14脚(T1OUT)为第一数据通道。

8脚(R2IN)、9脚(R2OUT)、10脚(T2IN)、7脚(T2OUT)为第二数据通道。

TTL/CMOS数据从T1IN、T2IN输入转换成RS-232数据从T1OUT、T2OUT送到电脑DB9插头;DB9插头的RS-232数据从R1IN、R2IN输入转换成TTL/CMOS数据后从R1OUT、R2OUT输出。

第三部分是供电。

15脚GND、16脚VCC(+5v)。

LCD16022. 软件设计a) 流程图b) 代码 (请参照代码附录第10页)调试连线装载下位机程序后开始调试。

打开下位机电源,在输出文本框中输入字母abc,点发送没反应。

点击握手按钮后,在接收文本框中显示握手成功后再点击发送按钮,LCD上显示出字母"abc"。

每点击一次就发送一次,LCD第一行被字母填满后会自动跳到第二显示,第二行也填满后会重新跳到第一行来继续显示,如此循环。

如果下位机电源没打开就向下位机发送握手,则会在接收文本框中显示握手失败。

发送的字母和数字,还有符号都能正确显示。

发送中文则显示为乱码。

代码附录下位机#include <reg51.h>#define uint unsigned int#define uchar unsigned charsbit RS = P2^6; //lcd命令数据状态口sbit RW = P3^6; //lcd读写口sbit E = P2^5; //lcd使能口uchar dispEn=0; //表示是否能把数据显示出来的状态,如果是1才能显示发来的内容,如果是0就要先握手uchar control; //上位机发来的不是数据的东西(比如握手请求)就存在这个变量uchar current=0; //数组下标,用来表示当前写入数据数组的第几个uchar dataArr[32]={"hello hx waiting for shake hand"};code uchar shOKStr[32]=("shake hand succesful");void lcd_init();void lcd_command(uchar); //lcd命令字写入void lcd_dataArr(uchar); //lcd显示数据写入void delay(uchar); //延时void displayArray(uchar *arr[]) ; //显示一个数组的内容void clearDataArr(); //清空显示数组void serial_init(void);void serial(void);// LCD 初始化void lcd_init(){lcd_command(0x38);lcd_command(0x38);lcd_command(0x08); // 显示开关lcd_command(0x01); // 清除LCD的显示内容lcd_command(0x06);lcd_command(0x0c);delay(2);}// LCD 指令void lcd_command(uchar l_data){RS=0;RW=0;E=1;P0=l_data;E=0;delay(2);RW=1;}// LCD 数据void lcd_data(uchar l_data){RS=1;RW=0;E=1;P0=l_data;E=0;delay(2);RW=1;}// 延时void delay(uchar i){uchar j;while(i--){j=128;while(j--);}}// 串口中断服务程序,从RI判断接收中断,TI判断发送中断,由软件清除void serial() interrupt 4 using 1{while(RI==0); //等待接收RI=0;if(current==32)current=0;//如果写到数组结尾就从头开始if(dispEn==1){dataArr[current]=SBUF; //如果已经握手成功就把SBUF送数据数组current++;}if(dispEn==0){control=SBUF; //如果没有握手成功就把SBUF送控制字符}if(control==0x00) //如果控制字符是握手00,那就回复01表示接受{SBUF=0x01; //发送回上位机说明握手接受while(TI==0);TI=0;for(current=0;current<32;current++) //显示握手成功dataArr[current]=shOKStr[current];dispEn=1; //我收过后可以接受数据了control = 0x01; //清除}}// 显示控制void displayArray(uchar arr[]){uchar i=0;lcd_command(0x80); //写第一行for(i=0;i<16;i++){lcd_data(arr[i]);}lcd_command(0xc0); //写第二行for(i=16;i<32;i++){lcd_data(arr[i]);}}void clearDataArr(){for(current=0;current<32;current++)dataArr[current]=" ";}// 初始化串口void serial_init(void){TMOD=0x20;TH1=0xf3; //2400波特TL1=0xf3;SCON=0xd8; //方式3PCON=0x00;TR1=1;ES=1;//打开串口中断EA=1;//允许中断RI=0;TI=0;}// 主函数void main(void){serial_init();lcd_init();delay(20000);while(1){displayArray(dataArr);//processmsg();}}上位机Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) '延时函数Private Sub clear_receivetext_Click()receivetext.Text = ""End SubPrivate Sub clear_sendtext_Click()sendtext.Text = ""End SubPrivate Sub close_Click()MSComm1.PortOpen = False '关闭串口Label3 = "当前状态:关闭"End SubPrivate Sub Command1_Click()End SubPrivate Sub clr_Click()On Error Resume Next '简单的错误处理If MSComm1.PortOpen = False ThenMsgBox "串口已关闭"End IfMSComm1.Output = Chr(255) '用FF代表清屏MSComm1.InputMode = comInputModeText '设置接受模式是文本接受,还是二进制接受End SubPrivate Sub Form_Load()Label3 = "当前状态:关闭"End SubPrivate Sub open_Click()mPort = 4 '使用串行端口4MSComm1.Settings = "2400,N,8,1" '设置波特率等MSComm1.InputLen = 0 '清空从接收缓存器中读到的字符MSComm1.PortOpen = True '打开端口Label3 = "当前状态:打开"End SubPrivate Sub receive_Click()receivetext.Text = MSComm1.Input '实现将接受到的数据以文本形式写到接收部分的窗体内这是核心代码。

相关文档
最新文档