发新帖我要提问
12
返回列表
打印
[51单片机]

8031单片机配合使用外部程序存储器和外部数据存储器问题

[复制链接]
楼主: chenjianmal
手机看帖
扫描二维码
随时随地手机跟帖
21
戈卫东| | 2013-11-27 12:31 | 只看该作者 回帖奖励 |倒序浏览
Serial_Rec_Str(), Serial_Send_Str() 这些函数感觉像是收/发多个字节的, 真的不知道在ISR里面调用它们会发生什么状况.....

使用特权

评论回复
22
戈卫东| | 2013-11-27 12:33 | 只看该作者
airwill 发表于 2013-11-26 15:16
稍稍有点复杂, 得结合你的实际数据来看了.
可以先用个简单的中端服务来测试, 再一步步地实现你的功能.
或者 ...

8031很可能没有仿真器可用.....

使用特权

评论回复
23
chenjianmal|  楼主 | 2013-11-27 13:19 | 只看该作者
yangfan19641964 发表于 2013-11-27 10:25
不知道Serial_Send_Data、Serial_Rec_Data、while(Serial_Rec_Str());这三个函数的内容

/************************************************************
**函数名称:void Serial_Init(void)
**参数说明:void
**函数功能:串口通信初始化设置函数
**函数返回:void
************************************************************/
void Serial_Init(void)
{
        SCON=0xf0;                         //设置串口工作方式3即:SM0SM1=11,SM2=1,REN=1
        TMOD|=0x20;                        //设置定时器T1为工作方式2
        TH1=0Xfd;                         // 波特率为9600下的初值设置
        TL1=0Xfd;                               
        TR1=1;                                        //打开定时器T1
        ES=1;                                                //打开串口中断
        EA=1;                                                //打开总中断
}

/************************************************************
**函数名称:void Serial_Send_Data(uchar byte)
**参数说明:byte--->即要发送的无符号型数据;
**函数功能:9位异步收发数据的串口发送数据函数
**函数返回:void
************************************************************/
void Serial_Send_Data(uchar byte)
{
        //TB8=0;                                //TB8---即多机通信中9位异步收发数据的第九位数据,TB8=1指发送的是地址,TB8=1指发送的是数据
        SBUF=byte;
        while(!TI);
        TI=0;
}

/************************************************************
**函数名称:void Serial_Rec_Data(uchar byte)
**参数说明:void
**函数功能:9位异步收发数据的串口接收数据函数
**函数返回:temp--->串口接收到的数据
************************************************************/
uchar Serial_Rec_Data(void)
{
        uchar temp;
        while(!RI);
        RI = 0;
        temp = SBUF;
        return temp;
}

/************************************************************
**函数名称:uchar Serial_Send_Str(void)                
**参数说明:void
**函数功能:9位异步收发数据的串口发送字符串函数
**函数返回:主机接收到字符串后的校验值
************************************************************/
uchar Serial_Send_Str(void)                
{  
        uchar p,i,temp;
        p=0;                                                                                                        //p=0--->清校验和
        for(i=0;i<BN;i++)
        {               
          p+=tbuf;
                Serial_Send_Data(tbuf);  //发送一数据
        }       
        Serial_Send_Data(p);                      //发送校验和
        temp = Serial_Rec_Data();     //接收校验结果
        return temp;
}

/************************************************************
**函数名称:uchar Serial_Rec_Str(void)        
**参数说明:void
**函数功能:9位异步收发数据的串口接收字符串函数
**函数返回:0--->接收字符串成功
**                                        1--->接收字符串失败
************************************************************/
uchar Serial_Rec_Str(void)                        
{  
        uchar p,i,temp;
        p=0;                                                                                                           //p=0--->清校验和
        for(i=0;i<BN;i++)
        {
                rbuf = Serial_Rec_Data();        //接收数据
    p+=rbuf;
        }
        temp = Serial_Rec_Data();                                //接收校验码
        if(temp==p)
        {
                Serial_Send_Data(0x00);                                //校验和相同发"00"
                return 0;
        }                        
        else
        {
                Serial_Send_Data(0xFF);                                //校验和不同发"FF",重新接收
                return 1;
        }
}

使用特权

评论回复
24
chenjianmal|  楼主 | 2013-11-27 13:24 | 只看该作者
戈卫东 发表于 2013-11-27 12:23
这么古老的东西现在还找的到么?

还有,就是不好找8031  但公司的总工程师要求使用8031   不能改为89C51系列芯片,以前一直使用C51系列芯片

使用特权

评论回复
25
chenjianmal|  楼主 | 2013-11-27 13:25 | 只看该作者
戈卫东 发表于 2013-11-27 12:33
8031很可能没有仿真器可用.....

8031好像还真没有仿真器可用

使用特权

评论回复
26
chenjianmal|  楼主 | 2013-11-27 13:26 | 只看该作者
本帖最后由 chenjianmal 于 2013-11-27 13:33 编辑
戈卫东 发表于 2013-11-27 12:31
Serial_Rec_Str(), Serial_Send_Str() 这些函数感觉像是收/发多个字节的, 真的不知道在ISR里面调用它们会发 ...

需要使用串口多机通信,发送和接受字符串,不知有什么好的方法来实现这个功能啊?

使用特权

评论回复
27
ayb_ice| | 2013-11-27 14:03 | 只看该作者
漏洞百出
既然是发送查询
void Serial_Send_Data(uchar byte)
{
        //TB8=0;                                //TB8---即多机通信中9位异步收发数据的第九位数据,TB8=1指发送的是地址,TB8=1指发送的是数据
        SBUF=byte;
        while(!TI);
        TI=0;
}
但却又没有关串口中断,而串口中断居然没有判断中断源,太有才了

使用特权

评论回复
28
mamalihui| | 2013-11-27 14:09 | 只看该作者
我只想说两个字 “呵呵”

使用特权

评论回复
29
yangfan19641964| | 2013-11-27 14:58 | 只看该作者
说明三点:
1  C51设置波特率时用不着自己算出立即数,而是:
   TH1=TL1=(uchar)( (float)256 - (float)Fosc*1000000 / ((float)192*BAUD_rate) );
2  对于校验和,更高效的是其与前面所有数据之和相加为0、而不是直接判断二者相等。
3  8031照常用通用仿真机即可。应用时取下外部程序存储器。

使用特权

评论回复
30
yangfan19641964| | 2013-11-27 15:00 | 只看该作者
SMOD=1    ————————》192
SMOD=0   ————————》 384

使用特权

评论回复
31
yangfan19641964| | 2013-11-28 15:22 | 只看该作者
我看了一下你的程序,还未理解透方式2或3是如何实现多机通讯的。申明一下,多机通讯需要硬件电路做保证、多选用RS485芯片。一般RS485搭建成半双工(对于多机通讯,全双工很难实现,并且容易软件崩溃)。我没有看见程序中有RS485的方向选择控制。

在你的基础上大概改了一下,无法验证、也没改完,你自己去完成。发送多字节部分未改成建队列发送的方法。

void Uart_Gets(void)interrupt 4
{
        if (RI)
        {
                RI=0;        temp==SBUF;

                if (RB8)        //不管原来是否有通讯或通讯流程是否结束,首先监测是否发的是地址(也许重新开始发)
                {
                        RB8=0;

                        if(temp == P1)
                        {
                                SM2=0;                //匹配,以后接收数据
                                SBUF=temp;        //发回从机地址

                                Border=1;        Bdata=0;        Bcheck=0;
                        }               
                        else
                                SM2=1;                        //如果不匹配,下次只有收到地址(RB8=1))才进入接收中断

                        return;                       
                }

        /************************************************/

                if (Border)
                {
                        Border=0;       

                        switch(temp)
                        {
                                case 0xff:                //接收到复位命令
                                                break;
                                case 0x01:
                                                if(rrdy == 1)
                                                {
                                                        SBUF=0x01;
                                                        Bdata=1;        //以后接收数据
                                                        CheckSum=0;
                                                        total=BN;       
                                                }
                                                else
                                                {
                                                        SBUF=0x00;
                                                        SM2=1;                //未准备好,异常结束;下次只能接收地址
                                                }

                                                break;
                                case 0x02:
                                                if(rrdy == 1)
                                                {
                                                        SBUF=0x02;
                                                        SENDing=1;        //在主程序中根据该标志发送
                                                        SM2=1;
                                                }
                                                else
                                                {
                                                        SBUF=0x00;
                                                        SM2=1;                //未准备好,异常结束;下次只能接收地址
                                                }

                                                break;
                                default:
                                                SBUF=0x80;
                                                SM2=1;
                                                break;
                        }

                        return;
                }

        /************************************************/

                CheckSum+=temp;

                if (Bdata)
                {
                        rbuf[BN-total]=temp;
                        total--;
                        if (total)        return;

                        Bdata=0;        Bcheck=1;
                        return;
                }

        /************************************************/

                if (Bcheck)
                {
                        Bcheck=0;

                        if (!CheckSum)
                                SBUF=0x00;
                        else
                                SBUF=0xff;

                        SM2=1;

                        return;
                }

        /************************************************/

        }
        else
        {
                TI=0;        Bsend=1;
        }

}

/************************************************************

在主程序中:

        if (SENDing)
        {
                while(!Bsend);        Bsend=0;        //等待原来的应答发完

                for (i=0; i<BN; i++)
                {
                        SBUF=tbuf[i];
                        p+=tbuf[i];
                        while(!Bsend);        Bsend=0;
                }
                p=0x100-p;
                SBUF=p;
                while(!Bsend);        Bsend=0;
                //没必要再接收校验和
        }

使用特权

评论回复
32
zy19860818| | 2013-11-29 13:30 | 只看该作者
收藏,学习了~~~

使用特权

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

本版积分规则