打印

51串口中断问题,发送命令后没有返回命令,麻烦大家帮我解决下谢谢!

[复制链接]
4521|29
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
time_12|  楼主 | 2013-9-25 15:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg51.h>
#include <string.h>
#define uchar unsigned char
#define length 13                        //数据长度
unsigned char FlagGetDataNumber;
unsigned char read_buf[6];                                      
unsigned int write_buf[13]={0xAA,0x0A,0xEA,0x00,0x28,0x01,0x02,0x01,0x00,0x00,0x01,0xCB,0xCC};
unsigned int i,j;
bit read_flag = 0;                            //取数标记
bit flag=0;

void delay_50ms(int t)        //延时子程序ms
{
        int j;   
           for(t;t>0;t--)
           for(j=6000;j>0;j--);        
}

void init(void)                  
{
        P1=0xff;
        P3=0xff;


        TMOD =0x20;               //定时器0工作在模式1,GATE=0,C/T=0,16位模式
        SCON =0x50;                                  //串口方式1
        PCON = 0x80;              //SMOD=1,表示数据传输率加倍
        TH1=0xfA;                                  //定时器1初值,设置波特率9600           MAO
        ET1 =0;
        //TH1=0xfd;
    //TL1=0xfd;                                      //MAO
        ES=1;                                          //串口中断允许 工作于方式1   MAO
        TR1=1;                                          //启动定时器1  
        PS=1;                     //设计串行口中断优先级           MAO

        TH0=(65536-50000)/256;    //设定时器0高8位初值  0x3C=60(10)
        TL0=(65536-50000)%256;    //设定时器0低8位初值   0xB0==176(10)
        ET0=1;                    //允许定时器0中断
        TR0=1;                    //启动定时器0



        IT0=1;                //外部中断0下降沿触发方式
        IT1=1;                //外部中断1下降沿触发方式
        EX0=1;                //开外部中断0
        EX1=1;                //开外部中断1
        EA=1;                //开总中断

        count_i=0;                //dog count num
}
/* 向串口发送一个字符 */
  void send_char( unsigned char x)
{
     SBUF=x;
     while (TI== 0 );
     TI= 0;
}


/* 向串口发送一个字符串,string_length为该字符串长度 */
  void send_string_com( unsigned char *s, unsigned int string_length)
{
     unsigned int i= 0;
     do
         {
           send_char(*(s + i));              //向串口发送一个字符
         i++;
         }
     while ( i<string_length);
}




/* 串口接收中断函数 */
void serial () interrupt 4 using 3
{
     if (RI)
      {
        RI = 0;
        read_buf[FlagGetDataNumber]=SBUF;
        FlagGetDataNumber++;                 
        if(6==FlagGetDataNumber){
                FlagGetDataNumber=0;
                if(0x69==jiaoyan1(4)){
                  read_flag=1;   //就置位取数标志
        }               
            
      }
}





/////////***********主函数**********///////////
void main()
{
       
        wrsr(0x30);        //看门狗设置
        delay_50ms(10);// jinyong
        init();                        //初始化       
        send_string_com(write_buf,length);     //测试
        test=~test; //测试
        delay_50ms(10);//    500mS test
        while(1)        
        {
               if(read_flag)  //如果取数标志已置位,就将读到的数从串口发出
          {
               read_flag=0;
              {          
                                    
                  send_string_com( write_buf, 13);//发送13个byte数据
                  }
            
          }
}

unsigned char jiaoyan1 (unsigned int m)        // 校验函数
{
int i,buf;
buf=read_buf[1];   
for(i=2;i<=m;i++)
buf=buf^read_buf[i];
return buf;

}

发的命令:AA 03 E0 8A 69 CC
回的命令:AA 0A EA 00 28 01 02 01 00 00 01 CB CC

相关帖子

沙发
time_12|  楼主 | 2013-9-25 15:56 | 只看该作者
我感觉串口中断函数写错了,但是找不到原因,麻烦哪位大虾帮我下,谢谢

使用特权

评论回复
板凳
ayb_ice| | 2013-9-25 16:16 | 只看该作者
要么中断驱动,要么查询驱动,你这不伦不类的

使用特权

评论回复
地板
NE5532| | 2013-9-25 16:16 | 只看该作者
发送调通了没?波特率对不对?

使用特权

评论回复
5
time_12|  楼主 | 2013-9-25 16:30 | 只看该作者
NE5532 发表于 2013-9-25 16:16
发送调通了没?波特率对不对?

波特率对,把校验那部分去掉就好用。。。

使用特权

评论回复
6
yangfan19641964| | 2013-9-25 17:06 | 只看该作者
一、程序可以改的简洁一些
    do
         {
           send_char(*(s + i));              //向串口发送一个字符
         i++;
         }
     while ( i<string_length);


    do
         {
           send_char(s[i++]);              //向串口发送一个字符
         }
     while ( i<string_length);

二、我看到的是你的串口中断函数括号不配对

使用特权

评论回复
7
time_12|  楼主 | 2013-9-25 17:18 | 只看该作者
yangfan19641964 发表于 2013-9-25 17:06
一、程序可以改的简洁一些
    do
         {

这个括号肯定对

使用特权

评论回复
8
time_12|  楼主 | 2013-9-25 17:19 | 只看该作者
ayb_ice 发表于 2013-9-25 16:16
要么中断驱动,要么查询驱动,你这不伦不类的

我这个就是中断的

使用特权

评论回复
9
time_12|  楼主 | 2013-9-25 17:23 | 只看该作者
yangfan19641964 发表于 2013-9-25 17:06
一、程序可以改的简洁一些
    do
         {

我只是复制了一小部分,可能是落下了一个括号

使用特权

评论回复
10
NE5532| | 2013-9-25 21:34 | 只看该作者
既然已经发现校验有问题,为啥不在这个方向上继续找下去??

使用特权

评论回复
11
ayb_ice| | 2013-9-26 07:56 | 只看该作者
time_12 发表于 2013-9-25 17:19
我这个就是中断的

  void send_char( unsigned char x)
{
     SBUF=x;
     while (TI== 0 );
     TI= 0;
}

使用特权

评论回复
12
time_12|  楼主 | 2013-9-26 09:59 | 只看该作者
NE5532 发表于 2013-9-25 21:34
既然已经发现校验有问题,为啥不在这个方向上继续找下去??

暂时没有找到。。。

使用特权

评论回复
13
yangfan19641964| | 2013-9-26 10:39 | 只看该作者
是不是开机从来就没对过?
有一个可能:开机时由于电源抖动,在RXD有一串脉冲,单片机已进入串口中断收到数据。你再发6个字节的命令,中断在中途就进行判断了。而你的程序没有正确的归零,所以出错。有两个方法:
1、  开机后延时一段时间,清RI标志,再开中断。
2、编写定时程序,如果一定的时间内没有收到串口数据,则计数单元清零。

使用特权

评论回复
14
yangfan19641964| | 2013-9-26 10:42 | 只看该作者
你把校验取掉后,串口只要收到6个字节就发返回。看起来是校验的问题,实际上很可能是我上面说的问题。我在实际问题中常遇到这种现象。

使用特权

评论回复
15
time_12|  楼主 | 2013-9-26 11:27 | 只看该作者
yangfan19641964 发表于 2013-9-26 10:39
是不是开机从来就没对过?
有一个可能:开机时由于电源抖动,在RXD有一串脉冲,单片机已进入串口中断收到数 ...

嗯,每次发送命令都没有返回,但是用send_string_com 发的字符串是对的字符串。我试下你的办法,谢谢了

使用特权

评论回复
16
yangfan19641964| | 2013-9-26 12:11 | 只看该作者
void serial () interrupt 4 using 3
{
     if (RI)
      {
        RI = 0;

        TH0=xx;  TL0=xx;    TR0=1;   ET0=1;

        read_buf[FlagGetDataNumber]=SBUF;
        FlagGetDataNumber++;                 
        if(6==FlagGetDataNumber){
                FlagGetDataNumber=0;
                if(0x69==jiaoyan1(4)){
                  read_flag=1;   //就置位取数标志
        }               
            
      }
}


void  T0_service   interrupt  1
{
     TR0=0;
     FlagGetDataNumber=0;
}

使用特权

评论回复
17
tergy2012| | 2013-9-26 14:19 | 只看该作者
路过看看的

使用特权

评论回复
18
time_12|  楼主 | 2013-9-26 14:35 | 只看该作者
yangfan19641964 发表于 2013-9-26 12:11
void serial () interrupt 4 using 3
{
     if (RI)

大虾我试了还是不好用,我今天把校验和中断接收都是试了,校验得到的数是对的,中断接收换别的程序也好用,应该是这块的问题:  read_buf[FlagGetDataNumber]=SBUF;
                          FlagGetDataNumber++;                 
                          if(6==FlagGetDataNumber){
                          FlagGetDataNumber=0;
                          if(0x69==jiaoyan1(4)){
                          read_flag=1;   //就置位取数标志
        }               

使用特权

评论回复
19
yangfan19641964| | 2013-9-26 15:56 | 只看该作者
你的问题十有**是我说的。开机时由于RXD上的纹波,串口中断已视为收到若干字节。另外,在通讯中需要把一帧数据的开头予以识别:
bit COMing;  定义全局变量

temp=SBUF;

if (!COMing)
{
       if (temp=0xAA)
       {
              COMing=1;
              read_buf[0]=temp;
              FlagGetDataNumber=1;
       }
       return;
}

read_buf[FlagGetDataNumber]=temp;
FlagGetDataNumber++;   
            
if(6==FlagGetDataNumber){
      COMing=0;
      if(0x69==jiaoyan1(4)){
             read_flag=1;   //就置位取数标志
    }
}

使用特权

评论回复
20
time_12|  楼主 | 2013-9-26 16:30 | 只看该作者
yangfan19641964 发表于 2013-9-26 15:56
你的问题十有**是我说的。开机时由于RXD上的纹波,串口中断已视为收到若干字节。另外,在通讯中需要把一帧 ...

我按你这么写,第一次发送时接收到的是 0x00 ,接下来发送接收到的是 01 00 00 00 00 00 00 00 00 00 00 FC

使用特权

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

本版积分规则

4

主题

36

帖子

0

粉丝