打印
[51单片机]

请大家解释一下这段程序中的疑问处?

[复制链接]
809|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
定格|  楼主 | 2015-6-25 16:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请大家解释一下这是一个主机发往从机地址0x10发送数据0x12 ,0x34功能字节为0X55,
起始字节
标志
功能
校验和
帧长度
地址
数据字节1
数据字节2
……
数据字节n
结束字节
数据帧中以8位为数据单位,采用16进制;
功能:数据字节的功能,若无数据字节,功能字节就为0X00,采用压缩BCD数据格式?功能码采用压缩BCD数据格式?

帧长度:数据字节的长度

例如主机向地址为0X10的从机发送数据0X12,0X34,功能字节为0X55,则发送的一帧数据如图
OXAA
0X 0F
0X55
0X39
0X02
0X10
0X12
0X34
0XDD


#include<string.h>
#include<reg52.h>
#define uchar unsigned char
#define uint  unsigned int
#define CHK_OK         0X01//为什么是0x01
#define CHK_ERR        0XFF
#define CLIENT         0X0F
#define HOST           0XF0
#define SYN            0XAA
#define FIN            0XDD
#define RECV_DATA_STAT 0x01//为什么是0x01

#define RECV_HDR_STAT  0X02//为什么是02
#define MAX_RECV_NUM   50//??????????
#define MAX_SEND_NUM   50//????????
/*相关全局变量定义*/
uchar data  client_addr;
uchar data  recv_tmp;
uchar data  recv_status;
uchar data  recv_counter;
uchar idata recv_buf[ MAX_RECV_NUM ];
uchar idata send_buf[ MAX_SEND_NUM ];
bit         recv_frame_ok;
uchar calc_chksum( void );
void  seri_init( void );
void  seri_send( uchar *p,uchar data_len);
void  get_client_addr( void );
(1)串行中断服务子程序void seri_isr()
void seri_isr( void ) interrupt 4 using 1
{
    if(1==TI)
    {
        TI=0;
    }
    if(0==RI)
    {
        return;
    }
    recv_tmp = SBUF;

    switch( recv_status )
    {
        case RECV_DATA_STAT://为什么要比较RECV_DATA_STAT
        {
            recv_buf[ recv_counter]=recv_tmp;
            recv_counter ++;
            if( recv_counter == recv_buf[4] )//为什么是4
            {
                recv_status = RECV_HDR_STAT;
            }
            else
            {
                return;
            }
            break;
        }
        case RECV_HDR_STAT:
        {
            if( recv_tmp == SYN )
            /* 如果是开始字节 */
            {
                recv_buf[ recv_counter ] = recv_tmp;
                recv_counter ++;
                if( 6 == recv_counter )
                {
                    recv_status = RECV_DATA_STAT;
                }
            }
            else if( recv_tmp == FIN )
            /* 如果是结束字节 */
            {
                recv_buf[ recv_counter ] = recv_tmp;
                recv_counter ++;
                if( ( CHK_OK == calc_chksum()    ) &&

                ( recv_buf[5] == client_addr ) )
                {
                    recv_frame_ok = 1;
                }
                else
                {
                    recv_counter = 0;
                    recv_status  = RECV_HDR_STAT;
                }
            }
            else
            {
                recv_counter = 0;
                recv_status  = RECV_HDR_STAT;
            }
            break;
        }
        default:
        {
            recv_status  = RECV_HDR_STAT;
            memset(recv_buf,0x00,MAX_RECV_NUM);
            recv_counter = 0;
            break;
        }
    }
}
(2)主程序void main()
void main( void )
{
    seri_init();
    get_client_addr();
    seri_send("test",4);
    if( 1 == recv_frame_ok )
    /* 接收到数据 */
    {
        /* 对接收到数据进行处理  */
    }
    /* 其他代码等 */
}
(3)计算校验和子程序uchar calc_chksum()
uchar calc_chksum( void )
{
    uchar i;
    uchar chksum2;
    if( ( recv_counter == 0           )||

    ( recv_buf[4]  != recv_counter)  )//recv_buf[4]??
    {
        return CHK_ERR;
    }
    chksum2 = 0;
    for( i=0; i<recv_counter; i++)
    {
        if( i!= 3)
        /* 跳过校验和部分 */
        {
            chksum2 += recv_buf;
        }
    }
    if( chksum2 == recv_buf[3] )
    {
        return CHK_OK;
    }
    else
    {
        return CHK_ERR;
    }
}
(4) 串行口发送子程序void seri_send()
void seri_send( uchar *p,uchar data_len )
{
    uchar i;
    uchar chksum=0;
    /* 准备数据帧头  */
    send_buf[0] = SYN;
    send_buf[1] = CLIENT;
    send_buf[2] = 0x00;
    /*功能字节假设为0x55 */
    send_buf[3] = 0x00;//已经假设为55为什么要存0x00?
    send_buf[4] = data_len+7;
    send_buf[5] = client_addr;
    send_buf[ data_len ] = FIN;
    for( i=0; i< data_len; i++)
    {
        send_buf[i+6] = *p;
        p++;
    }
    for( i=0;i<(data_len + 7); i++)
    {
        chksum +=send_buf;
    }
    send_buf[3] = chksum;
    /* 数据帧准备完毕,下一步是发送 */
    for( i=0;i<(data_len + 7); i++)
    {
        SBUF = send_buf;
        while( TI == 0 );
        TI = 0;
    }
}
(5) 串口初始化子程序void seri_init()
void seri_init( void )
{
    recv_status   = RECV_HDR_STAT;
    recv_counter  = 0;
    recv_frame_ok = 0;
    memset( recv_buf,0x00,MAX_RECV_NUM);
    memset( send_buf,0x00,MAX_SEND_NUM);
    TMOD = 0X20;
    TH1  = 0XFD;
    /* 波特率为9600bit/s */
    TL1  = 0XFD;
    EA   = 1;
    ET0  = 0;
    ES   = 1;
    SCON = 0X50;
    /* 串行口工作在方式1,允许接收 */
    PCON = 0X00;
    TR1  = 1;
}
(6) 读取数据子程序void get_client_addr()
void  get_client_addr( void )
{
    client_addr = P1;
}

相关帖子

沙发
gx_huang| | 2015-6-25 16:50 | 只看该作者
我是色盲,看不见

使用特权

评论回复
板凳
ayb_ice| | 2015-6-25 17:18 | 只看该作者
这个协议有严重问题吧

case RECV_DATA_STAT://为什么要比较RECV_DATA_STAT
        {
            recv_buf[ recv_counter]=recv_tmp;
            recv_counter ++;
            if( recv_counter == recv_buf[4] )//为什么是4
            {
                recv_status = RECV_HDR_STAT;
            }
当接收第一个数据时,recv_buf[4]可能随机值,或者根本没有意义的数据,但仍有可能等于recv_counter
值,造成逻辑错误

使用特权

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

本版积分规则

7

主题

7

帖子

0

粉丝