- const uint8_t u8Image[DATA_PER_SCREEN] = { 0XF7,0XBE,0XF7,0XDE,0XF7,0XDE,0XF7,0XDE,0XF7,0XDE,0XF7,0XBE,0XF7,0XBE,0XF7,0XBE, 0XEF,0X9D,0XE7,0X7C,0XE7,0X7C,0XE7,0X7C,0XE7,0X7C,0XE7,0X7C,0XE7,0X7C,0XE7,0X7C, 0XE7,0X7C,0XE7,0X7C,0XE7,0X7C,0XE7,0X9C,0XE7,0X9D,0XE7,0X9D,0XE7,0X9C,0XE7,0X9C, 0XE7,0X7C,0XE7,0X9C,0XE7,0X9C,0XE7,0X9D,0XE7,0X9D,0XE7,0X9D,0XE7,0X9D,0XEF,0X9D, 0XEF,0X9D,0XEF,0X9E,0XEF,0XBD,0XEF,0XBE,0XEF,0XBE,0XEF,0XBD,0XEF,0XBD,0XEF,0X9D, …… 0X3B,0X67,0X32,0XC6,0X2A,0X24,0X19,0X83,0X19,0X83,0X21,0XA4,0X2A,0X05,0X2A,0X25, 0X21,0XE4,0X21,0XC3,0X21,0XC3,0X21,0X83,0X19,0X43,0X21,0X63,0X2A,0X04,0X32,0X45, 0X2A,0X04,0X32,0X65,0X3A,0XC7,0X2A,0X25,0X19,0X83,0X21,0XC4,0X29,0XE5,0X21,0XA4, 0X19,0X43,0X19,0X43,0X21,0X83,0X21,0X63,0X19,0X22,0X19,0X02,0X10,0XE2,0X10,0XC2, 0X10,0XC2,0X10,0XC2,0X10,0XC2,0X10,0XC2,0X10,0XC2,0X10,0XC2,0X10,0XC2,0X10,0XA2, };
- #define DATA_PER_SCREEN (153600UL)
主函数包括对系统,对UART0、USCI_SPI0、PWM、SPI0,对TFT驱动芯片,对SPI FLASH,对Timer0初始化,最后执行主循环。代码位于main函数。
主循环函数,用于实现将FLASH中数据搬移到TFT显示。当一屏数据传输完成后,串口输出传输所花的时间。代码位于 Copy_FlashData_To_TFT_WithPDMA 函数。
- /* Data read from FLASH is sent to TFT via PDMA */
- void Copy_FlashData_To_TFT_WithPDMA(void)
- {
- uint32_t u32RegValue, u32Abort;
- /* Data Width is swtich to 8 Bits */
- Switch_DataWidth_Is_Byte(TRUE);
- /* Reset LCD display position */
- LCD_Set_Pos();
- /* Reset read start address */
- SpiFlash_SetReadAddress(0x000000);
- /* Data Width is swtich to 16 Bits */
- Switch_DataWidth_Is_Byte(FALSE);
- /* Init PDMA */
- PDMA_Init();
- /* CS = 0 : select chip */
- USPI_CS_CLR;
- /* DC = 1 : write data */
- LCM_DC_SET;
- /* Enable SPI RX PDMA function */
- SPI_TRIGGER_RX_PDMA(SPI0);
- while (1)
- {
- /* Get interrupt status */
- u32RegValue = PDMA_GET_INT_STATUS(PDMA);
- /* Check the PDMA transfer done interrupt flag */
- if (u32RegValue &PDMA_INTSTS_TDIF_Msk)
- {
- /* Check the PDMA transfer done flags */
- if ((PDMA_GET_TD_STS(PDMA) & (0x01 << SPI_MASTER_RX_DMA_CH)) ==
- (0x01 << SPI_MASTER_RX_DMA_CH))
- {
- /* Clear the PDMA transfer done flags */
- PDMA_CLR_TD_FLAG(PDMA, (0x01 << SPI_MASTER_RX_DMA_CH));
- /* Enable SPI RX PDMA function */
- SPI_TRIGGER_RX_PDMA(SPI0);
- u8TransferCnt++;
- if (u8TransferCnt >= TRANSFER_TIMES)
- {
- u8TransferCnt = 0;
- printf("\nIt takes %d ms to transmit a screen of data. \n",
- (u8TimerCnt*10));
- /* Disable Timer0 NVIC */
- NVIC_DisableIRQ(TMR0_IRQn);
- while (1);
- }
- }
- }
- /* Check the DMA transfer abort interrupt flag */
- if (u32RegValue &PDMA_INTSTS_ABTIF_Msk)
- {
- /* Get the target abort flag */
- u32Abort = PDMA_GET_ABORT_STS(PDMA);
- /* Clear the target abort flag */
- PDMA_CLR_ABORT_FLAG(PDMA, u32Abort);
- printf("\nabort happen\n");
- }
- /* Check the DMA time-out interrupt flag */
- if (u32RegValue &(PDMA_INTSTS_REQTOF0_Msk | PDMA_INTSTS_REQTOF1_Msk))
- {
- /* Clear the time-out flag */
- PDMA->INTSTS = u32RegValue &(PDMA_INTSTS_REQTOF0_Msk | PDMA_INTSTS_REQTOF1_Msk);
- printf("\ntime-out happen\n");
- }
- }
- }
设置命令的时候将传输位宽设为8 bits,传输数据的时候将位宽设置为16 bits。16 bits传输位宽比8 bits传输位宽更高效。代码位于 Switch_DataWidth_Is_Byte函数。
- void Switch_DataWidth_Is_Byte(_Bool bFlag)
- {
- if (bFlag)
- {
- /* USPI0 Transfer Data width is 8 Bits */
- USPI0->LINECTL &= ~USPI_LINECTL_DWIDTH_Msk;
- USPI0->LINECTL |= (0x08 << USPI_LINECTL_DWIDTH_Pos);
- /* SPI0 Transfer Unit is 8 Bits*/
- SPI0->CTL &= ~SPI_CTL_DWIDTH_Msk;
- SPI0->CTL |= (0x08 << SPI_CTL_DWIDTH_Pos);
- }
- else
- {
- /* USPI0 Transfer Data width is 16 Bits */
- USPI0->LINECTL &= ~USPI_LINECTL_DWIDTH_Msk;
- USPI0->LINECTL |= (0 << USPI_LINECTL_DWIDTH_Pos);
- /* SPI0 Transfer Unit is 16 Bits */
- SPI0->CTL &= ~SPI_CTL_DWIDTH_Msk;
- SPI0->CTL |= (0x10 << SPI_CTL_DWIDTH_Pos);
- }
- }
Timer0初始化,设置每隔10 ms进入一次中断,计数器初始化为0,代码位于Timer0_Init函数中。定时器中断函数,每进入中断对计数器进行加1,代码位于 TMR0_IRQHandler函数。
- void Timer0_Init(void)
- {
- /* Open Timer0 in periodic mode, enable interrupt
- and 1 interrupt tick per 10 millisecond */
- TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 100);
- TIMER_EnableInt(TIMER0);
- /* Start Timer0 counting */
- TIMER_Start(TIMER0);
- /* Clear timer counter */
- u8TimerCnt = 0;
- /* Enable Timer0 NVIC */
- NVIC_EnableIRQ(TMR0_IRQn);
- }
- void TMR0_IRQHandler(void)
- {
- if (TIMER_GetIntFlag(TIMER0) == 1)
- {
- /* Clear Timer0 time-out interrupt flag */
- TIMER_ClearIntFlag(TIMER0);
- /* Timer counter plus one */
- u8TimerCnt++;
- }
- }
因为TFT以RGB565模式显示,一个像素点需要16 bits来表示,且MCU与TFT之间传输基本单位也是16 bits,因此传输一屏图片即320x240像素点需要传输76800x16 bits数据。因为一个PDMA table 传输数量是用16 bits定义,最大传输数据为65536 x16 bits,因此传输一屏图片需要分2次传输,分别传输 38400 x16 bits数据。PDMA操作模式设置为Scatter-Gather。传输数量设置为38400。传输位宽设置为16 bits。传输类型设置为signal。源地址固定为SPI0 RX寄存器,目标地址固定为USPI0 TX寄存器。代码位于PDMA_Init函数。
- void PDMA_Init(void)
- {
- /* Descriptor table 1 configuration */
- DMA_DESC[0].ctl = ((TRANSFER_LEN - 1) << PDMA_DSCT_CTL_TXCNT_Pos) | PDMA_WIDTH_16 | PDMA_SAR_FIX | PDMA_DAR_FIX | PDMA_REQ_SINGLE | PDMA_OP_SCATTER;
- DMA_DESC[0].src = (uint32_t) &SPI0->RX;
- DMA_DESC[0].dest = (uint32_t) &USPI0->TXDAT;
- DMA_DESC[0].offset = (uint32_t) &DMA_DESC[1] - (PDMA->SCATBA);
- /* Descriptor table 2 configuration */
- DMA_DESC[1].ctl = ((TRANSFER_LEN - 1) << PDMA_DSCT_CTL_TXCNT_Pos) | PDMA_WIDTH_16 | PDMA_SAR_FIX | PDMA_DAR_FIX | PDMA_REQ_SINGLE | PDMA_OP_BASIC;
- DMA_DESC[1].src = (uint32_t) &SPI0->RX;
- DMA_DESC[1].dest = (uint32_t) &USPI0->TXDAT;
- DMA_DESC[1].offset = 0;
- /* Open PDMA channel 1 for SPI RX */
- PDMA_Open(PDMA, (1 << SPI_MASTER_RX_DMA_CH));
- /* Configure PDMA transfer mode */
- PDMA_SetTransferMode(PDMA, SPI_MASTER_RX_DMA_CH, PDMA_SPI0_RX, 1, (uint32_t) &DMA_DESC[0]);
- }