??本文章僅僅簡(jiǎn)單記錄32單片機(jī)的SPI+DMA驅(qū)動(dòng)顯示屏的性能測(cè)試,這里不花費(fèi)時(shí)間介紹SPI和DMA。
硬件材料:SPI顯示屏一個(gè),32單片機(jī)
軟件材料:
1.LCD的SPI驅(qū)動(dòng)顯示程序(SPI / SPI+DMA):
(1)SPI的配置程序:
SPI_HandleTypeDef SPI3_Handler; //create a SPI handle
/**
* @brief SPI3 master mode
* @param void
* @return void
*/
void SPI3_Init(void)
{
SPI3_Handler.Instance=SPI3;
SPI3_Handler.Init.Mode=SPI_MODE_MASTER;
SPI3_Handler.Init.Direction=SPI_DIRECTION_2LINES;
SPI3_Handler.Init.DataSize=SPI_DATASIZE_8BIT;
SPI3_Handler.Init.CLKPolarity=SPI_POLARITY_HIGH; //Idle state clock is high
SPI3_Handler.Init.CLKPhase=SPI_PHASE_2EDGE;
SPI3_Handler.Init.NSS=SPI_NSS_SOFT;
SPI3_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_2;//baudrate is highest
SPI3_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB;
SPI3_Handler.Init.TIMode=SPI_TIMODE_DISABLE;
SPI3_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;
SPI3_Handler.Init.CRCPolynomial=7; //omit
HAL_SPI_Init(&SPI3_Handler);
__HAL_SPI_ENABLE(&SPI3_Handler);
}
/**
* @brief SPI3 lower driver config:perip clock ,io
* @param hspi: the SPI handle pointer should be use
* @return void
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_SPI3_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_3|GPIO_PIN_5;
GPIO_Initure.Mode=GPIO_MODE_AF_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_Initure.Alternate=GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
}
(2)SPI的讀寫(xiě)接口(非DMA情況下需要使用到)
/**
* @brief SPI3 R/W one octet
* @param TxData the u8 data which should be writed
* @return the u8 data received
*/
u8 SPI3_ReadWriteByte(u8 TxData)
{
u8 Rxdata;
HAL_SPI_TransmitReceive(&SPI3_Handler,&TxData,&Rxdata,1, 1000);
return Rxdata;
}
/**
* @brief SPI3 Write one octet
* @param TxData the tx payload
* @param size payload length
* @return u8 0:success,others:fail
*/
u8 SPI3_WriteByte(u8 *TxData,u16 size)
{
return HAL_SPI_Transmit(&SPI3_Handler,TxData,size,1000);
}
(3)SPI的DMA配置初始化
我使用的是Stm32L4做SPI3+DMA的測(cè)試,首先看芯片手冊(cè)DMA相關(guān)的內(nèi)容:
??上面的表格羅列了DMA2每個(gè)通道的DMA請(qǐng)求,SPI3_Tx對(duì)應(yīng)通道2,請(qǐng)求3(0011),那么我們可以這樣配置SPI3的DMA通道:
void vidSPI3DMA_Config(void)
{
__HAL_RCC_DMA2_CLK_ENABLE();//DMA2 Clock Enable
__HAL_LINKDMA(&SPI3_Handler, hdmatx, SPI3TxDMA_Handler); //Link DMA to SPI3, here we use the dma tx function
//Tx Dma config
SPI3TxDMA_Handler.Instance = DMA2_Channel2; //select the channel
SPI3TxDMA_Handler.Init.Request = DMA_REQUEST_3; //request(CxS:0011)
SPI3TxDMA_Handler.Init.Direction = DMA_MEMORY_TO_PERIPH; //memory to peripheral
SPI3TxDMA_Handler.Init.PeriphInc = DMA_PINC_DISABLE; //peripheral not increment
SPI3TxDMA_Handler.Init.MemInc = DMA_MINC_ENABLE; //memory inc
SPI3TxDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //perip data length:8 bit
SPI3TxDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; //mem data length:8 bit
SPI3TxDMA_Handler.Init.Mode = DMA_NORMAL;
SPI3TxDMA_Handler.Init.Priority = DMA_PRIORITY_HIGH;
SPI3TxDMA_Handler.State = HAL_DMA_STATE_READY;
HAL_DMA_DeInit(&SPI3TxDMA_Handler);
HAL_DMA_Init(&SPI3TxDMA_Handler);
HAL_NVIC_SetPriority(DMA2_Channel2_IRQn, 0, 3);
HAL_NVIC_EnableIRQ(DMA2_Channel2_IRQn);
}
(4)使用DMA中斷需要調(diào)用DMA中斷函數(shù)去清除相關(guān)中斷標(biāo)志位。
/*
* @brief: DMA2 Channel2 IRQ handler function
* mainly clear the interrupt flag
*/
void DMA2_Channel2_IRQHandler(void)
{
HAL_DMA_IRQHandler(&SPI3TxDMA_Handler);
}
/*
* @brief: After Tx is completed, the SPI DMA should be stopped for next transfer
*/
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
HAL_SPI_DMAStop(hspi);
}
2.LCD顯示驅(qū)動(dòng)程序:
(1)LCD基于SPI的數(shù)據(jù)發(fā)送接口:
/**
* @brief LCD SPI send data API
* @return void
*/
#define NO_USING_DMA 1
static void LCD_SPI_Send(u8 *data, u32 size)
{
#if NO_USING_DMA
u32 i;
u32 delta = size/0xFFFF;
for(i = 0; i<=delta; i++)
{
if( i==delta ) /* Send the last data */
SPI3_WriteByte(&data[i*0xFFFF], size%0xFFFF);//cause this API 2nd param is u16 type
else /* send 0xFFFF octets */
SPI3_WriteByte(&data[i*0xFFFF], 0xFFFF);
}
#else
while(SPI3_Handler.State != HAL_SPI_STATE_READY);
HAL_SPI_Transmit_DMA(&SPI3_Handler, data, size);
#endif
return;
}
??往LCD寫(xiě)任何數(shù)據(jù)都是用的這個(gè)接口LCD_SPI_Send。關(guān)于圖片的繪制的函數(shù)這里不多余貼出來(lái),相信網(wǎng)上一大把程序可以參考,這里直接使用定時(shí)器去了解不開(kāi)DMA和開(kāi)DMA顯示同一張圖片耗時(shí)差異,時(shí)間從串口打印出來(lái):文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-698749.html
u32 t=0;
printf("Show a 240X82 picture,Start: %d | ", t);
vidEnableTIM3(1);//enable TIM3,and clear the counter
Display_240x82_pic(0, 0);
t = u32GetTim3Counter();
printf("End: %d\r\n", t);
??這里我定時(shí)器計(jì)數(shù)頻率分頻到1Mhz,最大計(jì)數(shù)50000次,也是就計(jì)數(shù)頻率1us,周期50ms。
?? 第一次我是以SPI+DMA驅(qū)動(dòng)LCD顯示240X82的圖片,可以看出顯示該圖片在有DMA(加DMA中斷)的加持下,耗時(shí)156us。第二次是我單獨(dú)用SPI驅(qū)動(dòng)LCD顯示240X82的圖片,耗時(shí)8685us,所以區(qū)別還是蠻大的。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-698749.html
到了這里,關(guān)于SPI+DMA傳輸性能比較的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!