现在扩展串口的办法主要有以下办法, ①、选用串口扩展芯片完结,如ST16C550、ST16C554、SP2538、MAX3110等,尽管本钱较高, 但体系的可靠性得到了确保,适用于数据量较大、串口需求较多的体系;②、选用分时切换的办法将一个串口扩展与多个串口设备通讯,分时复用的办法本钱低, 但只适用于数据量不大的场合, 而且只能由这个单片机自动和多个设备通讯,实时性差;③、用软件模仿的办法扩展串口,其优势也是本钱低、实时性好, 但要占用一些CPU时刻。
本文提出的模仿串口办法,仅运用2个一般I/O和1个守时器,因为不需求INT的约束,能够扩展出多个串口,且带FIFO的功用,该办法扩展模仿串口的收发数据在中止服务中完结,所以十分效率高,一般的单片机都支撑守时器中止,所以所以该办法在大多数单片机上都能够运用。
关于低速度的单片机(如89S51)能够扩展出低速串口(9600、4800等),关于高速单片机(如AVR、PIC、C8051、STC12)能够扩展高速串口(如19200、28800、38400、57600等)。现在单片机的处理速度越来越高,而价格越来越廉价,本文运用的STC12C1052芯片就具有高速度和低价格,价格仅为每片人民币3.8元。电子产品的开发设计时,要求在确保功用的情况下下降硬件本钱,软件模仿扩展串口供给了一种下降本钱的好办法。
1、串口通讯原理
在串口的异步通讯中,数据以字节为单位的字节帧进行传送,发送端和接纳端有必要按照相同的字节帧格局和波特率进行通讯,其间字节帧格局规则了开端位、数据位、寄偶效验位、中止位。开端位是字节帧的开端,使数据线处于逻辑0状况,用于向接纳端标明开端发送数据帧,起到使发送和接纳设备完结同步。中止位是字节帧的中止,使数据线处于逻辑1状况,用于向接纳端标明数据帧发送结束。波特率选用规范速度,如4800、9600、19200、28800、38400、57600等。
2、软件UART的规划思维
在本规划对硬件要求方面,只是占用单片机的恣意2个I/O端口和1个守时器,运用守时器的守时中止功用完结精确的波特率守时,发送和接纳都在守时中止的操控之下进行。
数据发送的思维是,当发动字节发送时,通过TxD先发开端位,然后发数据位和奇偶数效验位,最终再发中止位,发送进程由发送状况机操控,每次中止只发送1个位,通过若干个守时中止完结1个字节帧的发送。
数据接纳的思维是,当不在字节帧接纳进程时,每次守时中止以3倍的波特率监督RxD的状况,当其接连3次采样电平顺次为1、0、0时,就以为检测到了开端位,则开端发动一次字节帧接纳,字节帧接纳进程由接纳状况机操控,每次中止只接纳1个位,通过若干个守时中止完结1个字节帧的接纳。
为了进步串口的功用,在发送和接纳上都完结了FIFO功用,提高通信的实时性。FIFO的长度能够进行自在界说,适运用户的不同需求。
波特率的核算按照核算公式进行,在设置最高波特率时一定要考虑模仿串口程序代码的履行时刻,该守时时刻有必要大于模仿串口的程序的规则时刻。单片机的履行速度越快,则能够完结更高的串口通讯速度。
3、软件UART规划的完结
本程序在宏晶科技(深圳)出产的STC12C1052高速单片机上进行运转测验,STC12C1052单片机是单时钟/机器周期的MCS51内核单片机,与89C2051引脚彻底兼容,其作业频率达35MHz,适当与420MHz的89C2051单片机,每片人民币3.8元。因为该单片机的高速度,使得软件扩展串口的办法,更便利完结高速的串口。
本扩展串口的规划中,STC12C1052运用的晶振频率为22.1184Mhz,以波特率的3倍核算守时时刻,在接纳进程中以此守时进行接纳开端位的采样,在发送和接纳进程中再3分频得到规范波特率守时,进行数据发送与接纳。
3.1、数据界说
界说模仿串口程序所有必要的一些资源,如I/O引脚、波特率、数据缓冲区等。
#define Fosc 22118400 //晶振频率
#define Baud 38400 //波特率
#define BaudT (Fosc/Baud/3/12)
#define BufLong 16 //FIFO长度
sbit RxD1=P1^7; //模仿接纳RxD
sbit TxD1=P1^6; //模仿发送TxD
bit Brxd1,Srxd1;//RxD检测电平
BYTE Rbuf1[BufLong];//FIFO接纳区
BYTE Rptr1,Rnum1;
BYTE Tbuf1[BufLong];//FIFO发送区
BYTE Tptr1,Tnum1;
BYTE TImCnt1A,TImCnt1B;
BYTE Mtbuf1,Mrbuf1,TxdCnt1,RxdCnt1;
3.2、数据接纳子程序
数据接纳进程中,顺次存储RxD的逻辑位构成字节数据,当数据接纳结束且中止位为1时,表明接纳到了有用数据,就将成果存储到接纳FIFO行列中去。
void Recv()
{
if(RxdCnt1>0) //存数据位8个
{
Mrbuf1>>=1;
if(RxD1==1) Mrbuf1=Mrbuf1|0x80;
}
RxdCnt1–;
if(RxdCnt1==0&& RxD1==1) //数据接纳结束
{
Rbuf1[Rptr1]=Mrbuf1; //存储到FIFO行列
if(++Rptr1>BufLong-1) Rptr1=0;
if(++Rnum1>BufLong) Rnum1=BufLong;
}
}
3.3、数据发送子程序
该程序进程中,当数据发送状况结束时,检测发送FIFO行列是否为空,若非空则取出发送数据,然后发动发送状况;当处于发送状况时,则按照状况机的状况进行开端位、数据位和中止位的发送。
void Send()
{
if(TxdCnt1!=0) //字节发送状况机
{
if(TxdCnt1==11) TxD1=0;//发开端位0
else if(TxdCnt1>2) //发数据位
{ Mtbuf1>>=1; TxD1=CY;}
else TxD1=1; //发中止位1
TxdCnt1–;
}
else if(Tnum1>0) //检测FIFO行列
{
Tnum1–;
Mtbuf1=Tbuf1[Tptr1]; //读取FIFO数据
if(++Tptr1>=BufLong) Tptr1=0;
TxdCnt1=11; //发动发送状况机
}
}
3.4、中止程序
中止守时时刻为波特率守时的1/3,即以3倍的波特率对RxD进行采样,完结开端位的判别,当开端位抵达时发动接纳进程状况机。将该守时进行3分频再调用数据的发送和接纳进程,进行精确波特率下的串口通讯。
void Uart() interrupt 1 using 1
{
if(RxdCnt1==0 ) //接纳开端辨认
{
if(RxD1==0 && Brxd1==0 && Srxd1==1) { RxdCnt1=8; TImCnt1B=0;}
}
Srxd1=Brxd1; Brxd1=RxD1;
if(++TImCnt1B>=3 && RxdCnt1!=0) { TimCnt1B=0; Recv();}//数据接纳
if(++TimCnt1A>=3) { TimCnt1A=0; Send();} //数据发送
}
3.5、串口初始化
翻开守时器的中止,将守时器的设置为自装载形式,按照波特率设置守时中止的守时刻隔,发动守时器,并进行UART各变量的初始化。
void IniUart()
{
IE=“0x82”; TMOD=“0x22”;
TH0=-BaudT; TL0=-BaudT; TR0=1;
Rptr1=0;Rnum1=0;Tptr1=0;Tnum1=0;
}
4、结束语
本文提出的模仿串口规划办法,其共同之处在于:只是运用恣意2个一般I/O引脚和1个守时中止完结了全双工串口,对硬件的占用较少,具有多可串口扩展才能;在串口接纳的开端位判别时选用了接连3次采样的判别办法,该办法完结简略、精确率高;用守时中止完结了串口数据的发送和接纳,并完结了FIFO行列,使串口发送和接纳作业效率高。