利用外部中斷實(shí)現(xiàn)模擬串口數(shù)據(jù)的收發(fā)_第1頁
利用外部中斷實(shí)現(xiàn)模擬串口數(shù)據(jù)的收發(fā)_第2頁
利用外部中斷實(shí)現(xiàn)模擬串口數(shù)據(jù)的收發(fā)_第3頁
利用外部中斷實(shí)現(xiàn)模擬串口數(shù)據(jù)的收發(fā)_第4頁
利用外部中斷實(shí)現(xiàn)模擬串口數(shù)據(jù)的收發(fā)_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第第頁利用外部中斷實(shí)現(xiàn)模擬串口數(shù)據(jù)的收發(fā)這一節(jié)注意四個(gè)知識(shí)點(diǎn):第一個(gè):如何利用外部中斷實(shí)現(xiàn)模擬串口數(shù)據(jù)的收發(fā)。

第二個(gè):在退出外部中斷函數(shù)時(shí),必須通過軟件把外部中斷標(biāo)志位IE0清零,否則在接收到的數(shù)據(jù)包最后面會(huì)多收到一個(gè)無效的字節(jié)0xFF。

第三個(gè):實(shí)際做項(xiàng)目的時(shí)候,盡量利用單片機(jī)內(nèi)部自帶的集成串口,不到萬不得已盡量不要用自制的模擬串口,如果非要用本節(jié)講的模擬串口,那么一次接收的數(shù)據(jù)包不要太長,盡可能越短越好,因?yàn)樽约鹤龅哪M串口在穩(wěn)定性上肯定比不上單片機(jī)自帶的串口。這種模擬串口在批量生產(chǎn)時(shí)容易因?yàn)榫д竦恼`差,以及外界各地溫度的溫差而影響產(chǎn)品的一致性,是有隱患的。

第四個(gè):用模擬串口時(shí),盡量不要選用動(dòng)態(tài)數(shù)碼管的顯示方案,因?yàn)閱纹瑱C(jī)在收發(fā)串口數(shù)據(jù)時(shí),只能專心干一件事,此時(shí)不能中途被動(dòng)態(tài)數(shù)碼管掃描程序占用。而動(dòng)態(tài)數(shù)碼管得不到均勻掃描,就會(huì)產(chǎn)生略微閃爍的現(xiàn)象瑕疵。

具體內(nèi)容,請(qǐng)看源代碼講解。

(1)硬件平臺(tái):

基于朱兆祺51單片機(jī)學(xué)習(xí)板。當(dāng)把程序下載到單片機(jī)之后,要做以下跳線處理:

單片機(jī)原來的P3.1引腳是TI串口輸出引腳,P3.0是RI串口輸入引腳,分別把P3.1和P3.0的黃顏色跳冒去掉,同時(shí)也把外部中斷0的引腳P3.2和一根IO口P1.0引腳的換顏色跳冒去掉,把P3.2跳冒的右針連接到P3.0跳冒的左針,作為模擬串口的接收數(shù)據(jù)線。把P1.0跳冒的右針連接到P3.1跳冒的左針,作為模擬串口的發(fā)送數(shù)據(jù)線。

(2)實(shí)現(xiàn)功能:

波特率是:9600。

通過電腦串口調(diào)試助手模擬上位機(jī),往單片機(jī)任意發(fā)送一串不超過10個(gè)的數(shù)據(jù)包,單片機(jī)如實(shí)地返回接收到的整包數(shù)據(jù)給上位機(jī)。

例如:

(a)上位機(jī)發(fā)送數(shù)據(jù):0102030405060708090A

單片機(jī)返回:0102030405060708090A

(b)上位機(jī)發(fā)送數(shù)據(jù):0507EEA8F9

單片機(jī)返回:0507EEA8F9

(3)源代碼講解如下:

#include"REG52.H"

#defineconst_voice_short40//蜂鳴器短叫的持續(xù)時(shí)間

#defineconst_rc_size20//接收串口中斷數(shù)據(jù)的緩沖區(qū)數(shù)組大小

#defineconst_receive_time5//如果超過這個(gè)時(shí)間沒有串口數(shù)據(jù)過來,就認(rèn)為一串?dāng)?shù)據(jù)已經(jīng)全部接收完,這個(gè)時(shí)間根據(jù)實(shí)際情況來調(diào)整大小

/*解釋一:

*以下時(shí)序脈沖延時(shí)參數(shù)我是在keiluVision2平臺(tái)下,MemoryModel在small模式,CodeRomSize在Large模式下編譯的,

*如果在不同keil版本,不同的模式下,編譯出來的程序有可能此參數(shù)會(huì)不一樣。

*以下的時(shí)序脈沖延時(shí)參數(shù)是需要一步一步慢慢調(diào)的。我一開始的時(shí)候先編寫一個(gè)簡單的發(fā)送數(shù)據(jù)測試程序,

*先確調(diào)試出合適的發(fā)送時(shí)序延時(shí)數(shù)據(jù)。然后再編寫串口接收數(shù)據(jù)的程序,從而調(diào)試出接收時(shí)序的延時(shí)參數(shù)。

*比如:我第一步發(fā)送數(shù)據(jù)的測試程序是這樣的:

voidmain()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

//usart_service();//串口服務(wù)程序

eusart_send(0x08);//測試程序,讓它不斷發(fā)送數(shù)據(jù)給上位機(jī)觀察,確保發(fā)送延時(shí)時(shí)序的參數(shù)準(zhǔn)確性

delay_long(300);

eusart_send(0xE5);//測試程序,讓它不斷發(fā)送數(shù)據(jù)給上位機(jī)觀察,確保發(fā)送延時(shí)時(shí)序的參數(shù)準(zhǔn)確性

delay_long(300);

}

}

*/

#defineconst_t_110//發(fā)送時(shí)序延時(shí)1第一步先調(diào)出此數(shù)據(jù)

#defineconst_t_29//發(fā)送時(shí)序延時(shí)2第一步先調(diào)出此數(shù)據(jù)

#defineconst_r_17//接收時(shí)序延時(shí)1第二步再調(diào)出此數(shù)據(jù)

#defineconst_r_29//接收時(shí)序延時(shí)2第二步再調(diào)出此數(shù)據(jù)

voidinitial_myself(void);

voidinitial_peripheral(void);

voiddelay_long(unsignedintuiDelaylong);

voiddelay_short(unsignedintuiDelayShort);

voiddelay_minimum(unsignedcharucDelayMinimum);//細(xì)分度最小的延時(shí),用char類型一個(gè)字節(jié)

voidT0_time(void);//定時(shí)中斷函數(shù)

voidINT0_int(void);//外部0中斷函數(shù),在本系統(tǒng)中是模擬串口的接收中斷函數(shù)。

voidusart_service(void);//串口服務(wù)程序,在main函數(shù)里

voideusart_send(unsignedcharucSendData);

unsignedcharread_eusart_byte();//從串口讀一個(gè)字節(jié)

sbitbeep_dr=P2^7;//蜂鳴器的驅(qū)動(dòng)IO口

sbitti_dr=P1^0;//模擬串口發(fā)送數(shù)據(jù)的IO口

sbitri_sr=P3^2;//模擬串口接收數(shù)據(jù)的IO口也是外部中斷0的復(fù)用IO口

unsignedintuiSendCnt=0;//用來識(shí)別串口是否接收完一串?dāng)?shù)據(jù)的計(jì)時(shí)器

unsignedcharucSendLock=1;//串口服務(wù)程序的自鎖變量,每次接收完一串?dāng)?shù)據(jù)只處理一次

unsignedintuiRcregTotal=0;//代表當(dāng)前緩沖區(qū)已經(jīng)接收了多少個(gè)數(shù)據(jù)

unsignedcharucRcregBuf[const_rc_size];//接收串口中斷數(shù)據(jù)的緩沖區(qū)數(shù)組

unsignedcharucTest=0;

voidmain()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

usart_service();//串口服務(wù)程序

}

}

voidusart_service(void)//串口服務(wù)程序,在main函數(shù)里

{

unsignedchari=0;

if(uiSendCnt>=const_receive_time//處理一次就鎖起來,不用每次都進(jìn)來,除非有新接收的數(shù)據(jù)

//下面的代碼進(jìn)入數(shù)據(jù)協(xié)議解析和數(shù)據(jù)處理的階段

for(i=0;i

{

eusart_send(ucRcregBuf[i]);

}

uiRcregTotal=0;//清空緩沖的下標(biāo),方便下次重新從0下標(biāo)開始接受新數(shù)據(jù)

}

}

//往串口發(fā)送一個(gè)字節(jié)

voideusart_send(unsignedcharucSendData)//往上位機(jī)發(fā)送一個(gè)字節(jié)的函數(shù)

{

unsignedchari=8;

EA=0;//關(guān)總中斷

ti_dr=0;//發(fā)送啟始位

delay_minimum(const_t_1);//發(fā)送時(shí)序延時(shí)1delay_minimum是本程序細(xì)分度最小的延時(shí)

while(i--)

{

ti_dr=ucSendData//先傳低位

delay_minimum(const_t_2);//發(fā)送時(shí)序延時(shí)2delay_minimum是本程序細(xì)分度最小的延時(shí)

ucSendData=ucSendData>>1;

}

ti_dr=1;//發(fā)送結(jié)束位

delay_short(400);//每個(gè)字節(jié)之間的延時(shí),這里非常關(guān)鍵,也是最容易出錯(cuò)的地方。延時(shí)的大小請(qǐng)根據(jù)實(shí)際項(xiàng)目來調(diào)整

EA=1;//開總中斷

}

//從串口讀取一個(gè)字節(jié)

unsignedcharread_eusart_byte()

{

unsignedcharucReadData=0;

unsignedchari=8;

delay_minimum(const_r_1);//接收時(shí)序延時(shí)1。作用是等過起始位delay_minimum是本程序細(xì)分度最小的延時(shí)

while(i--)

{

ucReadData>>=1;

if(ri_sr==1)

{

ucReadData|=0x80;//先收低位

}

if(ri_sr==0)//此處空指令,是為了讓驅(qū)動(dòng)時(shí)序的時(shí)間保持一致性

{

;

}

delay_minimum(const_r_2);//接收時(shí)序延時(shí)2delay_minimum是本程序細(xì)分度最小的延時(shí)

}

returnucReadData;

}

voidT0_time(void)interrupt1//定時(shí)中斷

{

TF0=0;//清除中斷標(biāo)志

TR0=0;//關(guān)中斷

if(uiSendCnt

{

uiSendCnt++;//表面上這個(gè)數(shù)據(jù)不斷累加,但是在串口中斷里,每接收一個(gè)字節(jié)它都會(huì)被清零,除非這個(gè)中間沒有串口數(shù)據(jù)過來

ucSendLock=1;//開自鎖標(biāo)志

}

TH0=0xfe;//重裝初始值(65535-500)=65035=0xfe0b

TL0=0x0b;

TR0=1;//開中斷

}

voidINT0_int(void)interrupt0//INT0外部中斷函數(shù)

{

EX0=0;//禁止外部0中斷這個(gè)只是我個(gè)人的編程習(xí)慣,也可以不關(guān)閉

++uiRcregTotal;

if(uiRcregTotal>const_rc_size)//超過緩沖區(qū)

{

uiRcregTotal=const_rc_size;

}

ucRcregBuf[uiRcregTotal-1]=read_eusart_byte();//將串口接收到的數(shù)據(jù)緩存到接收緩沖區(qū)里

uiSendCnt=0;//及時(shí)喂狗,雖然main函數(shù)那邊不斷在累加,但是只要串口的數(shù)據(jù)還沒發(fā)送完畢,那么它永遠(yuǎn)也長不大,因?yàn)槊總€(gè)中斷都被清零。

/*解釋二:

*注意,此處必須把IE0中斷標(biāo)志清零,否則在接收到的數(shù)據(jù)包最后面會(huì)多收到一個(gè)無效的字節(jié)0xFF。

*/

IE0=0;//外部中斷0標(biāo)志位清零,必須的!

EX0=1;//打開外部0中斷

}

voiddelay_long(unsignedintuiDelayLong)

{

unsignedinti;

unsignedintj;

for(i=0;i

{

for(j=0;j<500;j++)//內(nèi)嵌循環(huán)的空指令數(shù)量

{

;//一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語句

}

}

}

voiddelay_short(unsignedintuiDelayShort)

{

unsignedinti;

for(i=0;i

{

;//一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語句

}

}

/*解釋三:

*由于IO口模擬的串口時(shí)序要求很高,所以用的延時(shí)函數(shù)盡可能細(xì)分度越高越好,以下用一個(gè)字節(jié)的延時(shí)計(jì)時(shí)器

*/

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論