这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » MAX78000使用硬件SPI驱动ST7796

共3条 1/1 1 跳转至

MAX78000使用硬件SPI驱动ST7796

工程师
2025-08-12 19:09:12     打赏
MAX78000使用硬件SPI驱动ST7796LCD屏一、max7800与LCD屏的连接
/*
* SCK  P0_7
* MOSI P0_5
* CS   P0_11
* DC   P1_6
* RST  P0-19
*/

其中sck、mosi是使用SPI0这个通道,CS选用SS1即P0_11。

【注意】由于max硬件spi的时钟与MOSI会在正式发送数据之前会有一个方波,因此必须使用硬件CS来配合才能正常。经用逻辑分析仪查看他的时序如下:

SPI时序图SPI时序图.png

DC与RST做为普通GPIO输出即可,BL目前采用直接接VCC3.3V开机即亮。

二、SPI初始化

在max78000的SDK中提供了很多的常用屏的现成驱动,有但是没有st7796的驱动,因此我们可以借用SDK中的屏驱动来学习。

1、宏定义

#define TFT_SPI_FREQ 25000000 // spi 总线线速度25MHz  

#define TFT_SPI0_PINS MXC_GPIO_PIN_5 | MXC_GPIO_PIN_6 | MXC_GPIO_PIN_7 | MXC_GPIO_PIN_11

#define DC_SET     MXC_GPIO_OutSet(DC_PORT,DC_PIN)

#define DC_CLR     MXC_GPIO_OutClr(DC_PORT,DC_PIN)

#define RST_SET    MXC_GPIO_OutSet(RST_PORT,RST_PIN)

#define RST_CLR    MXC_GPIO_OutClr(RST_PORT,RST_PIN)

2、spi初始化

static void tft_spi_init(void)

{

#if SOFT_SPI

mxc_gpio_cfg_t gpio_out;

   gpio_out.port = DC_PORT;

gpio_out.mask = DC_PIN;

gpio_out.pad = MXC_GPIO_PAD_NONE;

gpio_out.func = MXC_GPIO_FUNC_OUT;

gpio_out.vssel = MXC_GPIO_VSSEL_VDDIOH;

gpio_out.drvstr = MXC_GPIO_DRVSTR_0;

MXC_GPIO_Config(&gpio_out);


   gpio_out.port = SCK_PORT;

gpio_out.mask = SCK_PIN;

gpio_out.pad = MXC_GPIO_PAD_NONE;

gpio_out.func = MXC_GPIO_FUNC_OUT;

gpio_out.vssel = MXC_GPIO_VSSEL_VDDIOH;

gpio_out.drvstr = MXC_GPIO_DRVSTR_0;

MXC_GPIO_Config(&gpio_out);


   gpio_out.port = MOSI_PORT;

gpio_out.mask = MOSI_PIN;

gpio_out.pad = MXC_GPIO_PAD_NONE;

gpio_out.func = MXC_GPIO_FUNC_OUT;

gpio_out.vssel = MXC_GPIO_VSSEL_VDDIOH;

gpio_out.drvstr = MXC_GPIO_DRVSTR_0;

MXC_GPIO_Config(&gpio_out);


   gpio_out.port = CS_PORT;

gpio_out.mask = CS_PIN;

gpio_out.pad = MXC_GPIO_PAD_NONE;

gpio_out.func = MXC_GPIO_FUNC_OUT;

gpio_out.vssel = MXC_GPIO_VSSEL_VDDIOH;

gpio_out.drvstr = MXC_GPIO_DRVSTR_0;

MXC_GPIO_Config(&gpio_out);


   gpio_out.port = RST_PORT;

gpio_out.mask = RST_PIN;

gpio_out.pad = MXC_GPIO_PAD_NONE;

gpio_out.func = MXC_GPIO_FUNC_OUT;

gpio_out.vssel = MXC_GPIO_VSSEL_VDDIOH;

gpio_out.drvstr = MXC_GPIO_DRVSTR_0;

MXC_GPIO_Config(&gpio_out);


DC_CLR;

CS_SET;

SCK_CLR;

RST_SET;

#else


int master = 1;

int quadMode = 0;

int numSlaves = 2;

int ssPol = 0;

unsigned int tft_hz = TFT_SPI_FREQ;

mxc_spi_pins_t tft_pins;

mxc_gpio_cfg_t gpio_out;


   gpio_out.port = CS_PORT;

gpio_out.mask = CS_PIN;

gpio_out.pad = MXC_GPIO_PAD_NONE;

gpio_out.func = MXC_GPIO_FUNC_OUT;

gpio_out.vssel = MXC_GPIO_VSSEL_VDDIOH;

gpio_out.drvstr = MXC_GPIO_DRVSTR_0;

MXC_GPIO_Config(&gpio_out);

 gpio_out.port = DC_PORT;

gpio_out.mask = DC_PIN;

gpio_out.pad = MXC_GPIO_PAD_NONE;

gpio_out.func = MXC_GPIO_FUNC_OUT;

gpio_out.vssel = MXC_GPIO_VSSEL_VDDIOH;

gpio_out.drvstr = MXC_GPIO_DRVSTR_0;

MXC_GPIO_Config(&gpio_out);

gpio_out.port = RST_PORT;

gpio_out.mask = RST_PIN;

gpio_out.pad = MXC_GPIO_PAD_NONE;

gpio_out.func = MXC_GPIO_FUNC_OUT;

gpio_out.vssel = MXC_GPIO_VSSEL_VDDIOH;

gpio_out.drvstr = MXC_GPIO_DRVSTR_0;

MXC_GPIO_Config(&gpio_out);

   tft_pins.clock = true;

   tft_pins.ss0 = (ssel == 0); ///< Slave select pin 0

   tft_pins.ss1 = (ssel == 1); ///< Slave select pin 1

   tft_pins.ss2 = (ssel == 2); ///< Slave select pin 2

   tft_pins.miso = true; ///< miso pin

   tft_pins.mosi = true; ///< mosi pin

   tft_pins.sdio2 = false; ///< SDIO2 pin

   tft_pins.sdio3 = false; ///< SDIO3 pin

   spi = MXC_SPI0;

MXC_SPI_Init(spi, master, quadMode, numSlaves, ssPol, tft_hz, tft_pins);


   // Set  SPI0 pins to VDDIOH (3.3V) to be compatible with TFT display

MXC_GPIO_SetVSSEL(MXC_GPIO0, MXC_GPIO_VSSEL_VDDIOH, TFT_SPI0_PINS);

MXC_SPI_SetDataSize(spi, 8);

MXC_SPI_SetWidth(spi, SPI_WIDTH_STANDARD);

CS_SET;


#endif


}

在这个函数中,我使用条件编译添加要spi的硬件初始化,设置DMA中断发送,8位数据宽度发送。

3、st7796的数据发送

static void spi_transmit(void* datain, unsigned int count)

{

unsigned int            offset;

unsigned int            fifo;

volatile unsigned short* u16ptrin = (volatile unsigned short*) datain;

unsigned int             start = 0;


   // HW requires disabling/renabling SPI block at end of each transaction (when SS is inactive).

   spi->ctrl0 &= ~(MXC_F_SPI_CTRL0_EN);


   // Setup the slave select

   MXC_SETFIELD(spi->ctrl0, MXC_F_SPI_CTRL0_SS_ACTIVE, ((1 << ssel) << MXC_F_SPI_CTRL0_SS_ACTIVE_POS));


   // number of RX Char is 0xffff

   spi->ctrl1 &= ~(MXC_F_SPI_CTRL1_RX_NUM_CHAR);


   //DMA RX FIFO disabled

   spi->dma &= ~(MXC_F_SPI_DMA_RX_FIFO_EN);


   // set number of char to be transmit

   MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_TX_NUM_CHAR, count << MXC_F_SPI_CTRL1_TX_NUM_CHAR_POS);

   // DMA TX fifo enable

   spi->dma |= MXC_F_SPI_DMA_TX_FIFO_EN;


   /* Clear TX and RX FIFO in DMA

       TX: Set this bit to clear the TX FIFO and all TX FIFO flags in the QSPIn_INT_FL register.

           Note: The TX FIFO should be disabled (QSPIn_DMA.tx_fifo_en = 0) prior to setting this field.

           Note: Setting this field to 0 has no effect.

       RX: Clear the RX FIFO and any pending RX FIFO flags in QSPIn_INTFL.

           This should be done when the RX FIFO is inactive.

   */

   spi->dma   |= (MXC_F_SPI_DMA_TX_FLUSH | MXC_F_SPI_DMA_RX_FLUSH);

   // QSPIn port is enabled

   spi->ctrl0 |= (MXC_F_SPI_CTRL0_EN);


   // Clear master done flag

   spi->intfl = MXC_F_SPI_INTFL_MST_DONE;


   /* Loop until all data is transmitted */

   offset = 0;


do {

       fifo = (count > 8) ? 8 : count;

       count -= fifo;


while (fifo > 0) {

           /* Send data */

           spi->fifo16[0] = u16ptrin[offset];

           offset++;

           fifo--;

       }


       /*

           Master Start Data Transmission

               Set this field to 1 to start a SPI master mode transaction.

               0: No master mode transaction active.

               1: Master initiates a data transmission. Ensure that all pending transactions are

               complete before setting this field to 1.

               Note: This field is only used when the QSPIn is configured for Master Mode

               (QSPIn_CTRL0.master = 1).

       */

if (start == 0) {

           spi->ctrl0 |= MXC_F_SPI_CTRL0_START;

           start = 1;

       }


       /* Wait for data transmitting complete and then Deasserts nSS I/O */

       // Deassert slave select at the end of the transaction

       spi->ctrl0 &= ~MXC_F_SPI_CTRL0_SS_CTRL;

   }

while (count);


while (!(spi->intfl & MXC_F_SPI_INTFL_MST_DONE)) {

       // wait until done

   }


return;

}

4、然后修改相关的命令、数据发送就行了。

## 四、软件与硬件效果对比


使用逻辑分析仪对软件、硬件的sck时序对比,发送速度软件经过优化后最高可以工作到1MHZ

软件SPI速度截图.png


硬件SPI可以达到28MHz


硬件SPI速度截图.png






关键词: MAX78000     ST7796     驱动SPI    

专家
2025-08-12 22:09:08     打赏
2楼

感谢分享


专家
2025-08-13 08:02:35     打赏
3楼

谢谢分享


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]