51單片機在串口通信時需要有一個定時器去調節與計算機通信的波特率,而定時器設置時需要中斷寄存器(IE),
定時器控制寄存器(TCON)
,還有T/C控制寄存器共同配合作用,
但在啟動定時器功能時,這三個寄存器的配置順序十分重要,因為在數據傳輸時的高速情況下,一點點的數據誤差就會導致傳輸的數據出現錯誤。而在51單片機的串口通信時必須將配置TCON放在配置這三個寄存器的最后,因為在TCON中含有啟動定時器的TR1和TR0位,若先啟動后對工作方式和溢出率進行配置,就會導致啟動時定時器根本無法像預先設定的方式工作導致整體的工作出現系統誤差,無法消除,就像開車一般,方向選錯了,加快腳步也無法到達目的。在這里我舉個我開發的例子以供參考。(請注意紅字部分的順序)
經過正常計算在SMOD = 0,以P1作為計時器(工作方式為常數自動裝入的8位定時器),且串口工作方式為方式一時以9600Bd的波特率進行通信時,P1的起始數應為0xfd(工作方式為2時只有高4位在工作,低四位作為為儲存重裝數據儲存器而不參與波特率調節)。
代碼原稿
#include<reg52.h>
unsigned char num;
void initIE();
void initTCON();
void initSCON();
void initT1();
void initTMOD();
void init();
void main()
{
init();
initSCON();
initT1();
initTMOD();
initTCON();
initIE();
while(1){;}
}
void RES() interrupt 4
{
unsigned char resv;
if(RI)
{
RI = 0;
resv = SBUF;
num++;
SBUF = num;
while(!TI);
TI = 0;
SBUF = resv;
while(!TI);
TI = 0;
if(num>=256)num = 0;
}
}
void initIE()
{
EA =1;
ES =1;
}
void initSCON()
{
SM0 = 0;
SM1 = 1;
REN = 1;
}
void initTCON()
{
TR1 = 1;
}
void initTMOD()
{
TMOD = 0x20;
}
void initT1()
{
TH1 = 0xfd;
TL1 = 0xfd;
}void init()
{
num = 0;
}
第一種順序
initT1();
initTMOD();
initTCON();
在這種順序下,P1初始化數設置為計算好的0xfd,並沒有任何問題。
第二種順序
initTCON();
initT1();
initTMOD();
在這種順序下傳輸數據就會出現錯誤,在這種情況下就需要對定時器的初值進行重新實驗確定,經試驗后發現PH1 = 0xfc,PL1 = 0xfc。時傳輸的錯誤就消除了。
所以在大家平時開發單片機時應小心各個寄存器的配置先后順序,有時候檢查代碼發現邏輯並無錯誤而一直出錯時可以考慮是否是寄存器配置出現了並不在預想中的問題。