void SPI_Init(void) { instance->IER = 0x00000000; /* Interrupts not used */ instance->DER |= LPSPI_DER_RDDE(1)|LPSPI_DER_TDDE(1); /* DMA TRX request enable */ instance->CFGR0 = 0x00000000; /* Defaults: */ instance->CFGR1 |= LPSPI_CFGR1_MASTER(1); /* Configurations: master mode */ /* PCSCFG=0: PCS[3:2] are enabled */ /* OUTCFG=0: Output data retains last value when CS negated */ /* PINCFG=0: SIN is input, SOUT is output */ /* MATCFG=0: Match disabled */ /* PCSPOL=0: PCS is active low */ /* NOSTALL=0: Stall if Tx FIFO empty or Rx FIFO full */ /* AUTOPCS=0: does not apply for master mode */ /* SAMPLE=0: input data sampled on SCK edge */ /* MASTER=1: Master mode */ /* (1,0,10M) */ instance->TCR |= LPSPI_TCR_PRESCALE(1)| /* PRESCALE=2: Functional clock divided by 40M/2 = 20M */ LPSPI_TCR_PCS(2) | LPSPI_TCR_FRAMESZ(7) | /* FRAMESZ=7: # bits in frame = 7+1=8 */ LPSPI_TCR_CONT(0); //|LPSPI_TCR_CONTC(1) |LPSPI_TCR_RXMSK(1) instance->CCR |= LPSPI_CCR_SCKDIV(0) | /* 20/(0+2) = 10M */ LPSPI_CCR_DBT(8) | LPSPI_CCR_SCKPCS(4) | LPSPI_CCR_PCSSCK(4); instance->FCR = 0; instance->CR |= LPSPI_CR_MEN_MASK | LPSPI_CR_DBGEN_MASK; /* Enable module for operation */ /* DBGEN=1: module enabled in debug mode */ /* DOZEN=0: module enabled in Doze mode */ /* RST=0: Master logic not reset */ /* MEN=1: Module is enabled */ } /* DMA for spi SPI_DMA_RX_CH = 4 SPI_DMA_TX_CH = 5 */ static void InitTxDMA(LPSPI_Type *instance,uint8_t *psrc, uint32_t src_length) { DMA->TCD[SPI_DMA_TX_CH].CSR &= 0xFFFFFFFF ^ DMA_TCD_CSR_DONE_MASK; // Clear Channel Done flag DMA->TCD[SPI_DMA_TX_CH].SADDR = DMA_TCD_SADDR_SADDR(psrc); // Source Address DMA->TCD[SPI_DMA_TX_CH].SOFF = DMA_TCD_SOFF_SOFF(1); // Source Offset 源地址每次偏移1byte DMA->TCD[SPI_DMA_TX_CH].ATTR = DMA_TCD_ATTR_SMOD(0) | // Source address modulo feature is disabled DMA_TCD_ATTR_SSIZE(0) | // Source data transfer size: 0: 8-bit, 1: 16-bit, 2=32-bit 源数据宽度1byte DMA_TCD_ATTR_DMOD(0) | // Destination address modulo feature: 0=disabled, x= x power of 2 buffer[DMOD=4->buffer of 16bytes] DMA_TCD_ATTR_DSIZE(0); // Destination data transfer size: 0: 8-bit, 1: 16-bit, 2=32-bit 目的数据宽度1byte DMA->TCD[SPI_DMA_TX_CH].NBYTES.MLOFFNO = DMA_TCD_NBYTES_MLNO_NBYTES(1); // Minor Byte Transfer Count is 1-byte 副循环每次只传1byte DMA->TCD[SPI_DMA_TX_CH].SLAST = -src_length; // Last Source Address Adjustment is 0 DMA->TCD[SPI_DMA_TX_CH].DADDR = DMA_TCD_DADDR_DADDR(&(instance->TDR)); // Destination Address DMA->TCD[SPI_DMA_TX_CH].DOFF = DMA_TCD_DOFF_DOFF(0); // Destination Address Signed Offset is 0 目的地址无偏移(因为是寄存器) DMA->TCD[SPI_DMA_TX_CH].CITER.ELINKNO = DMA_TCD_CITER_ELINKNO_CITER(src_length) // Current Major Iteration Count is dst_length 主循环多次 | DMA_TCD_CITER_ELINKNO_ELINK(0); // The channel-to-channel linking is disabled DMA->TCD[SPI_DMA_TX_CH].DLASTSGA = DMA_TCD_DLASTSGA_DLASTSGA(0); // Destination last address adjustment is 0 DMA->TCD[SPI_DMA_TX_CH].BITER.ELINKNO = DMA_TCD_BITER_ELINKNO_BITER(src_length) | // Starting major iteration count is dst_length DMA_TCD_BITER_ELINKNO_ELINK(0); // The minor channel-to-channel linking is disabled DMA->TCD[SPI_DMA_TX_CH].CSR = DMA_TCD_CSR_BWC(0) | // BWC=0: No eDMA engine stalls - full bandwidth DMA_TCD_CSR_MAJORELINK(0) | // The channel-to-channel linking is disabled DMA_TCD_CSR_MAJORLINKCH(0) | // channel 1 will be called from ch0 DMA_TCD_CSR_ESG(0) | // The current channel�fs TCD is normal format - No scatter/gather DMA_TCD_CSR_DREQ(0) | // The channel's ERQ bit is affected DMA_TCD_CSR_INTHALF(0) | // The half-point interrupt is disabled DMA_TCD_CSR_INTMAJOR(1) | // The end-of-major loop interrupt is enable DMA_TCD_CSR_START(0); // The channel is not explicitly started //DMA->SERQ = 5; // enable DMA channel 5 HW trigger } static void InitRxDMA(LPSPI_Type *instance,uint8_t *pdst, uint32_t dst_length) //src_length个byte DMA触发一次 tx { DMA->TCD[SPI_DMA_RX_CH].CSR &= 0xFFFFFFFF ^ DMA_TCD_CSR_DONE_MASK; // Clear Channel Done flag DMA->TCD[SPI_DMA_RX_CH].SADDR = DMA_TCD_SADDR_SADDR(&(instance->RDR)); // Source Address DMA->TCD[SPI_DMA_RX_CH].SOFF = DMA_TCD_SOFF_SOFF(0); // Source Offset 源地址是串口的数据寄存器因此每次读完后不用偏移 DMA->TCD[SPI_DMA_RX_CH].ATTR = DMA_TCD_ATTR_SMOD(0) | // Source address modulo feature is disabled DMA_TCD_ATTR_SSIZE(0) | // Source data transfer size: 0: 8-bit, 1: 16-bit, 2=32-bit DMA_TCD_ATTR_DMOD(0) | // Destination address modulo feature: 0=disabled, x= x power of 2 buffer[DMOD=4->buffer of 16bytes] DMA_TCD_ATTR_DSIZE(0); // Destination data transfer size: 0: 8-bit, 1: 16-bit, 2=32-bit DMA->TCD[SPI_DMA_RX_CH].NBYTES.MLOFFNO = DMA_TCD_NBYTES_MLNO_NBYTES(1); // Minor Byte Transfer Count is 1-byte 副循环每次只传1byte DMA->TCD[SPI_DMA_RX_CH].SLAST = DMA_TCD_SLAST_SLAST(0); // Last Source Address Adjustment is 0 由于源地址固定(偏移为0)因此不需要调整 DMA->TCD[SPI_DMA_RX_CH].DADDR = DMA_TCD_DADDR_DADDR(pdst); // Destination Address of Buffer DMA->TCD[SPI_DMA_RX_CH].DOFF = DMA_TCD_DOFF_DOFF(1); // Destination Address Signed Offset is 1 目的地址偏移为1个字节即小循环每读一次偏移1byte DMA->TCD[SPI_DMA_RX_CH].CITER.ELINKNO = DMA_TCD_CITER_ELINKNO_CITER(dst_length) // Current Major Iteration Count is dst_length 主循环多次 | DMA_TCD_CITER_ELINKNO_ELINK(0); // The channel-to-channel linking is disabled DMA->TCD[SPI_DMA_RX_CH].DLASTSGA = -dst_length; // Destination last address adjustment is 0 DMA->TCD[SPI_DMA_RX_CH].BITER.ELINKNO = DMA_TCD_BITER_ELINKNO_BITER(dst_length) | // Starting major iteration count is dst_length 主循环多次 DMA_TCD_BITER_ELINKNO_ELINK(0); // The minor channel-to-channel linking is disabled DMA->TCD[SPI_DMA_RX_CH].CSR = DMA_TCD_CSR_BWC(0) | // BWC=0: No eDMA engine stalls - full bandwidth DMA_TCD_CSR_MAJORELINK(0) | // The channel-to-channel linking is disabled DMA_TCD_CSR_MAJORLINKCH(0) | // channel 1 will be called from ch0 DMA_TCD_CSR_ESG(0) | // The current channel�fs TCD is normal format - No scatter/gather DMA_TCD_CSR_DREQ(0) | // The channel's ERQ bit is not affected DMA_TCD_CSR_INTHALF(0) | // The half-point interrupt is disabled DMA_TCD_CSR_INTMAJOR(1) | // The end-of-major loop interrupt is enabled 主循环结束后中断 DMA_TCD_CSR_START(0); // The channel is not explicitly started 通道未显示启动P383 DMA->SERQ = SPI_DMA_RX_CH; // enable DMA channel 4 HW trigger } static void DMAMUX_Init(LPSPI_Type *instance) //将DMA源路由到DMA通道 { uint32_t DMA_CH_RX_MUX_NUM = 0; /* Rx route number */ if(instance == LPSPI0) DMA_CH_RX_MUX_NUM = 14; if(instance == LPSPI1) DMA_CH_RX_MUX_NUM = 16; if(instance == LPSPI2) DMA_CH_RX_MUX_NUM = 18; SIM->PLATCGC |= SIM_PLATCGC_CGCDMA(1); /* Enable DMA Clock P558 */ PCC->PCCn[PCC_DMAMUX_INDEX] |= PCC_PCCn_CGC_MASK; // CGC=1: Clock enabled for DMAMUX0 /* DMA Channel 4 for LPUART RX */ DMAMUX->CHCFG[SPI_DMA_RX_CH] &= ~ DMAMUX_CHCFG_ENBL(1); // Disabling the DMA channel 2 DMAMUX->CHCFG[SPI_DMA_RX_CH] |= DMAMUX_CHCFG_SOURCE(DMA_CH_RX_MUX_NUM); // LPUART RX is the source of the DMA0 channel 2 DMAMUX->CHCFG[SPI_DMA_RX_CH] |= DMAMUX_CHCFG_ENBL(1); // Enabling the DMA channel 2 /* DMA Channel 5 for LPUART TX */ DMAMUX->CHCFG[SPI_DMA_TX_CH] &= ~ DMAMUX_CHCFG_ENBL(1); // Disabling the DMA channel 3 DMAMUX->CHCFG[SPI_DMA_TX_CH] |= DMAMUX_CHCFG_SOURCE(DMA_CH_RX_MUX_NUM+1); // LPUART TX is the source of the DMA0 channel 3 DMAMUX->CHCFG[SPI_DMA_TX_CH] |= DMAMUX_CHCFG_ENBL(1); // Enabling the DMA channel 3 } void DMA4_IRQHandler(void) /* DMA channel 4 transfer complete 注意:只有前4个通道具有触发功能 */ { if((DMA->INT >> SPI_DMA_RX_CH) & 1) // if received 4 bytes { DMA->CINT = DMA_CINT_CINT(SPI_DMA_RX_CH); // clear channel 3 写入1则清除中断 } } void DMA5_IRQHandler(void) { if((DMA->INT >> SPI_DMA_TX_CH) & 1) /* 发送完成中断 */ { GPIO_Toogle(PTD,1); DMA->CINT = DMA_CINT_CINT(SPI_DMA_TX_CH); } } /****5ms 启动一次DMA抓100ms内的波形抓到21次******/ void DMA_TX_START(void) { DMA->SERQ = DMA_SERQ_SERQ(SPI_DMA_TX_CH); DMA->TCD[SPI_DMA_TX_CH].CSR |= DMA_TCD_CSR_START(1); //开始传输 } spi_buffer_t master_buffer = { .tx = {0xA,0xB,0xC,0xD,0xE,0xF,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0xAA}, .rx = {0} }; spi_buffer_t slave_buffer = { .tx = {0x01,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,0x20}, .rx = {0} }; void DMA_Init() { InitTxDMA(Instance,SPI_DMA_TX_CH,master_buffer.tx, 16); InitRxDMA(Instance,SPI_DMA_RX_CH,master_buffer.rx, 16); DMAMUX_Init(Instance,SPI_DMA_RX_CH,SPI_DMA_TX_CH); InterruptEnable(DMA4_IRQn,0xA); InterruptEnable(DMA5_IRQn,0xB); }