導航:首頁 > 操作系統 > 單片機串口接收超時時間

單片機串口接收超時時間

發布時間:2022-09-04 12:39:30

⑴ 51單片機串口通信

//////////////////////////////////////////////////////////////////////////////////////////////////
//E51Pro.c
//Easy 51Pro編程器主程序,負責通訊,管理編程操作
///////////////////////////////////////////////////////////////////////////////////////////////////

#include <E51Pro.h>

BYTE ComBuf[18];//串口通訊數據緩存,發送和接收都使用
UINT nAddress;//ROM中地址計數
UINT nTimeOut;//超時計數
ProWork pw;//編程器一般操作

void Delay_us(BYTE nUs)//微秒級延時<255us
{
TH0=0;
TL0=0;
TR0=1;
while(TL0<nUs)//利用T0做定時計數器,循環采樣,直到達到定時值
{
}
TR0=0;
}

void Delay_ms(UINT nMs)//豪秒級的延時<65535ms
{
UINT n=0;
TR0=1;
while(n<nMs)////利用T0做定時計數器,循環采樣,直到達到定時值
{
TH0=0;
TL0=20;
while(TH0<4)
{
}
n++;
}
TR0=0;
}

BOOL WaitComm()//等待上位機的命令,18位元組
{
BYTE n=0;
RI=0;
while(!RI){}//等待第一個位元組
ComBuf[n]=SBUF;
RI=0;
n++;
for(n;n<=17;n++)
{
nTimeOut=0;
while(!RI)
{
nTimeOut++;
if(nTimeOut>10000)//後17個位元組都有超時限制
return 0;
}
ComBuf[n]=SBUF;
RI=0;
}
return 1;
}

BOOL WaitResp()//等待上位機回應,1位元組,有超時限制
{
nTimeOut=0;
RI=0;
while(!RI)
{
nTimeOut++;
if(nTimeOut>50000)
{
return 0;
}
}
RI=0;
ComBuf[0]=SBUF;
return 1;
}

BOOL WaitData()//寫器件時等待上位機數據,18位元組,有超時限制
{
BYTE n;
RI=0;
for(n=0;n<=17;n++)
{
nTimeOut=0;
while(!RI)
{
nTimeOut++;
if(nTimeOut>10000)
{
return 0;
}
}
RI=0;
ComBuf[n]=SBUF;
}
return 1;
}

void SendData()//發送數據或回應操作完成,18位元組
{
BYTE n=0;
for(n;n<=17;n++)
{
TI=0;
SBUF=ComBuf[n];
while(!TI){}
TI=0;
}
}

void SendResp()//回應上位機1個位元組,在寫器件函數中使用
{
TI=0;
SBUF=ComBuf[0];
while(!TI){}
TI=0;
}

void SetVpp5V()//設置Vpp為5v
{
P3_4=0;
P3_3=0;
}

void SetVpp0V()//設置Vpp為0v
{
P3_3=0;
P3_4=1;
}

void SetVpp12V()//設置Vpp為12v
{
P3_4=0;
P3_3=1;
}

void RstPro()//編程器復位
{
pw.fpProOver();//直接編程結束
SendData();//通知上位機,表示編程器就緒,可以直接用此函數因為協議號(ComBuf[0])還沒被修改,下同
}

void ReadSign()//讀特徵字
{
pw.fpReadSign();
SendData();//通知上位機,送出讀出器件特徵字
}

void Erase()//擦除器件
{
pw.fpErase();
SendData();//通知上位機,擦除了器件
}

void Write()//寫器件
{
BYTE n;
pw.fpInitPro();//編程前的准備工作
SendData();//回應上位機表示進入寫器件狀態,可以發來數據
while(1)
{
if(WaitData())//如果等待數據成功
{
if(ComBuf[0]==0x07)//判斷是否繼續寫
{
for(n=2;n<=17;n++)//ComBuf[2~17]為待寫入數據塊
{
if(!pw.fpWrite(ComBuf[n]))//<<<<<<<<<<<<<<<<<<<調用寫該器件一個單元的函數
{
pw.fpProOver();//出錯了就結束編程
ComBuf[0]=0xff;
SendResp();//回應上位機一個位元組,表示寫數據出錯了
WaitData();//等待上位機的回應後就結束
return;
}
nAddress++;//下一個單元
}
ComBuf[0]=1;//回應上位機一個位元組,表示數據塊順利完成,請求繼續
SendResp();
}
else if(ComBuf[0]==0x00)//寫器件結束
break;
else//可能是通訊出錯了
{
pw.fpProOver();
return;
}
}
else//等待數據失敗
{
pw.fpProOver();
return;
}
}
pw.fpProOver();//編程結束後的工作
Delay_ms(50);//延時等待上位機寫線程結束
ComBuf[0]=0;//通知上位機編程器進入就緒狀態
SendData();
}

void Read()//讀器件
{
BYTE n;
pw.fpInitPro();//先設置成編程狀態
SendData();//回應上位機表示進入讀狀態
while(1)
{
if(WaitResp())//等待上位機回應1個位元組
{
if(ComBuf[0]==0)//ComBuf[0]==0表示讀結束
{
break;
}
else if(ComBuf[0]==0xff)//0xff表示重發
{
nAddress=nAddress-0x0010;
}
for(n=2;n<=17;n++)//ComBuf[2~17]保存讀出的數據塊
{
ComBuf[n]=pw.fpRead();//<<<<<<<<<<<<<<<<<<<調用寫該器件一個單元的函數
nAddress++;//下一個單元
}
ComBuf[0]=6;//向上位機發送讀出的數據塊
SendData();
}
else
break;//等待回應失敗

}
pw.fpProOver();//操作結束設置為運行狀態
ComBuf[0]=0;//通知上位機編程器進入就緒狀態
SendData();
}

void Lock()//寫鎖定位
{
pw.fpLock();
SendData();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//所支持的FID,請在這里繼續添加
///////////////////////////////////////////////////////////////////////////////////////////////////
extern void PreparePro00();//FID=00:AT89C51編程器
extern void PreparePro01();//FID=01:AT89C2051編程器
extern void PreparePro02();//FID=02:AT89S51編程器

void main()
{
SP=0x60;
SetVpp5V();//先初始化Vpp為5v
SCON=0x00;
TCON=0x00;
//PCON=0x00;//波特率*2
IE=0x00;
//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0
// 0 0 1 0 0 0 0 1
TMOD=0x21;//T0用於延時程序
TH1=0xff;
TL1=0xff;//波特率28800*2,注意PCON
//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI
// 0 1 0 1 0 0 0 0
SCON=0x50;
TR1=1;
Delay_ms(1000);//延時1秒後編程器自舉
ComBuf[0]=0;
SendData();
while(1)//串口通訊採用查詢方式
{
if(!WaitComm())//如果超時,通訊出錯
{
Delay_ms(500);
ComBuf[0]=0;//讓編程器復位,使編程器就緒
}
switch(ComBuf[1])//根據FID設置(ProWork)pw中的函數指針
{
case 0://at89c51編程器
PreparePro00();
break;
case 1://at89c2051編程器
PreparePro01();
break;
case 2://at89s51編程器
PreparePro02();
break;
//case 3:支持新器件時,請繼續向下添加
// break;
//case 4:
// break;
default:
ComBuf[0]=0xff;
ComBuf[1]=0xff;//表示無效的操作
break;
}
switch(ComBuf[0])//根據操作ID跳到不同的操作函數
{
case 0x00:
RstPro();//編程器復位
break;
case 0x01:
ReadSign();//讀特徵字
break;
case 0x02:
Erase();//擦除器件
break;
case 0x03:
Write();//寫器件
break;
case 0x04:
Read();//讀器件
break;
case 0x05:
Lock();//寫鎖定位
break;
default:
SendData();
break;
}
}
}

⑵ 報錯串口超時,是供電不足嗎

這很好檢查嗎,打開所有繼電器,這時測一下單片機的電壓是多少?是否低於5V,若低於5V,就是電壓不足唄。多麼簡單的事?繼電器是多少電壓的,是5V的,還是12Ⅴ的?5V繼電器需要的驅動電流很大,多個繼電器同時吸合,如果電源功率小,那供電電壓肯定下降,使單片機不能正常工作,串口不能收/發數據了,就超時唄。就邊個原因。測電壓吧。

⑶ STM32HAL輪詢模式串口接收函數超時等待問題

是的,HAL裡面這個HAL_UART_Receive()函數已經明明白白地寫了,它是阻塞式查詢工作方式,只要標志不置位或者超時不結束,就乾等到天荒地老。
如果你不需要阻塞式查詢工作方式,就應當選用中斷工作方式,改用 HAL_UART_Receive_IT()函數並配置對應的NVIC模塊、調用對應的中斷服務函數並且鉤上對應的回調。

⑷ C#串口通訊問題

收到數據後,啟動一個線程(這100個位元組做為參數傳過去),然後在這個新線程中處理變色(注意在別的線程中處理控制項要用委託,度娘一下C# 跨線程 訪問控制項),實際上,在這個新開的線程中,也可以同時再開啟比如10個線程,每個線程來處理10個位元組,這樣處理的速度至少可以提升10倍。
另外,用picturebox效率估計很低,建議自己用gdi來畫。

⑸ 串口超時接收的時間怎麼計算

單片機串口接收超時中斷是怎麼回事啊?
接收數據時,超過一定時間就算出錯.
這個超時的時間是單片機自己算出的嗎?
超時的時間是由編程序的人定的,他定多長就多長

⑹ 求單片機串口中斷接收程序,怎樣一次性接受多個字元

首先把變數a定義成一個數組a[10],數組大小,根據要接收的字元確定.再加一個變數J.
在開中斷ES=1後,加一個延時函數.我用過很多這樣的了.請多給點分,以後我還可以幫你.程序如下:
#include<reg52.h>

unsigned char flag,i,j;
unsigned int k;
unsigned char a[10];

unsigned char code table[6]="I get ";

void init()
{
TMOD=0x20; //設定定時器工作方式2
TH1=0xfd; //定時器1裝入初值
TL1=0xfd; //同上
TR1=1; //啟動T1定時器

SM0=0; //設定工作方式1
SM1=1; //同上
REN=1; //允許串口接收
EA=1; //開總中斷
ES=1; //開串口中斷
}

void main()
{
init();
while(1)
{
if(flag==1)
{
ES=0;
for(i=0;i<6;i++)
{
SBUF=table[i];
while(!TI);
TI=0;
}
ES=1;
for(k=0;k<0xffff;k++);
for(i=0;i<j;i++)
{
SBUF=a[i];
while(!TI);
TI=0;
}
flag=0;
}
}
}

void ser() interrupt 4 //中斷程序,接收數據塊,標志位置1
{
RI=0;
a[j]=SBUF;
flag=1;
j+=1;
}

⑺ 261位元組,會超時,可能是什麼原因

Windows和單片機不同,它不是實時操作系統,所以串口接收的延時不能固定在一個值內,安全的做法是:把你的串口命令加一個頭和一個尾,如果VISA讀取緩沖區,能夠把頭和尾都讀出來,那麼你再來做校驗,才可以。
LabVIEW做串口收發程序,你得自己弄個通信超時,比如設置為10秒,如果超過10秒你沒有接收到任何數據或數據不完整,就應當報錯。但在十秒內,你得不斷查詢串口緩沖區是否有數據上報上來。

⑻ 51單片機串口接收十六進制數組數據有誤

你使用這種方式發送vb數據的i話,發送的是ascii碼,比如發送的數據是123的話,計算機會連續發送0x31,0x32,0x33,所以單片機接收程序,需要重新轉換一下,你可是試著換一種方式發送十六進制數據
對於單片機接收程序,由於你發送的數據量比較小,而且發送數據時,相鄰兩個數據的時間間隔也很短,你可以在中斷裡面通過查詢的方式接收數據包
void
serial
()
interrupt
4
using
3
{
uchar
a,cnt;
a=0;
cnt=250;//如果你的波特率比較低,而系統時鍾又快的話,cnt應定義為int型,並把值設置的更大些
ri=0;
es=0;//關閉串口中斷
str[a++]
=sbuf;
while(cnt--){//如果cnt等於0時退出循環
if(ri){
ri=0;
str[a++]
=sbuf;
cnt=250;//接收到新的數據,重新設定超時
}
}
es=1;//重新開串口中斷
//這里可以做一個接收到數組的標志位,用於主程序查詢處理相關數據
mc=str[0];
n=str[1];
}

閱讀全文

與單片機串口接收超時時間相關的資料

熱點內容
win7下引導linux 瀏覽:793
陝西bgp伺服器雲主機 瀏覽:934
ug編程有幾種加工方式 瀏覽:447
錘子手機如何添加桌面文件夾 瀏覽:465
公司早會拍照用哪個app好 瀏覽:424
學習打卡聲音解壓視頻 瀏覽:824
如何使用代理伺服器加速上網 瀏覽:266
找企業負責人電話用什麼app 瀏覽:427
linux創建文本文件命令 瀏覽:390
計算機中文檔加密保護操作步驟 瀏覽:387
地暖解壓管 瀏覽:465
貪心演算法dijkstra 瀏覽:38
買零食用什麼app可以隔天到 瀏覽:632
android控制項動態設置高度 瀏覽:340
python網路編程pdf下載 瀏覽:96
java重排序 瀏覽:465
什麼app可以修改別人網路密碼 瀏覽:728
python如何遍歷list 瀏覽:71
mac查看文件大小命令 瀏覽:900
數據結構java下載 瀏覽:420