微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求大哥帮小弟解决下问题。谢谢!单片机串口判断字符串问题。串口接收保存在数组里面只有第一个字节

求大哥帮小弟解决下问题。谢谢!单片机串口判断字符串问题。串口接收保存在数组里面只有第一个字节

时间:10-02 整理:3721RD 点击:


#include"STC_NEW_8051.H"
#include"delay.h"
#include"INTRINS.H"
#define uchar unsigned char
#define uint unsigned int
#define ON 0
#define OFF 1
#define LOW 0
#define HIGH 1
#define M_TIME 100//定义不进电机频率为75
/*-----------inductor-----------*/                //感应器端口定义
sbit G=P0^0;                                //用做步进电机原点感应器
sbit L = P0^4;                                //标志步进电机终点感应器                               
sbit zhengzhuan=P0^1;                                    //手动  正转
sbit fanzhuan=P0^2;                                        //手动  反转                                                                                               
sbit zidong=P0^3;                                        //自动
                                                                                                                                                               

/*----------motor_GPIO()---------*/                 //马达输出口定义
                                                       
sbit M_Z = P2^0 ; //脉冲正极,
sbit M_F = P2^1;  //脉冲负极,
unsigned char date ,CHZT;
#define BUFSIZE 80//定义串口字节数组长度保存变量
uchar idata Rec_Buff[BUFSIZE]; //接收字符数组BUFSIZE长度

uchar Rec_cnt = 0;
bit Rec_ok;
uint Rec_timeout;
uchar stop_cnt = 0;

void zz_key_press();
void zd_key_press();
void fz_key_press();
void init_m();
void Send_Buf(uchar *p,uchar len) ;
void init_com()        ;
void clear_rec();
void zd();
uint i , j = 300;

void main()
{
        zhengzhuan = 1;
        fanzhuan = 1;
        G = 1;
        L = 1;
        M_Z = 0;
        M_F = 0;       
    init_m();                 //        初始化步进电机归初始状态
        init_com();
        Send_Buf("*******\r\n",9);
        while(1)
        {
                if(Rec_ok == 1)
                {
                  
                   if(Rec_Buff[0]=='s')          //start
                        {
                                Send_Buf("**s\r\n",5);          //测试是否进入
                                if(Rec_Buff[1]=='t')
                                {
                                        if(Rec_Buff[2]=='a')
                                        {
                                                if(Rec_Buff[3]=='r')
                                                {
                                                        if(Rec_Buff[4]=='t')
                                                        {
                                                            zd();
                                                                Send_Buf("start_ok\n",9);
                                                       
                                                                 
                                                        }
                                                }
                                        }
                                }
                       
                        }
                         if(Rec_Buff[0]=='l')           //left
                         {
                                 Send_Buf("l\r\n",3);          //测试是否进入
                                  if(Rec_Buff[1]=='e')
                                {
                                        Send_Buf("e\r\n",3);          //测试是否进入
                                        if(Rec_Buff[2]=='f')
                                        {
                                                Send_Buf("f\r\n",3);          //测试是否进入
                                                if(Rec_Buff[3]=='t')
                                                {
                                                        Send_Buf("t\r\n",3);          //测试是否进入
                                                        M_F = 0;
                                                        for(i=0;i<=j && L == 1;i++)
                                                        {
                                                                M_Z = 1;
                                                                delay_us(M_TIME);
                                                                M_Z = 0;
                                                                delay_us(M_TIME);
                                                        }
                                                        Send_Buf("left_ok\n",9);
                                                       
                                                               
                                                }
                                        }
                                }
                                  
                          }
                          if(Rec_Buff[0]=='r') //right
                          {
                                          Send_Buf("r\r\n",3);          //测试是否进入
                                        if(Rec_Buff[1]=='i')
                                        {
                                                if(Rec_Buff[2]=='g')
                                                {
                                                        if(Rec_Buff[3]=='h')
                                                        {
                                                                if(Rec_Buff[4]=='t')
                                                                {
                                                                        M_F = 1;
                                                                        for(i=0;i<=j && G == 1;i++)
                                                                        {
                                                                                 M_Z = 1;
                                                                                 delay_us(M_TIME);
                                                                                 M_Z = 0;
                                                                                 delay_us(M_TIME);
                                                                        }
                                                                        Send_Buf("right_ok\n",10);
                                                               
                                                                }
                                                        }
                                                }
                                        }
                           }
                           Rec_ok = 0;
                           clear_rec();
                           Rec_cnt = 0;
                        }
           zz_key_press();
           fz_key_press();
           zd_key_press();          
        }
}
/**************初始化串口通讯函数********************/
void init_com()                                                                                         //COM初始化
{
    AUXR=0x20;
        SCON=0x50;
        PCON=0x00;
        TMOD=0x21;
        TH1=0xfa;
        TL1=0xfa;
        PS=1;
        EA=1;
        ES=1;
        TR1=1;          
}


void send_byte(char date)
{
        ES=0;
    REN=0;
        //TI = 0;
        SBUF=date;
        while(!TI);
        TI = 0;        //串口发送完毕后,将在标志位TI置0
        REN=1;
        ES=1;
}

void Send_Buf(uchar *p,uchar len) //发送函数 *P(字符串) len(字符串的长度)
{
        while(len>0)
        {
                send_byte(*p);
                p++;
                len--;       
        }
}
void clear_rec()         //清空         Rec_Buff[BUFSIZE]里面的数据
{
        uchar i;
        for(i=0;i<BUFSIZE;i++)
        {
                Rec_Buff[i] = 0;       
        }
}
//******************检测串行中断********************//
void RX_com() interrupt 4
{
    //Send_Buf("test\r\n",6);
        if(TI)
        {
                TI = 0;
        }
                
        if(RI)
        {
                RI=0;
                Rec_timeout = 0;//超时函数
                Rec_Buff[Rec_cnt] = SBUF;        //循环把SBUF(串口接收的字符串)保存在数组         Rec_Buff[]里面 数组长度 BUFSIZE                           
                Send_Buf("test_RI\r\n",9); //测试是否进入
                  
                if((Rec_Buff[0]=='s'))
                {
                        stop_cnt = 5;//假如是s开头,默认为start ,stop_cnt = 5;
                        Send_Buf("s\r\n",3); //测试是否进入
                        if((Rec_Buff[1]=='t'))
                        {
                                Send_Buf("t\r\n",3); //测试是否进入
                        }
                }else if((Rec_Buff[0]=='l'))
                {
                        stop_cnt = 4; //假如是l开头,默认为left ,stop_cnt = 4;
                        Send_Buf("l**\r\n",5); //测试是否进入
                }else if((Rec_Buff[0]=='r'))
                {
                        stop_cnt = 5; //假如是r开头,默认为right ,stop_cnt = 5;
                        Send_Buf("r\r\n",3); //测试是否进入
                }
                Rec_cnt++;
                if(Rec_cnt>=BUFSIZE)
                {
                        Rec_cnt = 0;
                        ES =0 ;       
                }
                if(BUFSIZE>=stop_cnt)
                {
                        Rec_ok = 1;
                        Send_Buf("test_rec_ok\r\n",13); //测试是否进入
       
                }       
        }else{
                  Rec_ok = 0;
                  ES =0 ;                  //关中断,回复完了再ES=1;  
        }
       
       
}
void zd()
{
        M_F = 0;
        while(L == 1 )
        {
          M_Z = 1;
          delay_us(M_TIME);
          M_Z = 0;
          delay_us(M_TIME);
        }
       
       
       
        M_F=1;
       
        while( G == 1)//当原点感应器不在初始状态下,步进电机回原点
        {
          M_Z = 1;
          delay_us(M_TIME);
          M_Z = 0;
          delay_us(M_TIME);   
        }
}
       
/**************自动按钮控制函数********************/
void zd_key_press()
{
    if(CHZT = 1)//只有在步进电机在初始位置,自动按钮才生效
        {
                if(zidong == 0 )
                 {
                     delay_us(20);
                         if(zidong == 0 || G == 0 )
                         {
                              zd();  
                         }
                         CHZT = 1;//标志步进电机在初始位置
                 }       
        }
       
}
/**************手动反转按钮控制函数********************/
void fz_key_press()
{
     if(fanzhuan == 0)
         {
             delay_us(20);
                 if(fanzhuan == 0 )
                 {
                     M_F = 1;
                         
                         /*while(fanzhuan == 0 )           //反转按钮按下,而且初始状态感应器断开,才可以转。
                         {
                             M_Z = 1;
                                 delay_us(M_TIME);
                                 M_Z = 0;
                                 delay_us(M_TIME);
                         } */
                         if(G == 1)
                         {
                                  M_Z = 1;
                                 delay_us(M_TIME);
                                 M_Z = 0;
                                 delay_us(M_TIME);
                         }
                         CHZT = 1;//标志步进电机在初始位置
                 }
         }
}
/**************手动正转按钮控制函数********************/
void zz_key_press()
{
        if(zhengzhuan == 0)
        {
          delay_us(20);
          if(zhengzhuan == 0)
          {
             
              M_F = 0;
                  /*while(zhengzhuan ==  0 || L == 1)        //正转按钮按下,而且初始状态感应器断开,才可以转。
                  {
                      M_Z = 1;
                          delay_us(M_TIME);
                          M_Z = 0;
                          delay_us(M_TIME);
                  }*/
                  if(L == 1)
                  {
                            M_Z = 1;
                          delay_us(M_TIME);
                          M_Z = 0;
                          delay_us(M_TIME);       
                  }
                 CHZT = 1;//标志步进电机在初始位置
          }
        }
}
/**************初始化不进电机位置控制函数********************/
void init_m()
{
        M_F = 1;
        while(G == 1)  //当原点感应器不在初始状态下,步进电机回原点
        {
                M_Z=1;
                delay_us(M_TIME);
                M_Z=0;
                delay_us(M_TIME);
               
        }
        CHZT = 1;//标志 步进电机在初始位置
}


代码真心好长,大概看了下。首先你得把串口接收中断中的代码缩短,太长了,可能会在上位机发数据的时候你上一次的中断还没退出来,导致接收数据有误。中断执行时间要短!给你个参考

  1. void UART4_IRQHandler(void)
  2. {
  3.         u8 ch = 0,temp=0;
  4.         temp = UART4->SR;
  5.         if(temp&0X20)
  6.         {        
  7.                 if( cntRxd_RS485 < 128 )
  8.                 {
  9.                         Rs485_Buf[cntRxd_RS485++] = USART_ReceiveData(UART4);
  10.                 }
  11.                 else
  12.                 {
  13.                         ch = USART_ReceiveData(UART4);
  14.                 }
  15.         }
  16. …………………………

复制代码


数据接收到缓冲区后拿到中断外面去处理。还要做好错误帧的识别,假如数据接收数大于你设置的stop_cnt了,但是不是你要的指令怎么办?后续的数组要接收满了才能清零从0开始?  还有一帧数据和一帧数据要有个间隔时间,后续还有很多可以完善的地方。代码嵌套的也好多,你不头晕吗?

就是头晕,现在不知道哪里出了错误。

大哥,可以把你给的代码注释一下吗?我不怎么懂

自己先看看测试结果和程序之间 的对于关系

恩,我觉得自己的逻辑没有错,就是代码不知道哪里错了。弄成这样的结果

跟你说了不要在串口中断中处理那么多数据,尤其是还要发数据出去,假如都是波特率都是9600,接收一个数据后第二个数据来了你还在中断里发送你的那些啥“测试是否进入”之类的东西,都删掉

我给你的代码本来有注释的,复制过来是乱码我就删除了。
cntRxd_RS485跟你设置的Rec_cnt一个意思,缓冲数据最大128字节。
USART_ReceiveData(UART4);就是等同于51里的SBUF,表示进来一个字节的数据。
Rs485_Buf[cntRxd_RS485++]表示每接收一个数据就放入buf里,cntRxd_RS485加1,以便接收下一个数据。
cntRxd_RS485的清零都在中断外部处理的,buf里的数据识别也都是在中断外面。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top