最近需要用华大的hc32l136的硬件SPI+DMA传输,瞎写很久没调好,看参考手册,瞎碰一天搞通了。。。 
  先说下我之前犯的错误,也是最宝贵的经验,供参考 
    没多看参考手册直接写(即使有点烂仍然提供了最高的参考价值。。。),重点看SPI和DMAC章节 错误使用了软件触发传输,测到的现象是前两个字节可以正确发送,后面的无论是发送数量和数据都对不上了,误以为软件触发可用,自己的配置有问题,实际测试软件触发和规格书讲的一样,是不可用的或者说是不可靠的    再说下正确的使用方式,文末会粘上测试代码 
    关键点就一个,触发方式不要选DmaSWTrig软件触发(至于最后实例能用的这个,从软件的角度看还是软件触发,但官方的角度似乎不认为这是软件触发,或许是软件触发SPI硬件再触发DMA所以叫硬件触发?不管也罢,,,)       语文课兴许没及格,下面是参考手册的一些相关描述,没看明白:   
 
 先讲SPI支持软硬件访问    2.再讲只支持硬件块传输模式,且SPI和系统时钟不同频时不支持硬件触发(官方对软件/硬件触发的解释不是很到位,至少和我理解的不太一样)   但是spi时钟和系统时钟必然是不同频的,那硬件触发到底能不能用呢?   再看,所谓的软件/硬件DMA传输模式就是软件/硬件请求方式不同,似乎哪个也不支持了。。。软硬件触发和软硬件传输似乎没有关系?     
  
最后,还是实践出真知。。。 测试程序参考,每200ms用SPI+DMA发送24个字节:   
# define  SPI_HANDLE  M0P_SPI1  
# define  DMA_HANDLE  DmaCh1  
uint8_t  data_tx_test[ 24 ]  = 
{ 
  0x11 , 0x22 , 0x23 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 
  0x11 , 0x22 , 0x23 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 
  0x11 , 0x22 , 0x23 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 
} ; 
static  void  App_GpioInit ( void ) 		
{ 
    stc_gpio_cfg_t            stcPortCfg; 
    
    DDL_ZERO_STRUCT ( stcPortCfg) ; 							
    
    Sysctrl_SetPeripheralGate ( SysctrlPeripheralGpio,  TRUE) ;  
    
    stcPortCfg. enDrv =  GpioDrvH; 
    stcPortCfg. enDir  =  GpioDirOut; 
	
    Gpio_Init ( LCD_BK_PORT,  LCD_BK_PIN,  & stcPortCfg) ;   
	
    Gpio_Init ( LCD_CS_PORT,  LCD_CS_PIN,  & stcPortCfg) ;   
	Gpio_SetAfMode ( LCD_CS_PORT,  LCD_CS_PIN, GpioAf1) ;  				
	
    Gpio_Init ( LCD_RESET_PORT,  LCD_RESET_PIN,  & stcPortCfg) ;   
	
    Gpio_Init ( LCD_WR_PORT,  LCD_WR_PIN,  & stcPortCfg) ;   
	
    Gpio_Init ( LCD_SCK_PORT,  LCD_SCK_PIN,  & stcPortCfg) ;   
	Gpio_SetAfMode ( LCD_SCK_PORT,  LCD_SCK_PIN, GpioAf1) ;   			
	
    Gpio_Init ( LCD_SDA_PORT,  LCD_SDA_PIN,  & stcPortCfg) ;   
	Gpio_SetAfMode ( LCD_SDA_PORT,  LCD_SDA_PIN, GpioAf1) ;   			
} 
static  void  App_SPIInit ( void ) 
{ 
    stc_spi_cfg_t   SpiInitStruct; 
    Sysctrl_SetPeripheralGate ( SysctrlPeripheralSpi1, TRUE) ; 
    
    SpiInitStruct. enSpiMode =  SpiMskMaster;    		
    SpiInitStruct. enPclkDiv =  SpiClkMskDiv2;   		
    SpiInitStruct. enCPOL    =  SpiMskcpolhigh;   		
	SpiInitStruct. enCPHA 	=  SpiMskCphasecond;  	
    Spi_Init ( SPI_HANDLE,  & SpiInitStruct) ; 
	
	Spi_FuncEnable ( SPI_HANDLE, SpiMskDmaTxEn) ; 		
} 
static  void  App_DmaCfg ( void ) 
{  
    stc_dma_cfg_t  stcDmaCfg; 
   
    Sysctrl_SetPeripheralGate ( SysctrlPeripheralDma, TRUE) ;  			
  
    DDL_ZERO_STRUCT ( stcDmaCfg) ; 
  
    stcDmaCfg. enMode =   DmaMskBlock;                            		
    stcDmaCfg. u16BlockSize =  1 ;                              		
    stcDmaCfg. u16TransferCnt =  24 ;                     				
    stcDmaCfg. enTransferWidth =  DmaMsk8Bit;                    		
    stcDmaCfg. enSrcAddrMode =  DmaMskSrcAddrInc;                 		
    stcDmaCfg. enDstAddrMode =  DmaMskDstAddrFix;                 		
    stcDmaCfg. enDestAddrReloadCtl =  DmaMskDstAddrReloadEnable; 		
    stcDmaCfg. enSrcAddrReloadCtl =  DmaMskSrcAddrReloadEnable; 		
    stcDmaCfg. enSrcBcTcReloadCtl =  DmaMskBcTcReloadEnable; 			
    stcDmaCfg. u32SrcAddress =  ( uint32_t ) & data_tx_test[ 0 ] ;  			
    stcDmaCfg. u32DstAddress =  ( uint32_t ) & ( M0P_SPI1-> DATA) ;     		
    stcDmaCfg. enRequestNum =  DmaSPI1TXTrig;                         	
    stcDmaCfg. enTransferMode =  DmaMskOneTransfer;               		
    stcDmaCfg. enPriority =  DmaMskPriorityFix;                   		
    
    Dma_InitChannel ( DMA_HANDLE, & stcDmaCfg) ;                         	
  
    Dma_Enable ( ) ; 
    
} 
void  dma_test ( void ) 
{ 
	en_dma_stat_t  ste; 
	while ( 1 ) 
	{  
		delay1ms ( 200 ) ; 
		M0P_SPI1-> SSN =  FALSE; 
		Dma_EnableChannel ( DMA_HANDLE) ; 								
		
		ste =  Dma_GetStat ( DMA_HANDLE) ; 
		while ( ste !=  DmaTransferComplete) 
		{ 
			ste =  Dma_GetStat ( DMA_HANDLE) ; 
		} 
		M0P_SPI1-> SSN =  TRUE; 
		
	} 
} 
void  demo ( void ) 
{ 
	App_GpioInit ( ) ; 
	App_DmaCfg ( ) ; 
	App_SPIInit ( ) ; 
	
	dma_test ( ) ; 
} 
  
实测SPI主机发送ok: