导航:首页 > 操作系统 > 单片机串口接收超时时间

单片机串口接收超时时间

发布时间: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];
}

阅读全文

与单片机串口接收超时时间相关的资料

热点内容
云服务器在哪设置ftp 浏览:616
黑客社会工程学攻击pdf 浏览:990
专业中颖单片机程序开发 浏览:420
python多进程多线程实例 浏览:637
山东济南生产服务器云主机 浏览:310
算法员跳槽四年 浏览:730
秦九昭算法v0怎么求 浏览:384
斗鱼java 浏览:896
程序员对老师的感谢 浏览:29
什么app能查看银行卡照片 浏览:24
win7pdf虚拟打印 浏览:332
程序员喜欢的女生条件 浏览:123
阿里云服务器ip搭建教程 浏览:85
解压和拉伸这一动画的原理是什么 浏览:740
tbc战士的命令怒吼 浏览:481
idea快捷键看源码 浏览:976
手机碎屏解压工具 浏览:245
jsonrpcphp使用 浏览:566
网上求职系统源码 浏览:699
pdf数字不显示 浏览:890