用普通IO口驱动LCD显示

合集下载

用普通 IO 口驱动 LCD 显示

用普通 IO 口驱动 LCD 显示

用普通I/O口驱动LCD显示文件编码:HA0092s介绍:在一些特定环境,为了节省成本,控制I/O口需求较少,但芯片本身的I/O口又较多的情况下,客户往往用普通I/O口驱动LCD显示,而且在实际应用中很多学习者也需求这方面的知识,所以下面给出一个范例,以供参考。

理可以延长LCD的使用寿命。

如果LCD玻璃是3V,则V DD=3V;如果LCD玻璃是5V的,则V DD=5V。

5. 范例程序是以分钟计时的方式,从“00”~“59”循环显示。

图26. LCD 两个七段码对应表如表1所示。

表1程序清单:;*********************************************;FILE NAME: IO_LCD;MCU: HT46R22;MASK OPTION: WAKE-UP: PA6,PA7; PULL-HIGH: PA,PB,PC; IIC: DISABLE; PFD: DISABLE; PWM: DISABLE; WDT: ENABLE; CLRWDT: ONE; WDT CLOCK SOURCE: T1; WDT TIME OUT SELECT: WDT CLOCK SOURCE/32768 ; LVR: DISABLE; OSC: CRYSTAL; SYSVOLT: 3.0V; SYSFRAG: 4000KHZ;AUTHOR: RADOME;HISTORY: 2005.08.22;*********************************************include Ht46r22.incinclude Micro.inc;*********************************************IO_data .section 'data';*********************************************acc_bk db ?status_bk db ?pa_bk db ?pb_bk db ?pbc_bk db ?pulse_count db ?display_temp db ?display_temp0 db ?display_temp1 db ?display_temp2 db ?number0 db ?number1 db ?number2 db ?msecond db ?second db ?minute db ?;----------------------------------------segment0 equ pa_bk.0segment1 equ pa_bk.1segment2 equ pa_bk.2segment3 equ pa_bk.3segment4 equ pb_bk.4segment5 equ pb_bk.5com0 equ pb_bk.3com0_ctrl equ pbc_bk.3com1 equ pb_bk.6com1_ctrl equ pbc_bk.6com2 equ pb_bk.7com2_ctrl equ pbc_bk.7;*********************************************IO_code .section 'code';*********************************************org 0000hjmp initorg 0004h ;External Interrupt retiorg 0008h ;Timer Interruptjmp timer_intorg 0020h;*********************************************;Initializers;*********************************************init:clr intc0clr intc1clr tmrcclr msecondclr secondclr minuteclr pulse_countclr display_tempclr display_temp0clr display_temp1clr display_temp2clr number0clr number1clr number2mov a,11011111bmov pa,amov pa_bk,amov a,11010000bmov pac,aset pbset pb_bkmov a,00000001bmov pbc,amov pbc_bk,amov a,00000001bmov pc,aclr pccclr pdclr pdcmov a,00000101bmov intc0,amov a,94mov tmr,amov a,10010110bmov tmrc,a;********************************************* ;Main;********************************************* main_loop:clr wdtmov a,minuteadd a,bcd_tablemov tblp,atabrdl number2mov a,number2and a,0f0hswap accmov number0,amov a,number2and a,0fhmov number1,amov a,number0mov display_temp0,amov a,number1mov display_temp1,amov a,number2mov display_temp2,ajmp main_loop;********************************************* ;Interrupt;********************************************* timer_int: ;2592uspush;----------------------------------------;COM Operation Mode;----------------------------------------com_pulse:inc pulse_countmov a,pulse_countsub a,7snz cjmp $+3mov a,1mov pulse_count,amov a,pulse_countsdz accjmp $+2jmp com1_out_highsdz accjmp $+2jmp com1_out_lowsdz accjmp $+2jmp com2_out_highsdz accjmp $+2jmp com2_out_lowsdz accjmp com0_out_lowcom0_out_high:clr com0_ctrlset com0set com1_ctrlset com2_ctrljmp segment_pulsecom0_out_low:clr com0_ctrlclr com0set com1_ctrlset com2_ctrljmp segment_pulsecom1_out_high:set com0_ctrlclr com1_ctrlset com1set com2_ctrljmp segment_pulsecom1_out_low:set com0_ctrlclr com1_ctrlclr com1set com2_ctrljmp segment_pulsecom2_out_high:set com0_ctrlset com1_ctrlclr com2_ctrlset com2jmp segment_pulsecom2_out_low:set com0_ctrlset com1_ctrlclr com2_ctrlclr com2;---------------------------------------- ;SEGMENT Operation Mode;---------------------------------------- segment_pulse:;------------------------segment0_out:mov a,display_temp0add a,number_tablemov tblp,atabrdl display_temprl display_temprl display_temprl display_tempmov a,display_tempand a,00000111binc accsdz accjmp $+2jmp segment0_000sdz accjmp $+2jmp segment0_001sdz accjmp $+2jmp segment0_010sdz accjmp $+2jmp segment0_011sdz accjmp $+2jmp segment0_100sdz accjmp $+2jmp segment0_101sdz accjmp segment0_111jmp segment0_110segment0_000:mov a,com_000_table jmp segment0_next segment0_001:mov a,com_001_table jmp segment0_next segment0_010:mov a,com_010_table jmp segment0_next segment0_011:mov a,com_011_table jmp segment0_next segment0_100:mov a,com_100_table jmp segment0_next segment0_101:mov a,com_101_table jmp segment0_next segment0_110:mov a,com_110_table jmp segment0_nextsegment0_111:mov a,com_111_tablesegment0_next:add a,pulse_count mov tblp,atabrdl accclr segment0sz accset segment0 ;------------------------ segment1_out:rl display_temprl display_temprl display_tempmov a,display_temp and a,00000111binc accsdz accjmp $+2jmp segment1_000sdz accjmp $+2jmp segment1_001sdz accjmp $+2jmp segment1_010sdz accjmp $+2jmp segment1_011sdz accjmp $+2jmp segment1_100sdz accjmp $+2jmp segment1_101sdz accjmp segment1_111jmp segment1_110segment1_000:mov a,com_000_table jmp segment1_next segment1_001:mov a,com_001_table jmp segment1_next segment1_010:mov a,com_010_table jmp segment1_next segment1_011:mov a,com_011_table jmp segment1_next segment1_100:mov a,com_100_table jmp segment1_next segment1_101:mov a,com_101_table jmp segment1_next segment1_110:mov a,com_110_table jmp segment1_next segment1_111:mov a,com_111_tablesegment1_next:add a,pulse_count mov tblp,atabrdl accclr segment1sz accset segment1;------------------------ segment2_out:clr accsz display_temp.7 set acc.0inc accsdz accjmp $+2jmp segment2_000sdz accjmp $+2jmp segment2_001sdz accjmp $+2jmp segment2_010sdz accjmp $+2jmp segment2_011sdz accjmp $+2jmp segment2_100sdz accjmp $+2jmp segment2_101sdz accjmp segment2_111jmp segment2_110segment2_000:mov a,com_000_table jmp segment2_next segment2_001:mov a,com_001_table jmp segment2_next segment2_010:mov a,com_010_table jmp segment2_next segment2_011:mov a,com_011_table jmp segment2_next segment2_100:mov a,com_100_table jmp segment2_next segment2_101:mov a,com_101_table jmp segment2_next segment2_110:mov a,com_110_table jmp segment2_next segment2_111:mov a,com_111_tablesegment2_next:add a,pulse_count mov tblp,atabrdl accclr segment2sz accset segment2;------------------------ segment3_out:mov a,display_temp1 add a,number_table mov tblp,atabrdl display_temprl display_temprl display_temprl display_tempmov a,display_temp and a,00000111binc accsdz accjmp $+2jmp segment3_000sdz accjmp $+2jmp segment3_001sdz accjmp $+2jmp segment3_010sdz accjmp $+2jmp segment3_011sdz accjmp $+2jmp segment3_100sdz accjmp $+2jmp segment3_101sdz accjmp segment3_111jmp segment3_110segment3_000:mov a,com_000_table jmp segment3_next segment3_001:mov a,com_001_table jmp segment3_next segment3_010:mov a,com_010_table jmp segment3_next segment3_011:mov a,com_011_table jmp segment3_nextsegment3_100:mov a,com_100_table jmp segment3_next segment3_101:mov a,com_101_table jmp segment3_next segment3_110:mov a,com_110_table jmp segment3_next segment3_111:mov a,com_111_tablesegment3_next:add a,pulse_count mov tblp,atabrdl accclr segment3sz accset segment3;------------------------ segment4_out:rl display_temprl display_temprl display_tempmov a,display_temp and a,00000111binc accsdz accjmp $+2jmp segment4_000sdz accjmp $+2jmp segment4_001sdz accjmp $+2jmp segment4_010sdz accjmp $+2jmp segment4_011sdz accjmp $+2jmp segment4_100sdz accjmp $+2sdz accjmp segment4_111jmp segment4_110segment4_000:mov a,com_000_table jmp segment4_next segment4_001:mov a,com_001_table jmp segment4_next segment4_010:mov a,com_010_table jmp segment4_next segment4_011:mov a,com_011_table jmp segment4_next segment4_100:mov a,com_100_table jmp segment4_next segment4_101:mov a,com_101_table jmp segment4_next segment4_110:mov a,com_110_table jmp segment4_next segment4_111:mov a,com_111_tablesegment4_next:add a,pulse_count mov tblp,atabrdl accclr segment4sz accset segment4;------------------------ segment5_out:clr accsz display_temp.7 set acc.0inc accsdz accjmp $+2sdz accjmp $+2jmp segment5_001sdz accjmp $+2jmp segment5_010sdz accjmp $+2jmp segment5_011sdz accjmp $+2jmp segment5_100sdz accjmp $+2jmp segment5_101sdz accjmp segment5_111jmp segment5_110segment5_000:mov a,com_000_table jmp segment5_next segment5_001:mov a,com_001_table jmp segment5_next segment5_010:mov a,com_010_table jmp segment5_next segment5_011:mov a,com_011_table jmp segment5_next segment5_100:mov a,com_100_table jmp segment5_next segment5_101:mov a,com_101_table jmp segment5_next segment5_110:mov a,com_110_table jmp segment5_next segment5_111:mov a,com_111_tablesegment5_next:add a,pulse_countmov tblp,atabrdl accclr segment5sz accset segment5;---------------------------------------- ;Output COM&SEGMENT;---------------------------------------- output_com_segment:mov a,pb_bkmov pb,amov a,pbc_bkmov pbc,amov a,pa_bkmov pa,a;---------------------------------------- ;Time;---------------------------------------- inc msecondmov a,msecondsub a,192snz cjmp timer_endclr msecondinc secondmov a,secondsub a,120snz cjmp timer_endclr secondinc minutemov a,minutesub a,60snz cjmp timer_endclr minutetimer_end:popreti;********************************************* ;Table;********************************************* org 0700hnumber_table:; gbefadc0dw 11111010b ;"0" 0dw 00010010b ;"1" 1dw 10101110b ;"2" 2dw 10011110b ;"3" 3dw 01010110b ;"4" 4dw 11011100b ;"5" 5dw 11111100b ;"6" 6dw 00011010b ;"7" 7dw 11111110b ;"8" 8dw 11011110b ;"9" 9dw 00000100b ;"-" adw 00000000b ;" " b;-------------------------------------com_000_table:dw 0dw 1,0,1,0,1,0com_001_table:dw 0dw 1,0,1,0,0,1com_010_table:dw 0dw 0,1,1,0,1,0com_011_table:dw 0dw 0,1,1,0,0,1com_100_table:dw 0dw 1,0,0,1,1,0com_101_table:dw 0dw 1,0,0,1,0,1com_110_table:dw 0dw 0,1,0,1,1,0com_111_table:dw 0dw 0,1,0,1,0,1;----------------------------------------bcd_table:dw 00h,01h,02h,03h,04h,05h,06h,07h,08h,09h dw 10h,11h,12h,13h,14h,15h,16h,17h,18h,19h dw 20h,21h,22h,23h,24h,25h,26h,27h,28h,29h dw 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h dw 40h,41h,42h,43h,44h,45h,46h,47h,48h,49h dw 50h,51h,52h,53h,54h,55h,56h,57h,58h,59h dw 60h,61h,62h,63h,64h,65h,66h,67h,68h,69h dw 70h,71h,72h,73h,74h,75h,76h,77h,78h,79h dw 80h,81h,82h,83h,84h,85h,86h,87h,88h,89h dw 90h,91h,92h,93h,94h,95h,96h,97h,98h,99hend;*********************************************。

51单片机任意2个IO口驱动LCD1602

51单片机任意2个IO口驱动LCD1602

51单片机任意2个IO口驱动LCD1602相信大家对1602显示屏已经十分熟悉,驱动方式有8线制(需要11根线)和4线制(需要7根线),这里为大家推荐一种只需要2根线就能驱动1602的方法。

之前在网上见到Arduino通过IIC驱动1602的实例,本人完全不懂Arduino程序,看了一下驱动电路,发现PCF8574这个关键芯片,它就相当于一个桥梁,将IIC总线转换为8位准双向口。

思路1、单片机通过IIC与PCF8574进行通信。

首先写好IIC通信程序,网上到处都是IIC通信程序,很容易找。

PCF8574 的器件地址为40h,由于硬件地址引脚A0-A2可寻址8 个器件,所以器件地址并不唯一,具体说明大家去查查PCF8574芯片手册。

2、单片机4线制驱动1602网上也有很多相关程序,我就不再多说。

4线制驱动方式需要7个IO口(RS、RW、E 和4条数据线),而PCF8574提供了8位准双向口,所以管脚还有剩余。

3、IIC通信程序和1602的4线制驱动程序相结合4、51单片机任意2个IO口驱动1602成功!!!。

(我只是个业余爱好者,要是各位觉得太低端那就见谅了)驱动电路图效果图实物图Proteus仿真程序#include <reg52.h>#include <intrins.h>sbit SCL = P3^0;sbit SDA = P3^1;bit ack;unsigned char LCD_data;unsigned char code digit[ ]={"0123456789"}; //定义字符数组显示数字//*****************延时************************void delay_nus(unsigned int n) //N us延时函数{unsigned int i=0;for (i=0;i<n;i++)_nop_();}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i,j;for (i=0;i<n;i++)for (j=0;j<1140;j++);}void nop4(){_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期_nop_(); //等待一个机器周期}//***************************************void Start(){SDA=1;_nop_();SCL=1;nop4();SDA=0;nop4();SCL=0;_nop_();_nop_();}void Stop(){SDA=0;_nop_();SCL=0;nop4();//>4us后SCL跳变SCL=1;nop4();SDA=1;_nop_();_nop_();}//******************************************void Write_A_Byte(unsigned char c){unsigned char BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位{if((c<<BitCnt)&0x80) SDA=1; //判断发送位else SDA=0;_nop_();SCL=1; //置时钟线为高,通知被控器开始接收数据位nop4();_nop_();SCL=0;}_nop_();_nop_();SDA=1; //8位发送完后释放数据线,准备接收应答位_nop_();_nop_();SCL=1;_nop_();_nop_();_nop_();if(SDA==1)ack=0;else ack=1; //判断是否接收到应答信号SCL=0;_nop_();_nop_();}bit Write_Random_Address_Byte(unsigned char add,unsigned char dat){Start(); //启动总线Write_A_Byte(add); //发送器件地址if(ack==0)return(0);Write_A_Byte(dat); //发送数据if(ack==0)return(0);Stop(); //结束总线return(1);}//********************液晶屏使能*********************void Enable_LCD_write(){LCD_data|=(1<<(3-1));//E=1;Write_Random_Address_Byte(0x40,LCD_data);delay_nus(2);LCD_data&=~(1<<(3-1));//E=0;Write_Random_Address_Byte(0x40,LCD_data);}//*************写命令****************************void LCD_write_command(unsigned char command){delay_nus(16);LCD_data&=~(1<<(1-1));//RS=0;LCD_data&=~(1<<(2-1));//RW=0;Write_Random_Address_Byte(0x40,LCD_data);LCD_data&=0X0f; //清高四位LCD_data|=command & 0xf0; //写高四位Write_Random_Address_Byte(0x40,LCD_data);Enable_LCD_write();command=command<<4; //低四位移到高四位LCD_data&=0x0f; //清高四位LCD_data|=command&0xf0; //写低四位Write_Random_Address_Byte(0x40,LCD_data);Enable_LCD_write();}//*************写数据****************************void LCD_write_data(unsigned char value){delay_nus(16);LCD_data|=(1<<(1-1));//RS=1;LCD_data&=~(1<<(2-1));//RW=0;Write_Random_Address_Byte(0x40,LCD_data);LCD_data&=0X0f; //清高四位LCD_data|=value&0xf0; //写高四位Write_Random_Address_Byte(0x40,LCD_data);Enable_LCD_write();value=value<<4; //低四位移到高四位LCD_data&=0x0f; //清高四位LCD_data|=value&0xf0; //写低四位Write_Random_Address_Byte(0x40,LCD_data);Enable_LCD_write();}//**********************设置显示位置********************************* void set_position(unsigned char x,unsigned char y){unsigned char position;if (y == 0)position = 0x80 + x;elseposition = 0xc0 + x;LCD_write_command(position);}//**********************显示字符串*****************************void display_string(unsigned char x,unsigned char y,unsigned char *s){set_position(x,y);while (*s){LCD_write_data(*s);s++;}}//*************液晶初始化****************************void LCD_init(void){LCD_write_command(0x28);delay_nus(40);LCD_write_command(0x28);delay_nus(40);Enable_LCD_write();delay_nus(40);LCD_write_command(0x28); //4位显示!!!!!!!!!!!!!!!!!!LCD_write_command(0x0c); //显示开LCD_write_command(0x01); //清屏delay_nms(2);}void main(void){LCD_init();display_string(4,0,"imxuheng"); //显示一段文字display_string(2,1,"Hello Today!"); //显示一段文字while(1);}程序还不够完美,自身工作与电学没什么关系,只是业余爱好鼓捣鼓捣,希望各位能够提出修改意见。

如何使用普通IO口驱动LCD 单片机直接驱动 LCD 段码液晶 低成本 宁波北仑恒晶电子科技有限公司

如何使用普通IO口驱动LCD 单片机直接驱动 LCD 段码液晶 低成本 宁波北仑恒晶电子科技有限公司

如何使用普通I/O口驱动LCD一些特定环境,为了节省成本,又保证其性能。

在控制I/O口需求较少,但芯片本身的I/O口又较多的情况下,客户往往希望用普通I/O口驱动LCD显示,所以下面简单介绍一下,以供参考。

1、LCD简介:目前,市面主流LCD(液晶显示器)分成以下几大类:TN(扭曲阵列型)、STN(超扭曲阵列型)、DSTN(双层超扭曲阵列)、HPA(高性能定址或快速DSTN)、TFT(薄膜场效应晶体管)等。

由于成本因素,目前大多数采用的是TN型单色液晶显示器,它的原理是把液晶灌入两个列有细槽的平面之间。

这两个平面上的槽互相垂直(相交成90°),也就是说,若一个平面上的分子南北向排列,则另一平面上的分子东西向排列,而位于两个平面之间的分子被强迫进入一种90°扭转的状态。

由于光线顺着分子的排列方向传播,所以光线经过液晶时也被扭转90°。

当液晶上加一个电压时,分子便会重新垂直排列,使光线能直射出去,而不发生任何扭转。

LCD正是由这样两个相互垂直的极化滤光器构成的,所以在正常情况下应该阻断所有试图穿透的光线。

但是,由于两个滤光器之间充满了扭曲液晶,所以在光线穿出第一个滤光器后,会被液晶分子扭转90°,最后从第二个滤光器中穿出。

另一方面,若为液晶加一个电压,分子又会重新排列并完全平行,使光线不再扭转,所以正好被第二个滤光器挡住。

总之,加电将光线阻断,不加电则使光线射出。

LCD模型可以把其看成一个电容器,一个电极连接着公共极板,另一个连接着字符段。

LCD受电压的均方根值控制,当施加在LCD上的电压为零时,LCD呈透明状态。

当施加在字符段与公共极的电压大于LCD的阀值电压,则该字符段就显示出来。

如果用直流驱动LCD,将会引起显示单元永久性的损坏。

为了防止不可逆转的电化学反应使LCD损坏,加在所有字符段上的电压必须周期性翻转极性,以使加在字符段上的平均电压为0。

2、I/O口直接驱动LCD的实现方法下面介绍多路复用显示驱动方法。

用尽量少的IO来驱动1602

用尽量少的IO来驱动1602

上次发了个人肉驱动LCD1602的帖子,没什么技术含量,居然得裤子,有点不好意思,正好这几天有点时间,于是就再做一个小试验,用尽量少的IO来驱动16 02,以适应在某些引脚较少的MCU,如Tiny系列等。

废话少说,先上图,如果大家觉得有意思请起个哄...(原文件名:001.jpg)引用图片(原文件名:002.jpg)引用图片说明一下,连接LCD1602的四根引线,除了红黑两根电源,两根黄色的就是信号线,其中一根传送RS和E信号,另一根传送D4~D7信号,即用四位总线驱动。

电路和程序整理中,迟些上传。

[已上传]===================================================================== ================================================【59楼】更新:挑战一下极限,再减少一根线,仍然好使,不过要另加一个电容和一个二极管。

(原文件名:003.jpg)引用图片===================================================================== ================================================【167楼】更新:无线馈电及传送数据。

资料邮回复引用回编辑2010-10-03,23:08:10编辑删除2010-10-03,23:10:1资料邮件回复引用回沙渺编辑删除2010-10-03,23:1资料邮件回复引用回编辑删除2010-10-03,23:资料邮件回复引用回编辑删除2010-10-03,23:资料邮件回复引用回【5楼】JQ_Lin2010-10-03,23:46:3资料邮件回复引用回编辑删除编辑删除2010-10-04,00:资料邮件回复引用回编辑删除2010-10-04,00:资料邮件回复引用回2010-10-04,00:资料邮件回复引用回编辑删除v编辑删除2010-10-04,00:3资料邮件回复引用回积分:3205派别:等级:------来自:(原文件名:2wire_1602.PNG)引用图片示范程序很简单,不用多注释应该都能看懂。

51单片机io口输出低电平,但接了lcd后变成高电平

51单片机io口输出低电平,但接了lcd后变成高电平

51单片机io口输出低电平,但接了lcd后变成高电平1.引言1.1 概述概述部分的内容可以如下所示:在当前的电子设备应用中,单片机(Microcontroller)作为一种常见的电子控制器件,被广泛应用于各个领域。

而51单片机作为一种经典的单片机系列,也被广泛使用。

在使用51单片机进行控制时,IO口的控制是必不可少的一部分。

然而,在实际应用中,有时我们会遇到一些奇怪的问题。

比如,当我们将51单片机的IO口设置为输出低电平时,但是当我们接上LCD液晶显示屏之后,电平却变成了高电平,这究竟是为什么呢?本文将会对这个问题进行深入的探讨和分析。

首先,我们将介绍51单片机的IO口输出低电平的原理和应用场景。

然后,我们将会详细讨论当我们接上LCD液晶显示屏后,为什么IO口的电平会发生变化,其原因是什么。

通过本文的研究和分析,我们旨在帮助读者更好地理解51单片机的IO口输出低电平和LCD接口之间的关系,并引导读者解决此类问题时采取合适的措施。

接下来,我们将会从两个方面展开讨论。

首先,我们将介绍51单片机IO口输出低电平的基本原理和相关知识。

随后,我们将探讨当我们接上LCD液晶显示屏后,为什么IO口的电平会变为高电平。

通过本文的研究和分析,我们旨在帮助读者更好地理解这个问题,并提供一些解决方案,从而使读者能够更加顺利地进行51单片机与LCD液晶显示屏的接口设计和开发工作。

欢迎阅读本文,希望能为您带来有益的信息和启发。

1.2文章结构文章结构部分的内容可以包括以下内容:在本文中,将按照以下结构来描述和分析51单片机IO口输出低电平接上LCD后电平变高的现象。

首先,将在引言部分概述本文的主题和目的。

接下来,在正文部分,将详细介绍和解释51单片机IO口输出低电平的原理和机制,并通过实例来说明。

然后,将进一步探讨接上LCD后电平变高的原因,包括可能存在的电路连接问题和信号干扰等因素。

最后,在结论部分将总结全文的主要观点和结论,并进行结果分析和讨论。

基于IO的LCD显示频率计

基于IO的LCD显示频率计

通达学院2013 /2014 学年第一学期课程设计II实验报告模块名称Proteus软件设计(51单片机)专业通信工程学生班级100014学生学号10001435学生姓名朱昱光指导教师林建中第一部分实验目的和要求本课程设计是在理论课程的基础上,重点培养学生的动手能力,通过理论计算、实际编程、调试、测试、分析查找故障,解决在实际设计中的问题,使设计好的电路能正常工作,为下一部结合实际的硬件系统设计准备条件。

基本要求:1.用P1或P3口,产生一方波信号,频率为1000Hz,用一组数码管或LCD显示频率和周期以及脉宽等参数(也可用信号源或模拟信号源)。

2.将输出信号输入到另一端口(INT0/INT1)作频率计的信号输入端,测量此方波信号的频率、周期和脉宽,在另一组数码管或LCD上将参数值显示出来。

(刷新时间1秒)。

动态显示格式:自定根据提供的参考工程,在proteus平台自己重新画出实验所需要的电气原理图,并在此基础上编写相对应的程序,实现其功能,学习proteus软件的使用,其中包括原理图器件的选取、原理图的电气连接、程序的编写编译以及运行,并能查出其错误等。

第二部分实验工具及实验器件1.Proteus以及Keil软件的介绍Proteus是英国Labcenter公司开发的电路及单片机系统设计与仿真软件。

Proteus可以实现数字电路、模拟电路及微控制器系统与外设的混合电路系统的电路仿真、软件仿真、系统协同仿真和PCB设计等功能。

Proteus是目前唯一能对各种处理器进行实时仿真、调试与测试的EDA工具,真正实现了在没有目标原型时就可对系统进行调试、测试和验证。

Proteus软件大大提高了企业的产品开发效率,降低了开发风险。

由于Proteus软件逼真、真实的协同仿真功能,它也特别适合于作为配合单片机课堂教学和实验的学习工具。

Proteus软件提供了30多个元器件库、7000余种元器件。

元器件涉及电阻、电容、二极管、三极管、变压器、继电器、各种放大器、各种激励器、各种微控制器、各种门电路和各种终端等。

gpio控制lcd原理

gpio控制lcd原理

gpio控制lcd原理
GPIO(General Purpose Input/Output)控制LCD的基本原理是利用通用输入输出引脚实现LCD的显示控制。

具体来说,GPIO可以控制LCD的寄存器,以控制LCD的显示内容、颜色、亮度等。

在实现过程中,首先需要将LCD与树莓派的GPIO引脚连接起来,然后通过编程控制GPIO引脚的状态,从而控制LCD的显示。

例如,通过控制GPIO引脚的高低电平,可以控制LCD的背光亮灭、选择不同的显示区域、控制显示的字符等。

在编程方面,可以使用树莓派的GPIO库来实现对GPIO引脚的控制。

通过GPIO库提供的函数,可以方便地控制GPIO引脚的状态,从而实现LCD的显示控制。

需要注意的是,不同的LCD模块可能需要不同的GPIO引脚数量和控制方式,因此在实际应用中需要根据具体的LCD模块和树莓派型号进行相应的配置和控制。

一文解析段码LCD液晶屏驱动方法

一文解析段码LCD液晶屏驱动方法

一文解析段码LCD液晶屏驱动方法生活中小电器见到最多的lcd模组就是段码lcd液晶屏,段码lcd有普通的数码管的特征,又有点阵LCD的特征,固定的图形,优点是省成本而有好看,那么段码LCD 液晶屏是怎么驱动的呢?段码LCD液晶屏是如何显示的呢?跟随小编一起来了解一下吧。

段码LCD液晶屏驱动方法首先,不要以为用单片机来驱动就以为段码屏是直流驱动的,其实,段码屏是交流驱动,什么是交流?矩形波,正弦波等。

大家可能会经常用驱动芯片来玩,例如HT1621等,但是有些段式屏IO口比较少,或者说IO口充足的情况下,也可以省去写控制器的驱动了。

与单片机接口方便,而后者驱动电流小,功耗低、寿命长、字形美观、显示清晰、视角大、驱动方式灵活、应用广泛。

但在控制上LCD较复杂,因为LCD电极之间的相对电压直流平均值必须为0,否则易引起LCD氧化,因此LCD不能简单地用电平信号控制,而要用一定波形的方波序列来控制。

LCD显示有静态和时分割两种方式,前者简单,但是需要较多的口线;后者复杂,但所需口线较少,这两种方式由电极引线的选择方式确定。

下面以电子表的液晶显示为例,小时的高位同时灭或亮,分钟的高位在显示数码1~5时,其顶部和底部也是同时灭或亮,两个dot点也是同时亮或灭,其驱动方式是偏置比为1/2的时分割驱动,共有11个段电极和两个公共电极。

但是,IO模拟驱动段式液晶有一个前提条件,就是IO必须是三态,为什么?下面我们一起细细道来:第一步,段码式液晶屏的重要参数:工作电压,占空比,偏压比。

这三个参数非常重要,必须都要满足。

第二步,驱动方式:根据LCD 的驱动原理可知,LCD 像素点上只能加上AC 电压,LCD 显示器的对比度由COM脚上的电压值减去SEG 脚上的电压值决定,当这个电压差大于LCD 的饱和电压就能打开像素点,小于LCD 阈值电压就能关闭像素点,LCD 型MCU 已经由内建的LCD 驱动电路自动产生LCD 驱动信号,因此只要I/O 口能仿真输。

成功了!任意2个io直接驱动LCD1602,并且不需外加芯片很少的线驱动LCD1602

成功了!任意2个io直接驱动LCD1602,并且不需外加芯片很少的线驱动LCD1602

上次发了个人肉驱动LCD1602的帖子,没什么技术含量,居然得裤子,有点不好意思,正好这几天有点时间,于是就再做一个小试验,用尽量少的IO来驱动1602,以适应在某些引脚较少的MCU,如Tiny系列等。

废话少说,先上图,如果大家觉得有意思请起个哄...(原文件名:001.jpg)(原文件名:002.jpg)说明一下,连接LCD1602的四根引线,除了红黑两根电源,两根黄色的就是信号线,其中一根传送RS和E 信号,另一根传送D4~D7信号,即用四位总线驱动。

电路和程序整理中,迟些上传。

[已上传]============================================================================================ =========================【59楼】更新:挑战一下极限,再减少一根线,仍然好使,不过要另加一个电容和一个二极管。

(原文件名:003.jpg)============================================================================================ =========================【167楼】更新:无线馈电及传送数据。

(原文件名:007.jpg)这就是电路,细心的朋友会发现实物图中有几个贴片的阻容件,秘密就在这里,利用电容的记忆效应,把并行的数据转为串行。

(原文件名:2wire_1602.PNG)示范程序很简单,不用多注释应该都能看懂。

作为演示用途,其中有些长时间延时没有没有使用定时器,在多任务系统中当然要用定时中断来代替了。

// Drive a LCD1602 with 2 wire//===================================================//ICC-A VR application builder : 2010-10-3 19:30:02// Target : M16// Crystal: 4.0000Mhz#include <iom16v.h>#include <macros.h>#define Set_E PORTB|=2#define Clr_E PORTB&=~2#define Set_D PORTB|=1#define Clr_D PORTB&=~1#define Set_xy(y,x) Send(0,(y<<6)|(x&15)|0x80)//=================================================== void init_devices(void){CLI(); //disable all interruptsDDRB = 0x03;MCUCR = 0x00;GICR = 0x00;SEI(); //re-enable interrupts}//=================================================== void Delay(unsigned int i){while(i--);}//=================================================== void Send(unsigned char RS, unsigned char dat){unsigned char i;for (i = 2; i > 0; i--){if (dat & 0x80) Set_D; else Clr_D;Delay(10608);//14520usif (RS) Set_E;if (dat & 0x40) Set_D; else Clr_D;Delay(462); //660usif (dat & 0x20) Set_D; else Clr_D;Delay(18); //30usSet_E;if (dat & 0x10) Set_D; else Clr_D;_NOP(); //0.5us < t < 1.36usClr_E;dat <<= 4;}}//=================================================== void init_1602(void){unsigned char i = 3;Clr_D;Clr_E;Delay(10608);do{Clr_D;Delay(462);Set_D;Set_E;Delay(18);if (i == 0) Clr_D;_NOP();_NOP();_NOP();Clr_E;}while(i--);Send(0,0x28);Send(0,0x01);Send(0,0x0f);}//=================================================== void Send_S(unsigned char *p){while(*p) Send(1,*p++);}//=================================================== void main(void){unsigned char i;init_devices();init_1602();Set_xy(0,2);Send_S("Hello world!");Set_xy(1,3);Send_S("I'm COWBOY.");for (i=0;i<255;i++) Delay(10000);Send(0,0x01);Set_xy(0,3);Send_S("Welcome to");Set_xy(1,1);Send_S("");while(1);}。

LCD与FSMC连接原理

LCD与FSMC连接原理

LCD有如下控制线:CS:Chip Select片选,低电平有效RS:Register Select寄存器选择WR:Write写信号,低电平有效RD:Read读信号,低电平有效RESET:重启信号,低电平有效DB0-DB15:数据线假如这些线,全部用普通IO口控制。

根据LCD控制芯片手册(大部分控制芯片时序差不多):如果情况如下:DB0-DB15的IO全部为1(表示数据0xff),也可以为其他任意值,这里以0xff为例。

CS为0(表示选上芯片,CS拉低时,芯片对传入的数据才会有效)RS为1(表示DB0-15上传递的是要被写到寄存器的值),如果为0,表示传递的是数据。

WR为0,RD为1(表示是写动作),反过来就是读动作。

RESET一直为高,如果RESET为低,会导致芯片重启。

这种情况,会导致一个值0xff被传入芯片,被LCD控制芯片当作写寄存器值去解析。

LCD 控制芯片收到DB0-15上的值之后,根据其他控制线的情况,它得出结论,这个0xff是用来设置寄存器的。

一般情况下,LCD控制芯片会把传入的寄存器值的高8位当做寄存器地址(因为芯片内部肯定不止一个寄存器),低8位当做真正的要赋给对应寄存器值。

这样,就完成了一个写LCD控制芯片内部寄存器的时序。

如果上述情况不变,只将RS置低,那么得到的情况如下:LCD控制芯片会把DB0-15上的数据当做单纯的数据值来处理。

那么假如LCD处在画图状态,这个传入的值0xff,就会被显示到对应的点上,0xffff就表示白色,那么对应的点就是白色。

在这个数据值传递过来之前,程序肯定会通过设置寄存器值,告诉LCD控制芯片要写的点的位置在哪里。

如果上述两种情况都不变,分别把WR和RD的信号反过来(WR=1,RD=0),那么写信号就会被变成读信号。

读信号下,主控芯片需要去读DB0-15的值,而LCD控制芯片就会去设置DB0-15的值,从而完成读数据的时序。

读寄存器的时序麻烦一点。

MSP430 I-O 口驱动段式 LCD 设计(上)

MSP430 I-O 口驱动段式 LCD 设计(上)

MSP430 I/O 口驱动段式LCD 设计(上)
引言
本文介绍了使用MSP430 的GPIO 端口直接驱动LCD(液晶显示)的方法,从而扩展了不带LCD 控制器的MSP430 系列产品功能和使用场合,在一些要求低成本显示的场合,本方案具有很大的使用价值。

简介
针对LCD(液晶)显示,德州仪器MSP430 系列单片机可分为两类,一类内置LCD 控制器,另一类不带LCD 控制器。

内置LCD 控制器的单片机价
格较高,使用成本增加。

不带LCD 控制器的单片机可配合液晶驱动芯片使用,但需增加额外的芯片,也增加了成本。

本文介绍的方案,适用于不带LCD 控
制器的MSP430 系列单片机,通过使用通用I/O 口直接驱动LCD 显示,其显示效果以及占用的资源和内置液晶控制器的单片机相同。

市面上针对4-COM 和3-COM 的液晶,多是1/3Bias 偏压方式,本设计方法适用于1/3Bias 液晶屏,仅仅通过端口增加分压电阻即可完成显示。

1/2Bias 液晶屏的驱动设计见ti/lit/zip/slaa516 。

1/3 Bias LCD 使用1/2Bias 的驱动时序,会导致显示对比度下降,显示效果不理想。

LCD 显示原理
LCD 是利用液晶分子的光学特性和物理结构进行显示的一种元件。

液晶
分子是介于固体和液体之间的一种物质,多呈长棒状大分子形态,在自然形态下,液晶分子排列没有规则,具有光学各向异性的特点,不透光;在电(磁)场作
用下,液晶分子排列规则,光学各向同性,可透光。

将液晶分子灌入精良加工
的开槽平面,液晶分子大致会顺着槽排列。

假如那些槽非常平行,液晶分子也
大致平行。

单片机IO口直接驱动LCD

单片机IO口直接驱动LCD

利用单片机I/O口直接驱动LCD如何将小家电成本降低的同时,又保证其性能,是对应用工程师提出的更高要求。

本控制板需要进行温度控制,显示界面要求LCD显示。

带专用LCD驱动器,又带A/D转换器的单片机成本太高,因此选用台湾义隆公司带A/D的单片机EM78P259N直接驱动LCD。

该款单片机性价比高,性能可靠,很适合在家电控制中应用。

1 LCD简介清华微电子推出高频管分立器件裸片,已做到9G截止频率目前,市面主流LCD(液晶显示器)分成以下几大类:TN(扭曲阵列型)、STN(超扭曲阵列型)、DSTN(双层超扭曲阵列)、HPA(高性能定址或快速DSTN)、TFT(薄膜场效应晶体管)等。

由于成本因素,目前小家电大多数采用的是TN型单色液晶显示器,它的原理是把液晶灌入两个列有细槽的平面之间。

这两个平面上的槽互相垂直(相交成90°),也就是说,若一个平面上的分子南北向排列,则另一平面上的分子东西向排列,而位于两个平面之间的分子被强迫进入一种90°扭转的状态。

由于光线顺着分子的排列方向传播,所以光线经过液晶时也被扭转90°。

当液晶上加一个电压时,分子便会重新垂直排列,使光线能直射出去,而不发生任何扭转。

LCD正是由这样两个相互垂直的极化滤光器构成的,所以在正常情况下应该阻断所有试图穿透的光线。

但是,由于两个滤光器之间充满了扭曲液晶,所以在光线穿出第一个滤光器后,会被液晶分子扭转90°,最后从第二个滤光器中穿出。

另一方面,若为液晶加一个电压,分子又会重新排列并完全平行,使光线不再扭转,所以正好被第二个滤光器挡住。

总之,加电将光线阻断,不加电则使光线射出。

LCD模型可以把其看成一个电容器,一个电极连接着公共极板,另一个连接着字符段。

LCD受电压的均方根值控制,当施加在LCD上的电压为零时,LCD呈透明状态。

当施加在字符段与公共极的电压大于LCD的阀值电压,则该字符段就显示出来。

用IO驱动LCD

用IO驱动LCD

用I/O 驱动LCD在现今的电子产品中,LCD显示被广泛的应用。

LCD显示驱动有内建于MCU中的亦有独立于MCU单一的驱动IC。

这些LCD能驱动的点数一般比较多,在一些需要显示点数不多的应用中这些IC就显的浪费。

所以在这里我们介绍一种用I/O来驱动LCD做显示的方法来满足一些点数不多的显示应用。

1.I/O 驱动LCD 原理LCD的显示原理请参考3.6节,这里不多叙述。

大家都知道I/O口最多只能有三种状态: 高电平,低电平及悬空状态(Floating)如何造出LCD驱动波形呢? 下面我们以2X8(2个COM和8个SEG)的例子来做一介绍。

观察图5-14,这是一个1/2bias,1/2duty的LCD驱动波形,观察COM0和COM1可以发现同一时间内只有一个COM口有输出,它的平均电压为零。

节点信号SEGMENT则表示要显示的数据,如果节点信号与COM口之间有出现脉冲,代表对应的这个点是亮的,反之则是暗的。

在知道要显示的内容的情况下,如果是要显示,那么SEGMENT的信号就和COM 相反而产生脉冲,如果是不显示,那么SEGMENT的信号就和COM的信号一样而两端之间没有脉冲,没有显示。

有了LCD驱动波形的概念之后,接着就可以着手设计电路了,观察SEGMENT 上的波形,对微控制器来讲不是问题,VLCD=1,VSS=0就能造出漂亮的方波。

那COMMON上面的阶梯波怎么解决呢? 其实只要利用I/O Port三种状态就可实现,如图1-1所示,PD1、PD2为COM0、COM1的输出波形,利用两个分压电阻以及I/O Port 的特性,表1-1是它的真值表,由此表不难看出,要产生VDD或者0电压,只要利用端口输出1或者0就可以产生,可是没有直接输出1/2 VDD(V1)。

其实要产生1/2VDD是很简单的,因为当I/O Port设成输入时形成一个高阻抗的状态,对COM 而言所看到的只是R1和R2分压而已。

所以我们 将R1=R1=100K欧姆,那么在COM 端来说就是1/2VDD的电压了。

HOLTEK HT66Fx0 共用 I O Pin 来驱动 LCD、LED、KEY的 使用方法

HOLTEK HT66Fx0 共用 I O Pin 来驱动 LCD、LED、KEY的 使用方法

HT66Fx0共用I/O Pin来驱动LCD、LED、KEY的使用方法文件编码:HA0196S简介HT66Fx0内建有R-Type LCD功能,提供1/2 bias、4 个COM的驱动能力,本文以HT66F40为母体,说明共用I/O Pin来驱动LCD、LED、KEY的使用方法。

工作原理我们知道在微观上电子器件都是基于分时扫描的原理来驱动各个功能模块的,那么只要我们分时来驱动LCD、LED、扫描按键,就可以实现分时共用I/O的目的。

根据标准1/2 bias、1/4 duty COM的驱动波形,考虑下面的分时时序:在T0~T7时间片来驱动LCD,在T8时间片扫描按键,在T9时间片驱动LED。

首先来看LCD,根据LCD的驱动原理可知,LCD像素点上只能加上AC电压,LCD显示器的对比度由COM脚上的电压值减去SEG脚上的电压值决定,这个电压差的大小也决定了LCD像素点的打开与关闭。

LCD型MCU已经由内建的LCD驱动电路自动产生LCD驱动信号,因此只要I/O口能仿真输出该驱动信号,就能完成LCD的驱动。

由于LCD工作的最佳频率通常在25Hz~250Hz,当HT66F40系统频率为IRC 4MHz且Time Base输入频率等于f SYS/4时Time Base中设置溢出时间为2.048ms,以此为时基,1/4 Duty 时的帧周期为2.048 ms * 10 = 20.48 ms,即1000/ 20.48 =48.12Hz。

符合要求。

当然,也可以设置Time Base为其它的溢出时间,可根据具体应用设置,都能符合要求。

但需要注意,系统频率不适宜为FL,因系统频率太慢,无法让扫瞄达到视觉暂留的时间,从而导致LCD出现闪烁现象。

另外,当Time Base设置为其它溢出时间时,扫描频率会更快,可以增强LED的亮度。

HT66F40内部提供了4 COM的输出,通过设置SCOMC寄存器即可使PC0、PC1、PC6和PC7输出VDD/2电位,外部不需要再连接分压电阻器件,内部电路和设置方式如下:SCOM电路输出控制另外,不同的LCD面板需要的驱动电流可能不尽相同,为更好驱动不同的LCD面板,MCU 内部还提供有四种规格的驱动电流,用户可通过软件设置ISEL1、ISEL0 (SCOMC.6/5) 位来选择合适的LCD驱动电流,具体设置如下:ISEL1、ISEL0 =00: 25µA01: 50µA10: 100µA11: 200µA注意上述电流参数的条件是V DD=5V,具体数据请参考DataSheet。

普通MCU驱动液晶LCD方法

普通MCU驱动液晶LCD方法

LCD(Liquid Crystal Diodes)是液晶显示器的简称。

LCD显示器具有体积小、重量轻、功耗极低、易于定制、显示内容丰富等特点,被越来越广泛地应用于仪器仪表、通信产品、家用电器等领域。

根据不同种类的LCD,其驱动方式分为静态和动态两种,其中动态驱动方式可以减少LCD显示器的引线和相应的驱动电路,适用于较多位的字符显示和点阵式显示,是现在和将来LCD显示驱动的主导方式。

但LCD的动态驱动与控制较为复杂,实际应用中,通常都是使用专用的IC芯片,或直接采用具有动态LCD驱动接口的单片机。

前者一般较为昂贵,且通用性不好,后者则需具有针对相应单片机的开发系统或开发手段。

这些都限制了LCD显示器更为广泛的应用。

本文介绍了一种简单的方法,可以用一般并行接口配合单片机软件进行LCD的动态驱动,从而使得具有任何型号单片机开发手段的人都可以使用动态驱动的LCD显示器。

作为实例,本文采用与MCS51系列兼容的ATMEL 89C1051单片机串行口扩充的并行口实现了具有3个公共背极,5 1个显示段位的LCD的驱动,显示效果良好,费用极其低廉。

2 动态LCD的一般驱动原理[1]由于LCD的电化学特性,LCD的驱动一般采用交流驱动。

图1为基本的LCD驱动电路和工作波形。

图中A为显示频率信号,C为显示控制信号。

从中可以看出,当LCD两极间电压为零时,不显示;而当LCD两端为交替变化的电压时,LCD显示。

动态驱动方式的实质是用矩阵驱动法来驱动字段的显示。

在此,字段引线相当于行引线,公共背极引线相当于列引线,字符的每一字段相当于矩阵的一个点。

由于是交流驱动,因而不能采用象LED的动态驱动方法,即用LCD的公共电极作为显示的开关控制极;也不能将LCD驱动线悬空,否则在悬空线与选通线交点上的非选通点则会由于液晶所具有的电容特性而产生交叉显示效应,使清晰度下降。

一般作法是在非选通点上加上低于LCD显示阈值的电压信号,以消除交叉效应的影响,如偏压法。

普通IO口驱动LCD

普通IO口驱动LCD

LED数码管的驱动是比较简单也容易理解的,多位数码管一般是LED阵列的形式,每个数字使用一个公共端,不同数字的对应同笔段使用一个控制端;驱动采用分时扫描没个数字位,动态显示。

但是LED比较费电,我想做一个用电池供电的钟,用发光管电池就撑不了多久了。

于是我考虑用液晶。

在这边的电子市场我买到一个4位笔段式液晶屏,4个数字最中间有冒号,边上还有几个箭头符号,一共有15个引脚,正合适用A VR来驱动做一个钟。

笔段式LCD屏的结构与LED数码管很相似,但是由于是液晶,工作机理上不同,驱动方式也有很大差异:(1) LED有正负之分,液晶笔划没有。

(2) LED在直流电压下工作,液晶需要交流电压,防止电解效应。

(3) LED需要电流提供发光的能量,液晶笔划显示状态下电流非常微弱。

(4) LED对微小电流不反应,液晶则很敏感。

不难看出,用LED的驱动方式来对待LCD屏是行不通的。

我在买回来测试这块屏之前没有意识到,于是走了不少的弯路。

与LED驱动不同的是需要给每个笔划加上一个交流电压。

一般用30-60Hz的方波就可以了,频率再低显示会有所波动,频率高了功耗也会增加,因为LCD对电路呈现容性。

而且,正负电压都可以“点亮”液晶。

好在A VR的I/O口可以三态输出,也就是除了高/低电平,还可以呈现高阻抗,相当于断开连接。

于是我想到了这样的办法:不需要显示的那一组笔划对应的公共端悬空(I/O口选择三态),那么就不会加上电压了。

照这个思路,我的实验电路焊好,出来的显示却是一团糟:笔划都黑了看不清。

我这才考虑到液晶本身的问题:阻抗高,而且有电容,是不可一边悬空的!这个道理也许跟CMOS输入端差不多。

查找了一些关于液晶的资料,大致知道LCD屏不是那么简单的,驱动方式通常是1/N, 也就是电压不止高低两档。

可是单片机I/O没有那么多输出状态可以选择。

1/2 Bias驱动不显示的液晶笔划两端电压相等,显示的不等。

这样一个要求在扫描方式下不能满足,于是改为电压等级不同。

用单片机IO口直接驱动段式LCD的方法

用单片机IO口直接驱动段式LCD的方法

用单片机IO口直接驱动段式LCD的方法用IO口驱动段式LED(数码管)的方法相信大家比较清楚,但用IO口直接驱动段式LCD的方法相对复杂一些。

在网上搜了一下单片机IO口驱动段式LCD的方法,大部分资料讲得不够清晰、具体,而且简单问题复杂化。

后来查了LCD的显示原理,结合网上的相关介绍,发现IO口直接驱动段式LCD原理比较简单,用几句话就可以描述清楚:1.LCD和LED的显示原理不一样:LED是加正向电压发光,而LCD必须交替加正、反向电压才会持续显示(可以做个实验,如果把恒定电压加到LCD的一段上,该段会显示一下,但马上不能显示,而且长时间加恒定电压,会加速LCD的老化和损坏)2.常听说1/2bias,1/3bias LCD,是什么意思呢?对于1/2bias LCD,假如LCD的显示电压是3V,则1/2bias是1.5V,也就是说在±3V电压作用时,LCD有显示;±1.5V及以下的电压作用时没有显示3.普通单片机IO口不能直接输出半高电平(1.5V),但可以用相等的上下拉电阻实现,当IO口设置为输入(高阻)时,由于上下拉电阻的分压作用,则产生一个半高电平(1.5V)知道了以上3点后,动态驱动LCD就不是难事了,对于4*8段的LCD(4个COM,8个SEG,显示电压为3V,1/2bias),驱动方法如下:1、四个COM采用交替扫描的方式,每个COM在相邻两次扫描时又进行电压交变的方式。

2、若扫描到某一个COM时,该COM输出3V(0V):与该COM相连的SEG输出与COM相反,ΔV=±3V,则该相连点亮;与该COM相连的SEG输出与COM相同,ΔV=0,则该相连点不亮。

3、其他没有扫描到的COM,单片机IO口为输入,从而产生1/2 bias(1.5V),不管SEG为何值,ΔV<±1.5V,故该点不亮。

本人用4*8段的LCD自制了一个数字钟表,验证了以上方法的可行性,现把制作过程罗列如下1.原理图说明:由于管脚不够用,所以时钟芯片DS1302的RST和LCD的一个SEG是复用的,只要在这个SEG无效的时候去读取时间就可以了,另外,3PIN串口是ISP 下载程序用的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

用普通I/O口驱动LCD显示文件编码:HA0092s介绍:在一些特定环境,为了节省成本,控制I/O口需求较少,但芯片本身的I/O口又较多的情况下,客户往往用普通I/O口驱动LCD显示,而且在实际应用中很多学习者也需求这方面的知识,所以下面给出一个范例,以供参考。

理可以延长LCD的使用寿命。

如果LCD玻璃是3V,则V DD=3V;如果LCD玻璃是5V的,则V DD=5V。

5. 范例程序是以分钟计时的方式,从“00”~“59”循环显示。

图26. LCD 两个七段码对应表如表1所示。

表1程序清单:;*********************************************;FILE NAME: IO_LCD;MCU: HT46R22;MASK OPTION: WAKE-UP: PA6,PA7; PULL-HIGH: PA,PB,PC; IIC: DISABLE; PFD: DISABLE; PWM: DISABLE; WDT: ENABLE; CLRWDT: ONE; WDT CLOCK SOURCE: T1; WDT TIME OUT SELECT: WDT CLOCK SOURCE/32768 ; LVR: DISABLE; OSC: CRYSTAL; SYSVOLT: 3.0V; SYSFRAG: 4000KHZ;AUTHOR: RADOME;HISTORY: 2005.08.22;*********************************************include Ht46r22.incinclude Micro.inc;*********************************************IO_data .section 'data';*********************************************acc_bk db ?status_bk db ?pa_bk db ?pb_bk db ?pbc_bk db ?pulse_count db ?display_temp db ?display_temp0 db ?display_temp1 db ?display_temp2 db ?number0 db ?number1 db ?number2 db ?msecond db ?second db ?minute db ?;----------------------------------------segment0 equ pa_bk.0segment1 equ pa_bk.1segment2 equ pa_bk.2segment3 equ pa_bk.3segment4 equ pb_bk.4segment5 equ pb_bk.5com0 equ pb_bk.3com0_ctrl equ pbc_bk.3com1 equ pb_bk.6com1_ctrl equ pbc_bk.6com2 equ pb_bk.7com2_ctrl equ pbc_bk.7;*********************************************IO_code .section 'code';*********************************************org 0000hjmp initorg 0004h ;External Interrupt retiorg 0008h ;Timer Interruptjmp timer_intorg 0020h;*********************************************;Initializers;*********************************************init:clr intc0clr intc1clr tmrcclr msecondclr secondclr minuteclr pulse_countclr display_tempclr display_temp0clr display_temp1clr display_temp2clr number0clr number1clr number2mov a,11011111bmov pa,amov pa_bk,amov a,11010000bmov pac,aset pbset pb_bkmov a,00000001bmov pbc,amov pbc_bk,amov a,00000001bmov pc,aclr pccclr pdclr pdcmov a,00000101bmov intc0,amov a,94mov tmr,amov a,10010110bmov tmrc,a;********************************************* ;Main;********************************************* main_loop:clr wdtmov a,minuteadd a,bcd_tablemov tblp,atabrdl number2mov a,number2and a,0f0hswap accmov number0,amov a,number2and a,0fhmov number1,amov a,number0mov display_temp0,amov a,number1mov display_temp1,amov a,number2mov display_temp2,ajmp main_loop;********************************************* ;Interrupt;********************************************* timer_int: ;2592uspush;----------------------------------------;COM Operation Mode;----------------------------------------com_pulse:inc pulse_countmov a,pulse_countsub a,7snz cjmp $+3mov a,1mov pulse_count,amov a,pulse_countsdz accjmp $+2jmp com1_out_highsdz accjmp $+2jmp com1_out_lowsdz accjmp $+2jmp com2_out_highsdz accjmp $+2jmp com2_out_lowsdz accjmp com0_out_lowcom0_out_high:clr com0_ctrlset com0set com1_ctrlset com2_ctrljmp segment_pulsecom0_out_low:clr com0_ctrlclr com0set com1_ctrlset com2_ctrljmp segment_pulsecom1_out_high:set com0_ctrlclr com1_ctrlset com1set com2_ctrljmp segment_pulsecom1_out_low:set com0_ctrlclr com1_ctrlclr com1set com2_ctrljmp segment_pulsecom2_out_high:set com0_ctrlset com1_ctrlclr com2_ctrlset com2jmp segment_pulsecom2_out_low:set com0_ctrlset com1_ctrlclr com2_ctrlclr com2;---------------------------------------- ;SEGMENT Operation Mode;---------------------------------------- segment_pulse:;------------------------segment0_out:mov a,display_temp0add a,number_tablemov tblp,atabrdl display_temprl display_temprl display_temprl display_tempmov a,display_tempand a,00000111binc accsdz accjmp $+2jmp segment0_000sdz accjmp $+2jmp segment0_001sdz accjmp $+2jmp segment0_010sdz accjmp $+2jmp segment0_011sdz accjmp $+2jmp segment0_100sdz accjmp $+2jmp segment0_101sdz accjmp segment0_111jmp segment0_110segment0_000:mov a,com_000_table jmp segment0_next segment0_001:mov a,com_001_table jmp segment0_next segment0_010:mov a,com_010_table jmp segment0_next segment0_011:mov a,com_011_table jmp segment0_next segment0_100:mov a,com_100_table jmp segment0_next segment0_101:mov a,com_101_table jmp segment0_next segment0_110:mov a,com_110_table jmp segment0_nextsegment0_111:mov a,com_111_tablesegment0_next:add a,pulse_count mov tblp,atabrdl accclr segment0sz accset segment0 ;------------------------ segment1_out:rl display_temprl display_temprl display_tempmov a,display_temp and a,00000111binc accsdz accjmp $+2jmp segment1_000sdz accjmp $+2jmp segment1_001sdz accjmp $+2jmp segment1_010sdz accjmp $+2jmp segment1_011sdz accjmp $+2jmp segment1_100sdz accjmp $+2jmp segment1_101sdz accjmp segment1_111jmp segment1_110segment1_000:mov a,com_000_table jmp segment1_next segment1_001:mov a,com_001_table jmp segment1_next segment1_010:mov a,com_010_table jmp segment1_next segment1_011:mov a,com_011_table jmp segment1_next segment1_100:mov a,com_100_table jmp segment1_next segment1_101:mov a,com_101_table jmp segment1_next segment1_110:mov a,com_110_table jmp segment1_next segment1_111:mov a,com_111_tablesegment1_next:add a,pulse_count mov tblp,atabrdl accclr segment1sz accset segment1;------------------------ segment2_out:clr accsz display_temp.7 set acc.0inc accsdz accjmp $+2jmp segment2_000sdz accjmp $+2jmp segment2_001sdz accjmp $+2jmp segment2_010sdz accjmp $+2jmp segment2_011sdz accjmp $+2jmp segment2_100sdz accjmp $+2jmp segment2_101sdz accjmp segment2_111jmp segment2_110segment2_000:mov a,com_000_table jmp segment2_next segment2_001:mov a,com_001_table jmp segment2_next segment2_010:mov a,com_010_table jmp segment2_next segment2_011:mov a,com_011_table jmp segment2_next segment2_100:mov a,com_100_table jmp segment2_next segment2_101:mov a,com_101_table jmp segment2_next segment2_110:mov a,com_110_table jmp segment2_next segment2_111:mov a,com_111_tablesegment2_next:add a,pulse_count mov tblp,atabrdl accclr segment2sz accset segment2;------------------------ segment3_out:mov a,display_temp1 add a,number_table mov tblp,atabrdl display_temprl display_temprl display_temprl display_tempmov a,display_temp and a,00000111binc accsdz accjmp $+2jmp segment3_000sdz accjmp $+2jmp segment3_001sdz accjmp $+2jmp segment3_010sdz accjmp $+2jmp segment3_011sdz accjmp $+2jmp segment3_100sdz accjmp $+2jmp segment3_101sdz accjmp segment3_111jmp segment3_110segment3_000:mov a,com_000_table jmp segment3_next segment3_001:mov a,com_001_table jmp segment3_next segment3_010:mov a,com_010_table jmp segment3_next segment3_011:mov a,com_011_table jmp segment3_nextsegment3_100:mov a,com_100_table jmp segment3_next segment3_101:mov a,com_101_table jmp segment3_next segment3_110:mov a,com_110_table jmp segment3_next segment3_111:mov a,com_111_tablesegment3_next:add a,pulse_count mov tblp,atabrdl accclr segment3sz accset segment3;------------------------ segment4_out:rl display_temprl display_temprl display_tempmov a,display_temp and a,00000111binc accsdz accjmp $+2jmp segment4_000sdz accjmp $+2jmp segment4_001sdz accjmp $+2jmp segment4_010sdz accjmp $+2jmp segment4_011sdz accjmp $+2jmp segment4_100sdz accjmp $+2sdz accjmp segment4_111jmp segment4_110segment4_000:mov a,com_000_table jmp segment4_next segment4_001:mov a,com_001_table jmp segment4_next segment4_010:mov a,com_010_table jmp segment4_next segment4_011:mov a,com_011_table jmp segment4_next segment4_100:mov a,com_100_table jmp segment4_next segment4_101:mov a,com_101_table jmp segment4_next segment4_110:mov a,com_110_table jmp segment4_next segment4_111:mov a,com_111_tablesegment4_next:add a,pulse_count mov tblp,atabrdl accclr segment4sz accset segment4;------------------------ segment5_out:clr accsz display_temp.7 set acc.0inc accsdz accjmp $+2sdz accjmp $+2jmp segment5_001sdz accjmp $+2jmp segment5_010sdz accjmp $+2jmp segment5_011sdz accjmp $+2jmp segment5_100sdz accjmp $+2jmp segment5_101sdz accjmp segment5_111jmp segment5_110segment5_000:mov a,com_000_table jmp segment5_next segment5_001:mov a,com_001_table jmp segment5_next segment5_010:mov a,com_010_table jmp segment5_next segment5_011:mov a,com_011_table jmp segment5_next segment5_100:mov a,com_100_table jmp segment5_next segment5_101:mov a,com_101_table jmp segment5_next segment5_110:mov a,com_110_table jmp segment5_next segment5_111:mov a,com_111_tablesegment5_next:add a,pulse_countmov tblp,atabrdl accclr segment5sz accset segment5;---------------------------------------- ;Output COM&SEGMENT;---------------------------------------- output_com_segment:mov a,pb_bkmov pb,amov a,pbc_bkmov pbc,amov a,pa_bkmov pa,a;---------------------------------------- ;Time;---------------------------------------- inc msecondmov a,msecondsub a,192snz cjmp timer_endclr msecondinc secondmov a,secondsub a,120snz cjmp timer_endclr secondinc minutemov a,minutesub a,60snz cjmp timer_endclr minutetimer_end:popreti;********************************************* ;Table;********************************************* org 0700hnumber_table:; gbefadc0dw 11111010b ;"0" 0dw 00010010b ;"1" 1dw 10101110b ;"2" 2dw 10011110b ;"3" 3dw 01010110b ;"4" 4dw 11011100b ;"5" 5dw 11111100b ;"6" 6dw 00011010b ;"7" 7dw 11111110b ;"8" 8dw 11011110b ;"9" 9dw 00000100b ;"-" adw 00000000b ;" " b;-------------------------------------com_000_table:dw 0dw 1,0,1,0,1,0com_001_table:dw 0dw 1,0,1,0,0,1com_010_table:dw 0dw 0,1,1,0,1,0com_011_table:dw 0dw 0,1,1,0,0,1com_100_table:dw 0dw 1,0,0,1,1,0com_101_table:dw 0dw 1,0,0,1,0,1com_110_table:dw 0dw 0,1,0,1,1,0com_111_table:dw 0dw 0,1,0,1,0,1;----------------------------------------bcd_table:dw 00h,01h,02h,03h,04h,05h,06h,07h,08h,09h dw 10h,11h,12h,13h,14h,15h,16h,17h,18h,19h dw 20h,21h,22h,23h,24h,25h,26h,27h,28h,29h dw 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h dw 40h,41h,42h,43h,44h,45h,46h,47h,48h,49h dw 50h,51h,52h,53h,54h,55h,56h,57h,58h,59h dw 60h,61h,62h,63h,64h,65h,66h,67h,68h,69h dw 70h,71h,72h,73h,74h,75h,76h,77h,78h,79h dw 80h,81h,82h,83h,84h,85h,86h,87h,88h,89h dw 90h,91h,92h,93h,94h,95h,96h,97h,98h,99hend;*********************************************。

相关文档
最新文档