#申请原创# #有奖活动#[url=home.php?mod=space&uid=760190]@21小跑堂 [/url]
【简介】
AC7840xSPI (Serial Peripheral Interface,串行外设接口)是一种全双工协议的外设总线,通过片选信号(CS0、CS1、CS2、CS3)、时钟线(SCK)、数据线(SIN、SOUT)进行数据传输。SPI 模块支持单主机-单从机 通讯,也支持单主机-多从机通讯,通讯总线通过片选信号最多可连接 4 个从机设备。
此次的实验在官方提供的spi例程上,移植GC9306的驱动程。
【移植要点】
tft的spi的移植,主要是实现spi写一位数据的指令。其次是重写DC(数据、命令),RESET的控制IO,BLK背光的打开与关闭或者是亮度调节。
【实验的硬件】
1、AC7840x开发板
2、GC9306xTFT显示屏
【硬件的连接】
// ----------------------------------------------------------------
// GND 电源地
// VCC 3.3v电源
// SCL PB2(SCLK)
// SDA PB1(MOSI)
// RES PB5
// DC PB4
// CS PE2
// BLK PB8
// SDI PB3
// ----------------------------------------------------------------
【实验步骤】
1、复制一份SPI的例程,并重命名为05_SPI_Master_Polling_tft:
2、复制一份在其他单片机上的tft驱动包到工程目录下面。
3、打开工程,新建bsp分组,把tft下面的两个文件添加进工程,并且,把头文件添加进工程。
4、在spi中添加DC、RST、BLK引脚的端口、引用的宏定义以及写高低电平的宏定义:
<p>#define PORT_TFT_DC (PORTB)</p><p>#define PORT_TFT_RES (PORTB)</p><p>#define PORT_TFT_BLK (PORTB)</p><p>#define GPIO_TFT_DC (GPIOB)</p><p>#define GPIO_TFT_RES (GPIOB)</p><p>#define GPIO_TFT_BLK (GPIOB)</p><p>#define PIN_TFT_DC (4U)</p><p>#define PIN_TFT_RES (5U)</p><p>#define PIN_TFT_BLK (8U)</p><p>//-----------------LCD端口定义----------------</p><p>#define LCD_RES_Clr do{GPIO_DRV_WritePin(GPIO_TFT_RES, PIN_TFT_RES, 0);}while(0) //RES</p><p>#define LCD_RES_Set do{GPIO_DRV_WritePin(GPIO_TFT_RES, PIN_TFT_RES, 1);}while(0) </p><p>#define LCD_DC_Clr do{GPIO_DRV_WritePin(GPIO_TFT_DC, PIN_TFT_DC, 0);}while(0)//DC</p><p>#define LCD_DC_Set do{GPIO_DRV_WritePin(GPIO_TFT_DC, PIN_TFT_DC, 1);}while(0)</p><p>#define LCD_BLK_Clr do{GPIO_DRV_WritePin(GPIO_TFT_BLK, PIN_TFT_BLK, 0);}while(0)//BLK</p><p>#define LCD_BLK_Set do{GPIO_DRV_WritePin(GPIO_TFT_BLK, PIN_TFT_BLK, 1);}while(0)</p>
5、在spi配置与初始化中添加TFT屏的DC、RES、BLK的配置,配置为GPIO复用、输出模式。
/* ==================================== Functions declaration ===================================== */
<p>/*!</p><p> * [url=home.php?mod=space&uid=247401]@brief[/url] SPI模块引脚初始化配置,主机模式</p><p> *</p><p> * @param none</p><p> *</p><p> * [url=home.php?mod=space&uid=266161]@return[/url] none</p><p> */</p><p>static void SPI_Init_Gpio(void)</p><p>{</p><p> GPIO_DRV_SetMuxModeSel(PORT_SPI_SCK, PIN_SPI_SCK, PORT_MUX_ALT3); /*! SCK */</p><p> GPIO_DRV_SetMuxModeSel(PORT_SPI_SOUT, PIN_SPI_SOUT, PORT_MUX_ALT3); /*! SOUT */</p><p> GPIO_DRV_SetMuxModeSel(PORT_SPI_SIN, PIN_SPI_SIN, PORT_MUX_ALT3); /*! SIN */</p><p> GPIO_DRV_SetMuxModeSel(PORT_SPI_CS, PIN_SPI_CS, PORT_MUX_ALT2); /*! CS */</p><p>GPIO_DRV_SetMuxModeSel(PORT_TFT_DC, PIN_TFT_DC, PORT_MUX_AS_GPIO); /*! DC */</p><p> GPIO_DRV_SetMuxModeSel(PORT_TFT_RES, PIN_TFT_RES, PORT_MUX_AS_GPIO); /*! RES */</p><p> GPIO_DRV_SetMuxModeSel(PORT_TFT_BLK, PIN_TFT_BLK, PORT_MUX_AS_GPIO); /*! BLK */</p><p> GPIO_DRV_SetPinDirection(GPIO_TFT_DC, PIN_TFT_DC, 1); /*设置DC为输出*/</p><p> GPIO_DRV_SetPinDirection(GPIO_TFT_RES, PIN_TFT_RES, 1); /*设置RES为输出*/</p><p> GPIO_DRV_SetPinDirection(GPIO_TFT_BLK, PIN_TFT_BLK, 1); /*设置BLK为输出*/</p><p>}</p>
6、修改spi发送一个数据、命令的函数:
<p>/******************************************************************************</p><p> 函数说明:LCD串行数据写入函数</p><p> 入口数据:dat 要写入的串行数据</p><p> 返回值: 无</p><p>******************************************************************************/</p><p>void LCD_Writ_Bus(uint8_t dat)</p><p>{</p><p>//status_t ret = STATUS_ERROR;</p><p>g_spiTxBuff1[0] = dat;</p><p>//SPI_DRV_MasterTransferBlocking(SPI_INSTANCE, g_spiTxBuff1, g_spiRxBuff1, 1, 1); /*! SPI通信 */</p><p>SPI_DRV_MasterTransfer(SPI_INSTANCE, g_spiTxBuff1, g_spiRxBuff1, 1); /*! SPI通信 */</p><p> while (SPI_DRV_MasterGetTransferStatus(SPI_INSTANCE, NULL) == STATUS_BUSY);</p><p>}</p><p>/******************************************************************************</p><p> 函数说明:LCD写入数据</p><p> 入口数据:dat 写入的数据</p><p> 返回值: 无</p><p>******************************************************************************/</p><p>void LCD_WR_DATA8(uint8_t dat)</p><p>{</p><p>LCD_Writ_Bus(dat);</p><p>}</p><p>/******************************************************************************</p><p> 函数说明:LCD写入数据</p><p> 入口数据:dat 写入的数据</p><p> 返回值: 无</p><p>******************************************************************************/</p><p>void LCD_WR_DATA(uint16_t dat)</p><p>{</p><p>//LCD_Writ_Bus(dat>>8);</p><p>//LCD_Writ_Bus(dat);</p><p>LCD_DC_Set;//写数据</p><p>g_spiTxBuff1[0] = dat>>8;</p><p>g_spiTxBuff1[1] = dat;</p><p>//SPI_DRV_MasterTransferBlocking(SPI_INSTANCE, g_spiTxBuff1, g_spiRxBuff1, 2, 1); /*! SPI通信 */</p><p>SPI_DRV_MasterTransfer(SPI_INSTANCE, g_spiTxBuff1, g_spiRxBuff1, 2); /*! SPI通信 */</p><p> while (SPI_DRV_MasterGetTransferStatus(SPI_INSTANCE, NULL) == STATUS_BUSY);</p><p>}</p>
7、修改spi配置函数,根据屏的用户手册,修改为设置数据采样相位,第2个边沿采样数据、设置SCK工作时极性,工作时SCK为低。
<p>spi_master_config_t spiMasteConfig =</p><p>{</p><p> .bitsPerSec = 20000000UL, /*! 设置SPI波特率*/</p><p> .whichPcs = SPI_PCS2, /*! 设置SPI片选引脚*/</p><p> .pcsPolarity = SPI_ACTIVE_LOW, /*! 设置SPI片选低有效*/</p><p> .isPcsContinuous = true, /*! 设置片选连续模式*/</p><p> .bitcount = 8UL, /*! SPI 帧长度,支持 4~32 bits*/</p><p> .spiSrcClk = 60000000UL, /*! SPI时钟源频率*/</p><p> .clkPhase = SPI_CLOCK_PHASE_2ND_EDGE, /*! 设置数据采样相位,第2个边沿采样数据*/</p><p> .clkPolarity = SPI_SCK_ACTIVE_LOW, /*! 设置SCK工作时极性,工作时SCK为低*/</p><p> .msbFirst = true, /*! 选择从最高位开始收发*/</p><p> .transferType = SPI_USING_INTERRUPTS, /*! 选择通信类型为中断方式*/</p><p> .rxDMAChannel = 1UL, /*! 设置SPI DMA接收通道,若未使用DMA方式传输,则该配置可忽略*/</p><p> .txDMAChannel = 0UL, /*! 设置SPI DMA发送通道,若未使用DMA方式传输,则该配置可忽略*/</p><p> .callback = NULL, /*! 注册回调函数 */</p><p> .callbackParam = NULL, /*! 回调函数参数 */</p><p>};</p>
8、在主函数中添加头文件的引用,并加入测函数如下:
int main(void)
<p>{</p><p> SystemClock_Config(); /*! 时钟初始化 */</p><p> InitDebug(); /*! 初始化调试串口 */</p><p> GPIO_Init(); /*! GPIO Init */</p><p> SPI_Master_Init(); /*! SPI主机初始化 */</p><p>IVO28_GC9306_P4();</p><p>LCD_Fill(0,0,LCD_W,LCD_H,BLACK);</p><p>LCD_Fill(0,0,LCD_W,LCD_H,WHITE);</p><p>LCD_ShowString(10,10, "HELLO AC7840x",BLUE,WHITE,32,0);</p><p> while (1)</p><p> {</p><p> }</p><p>}</p>
【实验效果】
【讨论】
官方的示例给出spi发送的三种方式,我测试了中断与阻塞式的发送,速度差不多,spi最高可以设置40M的速度。建议在发送数据是要用块来发送,如果一位一位的发送,速度会慢得吓人,用逻辑分析仪看了一下时序,间隔1ms多,分析了一下原因,因为官方的spi驱动库进行了封装,有很多的判断,所以效率不高。
如果要追求速度,还需要自己用寄存器进行读写操作才能达到最好的效果。
附工程源码:
Master_Polling_tft.zip
(107.38 KB)
|