打印

如何做一个串口中断接收程序,一次接收一帧数据

[复制链接]
12689|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cyz7799|  楼主 | 2010-1-16 11:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我想请教一下大家,能否做一个串口中断的接收程序,每次进中断后接收一串数据,遇到指定的标志结束。
我搞了几天,当没办法,能否请朋友帮忙指点一下。
沙发
BlueBus| | 2010-1-22 15:03 | 只看该作者
应该可以,接收中断触发后采用查询方式接收
不过不建议这样做,查询方式接收就是等(阻塞),耗时间效率低,影响系统其他工作
建议每次接收中断就处理一个字节,存到数组中,主程序去判断是否收到结束标志

使用特权

评论回复
板凳
qnmdsb2008| | 2010-1-22 15:17 | 只看该作者
应该可以,利用switch语句就可以,进中断后用case条件判断

使用特权

评论回复
地板
dfsa| | 2010-1-22 20:49 | 只看该作者
串口通信不是只是半双工的吗

使用特权

评论回复
5
司徒老鹰| | 2010-1-22 22:44 | 只看该作者
是232还是422还是485?

使用特权

评论回复
6
司徒老鹰| | 2010-1-22 22:44 | 只看该作者
switch case是可以实现的

使用特权

评论回复
7
有意思| | 2010-1-23 12:53 | 只看该作者
没必要这样做吧?我一般这样做
在isr中buf[front++]=SBUF;收数据
在主程序中
while (front != rear) {
///根据通讯协议处理数据
   if (crc == true) {
        switch (cmd) {
        }
   }
}
中断中不喜欢处理太多事情

使用特权

评论回复
8
aozima| | 2010-1-23 13:17 | 只看该作者
本帖最后由 aozima 于 2010-1-23 13:19 编辑

如果发送方发送一个头后,后面的尾迟迟不发(已当机).那么...怎么死的都不知道.
发送倒是可以用DMA一次发帧,因为发送是可控的,主动权在自己,确定他会发送完成.
而接收是被动的.

使用特权

评论回复
9
成成| | 2010-1-23 14:32 | 只看该作者
本帖最后由 成成 于 2010-1-23 14:39 编辑

to aozima:
你说的这个问题是超时,实现的方式也简单。
如果你的系统有操作系统,在设计任务的时候加入一个超时等待处理;
/* pBuf --------- 接收数据的缓冲区指针
   Timeout  ----- 报文超时的时间(或者是操作系统心跳数目)
   Length ------- 任务所期望接收的数据长度
*/
ReceiveData(UINT8 *pBuf, UINT16 Timeout, UINT8 Length, ......)
{
      ……
   RxByteNum = 0;
   while(1){
         RxByteNum  += ReadRxBuf() ;
      if(RxByteNum < Length)
            TaskDelay(Timeout);    // 也可以把这个值设置为1,然后加一个计数器,可以实现最短的等待时间
   }
   ……
}
如果你的系统没有操作系统,只能用一个定时器作为计数操作,
把上面的程序TaskDelay部分替换掉就可以了。

使用特权

评论回复
10
eddy0317| | 2010-1-29 10:00 | 只看该作者
楼主这种按结束标志结束的方式很好做吧。不需要在中断里面弄,中断不断接收数据写入数组即可,或者用DMA。然后在死循环里面不断读数,读到结束标识就认为结束。如果有超时这个,就加个定时器来定时一下。

使用特权

评论回复
11
mohanwei| | 2010-1-29 11:05 | 只看该作者
7楼的:buf[front++]=SBUF;
前面一定要加上边界判断,否则一不小心系统怎么死的都不知道……
#define bufLen 32//和你的数据帧最大长度有关
u8 buf[bufLen];
……
中断里:
//先判断是否有未处理的帧,如有,则不可以写缓冲区
……
if(front >= _bufLen)//接着判断缓冲区是否溢出
{
      front =0;//或者用其它方式处理缓冲区溢出
}
buf[front++]=SBUF;//缓冲区未满,才可以把数据放进去
……

使用特权

评论回复
12
stm_zy| | 2010-1-29 14:02 | 只看该作者
综合利用串口中断和定时器
可以利用定时器,判断超时。如果超时,就把接收计数清零并将接收数组index清零,重新开始新一轮接收。
以下是部分代码(有点乱,慢慢看):

vu8 tim4_overrun = (u8)0x00;

vu8 tim4_of_10ms = (u8)0x00;//tim4_overrun_flag 10ms

@far @interrupt void TIM4_IR(void)
{
        TIM4->SR1 &= ~TIM4_SR1_UIF;
        if (++tim4_overrun > (u8)10)
        {
                tim4_of_10ms |= (u8)0x01;
                tim4_overrun &= (u8)0x00;
        }
        return;       
}



@far @interrupt void USART_RX(void)
{
        u8 dummy;
       
        //如果没有通讯错误,且接收寄存器非空
        if (!(UART1->SR & 0X0f))
        {
                TIM4->CNTR &= (u8)0x00;
                tim4_overrun &=(u8)0x00;
                if (tim4_of_10ms)
                {
                        RxCounter &= (u8)0x00;
                        tim4_of_10ms &= (u8)0x00;
                }
                TxBuffer[RxCounter++] = UART1->DR;
               
                if (RxCounter >= BufferSize)
                {
                        while((UART1->SR & 0x20))//等待接收标志清空
                        {
                                dummy =  UART1->DR;
                        }
                        RxCounter = 0;
                }
        }
       
        else//如果有通讯错误
        {
                LEDS_PORT->ODR ^= 0x40;
               
                RxCounter = 0;
               
                dummy = UART1->SR;
               
                dummy = UART1->DR;
        }
        return;       
}



//void main(void)中
        while (1)                                                //等待中断
        {
                if (tim4_of_10ms)
                {
                        RxCounter = 0;
                        tim4_of_10ms = 0;
                }
        }

使用特权

评论回复
13
cyz7799|  楼主 | 2010-1-29 15:07 | 只看该作者
我来按照几位高手的指点试一下看,看结果如何

使用特权

评论回复
14
gxgclg| | 2010-1-29 18:00 | 只看该作者
是的,我也觉得没必要用中断接收

使用特权

评论回复
15
ren0zhe| | 2013-10-8 22:39 | 只看该作者
大于一个时间间隔没有接收到新的数据,认为是一帧数据的结束。那个时间间隔由波特率决定的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

5

帖子

1

粉丝