打印

51单片机双机串口通信程序问题(很诡异)

[复制链接]
7847|31
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 青石向晚 于 2010-5-30 17:44 编辑

A机代码:
#include <reg51.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
unsigned char  sendData[]={'1','2','3','4','5','a','n','b','f'};//定义要发送的数据

void uart_init()                         //设置串口工作方式
{
        TMOD=0x20;
        TH1=0xFD;   
        PCON=0x00;
        TR1=1;
        SCON=0x50;
}

void shakeHand()                                        //握手信号
{
        do{
                          SBUF=0x01;
                while(TI==0);
                    TI=0;
                while(RI==0);
                     RI=0;
          }while(SBUF!=0x02) ;
}

void send(unsigned char sendData)          //发送数据程序
{
          SBUF=sendData;

          while(TI==0);
                 TI=0;
}

void send_char(void)                                       
{
        uchar i=0;
        uchar j=0;

        uart_init();

        shakeHand();

        for(;i<strlen(sendData)-1;i++)
                send(sendData);        
}

void main()
{
         send_char();
}

B机代码:

#include <reg51.h>
#include <string.h>

#define uchar unsigned char
#define uint unsigned int


uchar receivedata[15]={};
uchar count=0;

void baudrate_code(uchar a)
{
        switch (a)
        {
                case 0:        TH1=0xfd;break;
                case 1:        TH1=0xfa;break;
                case 2:        TH1=0xf4;break;
                case 3:        TH1=0xe8;break;
                default:TH1=0xfd;
        }
}

/******************* AB机握手时钟 **********************/

void resettime(void)
{
        EA = 1  ;                                /*开全局中断*/
        
        TMOD = 0x21 ;                   /*定时器0方式1  定时器1方式2*/

           TH0 = 0x3C ;                   /*定时器0 50MS定时*/
        TL0 = 0xB0 ;
        ET0 = 1 ;                               /*开定时器0中断*/
        TR0 = 1 ;                                /*启动T0  */
        PT0 = 1 ;                                /*定时0 高优先级*/
}

void stoptime(void)
{
        TR0 = 0 ;
}

void int50ms(void) interrupt 1                             //定时中断,实现波特率自动跟踪
{        
        TH0 = 0x3C ;
        TL0 = 0xB0 ;

        count++;
        if(count>3)
                count=0;

    baudrate_code(count);
}


void uart_init()                                //设置串口工作方式
{
        TMOD=0x20;
        TH1=0xe8;   
        PCON=0x00;
        TR1=1;
        SCON=0x50;
}


void shakeHand()                                   //握手信号
{
        resettime();
          do{
                  SBUF=0x02;

                while(TI==0);
                         TI=0;

                while(RI==0);
                        RI=0;
          }while(SBUF!=0x01) ;
               stoptime();
}

unsigned char receive()                      //字符接受程序
{
        while(RI==0);
                RI=0;

        return (SBUF);
}

void receive_char(void)
{
        uchar i=0;

        uart_init();
          shakeHand();

        do{
                receivedata=receive();
                i++;
        }while(SBUF!='f') ;
}

void main()
{        
        receive_char();
}

这是一个双机通信的程序,具有波特率自动跟随功能,可是如果去掉A机代码中那句红色的语句(那句没有任何实际意义,定义的j变量根本就不需要),通信就不能成功,研究了半天没研究出来什么原因,请各位大虾帮忙~~~

相关帖子

沙发
zhchyl| | 2010-5-30 18:22 | 只看该作者
把优化去掉试一试呢

使用特权

评论回复
板凳
青石向晚|  楼主 | 2010-5-30 19:03 | 只看该作者
优化?能说清楚点吗,不太懂,谢谢啊。 2# zhchyl

使用特权

评论回复
地板
ayb_ice| | 2010-5-31 09:25 | 只看该作者
那句的实际意义只有一定的延时功能

使用特权

评论回复
5
冷漠| | 2010-5-31 11:10 | 只看该作者

一个字符串必须以NUL字节结尾。

本帖最后由 冷漠 于 2010-5-31 11:18 编辑

青石兄字符串的概念:一个字符串必须以“NUL”字节结尾!
  
unsigned char  sendData[]={'1','2','3','4','5','a','n','b','f'};     //定义要发送的数据
.......
  for(;i<strlen(sendData)-1;i++)
                send(sendData);        



所以,你的sendData[]字符串最后少了一个'NUL'字节!于是,这个字符串成了没有结尾的无固定长度字串。当你用i<strlen(sendData)-1;获取字符串长度时,i=随机无限数,直到它找到一个‘NUL’(0x00字节)为止。于是程序崩溃了。

    当你定义了一个 uchar j=0; (恰好是NUL字节)

幸运啊!这个局部变量j=0;恰好被编译器分配在了全局变量sendData[]的后面,(也许前面还有一个i )充当了NUL字符串结尾,于是字串有NUL结尾啦,程序正常啦。

使用特权

评论回复
6
hotpower| | 2010-5-31 11:12 | 只看该作者
冷漠现在转为教授了~~~

使用特权

评论回复
7
冷漠| | 2010-5-31 11:22 | 只看该作者
教授满大街都是,冷漠只有一个。

使用特权

评论回复
8
ayb_ice| | 2010-5-31 11:33 | 只看该作者
本帖最后由 ayb_ice 于 2010-5-31 11:36 编辑

发错了位置

使用特权

评论回复
9
青石向晚|  楼主 | 2010-5-31 12:07 | 只看该作者
呃,这个也能想到,膜拜一下~~~那我修改修改看~~~谢谢啦~~~ 5# 冷漠

使用特权

评论回复
10
青石向晚|  楼主 | 2010-5-31 12:10 | 只看该作者
跟我想的差不多,可是放了一句_nop_()代替它,没有用,所以应该不是,5楼很有道理~~~不过还是要谢谢啦~~~ 4# ayb_ice

使用特权

评论回复
11
fywx| | 2010-5-31 12:21 | 只看该作者
确实,用错函数了
strlen是对字符串操作的;用sizeof就没问题了

使用特权

评论回复
12
青石向晚|  楼主 | 2010-5-31 12:24 | 只看该作者
把sendData[]里面的内容改成了"abcdef"还是没有用,这是为什么啊,难道还有别的原因?
我决定把那段程序改成这样:
unsigned char  sendData[]={'1','2','3','4','5','a','n','b','f'};//定义要发送的数据

do{                                                                    //发送字符
           send(sendData);
                i++;
}while(sendData[i-1]!='f') ;
可是还是一如既往的悲剧?? 5# 冷漠

使用特权

评论回复
13
mohanwei| | 2010-5-31 13:12 | 只看该作者
void SendStr(char *ptr)
{
    while(*ptr)//字符串尚未结束
    {
        SendByte(*ptr);//发送当前字符
        ptr++;//指向下一个字符
    }
}

void main(void)
{
    ……
    init();
    ……
    while(1)
    {
        SendStr("123456");
        ……
    }
}

使用特权

评论回复
14
冷漠| | 2010-5-31 13:46 | 只看该作者
本帖最后由 冷漠 于 2010-5-31 13:47 编辑

一看就知道悲剧发生在哪了:

NAME        TEXT2
?PR?_send?TEXT2      SEGMENT CODE
?DT?_send?TEXT2      SEGMENT DATA
?PR?main?TEXT2       SEGMENT CODE
?DT?main?TEXT2       SEGMENT DATA
?C_INITSEG           SEGMENT CODE
?DT?TEXT2            SEGMENT DATA
        EXTRN        CODE (?C_STARTUP)
        PUBLIC        sendData
        PUBLIC        main
        PUBLIC        _send

        RSEG  ?DT?_send?TEXT2
?_send?BYTE:
   sendData?040:   DS   1

        RSEG  ?DT?main?TEXT2
?main?BYTE:
          i?141:   DS   1

        RSEG  ?DT?TEXT2
       sendData:   DS   9

        RSEG  ?C_INITSEG
        DB        009H
        DB        sendData
        DB        031H
        DB        032H
        DB        033H
        DB        034H
        DB        035H
        DB        061H
        DB        06EH
        DB        062H
        DB        066H
;
; unsigned char  sendData[]={'1','2','3','4','5','a','n','b','f'};//¶¨ÒåÒª·¢Ë͵ÄÊý¾Ý
;  
; void send(unsigned char sendData)          //·¢ËÍÊý¾Ý³ÌÐò

        RSEG  ?PR?_send?TEXT2
_send:
                        ; SOURCE LINE # 10
        MOV          sendData?040,R7
; {
                        ; SOURCE LINE # 11
;           SBUF=sendData;
                        ; SOURCE LINE # 12
        MOV          SBUF,sendData?040
?C0001:
;           while(TI==0);
                        ; SOURCE LINE # 14
        JNB          TI,?C0001
?C0002:
;                  TI=0;
                        ; SOURCE LINE # 15
        CLR          TI
; }                        ; SOURCE LINE # 16
?C0003:
        RET         
; END OF _send

; void main( )

        RSEG  ?PR?main?TEXT2
main:
        USING        0
; {
; char i;
; i=0;
        MOV          i?141,#00H
?C0006:
; do{                                                                    //
;            send(sendData);
                        ; SOURCE LINE # 24
       MOV          R3,#00H
        MOV          R2,#HIGH (sendData)
        MOV          R1,#LOW (sendData)
        MOV          R7,AR1
        LCALL        _send
;                 i++;
                        ; SOURCE LINE # 25
        INC          i?141
; }while(sendData[i-1]!='f') ;
                        ; SOURCE LINE # 26
?C0004:
        MOV          R7,i?141
        MOV          A,#LOW (sendData+0FFFFH)
        ADD          A,R7
        MOV          R0,A
        MOV          A,@R0
        MOV          R7,A
        MOV          A,R7
        CJNE         A,#066H,?C0006
?C0005:
;
;
; }
                        ; SOURCE LINE # 29
?C0007:
        RET         
; END OF main

        END


compiling Text2.C...
TEXT2.C(24): warning C214: 'Argument': conversion: pointer to non-pointer
Text2.C - 0 Error(s), 1 Warning(s).

使用特权

评论回复
15
冷漠| | 2010-5-31 13:56 | 只看该作者
本帖最后由 冷漠 于 2010-5-31 14:09 编辑

如下写法还差不多:全局变量能做形参吗?按照存储器分配原则,全局变量首先分配在静态存储区,然后是形参动态存储区,那全局变量sendData[]即是静态变量又是动态变量?它占用2倍内存?

unsigned char  sendData[]={'1','2','3','4','5','a','n','b','f'};//¶¨ÒåÒª·¢Ë͵ÄÊý¾Ý

void send(  unsigned char aaa)          //·¢ËÍÊý¾Ý³ÌÐò
{
          SBUF=sendData[aaa];
          while(TI==0);
                 TI=0;
}

main()
{
char i;
i=0;
do{      
         send( i );
          i++;
}while(sendData[ i -1] !='f');

while(1);
}

使用特权

评论回复
16
冷漠| | 2010-5-31 14:23 | 只看该作者
unsigned char sendData[]="abcdef";             //  能一样么?


使用特权

评论回复
17
mbutterfly| | 2010-5-31 16:14 | 只看该作者
C语言中数组和指针很多因为边界出问题的现象。

使用特权

评论回复
18
mohanwei| | 2010-5-31 16:34 | 只看该作者
写代码的时候规范点就行了,C哪有这么多问题?

使用特权

评论回复
19
青石向晚|  楼主 | 2010-5-31 17:17 | 只看该作者
这么改了还是没有用,求助啊 15# 冷漠

使用特权

评论回复
20
冷漠| | 2010-5-31 17:43 | 只看该作者

你的原程序多发一字节都不行是吗?

本帖最后由 冷漠 于 2010-5-31 17:48 编辑

LZ原来说的通信能够成功(加上  uchar j=0;);经过修改,将原来的:
unsigned char  sendData[]={'1','2','3','4','5','a','n','b','f'};   修改为:

unsigned char  sendData[]={'1','2','3','4','5','a','n','b','f','\0'};

加了一字节反而不灵了是吗?(保留uchar  j=0; 原状态不变)你的原程序多发一字节都不行是吗?

使用特权

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

本版积分规则

13

主题

41

帖子

0

粉丝