打印
[ZLG-ARM]

Keil 3环境下仿真正确,下载之后程序出错,请帮忙分析原因

[复制链接]
2230|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
swordlife|  楼主 | 2009-7-15 20:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
原来在Keil 3环境下选择AT89S8253作为器件,编写了一段程序。在Keil 环境下用纯软件仿真,判断逻辑都没有错。串口能够按照要求输出自己定义好的观测字符。
但是下载到AT89S8253以后,发现以下问题:
1.串口输出的第一个字符是正确的以后,后面接着所有字符都错误。
2. 必须在Small模式下编译,在Compact模式和Large模式下编译的程序都不允许,串口无任何字符输出。
---------------------
我采取了以下措施,问题依旧:
1. 将串口波特率降低到9600。
2. 换掉目标板上的AT89S8253,重新焊接新的。
3. 将我程序中的“消息队列“相关函数去除,串口输出即可正确。
4. 换用陈明计老师的SmallRTOS的编写,软件仿真都正确,串口能够可以看到数据,但是下载之后无反应!
我的疑问:
1. 消息队列相关函数,我已经用Keil C里面纯软件仿真一步一步的调试过。逻辑没有问题!是否编译器参数设置问题?
2. 是否是软件代码问题?


我的编写的代码如下附件,请大家帮我找找原因!

#include "config_all.h"
uint8 Uart_ReceFrame_State=0;            //定义一个表示串口接收数据帧状态的变量,标明有没有接收到起始字符,帧长度,数据,校验字等状态

extern void Delay_50us(uint16 t);
#define MCU_SerialInData_FIFO_MaxNumber        30
#define MCU_SerialOutData_FIFO_MaxNumber    30
#define System_Message_FIFO_MaxNumber    10

uint8 xdata MCU_SerialInData_FIFO[MCU_SerialInData_FIFO_MaxNumber];            //定义存储PDA下发下来的数据的数组,[0]为存储数组中有效数据的长度,
uint8 xdata MCU_SerialOutData_FIFO[MCU_SerialOutData_FIFO_MaxNumber];
uint8 xdata System_Message_FIFO[System_Message_FIFO_MaxNumber];


uint8 xdata  Uart1_Datain_buffer[30];                /*定义子串口1接收PDA命令缓冲存储数组*/
uint8 xdata  Uart2_Datain_buffer[30];                /*定义子串口2接收PDA命令缓冲存储数组*/
uint8 xdata  Uart3_Datain_buffer[30];                /*定义子串口3接收PDA命令缓冲存储数组*/
uint8 xdata  Uart4_Datain_buffer[30];                /*定义子串口4接收PDA命令缓冲存储数组*/


 uint8  Test_Stop=0;
 uint8   Have_Right_Frame=0;


#define All_Frame_data_number 40
uint8 xdata  All_Frame_data[All_Frame_data_number];        //存储串口接收到得数据,保留的是一个完整的帧,方便以后计算
uint8 xdata  PDA_Command[40];        //存储串口接收到得数据,保留的是一个完整的帧,方便以后计算
uint8  Frame_Data_number1,Frame_Data_number2;    /*定义接收串口命令帧长度标识字符,通讯协议中的帧长度信息存入此变量*/
uint8  Frame_Data_Number_Flag;            //定义帧数据字节的长度,准备在接受帧数据中作为计数器使用
uint8  CRC_16_Number;
uint16 CRC_16_Result_Receiver;
uint16 CRC_16_Result_Change;

uint8 xdata MCU_SerialPort_CanSend;




extern void VK3234_UartOut(uint8 xdata  *Buf);
/*********************************************************************************************************
** 函数名称: void InitSerial(void)
** 功能描述: 串口0初始化
** 输 入: 
** 输 出: 
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        void InitSerial(void)
{
    SCON = 0x50;
    PCON = 0x00;                //波特率加倍
    TMOD = TMOD & 0x0f;
    TMOD = TMOD | 0x20;                    //工作于方式2,自动重装
    TH1 = 0xfD;                       //串口通信的波特率是 9600 b/s
    TL1 = 0xfD;

    //TH1=BAUDRATE;
    //TL1=BAUDRATE;
    TR1 = 1;
    ES = 1;
 
}


/*********************************************************************************************************
** 函数名称: CreateMessagePool(uint8 xdata *Buf,uint8 SizeOfBuf)
** 功能描述: 建立一个环形的消息管理队列,并且进行初始化
** 输 入: 
** 输 出: 
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8  CreateMessagePool(uint8 xdata  *Buf,uint8  SizeOfBuf)
{
    uint8 a=0xff;
    if((SizeOfBuf>4)&&(Buf!=NULL))
    {
    Disable_MCU_Interrupt();
    Buf[0]=0;                //标识消息环中有用消息的个数;
    Buf[1]=SizeOfBuf;        //标识消息队列最大可以存储多少个消息,Buf[1]以后固定不变,便于以后比较操作
    Buf[2]=3;                //存储真正存放有效消息的数组下标,指明哪一个数组值是要出消息对的
    Buf[3]=0;                //存放消息的的真正起始地址,这里存储第一个消息。
    Enable_MCU_Interrupt();
    a=Ture;
    } 
    else
    {
    a=False;
    }
    return a;
}
/*********************************************************************************************************
** 函数名称: PostMessagePool(uint8  *Buf,uint8 Data)
** 功能描述: 将一个消息放入消息队列
** 输 入: 
** 输 出: 
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
 uint8 PostMessagePool(uint8 xdata  *Buf,uint8 data Data)
{
    uint8 temp=0;

    if(Buf==NULL)
    {
        return False;
    }
    Disable_MCU_Interrupt();
    if(Buf[0]<(Buf[1]-3))    //判断消息队列中是否还有空间
    {
        temp=Buf[2]+Buf[0];    //Buf[2]是当前第一个消息的存储位置+Buf[0]当前还有几个有效消息+1
        if(temp>=Buf[1])        //判断存放的地址是否超过了消息最后一个存储位置(越界)
        {
            temp=temp-Buf[1]+3;    //存储地址越界了,则存放在消息环的第一个位置,形成环形
        }
        Buf[temp]=Data;            //存储消息值
        Buf[0]++;                //标识消息环中有用消息的个数加1
        Enable_MCU_Interrupt();
        return Ture;
    }
    else
    {
           Enable_MCU_Interrupt();
        return False;
    }
}
/*********************************************************************************************************
** 函数名称: uint8 PostMessagePool_Interrupt(uint8  *Buf,uint8 Data)
** 功能描述: 中断程序中使用,将一个消息放入消息队列,
** 输 入: 
** 输 出: 
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
 uint8 PostMessagePool_Interrupt(uint8 xdata  *Buf,uint8 data Data)
{
    uint8 temp=0;

    if(Buf==NULL)
    {
        return False;
    }
    Disable_MCU_Interrupt();
    if(Buf[0]<(Buf[1]-3))    //判断消息队列中是否还有空间
    {
        temp=Buf[2]+Buf[0];    //Buf[2]是当前第一个消息的存储位置+Buf[0]当前还有几个有效消息+1
        if(temp>=Buf[1])        //判断存放的地址是否超过了消息最后一个存储位置(越界)
        {
            temp=temp-Buf[1]+3;    //存储地址越界了,则存放在消息环的第一个位置,形成环形
        }
        Buf[temp]=Data;            //存储消息值
        Buf[0]++;                //标识消息环中有用消息的个数加1
        Enable_MCU_Interrupt();
        return Ture;
    }
    else
    {
           Enable_MCU_Interrupt();
        return False;
    }
}

/*********************************************************************************************************
** 函数名称: GetMessagePool(uint8  *Buf,uint8 Data)
** 功能描述: 从指定的消息队列取出一个消息
** 输 入: 
** 输 出:     调用成功,返回Ture,调用失败返回False
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
    uint8 GetMessagePool(uint8 xdata  *Buf,uint8 data *Data)
{

    if(Buf==NULL)
    {
        return False;
    }
    Disable_MCU_Interrupt();
    if(Buf[0]!=0)
    {

        *Data=Buf[Buf[2]];

        Buf[0]--;    //标识消息环中有用消息的个数减1
        Buf[2]++;    //出对的消息指针加1,指向下一个消息
        if(Buf[2]>=Buf[1])
        {
            Buf[2]=3;

        }
    
        Enable_MCU_Interrupt();
        return Ture;
    }
    else
    {
           Enable_MCU_Interrupt();
        return False;    
    }
}     



/*********************************************************************************************************
** 函数名称:uint8 GetMessageNumber(uint8  *Buf)
** 功能描述: 查询消息队列的消息个数
** 输 入: 
** 输 出:     返回消息个数
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
    uint8 GetMessageNumber(uint8 xdata  *Buf)
{
    uint8 temp;
    if(Buf==NULL)
    {
        return False;
    }

    if(Buf[0]!=0)
    {
        temp=Buf[0];
           Enable_MCU_Interrupt();
        return temp;
    }
    else
    {

        return 0;
    }
}     

/*********************************************************************************************************
** 函数名称:uint8 ClearMessagePool(uint8  *Buf)
** 功能描述: 清空消息队列
** 输 入: 
** 输 出:     返回消息个数
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
    uint8 ClearMessagePool(uint8 xdata  *Buf)
{
    if(Buf==NULL)
    {
        return False;
    }

    Buf[0]=0;                //标识消息环中有用消息的个数;
//    Buf[1]=SizeOfBuf;        //标识消息队列最大可以存储多少个消息,Buf[1]以后固定不变,便于以后比较操作
    Buf[2]=3;                //存储真正存放有效消息的数组下标,指明哪一个数组值是要出消息对的
    Buf[3]=0;                //存放消息的的真正起始地址,这里存储第一个消息。
    return Ture;
}     



/*********************************************************************************************************
** 函数名称: PutChar
** 功能描述: 发送一个字节
** 输 入: Data:发送的数据
** 输 出: 无
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
   void PutChar(uint8 data Data)
{
       Disable_MCU_Interrupt();
    if (MCU_SerialPort_CanSend == Ture)                         
    {
        MCU_SerialPort_CanSend = False;
        SBUF = Data;                                /* 串口空闲,直接发送   */
  }
    else
    {
       PostMessagePool(MCU_SerialOutData_FIFO,Data);;             /* 数据入队             */
    }
           Enable_MCU_Interrupt();
}  



/*********************************************************************************************************
** 函数名称: comm
** 功能描述: 串口中断处理程序
** 输 入: 无
** 输 出: 无
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年3月12日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/

        void comm(void) interrupt 4
{
    uint8 data temp;
//    uint8 data temp1;
    EA=0;
    if (RI == 1)        //这句适用于普通C51单片机
    {
        RI = 0;
        temp=SBUF;
        PostMessagePool_Interrupt(MCU_SerialInData_FIFO,temp);


    }
    if (TI == 1)
    {
        TI = 0;
       // if(GetMessageNumber(MCU_SerialOutData_FIFO)!=False)    //如果串口接收缓冲区有数据
    //    {
        //    if(    GetMessagePool(MCU_SerialOutData_FIFO,&temp1)==Ture)
        //    {
        //    SBUF=temp1;
        //    }
    
    //    }
        //else 
        //{
    //    MCU_SerialPort_CanSend=Ture;
    //    }
    }
    EA=1;
    return;

}
/*********************************************************************************************************;
** 函数名称: uint8 Frame_DataLengthNumber_ChangeFromat2(uint8 a1, uint8 a2)
** 功能描述: 解析上位机发送的命令中帧长度字符代表的长度
** 输 入: 帧长度字符1和帧长度字符2
** 输 出: 帧长度
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年5月3日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/

void Frame_DataLengthNumber_ChangeFromat2(void)


    if((Frame_Data_number1>=0)&&(Frame_Data_number1<10))
    {
    Frame_Data_number1=    Frame_Data_number1+Frame_Data_number1+Frame_Data_number1+Frame_Data_number1+Frame_Data_number1+
                        Frame_Data_number1+Frame_Data_number1+Frame_Data_number1+Frame_Data_number1+Frame_Data_number1;


    }
    Frame_Data_number2=Frame_Data_number1+Frame_Data_number2;
   //return Frame_Data_number2;
  }


/*********************************************************************************************************;
** 函数名称: uint16 cal_crc(uint8 cHar *ptr, uint8  len)   
** 功能描述: 计算CRC16的算法
** 输 入: 计算字符串地址,字符长度
** 输 出: CRC16计算结果
** 全局变量: 无
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年5月3日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/


uint16 Cal_CRC(uint8 xdata *ptr, uint8  len)    
{    
uint8   i;    
uint16  crc_value =0;    
while(len--)
     {
    for(i=0x80; i!=0; i>>=1 )
       {    
            if (crc_value&0x8000) 
            crc_value = (crc_value << 1) ^0x8005 ;
            else
            crc_value = crc_value << 1 ;
            if(*ptr&i)
            crc_value^=0x8005 ;    
        }
    ptr++;
    }    
return(crc_value);    
}


/*********************************************************************************************************;
** 函数名称: uint8 Faylse_Uart_Frame(uint8 Data)
** 功能描述: 串口接收帧数据帧分析
** 输 入:     
** 输 出: 
** 全局变量: 
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年5月3日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/

void Faylse_Uart_Frame(void)
{    
    uint8 temp;

    for(temp=0;temp<40;temp++)
        {
        PDA_Command[temp]=0;                //PDA_Command[0]包含了命令字1个字节的长度+ 真正有效数据的长度
        }
    PDA_Command[0]=Frame_Data_number2;        //PDA_Command[0]保存着帧数据长度,这长度包含了转义字符的长度,实际使用的时候要转换
    if(All_Frame_data[3]==1)                //数据发往子串口1
        {
        PDA_Command[1]=1;
        }
    
    else if(All_Frame_data[3]==2)            //数据发往子串口2
        {
        PDA_Command[1]=2;
        }
    else if(All_Frame_data[3]==3)            //数据发往子串口3
        {
        PDA_Command[1]=3;
        }    
    else if(All_Frame_data[3]==4)            //数据发往子串口4
        {
        PDA_Command[1]=4;
        }
    for(temp=0;temp<Frame_Data_number2-1;temp++)    //取出缓冲数组的值,并且分析专业字符,重新计算字节的长度
        {
         if(All_Frame_data[3+2+temp]==Uart_ReceFrame_StartByte2)
            {
                 if(All_Frame_data[3+2+1+temp]==Uart_ReceFrame_StartByte2)
                    {
                     PDA_Command[temp+2]=0x56;
                     PDA_Command[0]--;
                     temp++;
                    }
                else if(All_Frame_data[3+2+1+temp]==Uart_ReceFrame_StartByte3)
                    {
                     PDA_Command[temp+2]=0x57;
                    PDA_Command[0]--;
                     temp++;
                    }    
            }
         else
            {
                     PDA_Command[temp+2]=All_Frame_data[3+1+temp];            
            }
        }
                PDA_Command[0]--;            //减去命令字节的1个字节长度,剩下数值只表示要发送到串口数据的字节数            
        
}






/*********************************************************************************************************;
** 函数名称: void Detet_Receiver()
** 功能描述: 检测串口状态,等待接收到一个完整的有效的帧,发送消息到系统消息队列
** 输 入:     
** 输 出: 
** 全局变量: 
** 调用模块: 无
**
** 作 者: LXJ
** 日 期: 2009年5月3日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void Detet_Receiver()
    {

        uint8 data temp1;

        uint16    CRC_Result_temp=0;

        if(GetMessageNumber(MCU_SerialInData_FIFO)!=False)    //如果串口接收缓冲区有数据
        {
            if(    GetMessagePool(MCU_SerialInData_FIFO,&temp1)==Ture)        //假如取值成功
                {    
                    switch(Uart_ReceFrame_State)
                    {
                     case Uart_Dete_Frame_InitState:
    
                                    if(temp1==Uart_ReceFrame_StartByte1)                //判断是否是帧起始字符0x55
                                            {
                                                Uart_ReceFrame_State=Uart_Dete_Frame_StartByte_End;//标明串口已经接收到帧起始字符
                                                All_Frame_data[0]=0x55;                //存储帧起始字符
                                             }
                                    else
                                            {
                                                 Uart_ReceFrame_State=Uart_Dete_Frame_InitState;
                                                Frame_Data_Number_Flag=0;
                                                Frame_Data_number2=0;
                                            }

                                    break;
                    case Uart_Dete_Frame_StartByte_End:
                                    {
                                        Frame_Data_number1=temp1;
                                        All_Frame_data[1]=Frame_Data_number1;                                    
                                        Uart_ReceFrame_State=Uart_Dete_Frame_LengthByte1_End;//标明串口已经接收到帧长度的第一个字符

                                    }
                                    break;
                    case Uart_Dete_Frame_LengthByte1_End:
                                    {
                                        Frame_Data_number2=temp1;
                                        All_Frame_data[2]=Frame_Data_number2;
                                        Frame_DataLengthNumber_ChangeFromat2();
                                        if(Frame_Data_number2>99)/*通讯协议的帧长度字符超出了所定义的最大长度*/
                                                            
                                                {
                                                /*****************************************
                                                这里发送数据帧长度出错的信息个PDA
                                                *****************************************/
                                                ClearMessagePool(MCU_SerialInData_FIFO);                /*清空串口输入消息队列*/
                                                All_Frame_data[0]=0;
                                                All_Frame_data[1]=0;
                                                All_Frame_data[2]=0;
                                                //OSQPost(CommandData, Frame_Length_Wrong);/*发送串口出错消息到主程序处理*/
                                                Uart_ReceFrame_State=Uart_Dete_Frame_InitState;        
                                                }
                                        else    /*通讯协议的帧长度字符没有超出了所定义的最大长度*/            
                                                {
                                                
                                                PDA_Command[0]=Frame_Data_number2;    //将串口帧数据长度放入PDA_Command[0]    
                                                
                                                }
                                        Uart_ReceFrame_State=Uart_Dete_Frame_LengthByte2_End;//标明串口已经接收到帧长度的第二个字符
                                    }
                                    break;
                    case Uart_Dete_Frame_LengthByte2_End:
                                    {
                                          if((temp1>0)&&(temp1<5))
                                            {
                                                PDA_Command[1]=temp1;            /*将传输数据帧中的指令类型字节放入数组的第二个字节,标明数据是发往哪个子串口的*/
                                                  All_Frame_data[3]=temp1;                /*整理帧数据第四个字节,便于计算CRC*/
                                                Uart_ReceFrame_State=Uart_Dete_Frame_OrdeTyte_End;//标明串口已经接收到帧长度的命令类型字符
                                                Frame_Data_Number_Flag++;
                                            }
                                           else
                                               {
                                                ClearMessagePool(MCU_SerialInData_FIFO);                /*清空串口输入消息队列*/
                                                All_Frame_data[0]=0;
                                                All_Frame_data[1]=0;
                                                All_Frame_data[2]=0;
                                                //OSQPost(CommandData, Frame_Length_Wrong);/*发送串口出错消息到主程序处理*/
                                                Frame_Data_Number_Flag=0;
                                                Uart_ReceFrame_State=Uart_Dete_Frame_InitState;        
                                            }
                                    }
                                    break;
                    case Uart_Dete_Frame_OrdeTyte_End:
                                    {
                                                                                        
                                                 if((Uart_ReceFrame_State==Uart_Dete_Frame_OrdeTyte_End)&&(Frame_Data_Number_Flag<Frame_Data_number2))        
                                                {    
                                                All_Frame_data[3+Frame_Data_Number_Flag]= temp1;    //存入All_Frame_data[]准备计算CRC
                                                Frame_Data_Number_Flag++;                        //接收到数据变量加1
                                                }
                                                if(Frame_Data_Number_Flag==Frame_Data_number2)
                                                {
                                                Uart_ReceFrame_State=Uart_Dete_Frame_DataByte_End;    
                                                }
 
                                    }
                                    break;
                    case Uart_Dete_Frame_DataByte_End:
                                    {
                                                if(CRC_16_Number==0)
                                                    {
                                                    CRC_16_Result_Receiver=temp1;
                                                    All_Frame_data[Frame_Data_Number_Flag+3]=temp1;
                                                    CRC_16_Result_Receiver=CRC_16_Result_Receiver<<8;
                                                    CRC_16_Number=1;
                            

相关帖子

沙发
armecos| | 2009-7-15 23:04 | 只看该作者

这个问题在《ucos51》产品里有详细说明,

如何解决在软件仿真中正确,一旦下载到flash里就错误的问题。

www.armecos.com

使用特权

评论回复
板凳
qtopia| | 2009-7-17 12:42 | 只看该作者

最后可能的是配置

使用特权

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

本版积分规则

35

主题

51

帖子

0

粉丝