《单片机串行口与74LS164的正确配合使用方法.doc》由会员分享,可在线阅读,更多相关《单片机串行口与74LS164的正确配合使用方法.doc(8页珍藏版)》请在三一文库上搜索。
1、单片机串行口与74LS164的正确配合使用方法在单片机系统中,如果并行口的IO资源不够,那么我们可以使用74LS164来扩展并行IO口,节约单片机IO资源。74LS164是一个串行输入并行输出的移位寄存器,并带有清除端。时序分析,单片机串行口时序单片机串行口作显示端口时应工作在方式发送状态,其时序如图所示。从时序图中可以看出,当一个数据输入到串行口发送缓冲器SBUF时,串行口将8位数据以Fosc/12的波特率从低位到高位(即从D0D7)依次通过RXD引脚输出,当位发送完以后,中断标志TI置1,结束一个发送过程。这里应当注意的是串行口物出一个字节数字的次序,它是单片机串行口与74LS164正确配
2、合的关键所在。图2所示为8位串行输入、并行输出移位寄存器74LS164的工作时序。从图2中我们可以看出,使能端B(引脚2)为低电平时,寄存器禁止输入数据,当B为高电平时,数据可以从A端(引脚1)输人。图2中表明,先输入的数据首先Qa从(引脚3)输出。当寄存器74LS164接收完8位数据时,先输入的1位移至Q(引脚13)输出,而Qa端输出的则是最后接收到的1位。从以上对单片机串行口及74LS164的时序分析可知,移位寄存器首先块收到单片机串行口输出的最低位D0。,最后接收到该字节的最高位D7。因此,当接收完8位数据后,移位寄存器QH端输出的是D0。,而QA输出的是D7。以上谈到的两文中所出现的错
3、误原因,就是忽视了这一重要特点。他们给出的硬件电路如图3所示。字形代码及真值表如表所示。从表1可以看出,字形代码把段码a当作D0位,把段码h当作D7位依次对应。在移位寄存器接收到一个完整的字形码时,QA输出的不是段码a,而是段码h(h为小数点,也可不接。)这样处理的结果,使输出的段码次序刚好相反,所以,显示出的字形就不对了。表1右侧列出了(h连小数点时的)错显字形。若要显示正确字形,在使用图3所示电路时字形码应做调整,调整后的字形代码和真值表如表2所示。这种字形码输入到74LS164内时,在其输出脚QAQH上依次输出段码ah,从而正确显示出要显示的内容。在某些场合,设计者仍想使用表1所列的字形
4、码,那么只需把显示器与74LS164的连接做一调整即可。硬件电路如图4所示通过对单片机串行口和74LS164时序的分析,给出了两种正确的软件与硬件组合方法。笔者在研制成功的智能离心开关断开测速仪中利用表2所列的字形码与图3所示硬件相配合,使用结果令人满意。另外,有的设计中也可能遇到8位并入串行输出移位寄存器74LS165与单片机串行口的配合间题,其研究方法仍然应从时序入手,与本文所介绍方法类同,此不赘述proteus仿真图和代码附上。#includereg51.h#define HIGH 1#define LOW 0#define SEG_PORT P0sbit DATA = P0;sbit
5、CLK = P0;unsigned char TImer0IRQEvent = 0;unsigned char TIme1SecEvent = 0;unsigned int TImeCount = 0;unsigned char SegCurPosition = 0;code unsigned char SegCode10 = 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F;code unsigned char SegPosition4 = 0xFE,0xFD,0xFB,0xF7;unsigned char SegBuf4 = 0;void
6、LS164_DATA(unsigned char x)if(x)DATA = 1;elseDATA = 0;void LS164_CLK(unsigned char x)if(x)CLK = 1;elseCLK = 0;/*函数名称:LS164Send*输 入:byte单个字节*输 出:无*功 能:74LS164发送单个字节*/void LS164Send(unsigned char byte)unsigned char j;for(j=0;j=7;j+)if(byte(1(7-j)LS164_DATA(HIGH);elseLS164_DATA(LOW);LS164_CLK(LOW);LS16
7、4_CLK(HIGH);/*函数名称:SegRefreshDisplayBuf*输 入:无*输 出:无*功 能:数码管刷新显示缓存*/void SegRefreshDisplayBuf(void)SegBuf0 = TimeCount%10;SegBuf1 = TimeCount/10%10;SegBuf2 = TimeCount/100%10;SegBuf3 = TimeCount/1000%10;/*函数名称:SegDisplay*输 入:无*输 出:无*功 能:数码管显示数据*/void SegDisplay(void)unsigned char t;SEG_PORT = 0x0F;t
8、= SegCodeSegBufSegCurPosition;LS164Send(t);SEG_PORT = SegPositionSegCurPosition;if(+SegCurPosition = 4)SegCurPosition = 0;/*函数名称:TimerInit*输 入:无*输 出:无*功 能:定时器初始化*/void TimerInit(void)TH0 = (65536 - 5000)/256;TL0 = (65536 - 5000)%256;TMOD = 0x01;/*函数名称:Timer0Start*输 入:无*输 出:无*功 能:定时器启动*/void Timer0St
9、art(void)TR0 = 1;ET0 = 1;/*函数名称:PortInit*输 入:无*输 出:无*功 能:I/O初始化*/void PortInit(void)P0 = P1 = P2 = P3 = 0xFF;/*函数名称:main*输 入:无*输 出:无*功 能:函数主题*/void main(void)PortInit();TimerInit();Timer0Start();SegRefreshDisplayBuf();EA = 1;while(1)if(Timer0IRQEvent)Timer0IRQEvent = 0;if(Time1SecEvent)Time1SecEvent = 0;if(+TimeCount = 9999)TimeCount = 0;SegRefreshDisplayBuf();SegDisplay();/*函数名称:Timer0IRQ*输 入:无*输 出:无*功 能:定时器中断函数*/void Timer0IRQ(void) interrupt 1static unsigned int cnt = 0;TH0 = (65536 - 5000)/256;TL0 = (65536 - 5000)%256;Timer0IRQEvent = 1;if(+cnt = 200)cnt = 0;Time1SecEvent = 1;
链接地址:https://www.31doc.com/p-3398181.html