发新帖我要提问
12
返回列表
打印

<已解决>如何优化从SRAM(XData)倒数据到外设的代码

[复制链接]
楼主: 古道热肠
手机看帖
扫描二维码
随时随地手机跟帖
21
古道热肠|  楼主 | 2009-3-24 14:08 | 只看该作者 回帖奖励 |倒序浏览

俺也想用串口发码到VS1003B,可是呢,俺那MP3板要用串口ISP程序

而且不打算改PCB了,改起来太累,还有一种硬件方式,就是用P0(PX都可以),再接1个并转串芯片(如HC165),采用串转并的硬件转换,单片机再用一个GPIO口输出时钟,HC165的SOUT引脚接VS1003B的MOSI引脚,这样发码流量可提高15-20%

使用特权

评论回复
22
古道热肠|  楼主 | 2009-3-24 14:18 | 只看该作者

为什么不用M8,P89LV51RD2的性价比还是可观的.

在64K程序容量的前提下,可发挥的空间较大,用M8,代码空间太少了,无法完成复杂应用功能.
不要看不起51单片机,矩力MP3还用Z80的指令集呢,很多消费类电子用的都是51核整出的专用SOC芯片,俺就习惯51的软件仿真和KEIL IDE开发环境,开发AVR的那个ICC环境多文件项目找个函数实现的位置,半天找不到.

使用特权

评论回复
23
古道热肠|  楼主 | 2009-3-24 16:44 | 只看该作者

哈哈,终于顺畅播放256Kbps的MP3歌曲<步步高>

通过优化SD卡读数据,终于在串口看到了MCU is Free,
SD卡读块经优化化的函数如下:

uint8 SD_Read_Block(uint8 *CMD,uint8 xdata *Buffer)
//****************************************************************************
{  
//   uint16 i;
    uchar uci;
   uint8 retry, temp;
    
   //Send Command CMD to MMC/SD-Card
   retry=0;

//#if 1
   do
   {  //Retry 100 times to send command.
//      temp=Write_Command_SD(CMD);
        temp=Write_Command_SD_HighSpeed(CMD);
      if(retry++ == 100) 
        return READ_BLOCK_ERROR; //block write Error!
   }
   while (temp != 0); 
               
   //Read Start Byte form MMC/SD-Card (FEh/Start Byte)
   while (SD_SPI_ReadByte() != 0xfe);
//#endif


   //Read blocks(normal 512Bytes) to MMC/SD-Card
#if 1
//   for (i = 0; i < Bytes; i++)                //int count for loop cost 13 machine cycle
    uci     = 16;

    do 
       {
//      *Buffer++ = SPI_ReadByte();            //Cost 70 Machine Cycle
                                            //When define point is a Xdata point then Cost 62 Machine Cycle
      *Buffer++ = SD_SPI_ReadByte();            //Cost 70 Machine Cycle
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();

      *Buffer++ = SD_SPI_ReadByte();        
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();

      *Buffer++ = SD_SPI_ReadByte();        
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();

      *Buffer++ = SD_SPI_ReadByte();        
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
         // put_c(*Buffer);
   }while(--uci);
#endif 


   //CRC-Byte
//   SPI_ReadByte();//CRC - Byte 
//   SPI_ReadByte();//CRC - Byte
    SD_SPI_ReadByte();
    SD_SPI_ReadByte();

   //set MMC_Chip_Select to high (MMC/SD-Card invalid)
   SD_Disable();

   return READ_BLOCK_OK;
}

基中SD_SPI_ReadByte()函数就是采用当年老X的终极优化软件仿真SPI数据读的函数,见下:

uint8 SD_Read_Block(uint8 *CMD,uint8 xdata *Buffer)
//****************************************************************************
{  
//   uint16 i;
    uchar uci;
   uint8 retry, temp;
    
   //Send Command CMD to MMC/SD-Card
   retry=0;

//#if 1
   do
   {  //Retry 100 times to send command.
//      temp=Write_Command_SD(CMD);
        temp=Write_Command_SD_HighSpeed(CMD);
      if(retry++ == 100) 
        return READ_BLOCK_ERROR; //block write Error!
   }
   while (temp != 0); 
               
   //Read Start Byte form MMC/SD-Card (FEh/Start Byte)
   while (SD_SPI_ReadByte() != 0xfe);
//#endif


   //Read blocks(normal 512Bytes) to MMC/SD-Card
#if 1
//   for (i = 0; i < Bytes; i++)                //int count for loop cost 13 machine cycle
    uci     = 16;

    do 
       {
//      *Buffer++ = SPI_ReadByte();            //Cost 70 Machine Cycle
                                            //When define point is a Xdata point then Cost 62 Machine Cycle
      *Buffer++ = SD_SPI_ReadByte();            //Cost 70 Machine Cycle
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();

      *Buffer++ = SD_SPI_ReadByte();        
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();

      *Buffer++ = SD_SPI_ReadByte();        
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();

      *Buffer++ = SD_SPI_ReadByte();        
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
      *Buffer++ = SD_SPI_ReadByte();
         // put_c(*Buffer);
   }while(--uci);
#endif 


   //CRC-Byte
//   SPI_ReadByte();//CRC - Byte 
//   SPI_ReadByte();//CRC - Byte
    SD_SPI_ReadByte();
    SD_SPI_ReadByte();

   //set MMC_Chip_Select to high (MMC/SD-Card invalid)
   SD_Disable();

   return READ_BLOCK_OK;
}





使用特权

评论回复
24
古道热肠|  楼主 | 2009-3-24 17:25 | 只看该作者

试放了一下320Kbps的MP3,有杂音,系数据断流所致.

下面这个函数请大家看看,如何才能达到最优化的速度.这个函数调用上贴中的函数,先听听大家对此函数优化的意见和建议,再作优化.

uint8 SD_read_sector(uint32 addr,uint8 xdata *Buffer)
//****************************************************************************
{
       //Command 16 is reading Blocks from MMC/SD-Card
   uint8  CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; 
   
//   asm("cli"); //clear all interrupt.
   //Address conversation(logic block address-->byte address)  
   addr = addr << 9; //addr = addr * 512

   CMD[1] = ((addr & 0xFF000000) >>24 );
   CMD[2] = ((addr & 0x00FF0000) >>16 );
   CMD[3] = ((addr & 0x0000FF00) >>8 );

   return SD_Read_Block(CMD, Buffer);      
}

使用特权

评论回复
25
ayb_ice| | 2009-3-24 20:48 | 只看该作者

觉得还是要用汇编

为特定函数分配专用寄存器组

使用特权

评论回复
26
古道热肠|  楼主 | 2009-3-25 11:05 | 只看该作者

经过昨晚努力,已攻克最后一关,顺利跨过320Kbps

感觉就象当年玩游戏打死老怪后的舒心.在此,要非常感谢老X,提出的优化指导思想起了很大的作用.

使用特权

评论回复
27
古道热肠|  楼主 | 2009-3-25 11:07 | 只看该作者

贴上优化后的关键汇编代码.

; .ObjReadOneSectorFromSDCard.SRC generated from: ....MP3播放器规范化MP3ReadOneSectorFromSDCard.c
; COMPILER INVOKED BY:
;        C:KeilC51BINC51.EXE ....MP3播放器规范化MP3ReadOneSectorFromSDCard.c BROWSE DEBUG OBJECTEXTEND PRINT(.ObjReadOneSectorFromSDCard.lst) SRC(.ObjReadOneSectorFromSDCard.SRC)

SPI_CLK        BIT     P1.7
SPI_MOSI    BIT     P1.5
SPI_MISO    BIT     P1.6
ACC_7        BIT    ACC.7
ACC_6        BIT    ACC.6
ACC_5        BIT    ACC.5
ACC_4        BIT    ACC.4
ACC_3        BIT    ACC.3
ACC_2        BIT    ACC.2
ACC_1        BIT    ACC.1
ACC_0        BIT    ACC.0


NAME    READONESECTORFROMSDCARD

?PR?Read_OneSector_From_SDCard_To_SRAM?READONESECTORFROMSDCARD SEGMENT CODE 
    PUBLIC    Read_OneSector_From_SDCard_To_SRAM
; void    Read_OneSector_From_SDCard_To_SRAM(void)

    RSEG  ?PR?Read_OneSector_From_SDCard_To_SRAM?READONESECTORFROMSDCARD
Read_OneSector_From_SDCard_To_SRAM:
            ; SOURCE LINE # 1
; {
            ; SOURCE LINE # 2
;     ;
; }
            ; SOURCE LINE # 4

;Save Background
;    PUSH B
;    PUSH ACC

    MOV R7,#02H
 SD_ReadData_Loop2:

;Initialize Loop Count Register
    MOV B,#080H        ;Loop Connect is 128X4 = 512 Byte

;Loop Enter
  ReadOneByte_From_SDCard_LoopEnter_1:
      ;Loop Body

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;Read The Fist Byte            --1
        SETB SPI_MOSI
    ;Read Byte Bit7
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    

    ;Read Byte Bit6
        CLR SPI_CLK            ;1
        SETB SPI_CLK            ;1
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit5
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit4
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit3
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit2
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit1
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit0
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    

        MOVX @DPTR,A
        INC DPTR

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    ;Read The Second Byte            --2
    ;Read Byte Bit7
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    

    ;Read Byte Bit6
        CLR SPI_CLK            ;1
        SETB SPI_CLK            ;1
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit5
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit4
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit3
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit2
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit1
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    
    
    ;Read Byte Bit0
        CLR SPI_CLK
        SETB SPI_CLK
        MOV C,SPI_MISO
        RLC A    

        MOVX @DPTR,A
        INC DPTR
    ;loop untill The 512 Byte Read Complete
    DJNZ B,ReadOneByte_From_SDCard_LoopEnter_1
    DJNZ R7,SD_ReadData_Loop2

;Restore Background
;    POP ACC
;    POP B

    RET      
; END OF Read_OneSector_From_SDCard_To_SRAM

    END

使用特权

评论回复
28
古道热肠|  楼主 | 2009-3-25 11:09 | 只看该作者

上贴中汇编函数的主调函数

uint8 SD_Read_Block(uint8 idata *CMD,uint8 xdata *Buffer)
//****************************************************************************
{  
//   uint16 i;
//    uchar uci;
   uint8 retry;// temp;
    
   //Send Command CMD to MMC/SD-Card
   retry=0;

    if(Write_Command_SD_HighSpeed(CMD))
    {
        return READ_BLOCK_ERROR; //block write Error!
    }
               
   //Read Start Byte form MMC/SD-Card (FEh/Start Byte)
   while (SD_SPI_ReadByte() != 0xfe)
   {
//           ComShowString(c_COM1,"MCU is Wait SD Card Send Read Date Poke,So MCU is Free");
        LED3Pin = ~LED3Pin;        //指示灯闪烁    
   }

   //Read blocks(normal 512Bytes) From MMC/SD-Card
    DPH = (unsigned char )(Buffer)>>8;
    DPL = (unsigned char )(Buffer);

    Read_OneSector_From_SDCard_To_SRAM();



   //CRC-Byte
    SD_SPI_ReadCRC16();            //Exec Null Read,The Read Data is No Care,So Now Data Return

     //set MMC_Chip_Select to high (MMC/SD-Card invalid)
       SD_Disable();

   return READ_BLOCK_OK;
}

使用特权

评论回复
29
古道热肠|  楼主 | 2009-3-25 11:12 | 只看该作者

上贴中函数的主调函数,经过优化,与24楼代码相比,大幅减少耗

#if 1
uint8 SD_read_sector(uint32 addr,uint8 xdata *Buffer)
//****************************************************************************
{

       //Command 16 is reading Blocks from MMC/SD-Card
   uint8 idata CMD[6]; 
    union SDSector
    {
        uint32 ulAddress;
        uint8 ucADDByte[4];
    } CurrentSDSector;

   CMD[0] = 0X51;
   CMD[4] = 0X00;
   CMD[5] = 0XFF;

//   asm("cli"); //clear all interrupt.
   //Address conversation(logic block address-->byte address)  
   addr = addr << 9; //addr = addr * 512
   CurrentSDSector.ulAddress =addr;

   CMD[1] = CurrentSDSector.ucADDByte[0];
   CMD[2] = CurrentSDSector.ucADDByte[1];
   CMD[3] = CurrentSDSector.ucADDByte[2];

   return SD_Read_Block(CMD, Buffer);      
}

#endif

使用特权

评论回复
30
古道热肠|  楼主 | 2009-3-25 11:22 | 只看该作者

优化要点总结如下: 请大家多补充

1.老X提到的很实用,不重述了.
2.指明所有的指针指向的单元的存储器特性,Demo 如下
unsigned char idata *mIdataBuff;
void WriteIDataBuff(unsigned char iData *mIdataBuff)
3.使用联合体分割长整形(unsinged long)或短整型(unsigned int)的每个字节内容,而不用移位操作分割
4.局部函数用汇编实现,数据缓冲区指针或数组用取地址方式,将缓冲区的起始地址传入MCU的内部寄存器,再调用汇编函数.局部变量也可采用此法,Demo如下
{
  xdata unsigned char ucDataBuff[64];
  data unsigned char  ucTemp;

 DPH = (unsinged char )(ucDataBuff>>8);
 DPL = (unsinged char )ucDataBuff;

 R7 = &ucTemp;
 
 CallASMFunction()

.......
  

}xdata

使用特权

评论回复
31
bjc125| | 2009-3-25 16:41 | 只看该作者

路过 学习中

使用特权

评论回复
32
aceice| | 2009-3-26 09:41 | 只看该作者

e......XX说的对,不要折磨51了

话说为什么都喜欢把东西用到极限呢?

使用特权

评论回复
33
hotpower| | 2009-3-26 09:51 | 只看该作者

51累心,俺最近就被困住了,资源太少~~~

使用特权

评论回复
34
古道热肠|  楼主 | 2009-3-26 10:29 | 只看该作者

哈哈,优化带的好处是省钱提价值,为什么不追求完美呢?

与其让CPU闲着,不如让他忙着,反正闲着也是闲着.浪费在无用的指令上更不值.
当然啦,还是那个原则,尽量用C语言来完成优化,只有迫不得以,可采用汇编与C混合编程,尽量不用全汇编做,效率是高,但开发过程的软件调试和维护工作量也大,重复利用的价值反而低.

使用特权

评论回复
35
古道热肠|  楼主 | 2009-3-26 10:34 | 只看该作者

已解决提出的问题,再次谢谢大家的出谋划策.

结论:
用P89LV51RD2工作在24M外部晶体,内部6时钟指令的前提下,软件仿真SPI读写并中转数据流,速度可高达320Kbps,如果是单读或读写估计能达到640kbps或以上的吞吐量.

使用特权

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

本版积分规则