一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

搜索
楼主: LBQ691477940

[其他综合] 关于数据长度不相等的串口中断程序

[复制链接]
 楼主| 发表于 2010-9-18 19:44 | 显示全部楼层
本帖最后由 LBQ691477940 于 2010-9-18 19:46 编辑

回复 10# huayuliang


改成这样再长的数据也不冲跑程序了,不过感觉反应不怎么灵敏。
#define   length 9
volatile unsigned char k ;
volatile unsigned char sbuf[length];

//=============中断服务程式=============================/
void UART_Interrupt_Receive(void) interrupt 4 using 3
{
if(RI==1)
{
  RI=0;
  sbuf[k]=SBUF;
  ++k;
  if((k==sbuf[4])||( k>8 ))
  k=0;
  return;
}
else
{
  TI=0;
}
}
读完后将全部缓冲区清O
//================================================
void  cal()     // 全部缓冲区清O
{ uchar k;
  for(i=0;i<8;i++)
  {
   sbuf[k]=0x00;   
  }
  k=0;
}
回复

使用道具 举报

发表于 2010-9-18 23:57 | 显示全部楼层
不灵敏?是不是有时候上位机发出去,下位机没反应?
回复

使用道具 举报

发表于 2010-9-19 08:07 | 显示全部楼层
没细看你的程序,  感觉可以简单些。(不一定正确)

式中:temp----------定义一变量
        x      ----------数据长度


//=============中断服务程式=============================/
void UART_Interrupt_Receive(void) interrupt 4 using 3
{     
       ES=0;                   //  关中断      
       RI=0;                   // 清接收标志
       temp=SBUF;              //  转存         
       sbuf[k]=temp;           // 送数组                                          
       k++;                   //  接收下一个
       if(k==x)               //  x=数据长度
       k=0;
       ES=1;                //开中断
}

     说明:1.如增加一结束标志则更好。

             2.可以的话,波特率能否小一点。如用9600
回复

使用道具 举报

 楼主| 发表于 2010-9-19 13:14 | 显示全部楼层
没细看你的程序,  感觉可以简单些。(不一定正确)

式中:temp----------定义一变量
        x      -- ...
倪大德 发表于 2010-9-19 08:07 https://www.yleee.com.cn/images/common/back.gif

多谢回帖赐教
请问x=数据长度  这里怎样确定长度呢?我按如下改动后也能用(用 青云ComMax串口调试助手)还是有时不灵敏,(用 STC-ISP串口调试助手)又好像灵敏些不懂还是不懂!!
如果将if((k==sbuf[4])||(k>9))  改成 if(k==sbuf[4])这样只要有一个长数据过来就死期期

    //=============中断服务程式=============================/
void UART_Interrupt_Receive(void) interrupt 4 using 3
{      uchar temp;
       ES=0;                   //  关中断      
       RI=0;                   // 清接收标志
       temp=SBUF;              //  转存         
       sbuf[k]=temp;           // 送数组                                          
       k++;                   //  接收下一个
       if((k==sbuf[4])||(k>9))               //  x=数据长度
       k=0;
       ES=1;                //开中断
}
回复

使用道具 举报

 楼主| 发表于 2010-9-19 13:37 | 显示全部楼层
应该串口调试助手问题,换用其他串口调试助手软没问题
//机器人测试程式  用UM5140X计时器电路改装
//晶体振荡器为22.1184MHZ           16/09/2010
#include<AT89X52.h>
#define uchar unsigned char
#define uint unsigned int
//void scan1();//发送指令02030405070217
//void scan2();//发送指令02030405070318
void cal();           //缓冲区清零
void beep();//读return值是否为0203040509024F4BB3
void adc1(); //读return值是否为0203040508030019*/
void display(uchar , uchar , uchar , uchar );   //显示函数
void delay_1ms(uint x);//1MS延时
//sbit start_key = P3^3;//开始定时器0
uchar bai , shi , ge ,i ,  a = 0 , k=0;
bit l=0 , M =0 ,E=0;
uint shu ;
uchar code FCT1[7]={0x02,0x03,0x04,0x05,0x07,0x02,0x17};//指令1
uchar code  FCT2[7]={0x02,0x03,0x04,0x05,0x07,0x03,0x18};//指令2
#define   length 9
volatile unsigned char k ;
volatile unsigned char sbuf[length];
uchar code table[]={
//   0          1                2        3         4          5           6        7         8       
        0x14,0xD7,0x4C,0x45,0x87,0x25,0x24,0x57,0x04,
//         9           A        S         t          o           P                E          r          g                0
        0x05,0x06,0x25,0xAC,0xE4,0x0E,0xff,0x2C,0xEE,0x05 ,0x0f
        };//共阳极数字编码
//=============================++++++++++++++++++++++++=====================
void main()
{       
        P1 = 0x0F;                        //4 3 2 1  - - - - 关闭四位LED显示器
        P3_1 = 0;                        //TX=0让机器人PCB'A进入测试模式
        TMOD=0x21;                        //设置定时器1为模式2;定时器0为模式1          
        TH0=(65536-46000)/256; //约50MS定时器初值                   11.0592 = 4600
        TL0=(65536-46000)%256; //约50MS定时器初值
    ET0 = 1;
        TH1=0xff;                        //装初值设定波特率//22.1184MHZ=57600
        TL1=0xff;                                                             //19200=0xfd
        TR1=1;                                //启动定时器                SM0  SM1
        SM0=0;                                //串口通信模式设置         0          0 = 0
        SM1=1;                                                                //         0          1 = 1
        REN=1;                                //串口允许接收数据         1          0 = 2
                                                                         //                 1          1 = 3
        PS=1;                                //串行口定义为高优先级中断源
        //EX0=1;                                //使能外部中断0中断
        //IT0=1;                                 //设为下降沿触发方式
        EX1=1;                                //使能外部中断1中断
        IT1=1;                                 //设为下降沿触发方式
        ES=1;                                //开串中断
        EA=1;                                //开总中断       
        //PCON=0x80;                 //        波特率不加倍
                                                 //若为PCON=0x80波特率加倍(11.0592MHZ=57600)
        while(1)
        {
                 if(E==0)
                         {
                                 display(1,4,0,0);                                //开机画面显示1400机型
                         }
                 else
                         {
                                 if(M==1 && P3_3==1)
                                   {
                                           delay_1ms(5);
                                        if(M==1 && P3_3==1)
                                                {       
                                                         l = 1;
                                                         P3_1 = 0;                        //TX=0
                                                         shu = 0;
                                                         M=0;
                                                         P1_0 =1;
                                                         P1_0 =1;                       
                                                         TR0 = 0;//开始定时器0
                                                }                                                
                                   }
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++       
                                if(l==0)                 //   M=H TR=H  P1.0 &  P1.1=H  P3.3=L
                                        display(15,bai,shi,ge);                                //显示时间
                                else
                                        {
                                                if(        P1_0==0 && P1_1==0)                         
                                                        {
                                                                if(TR0 ==0 && M==0 && P3_3==1)         //如果PASS后经关电则P3.3为高 显示go
                                                                        {
                                                                                display(15,15,18,19);         //显示go
                                                                        }
                                                                else                                                          // M=H TR=L   P3.3  P1.0   P1.1=L
                                                                        {
                                                                                   display(14,10,11,11);         //如果PASS后不关电关电则一直显示pass
                                                                        }
                                                        }
                                                else
                                                        {
                                                                   display(15,16,17,17);         //显示Err
                                                        }                                  
                                        }
                                beep();         //读return值
                                  adc1();         //读return值
                        cal();         //缓冲区清零
                        }
        }
}
//========读return值是否为0203040509024F4BB3==============
void beep()
        {
                 if(sbuf[0]+sbuf[1]+sbuf[2]+sbuf[3]+sbuf[4]+sbuf[5]+sbuf[6]+sbuf[7] ==sbuf[8] && sbuf[8] == 0xb3)
                   {
                           P1_0=0;           //P1_0=~P1_0; //为了方便观察将其取反
                   }
        }
//========读return值是否为0203040508030019============
void adc1()
        {
                 if(sbuf[0]+sbuf[1]+sbuf[2]+sbuf[3]+sbuf[4]+sbuf[5]+sbuf[6] == sbuf[7] && sbuf[7] == 0x19)
                   {
                           P1_1=0;          //P1_1=~P1_1;        //为了方便观察将其取反
                   }
        }
/*/=================scan:02030405070217=====================
void  scan1()
{               
                for(i=0;i<7;i++)
                {       
                        ES=0;//进入发送数据时先关闭串行中断
                        SBUF=FCT1[i];//将数据原样发回?
                        while(!TI);//等待数据发完
                        TI=0;
                        ES=1;//退出再开串行中断
                }
}
//==================scan:02030405070318====================
void  scan2()
{
                for(i=0;i<7;i++)
                {
                        ES=0;//进入发送数据时先关闭串行中断
                        SBUF=FCT2[i];//将数据原样发回?
                        while(!TI);//等待数据发完
                        TI=0;
                        ES=1;//退出再开串行中断
                }
}*/
//++++++  scan:02030405070217  &  scan:02030405070318 +++++
//向串口发送一个字符
void send_char_com(uchar ch)  
{
    SBUF= ch;
    while(!TI);        //如果TI为0等待
    TI = 0;
}
//===========================================================
//向串口发送一个字符串,strlen为该字符串长度
void send(uchar *str,uchar strlen)
{               
    uchar k=0;
        ES=0;
    do
    {
        send_char_com(*(str + k));
        k++;
    }
        while(k < strlen);
        ES=1;
}
//================================================
void  cal()           //缓冲区清零
{        uchar i;       
                for(i=0;i<8;i++)
                {       
                        sbuf[i]=0x00;                       
                }
                k=0;
}
/*/=============中断服务程式=============================/

void UART_Interrupt_Receive(void) interrupt 4// using 3
{
        if(RI==1)
        {       
                RI=0;
                sbuf[k]=SBUF;
                ++k;
                if((k==sbuf[4])||( k>8 ))
                k=0;
                return;
        }
        else
        {
                TI=0;       
        }
} */
//=============中断服务程式=============================/
void UART_Interrupt_Receive(void) interrupt 4 using 3
{      
           uchar temp;
       ES=0;                   //  关中断      
       RI=0;                   // 清接收标志
       temp=SBUF;              //  转存         
       sbuf[k]=temp;           // 送数组                                          
       k++;                   //  接收下一个
       if((k==sbuf[4])||(k>8)) //  x=数据长度
       k=0;
       ES=1;                //开中断
}
/*/==========================================================
//外部中断0子函数
void int_0 () interrupt 0 //using 0
        {
                EX0=0;                                //暂时关闭外部中断0中断
                P3_4 = ~P3_4; //每中断一次取反一次
                if(P3_4)
                        {
                                TR0 =0;
                                M = 0;
                                P3_3 = 1;
                        }

       
                EX1=0;                                //使能外部中断0中断
        } */
//==========================================================
//外部中断1子函数
void int_1 () interrupt 2 //using 2
        {
                EX1=0;                                //暂时关闭外部中断1中断
                E = 1;
                TR0 = ~TR0; //每中断一次取反一次
                if(TR0==0)
                        {                               
                                shu = 0;
                                P3_1 = 0;                        //TX=0
                        }
                if(TR0==1)
                        {       
                                M=1;
                                l = 0;
                                P1_0 =1;
                                P1_0 =1;
                        }
                EX1=1;                                //使能外部中断1中断
        }
//=========================================================
/*22.1184MHZ时=1.0026MS为单位的延时程序*/
void delay_1ms(uint x)
{
    uchar j;
    while(x--)
        {
        for(j=0;j<227;j++)
            {;}
    }   
}
//==========================================================
void InitTimer0(void) interrupt 1 // using 1 //约50ms中断一次
{
        TH0=(65536-46000)/256; //约50MS定时器初值                 11.0592 = 4600
        TL0=(65536-46000)%256; //约50MS定时器初值
        a++;                                          //约每50ms A自加一
                if(a==40)                        //如果到了约1s
                   {
                    a=0;
                        shu++;
                        bai=shu/100;
                        shi=shu%100/10;
                        ge=shu%10;
                        switch(shu)
                        {
                        case  1:
                                        {
                                         P3_1 = 1;        break;                //TX=1
                                        }                               
                        case  120:          //120S        等待2分钟
                                        {
                                                 //scan1();
                                                 send(&FCT1[0],7);       
                                                 break;
                                        }
                        case  121:
                                        {
                                                if(P1_0==1)
                                                {
                                                        shu = 0;
                                                        l=1;
                                                        TR0=0;
                                                }
                                                break;
                                         }
                        case  168: //48S 后判忙
                                        {
                                         //scan2();
                                         send(&FCT2[0],7);       
                                         break;
                                        }
                        case  173:
                                        {
                                                if(P1_1==0)
                                                {
                                                        P1_1=1;
                                                        P1_0=1;
                                                        shu = 0;
                                                        l=1;
                                                        TR0=0;
                                                }
                                                break;
                                        }
                        case  365: //365        等待4分钟
                                        {
                                                //scan2();
                                                send(&FCT2[0],7);  
                                                break;       
                                        }
                        case  380:         //20S
                                        {
                                                l=1;
                                                shu = 0;
                                                TR0 = 0;
                                                M = 0;
                                                P3_1 = 0;                        //TX=0
                                                break;        //20s
                                        }
                        }
                }
        }
                //default:  
//////////////////////////////////////////////////////////////
void display(uchar k,uchar b,uchar s,uchar g)   //显示函数
{
           P1_7 = 0;
           P2 = table[k];
           P1_4 = 1;
           delay_1ms(5);
           P2 = table[b];
           P1_4 = 0;
           P1_5 = 1;
           delay_1ms(5);
           P2 = table[s];
           P1_5 = 0;
           P1_6 = 1;
           delay_1ms(5);
           P2 = table[g];
           P1_6 = 0;
           P1_7 = 1;
           delay_1ms(5);
}
回复

使用道具 举报

 楼主| 发表于 2010-9-19 13:43 | 显示全部楼层
刚开始自学C语言这是我自己写的确实很乱(新人成长不容易 ,还望高手们多多赐教 谢谢!)
回复

使用道具 举报

发表于 2010-9-19 14:31 | 显示全部楼层
俺用的是 Eltima Software 的 Serial Port Monitor
Virtual Serial Port Driver 6.0 也是这家公司的。

终端软件用的是 Tera Term

都是最好的。
回复

使用道具 举报

发表于 2010-9-20 08:00 | 显示全部楼层
感觉还是加入结束字符比较好!如加入二个0XFF


         uchar  temp, k1;



         。。。。。。。。。。。

         if(temp==0xff) k1++;          //接收到结束符
         if(k1==2)                           //如连续接收到二个结束符
         {   k1=0;k=0;}                  //清0

        。。。。。。。。。。。。。。。。
回复

使用道具 举报

发表于 2010-9-20 08:21 | 显示全部楼层
本帖最后由 倪大德 于 2010-9-20 09:05 编辑
多谢回帖赐教
请问x=数据长度  这里怎样确定长度呢?我按如下改动后也能用(用 青云ComMax串口调试助手) ...
LBQ691477940 发表于 2010-9-19 13:14 https://www.yleee.com.cn/images/common/back.gif



          x=数据长度,只是提供一下思路,你要自己加入在程序中 ,如:

uchar x=0;

。。。。。。。。。。。。。。。。。。。

ES=0;                   //  关中断      
       RI=0;                   // 清接收标志
       temp=SBUF;              //  转存         
       sbuf[k]=temp;           // 送数组   
       if(k==4) x=temp;        //取长度数据送入x                             
       k++;                   //  接收下一个
       if(k==x)               //  x=数据长度
       {k=0; x=0;}
       ES=1;                //开中断

。。。。。。。。。。。。。。。。。。。。
回复

使用道具 举报

发表于 2010-9-20 20:56 | 显示全部楼层
本帖最后由 huayuliang 于 2010-9-20 20:57 编辑

说下俺常用的一个简单格式吧:
【0x55 0xAA】【长度】【内容】【CRC8】【0x0D 0x0A】
帧尾的结束字符也可以只用 【0x0D】,CRC8 也可以用其他校验。
接收时,先检测帧首 【0x55 0xAA】,如果在这里就出现了无码、干扰,就重新开始接收检测。
之后按【长度】把后续数据存入缓冲,【长度】只是【内容】部分的长度。
之后继续读【CRC8】以及帧尾【0x0D 0x0A】,如果在已定义的时间内未接收到校验和帧尾,则判为数据不完整,发送一报文回复给发送端请求重发,并清空所有用到的变量。同样CRC8校验错误也会发一报文。

其实这就是个协议,不过比较简单。完整的协议其实还是比较复杂的。即便看着简单,但写起来也不少代码。
推荐你看看MODBUS。。不过俺很少用MODBUS,多数时候都在用自己的协议。将来的项目会涉及到网络,所以俺也得经常用MODBUS了。。
回复

使用道具 举报

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-8-18 07:29 , Processed in 0.030336 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表