一乐电子

一乐电子百科

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

QQ登录

只需一步,快速开始

快捷登录

手机号码,快捷登录

搜索
查看: 6003|回复: 20
收起左侧

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

[复制链接]
发表于 2010-9-17 20:01 | 显示全部楼层 |阅读模式
求助各位大师能否帮我写一个数据长度不相等的串口中断程序
要求晶振为11.0592m  或22.1184m    波特率为:57600
首先从串口发送一个 02 03 04 05 07 02 17 的十六进制码
如果接收到是:       02 03 04 05 09 02 4F 4B B3 的十六进制码,则P1.0为低,反之P1.0为高

再发从串口发送一个 02 03 04 05 07 03 18 的十六进制码
如果接收到是:       02 03 04 05 08 03 00 19 的十六进制码,则P1.1为低,反之P1.1为高

蓝色字体为头     红色字体为数据长度     绿色为检验码

谢谢!
我自已写的其本上能实现上述功能,但是如果接收到十六进制码长度如果大于9则程序飞跑了.刚学C语言写得很乱
//晶体振荡器为22.1184MHZ
#include<AT89X52.h>
#define uchar unsigned char
#define uint unsigned int
void scan1();//发送指令02030405070217
void scan2();//发送指令02030405070318
void beep();//读return值是否为0203040509024F4BB3
void adc1(); //读return值是否为0203040508030019*/
void display(uchar , uchar , uchar , uchar );   //显示函数
void delay_1ms(uint x);//1MS延时
#define length 9                        //数据长度
uchar SBUFF[length];
uchar bai , shi , ge ,i , a = 0 , k=0;
bit l,  M ;
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
void main()
{
    TMOD=0x21;   //设置定时器1为模式2;定时器0为模式1   
    TH0=(65536-46000)/256; //约50MS定时器初值
    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
    EA=1;    //开总中断    1   1 = 3
    PS=1;    //串行口定义为高优先级中断源
    ES=1;    //开串中断
    PCON=0x80;    // 波特率不加倍
       //若为PCON=0x80波特率加倍(11.0592MHZ=57600)
while(1)
{
  if(start_key==0 && M==0)  //开始定时器0
     {
      delay_1ms(5);
    if(start_key==0 )
     {
       M = 1;   
       TR0 = 1;//开始定时器0
      }
    // while(!start_key) ;      
     }
        beep();
//////////////////////////////////////////////////////////
  if(l!=1)
   display(15,bai,shi,ge);    //显示时间
  else
   {
    if( P1_0==0 && P1_1==0)
     {
         display(14,10,11,11);  //显示pass
     }
    else
     {
         display(15,16,17,17);  //显示Err
     }      
   }
     adc1();
}
}
//========读return值是否为0203040509024F4BB3==============
void beep()
{
   if(SBUFF[0]+SBUFF[1]+SBUFF[2]+SBUFF[3]+SBUFF[4]+SBUFF[5]+SBUFF[6]+SBUFF[7] ==SBUFF[8] && SBUFF[8] == 0xb3)
     {
      P1_0=0;
     }
}
//========读return值是否为0203040508030019============
void adc1()
{
   if(SBUFF[0]+SBUFF[1]+SBUFF[2]+SBUFF[3]+SBUFF[4]+SBUFF[5]+SBUFF[6] == SBUFF[7] && SBUFF[7] == 0x19)
     {
      P1_1=0;
     }
}
//=================scan:02030405070217===================== */
void  scan1()
{  
  for(i=0;i<7;i++)
  {
   ES=0;//进入发送数据时先关闭串行中断
   SBUF=FCT1;//将数据原样发回?
   while(!TI);//等待数据发完
   TI=0;
   ES=1;//退出再开串行中断
  }
}
//==================scan:02030405070318====================
void  scan2()
{
  for(i=0;i<7;i++)
  {
   ES=0;//进入发送数据时先关闭串行中断
   SBUF=FCT2;//将数据原样发回?
   while(!TI);//等待数据发完
   TI=0;
   ES=1;//退出再开串行中断
  }
}
//=============中断服务程式================================ */
void UART_Interrupt_Receive(void) interrupt 4
{
if(RI==1)
{
  RI=0;
  SBUFF[k]=SBUF;
  ++k;
  if(k==SBUFF[4])
  k=0;
}
else
{
  TI=0;
}
}
//=========================================================
/*22.1184MHZ时=1.0026MS为单位的延时程序*/
void delay_1ms(uint x)
{
    uchar j;
    while(x--)
{
        for(j=0;j<227;j++)
            {;}
    }   
}
//==========================================================
void InitTimer0(void) interrupt 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  120:         //120S 等待2分钟
     {
      scan1(); break;
     }
   case  365:         //48S
     {
      scan2();  break; //375  等待4分钟
     }
   case  380:         //48S
     {
      l=1;
      shu = 0;
      TR0 = 0;
      break; //20s
     }
   }
  }
}
  //default:  
//////////////////////////////////////////////////////////////
void display(uchar k,uchar b,uchar s,uchar g)   //显示函数
{
   P0=table[k];
   dula=1;
   dula=0;
   P0=0x7b;// 0x04; //
   wela=1;
   wela=0;
   delay_1ms(2);
   dula=0;
   P0=table;
   dula=1;
   dula=0;
   P0=0x77;// 0x08;//
   wela=1;
   wela=0;
   delay_1ms(2);
   dula=0;
   P0=table;
   dula=1;
   dula=0;
   wela=0;
   P0=0x6f;//0x10;//
   wela=1;
   wela=0;
   delay_1ms(2);
   P0=table[g];
   dula=1;
   dula=0;
   P0=0x5f;// 0x20; //
   wela=1;
   wela=0;
  delay_1ms(2);
}
发表于 2010-9-17 20:12 | 显示全部楼层
和俺以前刚开始学的时候差不多。。。

你为接收缓冲区定义的数组超了,之后指针就飞了。。修改下缓冲区长度。。
中断子程序里再加个判断。
俺一般除了用长度控制读取次数之外还要在帧末加上个结束符。
 楼主| 发表于 2010-9-17 20:29 | 显示全部楼层
回复 2# huayuliang


    也试修改缓冲区长度是有一定的效果,但也是不能解决飞跑问题 还望多多指教。谢谢
发表于 2010-9-17 22:43 | 显示全部楼层
回复 3# LBQ691477940


    之前没仔细看你的程序,里面已经有了限制。才发现你的变量定义有问题:


  1. void UART_Interrupt_Receive(void) interrupt 4
  2. {
  3.     if(RI==1)
  4.     {
  5.         RI=0;
  6.         SBUFF[k]=SBUF;
  7.         ++k;
  8.         if(k==SBUFF[4])
  9.             k=0;
  10.     }
  11.     else
  12.     {
  13.         TI=0;
  14.     }
  15. }
复制代码


把其中的两个全局变量单独定义下:
volatile uchar SBUFF[length];
volatile uchar k=0;
就可以了。(据说是不懂这个就不会用C写单片机程序,

那个 SBUFF 不要这么命名变量,会和SBUF弄混的,将来自己都看着迷糊,定义个 sbuf 就是了。
 楼主| 发表于 2010-9-18 00:18 | 显示全部楼层
回复  LBQ691477940


    之前没仔细看你的程序,里面已经有了限制。才发现你的变量定义有问题:


...
huayuliang 发表于 2010-9-17 22:43 https://www.yleee.com.cn/images/common/back.gif



    还是不行只要发一串 02 03 04 05 09 02 4F 4B B3 45 52 12 54 45 45 45 45 45这样子的码过去没两下就跑飞了
发表于 2010-9-18 01:15 | 显示全部楼层
汗啊。。
才注意到。。k==SBUFF[4] 是啥意思?
发表于 2010-9-18 01:38 | 显示全部楼层
回复 5# LBQ691477940

试试这个吧。这个程序结构漏洞太多,数据接收处理得整个重写。

  1. volatile unsigned char k ;
  2. volatile unsigned char sbuf[length];

  3. void UART_Interrupt_Receive(void) interrupt 4
  4. {
  5.     unsigned char s, l;
  6.     if (RI==1)
  7.     {
  8.         RI=0;
  9.         sbuf[k]=SBUF;
  10.         ++k;
  11.         if (k==4) l = sbuf[4];
  12.         if (l==0 || k==l+4)
  13.         {
  14.             k=0;
  15.             return;
  16.         }
  17.     }
  18.     else
  19.     {
  20.         TI=0;
  21.     }
  22. }

复制代码


哦,改成你自己的变量名。
还有就是,数组使用完毕之后,做一次清零,避免出问题。
 楼主| 发表于 2010-9-18 18:42 | 显示全部楼层
[quote]回复  LBQ691477940

试试这个吧。这个程序结构漏洞太多,数据接收处理得整个重写。


谢谢!不过还是不行
“k==SBUFF[4] 是啥意思?”本想用来自动控制数据长度
 楼主| 发表于 2010-9-18 18:45 | 显示全部楼层
发表于 2010-9-18 19:08 | 显示全部楼层
还是超过9个就跑飞么?

上面的程序俺也弄混了。。。自己也在弄串行收发呢。

把这个
if (l==0 || k==l+4)

改成
if (l==0 || k==l)  
试试。

俺习惯了从实际数据开始计算长度。这样可以避免干扰信号对长数据帧的影响。

本版积分规则

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

GMT+8, 2024-6-11 21:45 , Processed in 0.075035 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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