實現的是在上位機(pc機)上用串口調試助手發送一個字符X,單片機收到字符后返回給上位機I get X串口波特率設為9600bps。代碼如下:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
unsigned char flag,a,i;
uchar code table[]="I get ";
/*--------初始化操作---------------*/
void init()
{
TMOD=0x20; //T1定時器工作方式2
TH1=0xfd; //裝初值
TL1=0xfd; //裝初值
TR1=1; //啟動定時器1
//***********************************
SM0=0; //設定串口工作方式1
SM1=1; //同上
REN=1; //允許串口接收
//***********************************
EA=1; //開總中斷
ES=1; //開串口中斷
//因為定時器2是自動重裝初值的因此不需要開定時器中斷
}
/*---------------------------------*/
/*-------------主函數--------------*/
void main()
{
init();
while(1)
{
if(flag==1)
{
ES=0;
for(i=0;i<6;i++) //發送數據
{
SBUF=table[i];
while(!TI);
TI=0;
}
SBUF=a;
while(!TI);
TI=0;
ES=1;
flag=0;
}
}
}
/*-----------------------------------*/
/*--------------串口中斷---------------*/
void ser() interrupt 4
{
RI=0;
a=SBUF;
flag=1;
}
/*------------------------------------*/
主程序的工作過程:當我們用串口調試助手發數據給單片機時,發送完后單片機接收到數據后會觸發接收中斷然后程序就會進入到接收中斷中進行必要的處理,RI由軟件清零為下一次中斷做準備,然后把SBUF寄存器(接收到的)數據給變量a,最后置flag=1.然后回到主程序中檢測到flag=1,再將前面定義的字符I get和串口發送的字符發送給pc機。while(!TI);是等待是否發送完畢的作用,當發送完畢后觸發發送串口中斷這時TI會自動置1,假設這時候已經發送完了我們就把TI由1置為0,再開串口中斷,flag置零。又進行下一次了接收了。。。 溢出率的計算 單片機有四種串口方式,方式0和方式2的波特率是固定的,而方式1和3的波特率是可變的,具體設置多少由定時器T1的溢出率決定,溢出的頻率越高波特率也越高,通信的速度也就越快。當然還與別的因素有關,具體波特率的計算有專門的公式。方式1的波特率計算公式(2^SMOD/32)x(T1溢出率)而方式0的波特率為fosc/12是固定的其中 fosc是單片機的晶振頻率,通常為12MHZ和11.0592MHZ,公式中的SMOD是PCON(電源管理寄存器)的最高位,當設置SMOD的最高位為0時,串口方式1的波特率沒有加倍,如果設置為1顯然其他條件不變的情況下波特率會加倍,PCON的其他位跟這個程序就沒多大的關系了呵呵,直接無視 ,要用到的時候再研究^-^。由于這個程序用到的是串口方式1,波特率是可以設置的,假如要設置波特率為9600bps的話,已知單片機的晶振為11.0592MHZ。因為溢出率就是溢出的頻率即定時器每計多少個數產生一次溢出。這里采用定時器1來計數,因為定時器1有這樣的特點即每發生一次溢出它會自動重裝初值,不需要人為的去設定,顯然這個特點可以提高溢出的精度,因此采用了定時器T1.來實現精確溢出。現在就是要求出定時器T1中的TH1和TL1裝的初值是多少了,我們假設TH1和TL1裝的初值都是X,因為TH1和TL1都是八位的所以最多能計數256個,其計數原理是:因為假設的是TH1和TL1都裝的是X,那么每發生一次溢出后單片機會自動把TL1中的值重裝入TH1中,開始進行第二次溢出了,就這樣重復著進行下去。。。設所求的數為X,由前面分析可知定時器每計256-X個就溢出一次,而每記一個數的時間是一個機器周期,因為一個機器周期是12個時鐘周期所以計一個數的時間為12/11.0592s,那么定時器溢出一次的時間為(256-x)x 12/11.0592s 那么溢出率就是時間的倒數為11.0592/(256-x)x12,這里SMOD取的是0,則波特率為 1/32 x【11.0592/(256-X)x12】=9600 這樣就可以計算出X的值也就是TH1和TL1的值。而通常波特率都是固定的就是這個原因,因為這樣計算出的X才會是整數。 串行口控制寄存器SCON 
SM0,SM1是工作方式選擇位 該程序中SM0=0,SM1=1初始化串口工作方式為1.REN是允許串行口接收位REN等于1時就允許了,該程序中初始化為1 最后是TI和RI 其中TI是發送中斷位,在方式1下串行發送停止位的開始時,系統自動置1,然后申請中斷。RI是接收中斷位串行接收停止位時系統自動置1,申請中斷,SCON 的其他的位與該程序無關,直接無視。等用到的時候再研究^_^編程前首先要進行串行口1工作的初始化操作主要是設置產生波特率的定時器1、串行口控制和中斷控制。具體步驟如下:
1確定T1的工作方式(編程TMOD寄存器); 2計算T1的初值,裝載TH1、TL1 3啟動T1(編程TCON中的TR1位); 4確定串行口控制(編程SCON寄存器);
|