打印
[STC单片机]

串口接受遇到00后面的数据丢失

[复制链接]
3382|4
手机看帖
扫描二维码
随时随地手机跟帖
沙发
hunyungjw|  楼主 | 2016-5-26 09:29 | 只看该作者
请教各位高手,我的程序2为什么从机接受数据遇到0x00后,后面的数据接受不到了?急!急!急!

void main()
{
    uint i = 0;
//定时器0初始化
        Timer0Init();
//  调整输入函数的加载值可以改变串口波特率
        Uart1Init(0,1,253);//初始化串口1,设置波特率115200
        Uart2Init(1,0,1,220);//初始化串口2,设置波特率9600
        Uart2SendStr("AT1#/r");         
//主机发送AT1#,测距仪从机应答:ATD+3字节距离数据+校验和+结束符#
//例如:测距距离6692.4mm,距离大于6553.6mm接受正常
//主机发送Hex:41 54 31 23,从机应答Hex:41 54 44 01 1A 03 1E 23
//41 54 44   01 05 6C    72    23
// A        T  D  6692.4mm         校验和  #        十六进制数:1056c = 66924 结束符:#
//        校验和(只取后2位):01+05+6c =72
//当距离小于6553.6mm接受不正常,即3字节高位为00时就不正常只能显示41 54 44
//比如5763.1mm测距仪直接接串口调试助手程序1显示41 54 44 00 E1 1F 00 23
//程序2显示41 54 44
//以下是相关联程序:
/*------------------------------------------------------------------*/
/*----------------------程序1-------------------------*/

#include "reg51.h"
#include "intrins.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;

#define FOSC 11059200L      //System frequency
#define BAUD 9600         //UART baudrate

/*Define UART parity mode*/
#define NONE_PARITY     0   //None parity
#define ODD_PARITY      1   //Odd parity
#define EVEN_PARITY     2   //Even parity
#define MARK_PARITY     3   //Mark parity
#define SPACE_PARITY    4   //Space parity

#define PARITYBIT EVEN_PARITY   //Testing even parity

/*Declare SFR associated with the UART2 */
sfr AUXR  = 0x8e;           //Auxiliary register
sfr S2CON = 0x9a;           //UART2 control register
sfr S2BUF = 0x9b;           //UART2 data buffer
sfr BRT   = 0x9c;           //Baudrate generator
sfr IE2   = 0xaf;           //Interrupt control 2

#define S2RI  0x01          //S2CON.0
#define S2TI  0x02          //S2CON.1
#define S2RB8 0x04          //S2CON.2
#define S2TB8 0x08          //S2CON.3

bit busy;

void SendData(BYTE dat);
void SendString(char *s);

void main()
{
#if (PARITYBIT == NONE_PARITY)
    S2CON = 0x50;           //8-bit variable UART
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
    S2CON = 0xda;           //9-bit variable UART, parity bit initial to 1
#elif (PARITYBIT == SPACE_PARITY)
    S2CON = 0xd2;           //9-bit variable UART, parity bit initial to 0
#endif

    BRT = -(FOSC/32/BAUD);  //Set auto-reload vaule of baudrate generator
    AUXR = 0x14;            //Baudrate generator work in 1T mode
    IE2 = 0x01;             //Enable UART2 interrupt
    EA = 1;                 //Open master interrupt switch

    SendString("STC12C5A60S2\r\nUart2 Test !\r\n");
    while(1);
}

/*----------------------------
UART2 interrupt service routine
----------------------------*/
void Uart2() interrupt 8 using 1
{
    if (S2CON & S2RI)
    {
        S2CON &= ~S2RI;     //Clear receive interrupt flag
        P0 = S2BUF;         //P0 show UART data
        P2 = (S2CON & S2RB8);//P2.2 show parity bit
    }
    if (S2CON & S2TI)
    {
        S2CON &= ~S2TI;     //Clear transmit interrupt flag
        busy = 0;           //Clear transmit busy flag
    }
}

/*----------------------------
Send a byte data to UART
Input: dat (data to be sent)
Output:None
----------------------------*/
void SendData(BYTE dat)
{
    while (busy);           //Wait for the completion of the previous data is sent
    ACC = dat;              //Calculate the even parity bit P (PSW.0)
    if (P)                  //Set the parity bit according to P
    {
#if (PARITYBIT == ODD_PARITY)
        S2CON &= ~S2TB8;    //Set parity bit to 0
#elif (PARITYBIT == EVEN_PARITY)
        S2CON |= S2TB8;     //Set parity bit to 1
#endif
    }
    else
    {
#if (PARITYBIT == ODD_PARITY)
        S2CON |= S2TB8;     //Set parity bit to 1
#elif (PARITYBIT == EVEN_PARITY)
        S2CON &= ~S2TB8;    //Set parity bit to 0
#endif
    }
    busy = 1;
    S2BUF = ACC;            //Send data to UART2 buffer
}

/*----------------------------
Send a string to UART
Input: s (address of string)
Output:None
----------------------------*/
Void  Uart2SendStr (char *s)
{
    while (*s)              //Check the end of the string
    {
        SendData(*s++);     //Send current char and increment string ptr
    }
}
/********************程序1结束****************/

/********************程序段2开始****************/
#include "systerm.h"
uchar GsmRcv[MAXRCV] = {0};
uchar DebugBuf_U2[MAXBUF] = {0};
uchar DebugBuf_U1[MAXBUF] = {0};
uchar GsmRcvCnt = 0;
uchar GsmAtFlag = 0;
uchar GsmAtFlag2 = 0;
uchar Debug2RcvCnt = 0;
uchar Debug1RcvCnt = 0;
bit uart2Sending = 0;
bit uart1Sending = 0;
uchar receive_number[13]={0};//接收串口发送来的数据的数组  
uchar i=0;
uchar j;

/***************************串口2初始化函数函数*****************************/
/*函数原型:char Uart2Init(char s2smod,char brtx12,unsigned char reload)
/*函数功能:初始化用于连接gprs的串口2 ,串口2只能设置为独立波特率提供波特率
                        并打开串口2中断和全局中断
/*输入参数: S2_P4  S2_P4位 0/1         0:RXD2(P1.2)TXD2(P1.3)        1:RXD2(P4.2)TXD2(P4.3)
                        smod        s2smod位                        0/1
                        brtx12        brtx12位                          0/1
                        reload        reload寄存器数值          0-255
/*输出参数:        -1                s2smod位错误,没有写入0/1
                        -2                brtx12位错误,没有写入0/1
                        0        微波
/********************************************************************/
char Uart2Init(char s2_p4,char s2smod,char brtx12,unsigned char reload)
{
        S2CON = 0X50;//8位可变波特率,无奇偶位
        BRT        = reload;//设置独立波特率发生器波特率

        if(s2_p4 == 1)
        {
                AUXR1 |= S2_P4;   //S2_P4 = 1;//将串口2映射到P4口, 1:RXD2(P4.2)TXD2(P4.3)
        }
        else if(s2_p4 == 0)
        {
                AUXR1 &= (~S2_P4);   //S2_P4 = 0;//将串口2映射到P1口,0:RXD2(P1.2)TXD2(P1.3)
        }
        else
        {
                return -4;
        }
       
                if(s2smod == 1)
        {
                AUXR |= S2SMOD;   //S2SMOD = 1;//波特率倍速位
        }
        else if(s2smod == 0)
        {
                AUXR &= (~S2SMOD);   //S2SMOD = 0;//取消波特率倍速位
        }
        else
        {
                return -1;
        }
               
        if(brtx12 == 1)
        {
                AUXR |= BRTx12;//BRTx12 = 1;1T模式       
        }
        else if(brtx12 == 0)
        {
                AUXR &= (~BRTx12);//BRTx12 = 0;12T模式               
        }
        else
        {
                return -2;
        }               
        AUXR |= BRTR;//开启波特率发生器

        //设置串口2中断优先级       
        IP2H |= PS2H;                //设置串口2优先级为3(最高)
        IP2 |= PS2;

        if (UART2_PRIO & 0x02)
        {
                IP2H |= PS2H;
        }
        else
        {
                IP2H &= ~PS2H;
        }
        if (UART2_PRIO & 0x01)
        {
                IP2 |= PS2;
        }
        else
        {
                IP2 &= ~PS2;
        }       
       
                                                                                                                                                                       
        IE2 |= ES2;//        ES2 = 1;           //允许串口2中断
        EA = 1;           //开总中断
        return 0;       
}


/***************************串口2发送字符函数************************/
/*函数原型:void Uart2SendHex(uchar i)
/*函数功能:串口2发送函数,发送单一数据
/*输入参数:数据
/*输出参数:无
/********************************************************************/
void Uart2SendHex(uchar i)
{
        while(uart2Sending == 1);
        uart2Sending = 1;                              
        S2BUF = i;//装入数据                       
}

/***************************串口2发送字符串函数**********************/
/*函数原型:void Uart2SendStr(char* data_at)
/*函数功能:串口2发送函数,发送字符串
/*输入参数:字符串指针
/*输出参数:无
/********************************************************************/
void Uart2SendStr(char* data_at)
{
        while(*data_at)
        {
                Uart2SendHex(*data_at++);       
        }
}

/***************************串口1初始化函数**********************/
/*函数原型:char Uart1Init(char smod,char brtx12,unsigned char reload)
/*函数功能:串口1初始化
/*输入参数:        smod        smod位        0/1
                        brtx12        brtx12位  0/1
                        reload        reload寄存器数值  0-255
/*输出参数:        -1                smod位错误,没有写入0/1
                        -2                brtx12位错误,没有写入0/1
                        0
/*备注:串口设置位独立波特率提供波特率,和串口2使用同一个波特率,也可以使用定时器1来提供波特率
/********************************************************************/
char Uart1Init(char smod,char brtx12,unsigned char reload)
{
        SCON =  0X50;//8位可变波特率,无奇偶位(SM0=0,SM1=1),使能串口接收模块(REN=1)
        BRT        = reload;//设置独立波特率发生器波特率

        if(smod == 1)
        {
                PCON |= SMOD;   //SMOD = 1;//波特率倍速位
        }
        else if(smod == 0)
        {
                PCON &= (~SMOD);   //SMOD = 0;//取消波特率倍速位
        }
        else
        {
                return -1;
        }
               
        if(brtx12 == 1)
        {
                AUXR |= BRTx12;//BRTx12 = 1;1T模式       
        }
        else if(brtx12 == 0)
        {
                AUXR &= (~BRTx12);//BRTx12 = 0;12T模式               
        }
        else
        {
                return -2;
        }
       
          AUXR |= S1BRS;//串口1设置为使用独立波特率发生器                                                                               
        AUXR |= BRTR;//开启波特率发生器
       
        //设置串口1中断优先级
        if (UART1_PRIO & 0x02)
        {
                IPH |= PSH;
        }
        else
        {
                IPH &= ~PSH;
        }
        if (UART1_PRIO & 0x01)
        {
                PS = 1;                       
        }
        else
        {
                PS = 0;
        }                                                                       
                                                                                       
        ES = 1;           //开串口中断
        EA = 1;           //开总中断
        return 0;       
}

/***************************串口1发送函数**********************/
/*函数原型:void Uart1SendHex(char i)
/*函数功能:串口1发送函数
/*函数功能:串口1发送函数,发送单一数据
/*输入参数:数据
/*输出参数:无
/**************************************************************/
void Uart1SendHex(char i)
{

        while(uart1Sending);//等待发送完毕
        uart1Sending = 1;
        SBUF = i;//将数据放入寄存器发送
}

/***************************串口1发送字符串函数**********************/
/*函数原型:void Uart1SendStr(char* data_at)
/*函数功能:串口1发送函数,发送字符串
/*输入参数:字符串指针
/*输出参数:无
/********************************************************************/
void Uart1SendStr(char* at)
{
        while(*at)        //判断一串数据是否结束
        {
                Uart1SendHex(*at++);//发送数据
        }
               
}

/***************************串口1发送接收中断函数********************/
/*函数原型:void Uart1InterruptReceive(void) interrupt 4
/*函数功能:串口2发送接收中断函数
/*输入参数:无
/*输出参数:无
/*备注:接收函数内部不可以放入其他的中断或者发送函数,否则影响接收数据
/********************************************************************/
void Uart1InterruptReceive(void) interrupt 4
{
        char tmp = 0;
        if(RI)
        {

                ES=0;//关串行口中断
                RI=0;//接收中断信号清零,表示将继续接收
                tmp = SBUF;//接收数据

#ifdef UART1_DEBUG
                //将接收到的数据放入DebugBuf_U1,在定时器内,DebugBuf_U1会被串口2发送给GSM模块。
                //这样通过串口1发送到单片机的数据GSM模块就可以收到了,主要为了调试的方便。
                DebugBuf_U1[Debug1RcvCnt] = tmp;
                Debug1RcvCnt++;
                if(Debug1RcvCnt>=MAXBUF-1)
                {
                        Debug1RcvCnt = 0;       
                }
#endif

                ES=1;//开串行口中断       
        }
       
        if(TI)
        {
                TI = 0;
                uart1Sending = 0;
        }       
}

/***************************串口2发送接收中断函数**********************/
/*函数原型:void Uart2InterruptReceive(void) interrupt 8
/*函数功能:串口2发送接收中断函数
/*输入参数:无
/*输出参数:无
/*备注:接收函数内部不可以放入其他的中断或者发送函数,否则影响接收数据
                用于接收GPRS模块传输来的数据,将数据保存到GsmRcv[],在函数中使用strstr判断数据。
/********************************************************************/
void Uart2InterruptReceive(void) interrupt 8
{
        unsigned char tmp = 0;
        uchar i = 0;
        uchar m = 0;

        IE2 &= (~ES2);                //关闭串口2中断//ES2 = 0;
        if(S2CON & S2RI)        //if(S2RI == 1)
        {

                S2CON &= (~S2RI);//S2RI = 0;
                tmp = S2BUF;

#ifdef UART1_DEBUG
                //将接收到的数据放入DebugBuf_U2,在定时器内,DebugBuf_U2会被串口1发送给PC机。
                //这样GSM发送给单片机的数据也可以在电脑上观察到了。
                //H1005 071 1597422124 2000-01-01 01:01:01 0a0d
                DebugBuf_U2[Debug2RcvCnt] = tmp;
                Debug2RcvCnt++;
                if(Debug2RcvCnt>=MAXBUF-1)
                {
                        Debug2RcvCnt = 0;       
                }
#endif

                        GsmRcv[GsmRcvCnt] = tmp;
                        GsmRcvCnt++;

                if(GsmRcvCnt > MAXRCV)
                {
                        GsmRcvCnt = 0;
                        GsmAtFlag2 = 1;
//                        m = 0;
                }
               
        }

        if(S2CON & S2TI)
        {
                S2CON &= ~S2TI;
                uart2Sending = 0;               
        }

        IE2 |= ES2;//ES2 = 1;

}

/***************************初始化定时器0****************************/
/*函数原型:Timer0Init
/*函数功能:初始化定时器0
/*输入参数:无
/*输出参数:无
/********************************************************************/
void Timer0Init(void)
{
TMOD=0x01;       //设置定时器0为工作方式1
//AUXR|=T0x12;
TH0=T0H;         //放入初值,11.0592M,1ms
TL0=T0L;
// 设置定时器0中断优先级(优先级1)
IPH &= ~PT0H;
PT0 = 1;
EA=1;                           //开总中断
ET0=1;              //开定时器0中断
  TR0=1;            //启动定时器0
}

/***************************定时器0中断******************************/
/*函数原型:Timer0
/*函数功能:每1ms执行一次中断,中断内部重新赋值
/*输入参数:无
/*输出参数:无
/********************************************************************/
void timer0() interrupt 1
{
uchar i = 0;
TH0=T0H;
TL0=T0L;

#ifdef UART1_DEBUG//发送数据用于调试。
timer0_debug_cnt++;
if(timer0_debug_cnt == 20)
{
timer0_debug_cnt = 0;
for(i=0; i<MAXBUF; i++)
{
DebugBuf_U2[i] = 0;       
}
Debug2RcvCnt = 0;
Uart2SendStr(DebugBuf_U1);
for(i=0; i<MAXBUF; i++)
{
DebugBuf_U1[i] = 0;       
}
Debug1RcvCnt = 0;                       
}

#endif

timer0_cnt++;
if(timer0_cnt == 1000)
{
timer0_cnt = 0;
sec_cnt++;
}

#ifdef SHOW_TIME_DEBUG
if(timer0_cnt == 500)
{
//显示时间
ShowTime(0, 4);
//显示日期
ShowDate(0, 5);                       
}
#endif //SHOW_TIME_DEBUG
       
}
/***************************程序段2结束**************************/

使用特权

评论回复
板凳
kfawj| | 2016-5-26 17:09 | 只看该作者
搞这么大段程序上来?
还是看看你的是8位数据,还是9位数据吧?
还有是一个停止位,还是两个停止位?有没有校验和?
自己检查一下吧……

使用特权

评论回复
地板
xiaoxxxx| | 2016-6-18 14:03 | 只看该作者
程序有点长,没太看明白,不过基本上知道问题在哪。你掉用了Uart2SendStr函数来发送数据,在数据小于65536时,字符串中出现了0x00,而0x00是字符串结束符,在发送时遇到0x00就结束了,所以后面的就没发出来。
解决办法:编辑一个能指定缓冲区长度的函数,用以发送数据

使用特权

评论回复
5
liuyimao485812| | 2016-6-26 09:24 | 只看该作者
xiaoxxxx 发表于 2016-6-18 14:03
程序有点长,没太看明白,不过基本上知道问题在哪。你掉用了Uart2SendStr函数来发送数据,在数据小于65536 ...

很有道理。

使用特权

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

本版积分规则

2

主题

6

帖子

0

粉丝