串口通信问题,忍痛再问!!

kwenne 2005-01-22 04:30:06
我的串口数据接收程序(用c语言实现)通过中断接收数据,放入一个数据段中,然后在主程序中通过一个不停的循环来检测数据段中是否有新数据到来,有,就将新数据显示在屏幕上,没有就继续循环,(这样是不是有些画蛇添足,用了中断,还用相当于轮询的方式?),同时,我发现每次通过主程序中的检测轮询部分,然后显示数据的时候,一显示就有很多个数据(我设置了一个标记,可从屏幕上看出是不是在同一个检测轮询程序中显示出来的数据),然而从理论上分析,接收两个数据之间的空闲时间间隔(即没有中断处理的时间间隔)相对于cpu的处理速度来所是很长的,也就是说,对cpu来说,在没有中断处理的时间间隔内,cpu可以轮询检测很多次,如果这样的话,那怎么轮询检测一次就显示很多数据呢?应该只显示一个数据才对呀!假设我发端以960字节/s发送数据,也就是我发完第一个数据后,要隔960分之一秒再传送第二个数据,而对于cpu处理速度来说,960分之一秒内我可以检测轮询很多次,也就是说这期间我的检测轮询程序会把刚刚发过来的第一个数据接收并且显示了,从而第二个数据来的时候,我的检测轮询程序会发现还是只有一个新数据过来(因为第一个我已经接受过了),所以这次也是这能接受并且显示一个数据,可是实际情况却是显示了几个数据,是不是我哪里理解有误呢?我的程序在《rs232串口通信的若干问题,急,愿100分相送》这个问题中已经贴过了,如果有兴趣的可以看看,拜托了!!!真的是很急!!也是从csdn上收集的,请看看问题出在哪里?谢谢,如果彻底解决了,一定给100,困惑很久了!下午也问了这个问题,没人给答复,白白的送了100分,如果有人解答了,本人诚愿再给100分,期待!!!

还有,谁能告诉我下面这些语句都有什么用呢?我看不懂他的用意
outportb (0x20, 0x0B);/*这是不是相当于disable()屏蔽中断?*/
IntCom = (2 - ((inportb (0x20) & 0x18) >> 3));/*IntCom是0或者1,表示com的端口,不过我看不懂是怎么实现赋值的,而微机上的8259A编程讲的不是很详细*/
switch (inportb (com[IntCom].m_nIIR) & 0x06) /*0x06==00000110*/
{
case 0:
com[IntCom].m_nCarrier = (0x80 & inportb(com[IntCom].m_nMSR));
break;/*读MSR是为了清MSI中断,可为什么还要对m_ncarrier赋值呢?*/
case 2: /* DO Nothing */
;
break;
case 4:
outportb(com[IntCom].m_nLCR,inportb(com[IntCom].m_nLCR) & 0x7F);
if (inportb (com[IntCom].m_nRHR) != 0x00)
{
com[IntCom].m_InBuffer[com[IntCom].m_nInTail] = inportb (com[IntCom].m_nRHR);
com[IntCom].m_nInTail = (com[IntCom].m_nInTail + 1) % BUFSZ;
}
break;
case 6 : /* DO Nothing */
;/*LSI中断怎么复位,不是要读LSR吗*/
break;
}
outportb (0x20, 0x20);/*关闭中断*/

...全文
310 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
suyun9329 2005-04-01
  • 打赏
  • 举报
回复
up
niu3333 2005-03-21
  • 打赏
  • 举报
回复
up
gRempCH_eNter 2005-03-17
  • 打赏
  • 举报
回复
楼主写的那段程序应该是个中段服务程序:
第一句是关中断;
第二句是获得端口号,(inportb (0x20) & 0x18) >> 3)算出来不是1就是2;
如果没看错的话,应该用的是16550这个芯片,引发这个中段后,需要判断具体是那种情况引起的,那么那个switch语句段是选择具体情况,case1 和 case 6是具体是什么我不太记得了,得看一下它的说明文档,但case 2和case 4 一个是发送寄存器空(用于发送),一个是接收寄存器满(用于接收)。在接收中他用的是个队列的结构。

至于楼主说的那种情况,看是不是显示数据的函数出了问题(如果不是,得看看你的源程序了),而且也不建议这样写程序,一般来说是用队列的结构,设两个指针,一个指向已读的数据(读完一个就移动到下一个),一个指向新接收到的数据,只要判断两个指针是否指向同一个地方,就可以知道是否还有数据没有读。
cyymycc 2005-03-16
  • 打赏
  • 举报
回复
你的程序是否是单片机的?单片机的用楼上的即可。
PC机是慢,VB(X控件)的通信程序需要设参数。
li_hai_quan 2005-02-01
  • 打赏
  • 举报
回复
void UART_RECEIVE() interrupt 4 using 1 //T2接收中断
{
unsigned int CRC16;
unsigned char aa;
unsigned int bb;
unsigned char k;
if(RI)
{
aa=SBUF;
switch(INNUM)
{
case 1:
if(aa==3||aa==6);检测功能
{
inbuff[1]=aa;
INNUM=2;
START=2;
}
else INNUM=0;
break;
case 2://收几笔数据
inbuff[START++] = aa;
if(START==7)
INNUM++;
break;
case 3://CRC校验
bb=aa;
bb*=256;
bb+=inbuff[6];
CRC16=0xffff;
for(k=0;k<6;k++)
{
CRC16=(CRC16>>8)^CRCtbl[(CRC16&0xFF)^inbuff[k] ];
}
if(CRC16 == bb)
R_ALL=1;//置标志位
INNUM=0;
break;
default:
if(aa==adress&&!R_ALL)//检测地址并且上一笔数据处理完
{
INNUM=1;
inbuff[0] = aa;
}
else INNUM=0;
break;
}
RI=0;
}
else
{
TI = 0;
if(OUTNUM!=0)
{
..............................
}
else CTL_485=1;
}
}
li_hai_quan 2005-02-01
  • 打赏
  • 举报
回复
应该是这样的,如果你收一帧数据,检测头,中断收,收到结束校验,校验对,置标志位,在主程序中检测标志位 显示
扬州飞翔吧 2005-01-27
  • 打赏
  • 举报
回复
一般采用队列方式。在中段程序将数据写入队列,在显示程序中将数据取出。先进先出(FIFO)。
robin_wan 2005-01-25
  • 打赏
  • 举报
回复
在中断中判断标记,如下:
(几年都末写这方面的程序,只能写个大概意思)
char *flag="flag";
void interrupt ComPortIntHandler ()
{
*sStr++=inportb();
if(strstr(sStr,flag))
call 中断驻留程序;
}
li_hai_quan 2005-01-25
  • 打赏
  • 举报
回复
为什么不在中断中直接把数据显示出来呢,轮询方式浪费CPU资源,不建议这么做下去,楼主的问题我还不是很明白,新数据到来你是怎么判断的,应该根据中断中设定标志位来去读呀
h_bin16888 2005-01-25
  • 打赏
  • 举报
回复
为什么要在中断里面显示???你在中断里面设置一个标志就可以了,然后在另外地方显示就可以了
kwenne 2005-01-25
  • 打赏
  • 举报
回复
在中断里直接显示数据不行,显示了一会就不能显示了,一般在中断里不用printf()语句
qb90 2005-01-25
  • 打赏
  • 举报
回复
同意楼上的楼上,既然有中断能查出来了新数据了,就顺便显示就OK了啊
lpfreemail 2005-01-25
  • 打赏
  • 举报
回复
轮寻的方式容易受系统资源的影响,建议使用中断的方法。
ui_ppoppopp 2005-01-22
  • 打赏
  • 举报
回复
read LSR bit 0
1 data in buffer
0 buffer is empty

27,516

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧