1. 74HC164
74HC164是比较典型的移位寄存器,该移位寄存器有一个数据输入端口、一个时钟信号端口和八个输出端口。如图1所示。
当时钟信号从低电平变为高电平的时候将输出一个数据到输出端D0,当时钟第二次由低电平变为高电平的时候将输出第二个数据到D0,而第一个数据将转移到D1端口。依此类推,每一个时钟周期中都有一个串行数据输出到D0,而其他的数据则不断往高位移动直到所有数据传输结束。如果不再有时钟周期输入,则这些数据将暂存在输出端。
注意:初学者会误以为看到移位的过程,由于移位的时间很短,几微秒的时间人的眼睛是反应不过来的。
如果需要有更多的输出端口,可以把多个74HC164串联起来用。串联的方法如图2所示。
在上图的串联电路中,左边的锁存器D7与右边锁存器的串行数据输入端连接,当左边的锁存器D0~D7数据全部输出以后,再输入一个串行信号,左边锁存器D7数据将作为右边锁存器的输入数据并从右边锁存器D0端输出,从而实现了多个字节数据的移位锁存。这样利用74HC164就实现了串行数据到并行数据的转换。
注意到在上面的两个图中,无论输出什么长度的数据,所需要的输入信号都只有两个,一个是串行数据输入,另一个是锁存器的时钟信号输入。如果我们把这两个输入端口连接到 单片机的两个输出端口上,其中单片机的一个端口串行输出数据,另一个端口输出时钟信号以便控制串行数据的锁存方式,那么我们就只需要两个单片机端口几乎实现任意数量的并口输出。
2. 8051串口方式0的工作原理与时序
图3 串口方式0的时序
8051串口方式0的时序如图所示,RXD(P3.0)为数据端,TXD(P3.1)为同步移位脉冲端,每次串行发送、接收8位数据(一帧),低位在先。时钟为Fosc/12。
(1) 发送
执行任何一条MOV SUBF,#data指令时,启动内部串行发送允许,SEND置高电平,随后在TXD同步移位时钟的作用下,将数据data从RXD端移位输出。一帧数据发送完毕时,内部发送中断请求 ti有效。要再次发送一帧时,须用软件清TI。
(2) 接收
在串行口控制寄存器SCON中,REN=1和RI=0时,会启动一次接收过程。接收时,TXD仍为同步移位时钟输出,而串行移位数据仍从RXD移位输入。当接收完一帧后,内部接收中断请求RI有效,要再次接收一帧数据时,须用软件清零。
3. 电路原理
MCS-51单片机串行口方式0为移位寄存器方式,外接4片74LS164作为4位LED显示器的静态显示接口,把8031的RXD作为数据输出线,TXD作为移位时钟脉冲。74LS164为TTL单向8位移位寄存器,可实现串行输入,并行输出。其中A、B(第1、2脚)为串行数据输入端,2个引脚按逻辑与运算规律输入信号,共一个输入信号时可并接。T(第8脚)为时钟输入端,可连接到串行口的TXD端。每一个时钟信号的上升沿加到T端时,移位寄存器移一位,8个时钟脉冲过后,8位二进制数全部移入74LS164中。R(第9脚)为复位端,当R=0时,移位寄存器各位复0,只有当R=1时,时钟脉冲才起作用。Q1…Q8(第3-6和10-13引脚)并行输出端分别接LED显示器的hg···a各段对应的引脚上。在给出了8个脉冲后,最先进入74LS164的第一个数据到达了最高位,然后再来一个脉冲会有什么发生呢?再来一个脉冲,第一个脉冲就会从最高位移出,搞清了这一点,下面让我们来看电路,4片7LS164首尾相串,而时钟端则接在一起,这样,当输入8个脉冲时,从单片机RXD端输出的数据就进入到了第一片74LS164中了,而当第二个8个脉冲到来后,这个数据就进入了第二片74LS164,而新的数据则进入了第一片74LS164,这样,当第4个8个脉冲完成后,首次送出的数据被送到了最左面的164中。
图4 整体原理图
4.源程序
/*************************************************************
利用中断方式进行处理
**************************************************************/
#include
#define uchar unsigned char
***it P3_3=P3^3;
uchar a=3;
char code tab[]={0x99,0xB0,0xA4,0xF9,0xF9,0xA4,0xB0,0x99};//4321与1234的字形码
void timer(uchar);
void int4(void);
void main(void)
{
uchar i,j;
SCON=0;
EA=1;
ES=1;
for(;;)
{
P3_3=1;
for(i=0;i<4;i++)
{
SBUF=tab[a];
j=a;
while(j==a);
}
P3_3=0;
timer(100);
if(a==255)
a=7;
}
}
void int4(void)interrupt 4
{
TI=0;
a--;
}
void timer(uchar t)
{
uchar i;
for(i=0;i
{
TMOD=0x01;
TH0=10000/256;
TL0=10000%256;
TR0=1;
while(!TF0);
TF0=0;
}
}
/*****************************************************************************/
|