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