




版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 醫(yī)院顧問合同范本
- 勞務(wù)施工電梯合同范本
- 加工制造合同范本
- 協(xié)議單合同范本
- 北京裝修勞務(wù)合同范本
- 加盟串串香合同范本
- 住宅用地轉(zhuǎn)讓買賣合同范本
- 倉庫維修協(xié)議合同范本
- 個(gè)人定制菜地合同范本
- 中介轉(zhuǎn)租店鋪合同范本
- 《我的家族史》課件
- 干部考察報(bào)告表()
- 《攝影圖片分析》課件
- 青少年社會(huì)支持評(píng)定量表
- kW直流充電樁的設(shè)計(jì)
- 施工圖總目錄
- 《裝配化工字組合梁鋼橋六車道3x30m通用圖》(3911-05-2021)【可編輯】
- 02S404給排水圖集標(biāo)準(zhǔn)
- 人民醫(yī)院診斷證明書
- 六年級(jí)勞動(dòng)與技術(shù)下冊(cè)《課程綱要》
- 掛牌督辦安全生產(chǎn)重大事故隱患銷號(hào)申請(qǐng)表
評(píng)論
0/150
提交評(píng)論