昨天搞单片机的串口通信,突然一下就对前面学的中断有了进一步的理解。
单片机的串行口控制寄存器是SCON, 其格式如下:
串行口有4种工作方式,分别为00,01,10,11。 方式0为同步移位寄存器,方式1,2 ,3分别为异步10,11,11位收发方式。一般比较常用的是方式1,即10位异步收发方式。
方式01的10位数据收发具体分析如下:
要发送的数据SBUF=0X34,根据波形图,10位数据,起始位为1(这里的波形图上未标出),最后一位由波形图知为1,中间的即为8位数据00110100(0x34)。当第8位发送完毕后,单片机会自动发送一位结束标志位,即把TI置1,TI置1表示数据发送完毕,TI不能自动清零,所以每次发送完数据后需要软件清零:
同上,当单片机需要接受数据的时候,也是执行相同的步步骤。首先接收8位数据,然后把接收标志位RI置1.
串行口的初始化步骤,主要是设定产生波特率的定时器1,串行口控制盒中断控制,步骤如下:
代码:
//串口初始化程序
TMOD&=0x0f;
TMOD|=0x20;
TH1=0XFD; //设定波特率为9600
TL1=0xFD;
TR1=1; //启动定时器T1
SCON=0X50; //10位数据异步收发,波特率由定时器T1控制,允许串口接收
ES=1; //允许串口中断
//串口初始化完毕
下面我写了一个串口与PC通信的程序:
#include<reg52.h>
unsigned char flag,i;
unsigned int k,j;
unsigned char a[32]={0};
unsigned char code table[6]="I get ";
void init()
{
TMOD=0x20; //设定定时器工作方式2
TH1=0xfd; //定时器1装入初值
TL1=0xfd; //同上
TR1=1; //启动T1定时器
SM0=0; //设定工作方式1
SM1=1; //同上
REN=1; //允许串口接收
EA=1; //开总中断
ES=1; //开串口中断
}
void main()
{
init();
while(1)
{
if(flag==1)
{
ES=0;
for(i=0;i<6;i++)
{
SBUF=table[i];
while(!TI);
TI=0;
}
ES=1;
for(k=0;k<0xFFFF;k++);
for(i=0;i<32;i++)
{
SBUF=a[i];
while(!TI);
TI=0;
}
flag=0;
}
}
}
void ser() interrupt 4 //中断程序,接收数据块,标志位置1
{
flag=1;
if(RI==1){
a[j++]=SBUF;
RI=0; //手动清零
}
}
串口通信效果如下:
但是我的这个程序有点小问题,我自己想了很多种办法来试着解决,但是都以失败告终。当我输入的数据大于2个字节时,它只能返回前两个字节的数据。如下图:
希望有哪位高手能指点我一二。今天就到这儿吧。