- #include "ST7789.h"
 
-  
 
- void LCD_GPIO_init(void)
 
- {
 
- #if LCD_USE_HARDWARE_SPI == 1
 
-  
 
-     gpio_init_type gpio_init_struct;
 
-  
 
-     // =========================> 初始化 SPI数据总线 GPIO <=========================
 
-     crm_periph_clock_enable(LCD_SPIx_GPIO_CRM, TRUE);
 
-  
 
-     gpio_default_para_init(&gpio_init_struct);
 
-  
 
-     gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
 
-     gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
 
-     gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
 
-     // SCLK
 
-     gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
 
-     gpio_init_struct.gpio_pins = LCD_SPIx_SCLK_GPIO_PIN;
 
-     gpio_init(LCD_SPIx_GPIO, &gpio_init_struct);
 
-     gpio_pin_mux_config(LCD_SPIx_GPIO, LCD_SPIx_SCLK_SOURCE, LCD_SPIx_MUX_SEL);
 
-  
 
-     // MOSI
 
-     gpio_init_struct.gpio_pull = GPIO_PULL_UP;
 
-     gpio_init_struct.gpio_pins = LCD_SPIx_MOSI_GPIO_PIN;
 
-     ;
 
-     gpio_init(LCD_SPIx_GPIO, &gpio_init_struct);
 
-     gpio_pin_mux_config(LCD_SPIx_GPIO, LCD_SPIx_MOSI_SOURCE, LCD_SPIx_MUX_SEL);
 
-  
 
- #if LCD_SHARE_SPI_WITH_TOUCH_IC == 1
 
-     // LCD和触摸IC共用SPI,CS由软件管理,此处不作配置
 
-     // 由于要接收触摸IC的数据,需要配置MISO,注意XPT2046的数据输出引脚外部不能上拉或下拉,只能配置成浮空输入
 
-     gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
 
-     gpio_init_struct.gpio_pins = LCD_SPIx_MISO_GPIO_PIN;
 
-     gpio_init(LCD_SPIx_GPIO, &gpio_init_struct);
 
-     gpio_pin_mux_config(LCD_SPIx_GPIO, LCD_SPIx_MISO_SOURCE, LCD_SPIx_MUX_SEL);
 
- #else
 
-     // LCD单独使用SPI,无需配置MISO,并且为硬件管理CS,
 
-     gpio_init_struct.gpio_pull = GPIO_PULL_UP;
 
-     gpio_init_struct.gpio_pins = LCD_SPIx_CS_GPIO_PIN;
 
-     gpio_init(LCD_SPIx_GPIO, &gpio_init_struct);
 
-     gpio_pin_mux_config(LCD_SPIx_GPIO, LCD_SPIx_CS_SOURCE, LCD_SPIx_MUX_SEL);
 
- #endif
 
-  
 
-     // =========================> 初始化其余信号线的GPIO <=========================
 
-     crm_periph_clock_enable(LCD_GPIOPORT_CRM, TRUE);
 
-  
 
-     gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
 
-     gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
 
-     gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
 
-     gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
 
-  
 
- #if LCD_SHARE_SPI_WITH_TOUCH_IC == 1
 
-     // LCD和触摸IC共用SPI,CS由MCU直接控制GPIO实现
 
-     gpio_init_struct.gpio_pins = LCD_PINS_RST | LCD_PINS_DC | LCD_PINS_BLK | LCD_PINS_CS;
 
-     gpio_init(LCD_GPIOPORT, &gpio_init_struct);
 
-     gpio_bits_set(LCD_GPIOPORT, LCD_PINS_RST | LCD_PINS_DC | LCD_PINS_BLK | LCD_PINS_CS);
 
- #else
 
-     // LCD单独使用SPI,CS已经由硬件实现,此处不作配置
 
-     #error "Hardware CS is is a piece of shit, DO NOT try!"
 
-     gpio_init_struct.gpio_pins = LCD_PINS_RST | LCD_PINS_DC | LCD_PINS_BLK;
 
-     gpio_init(LCD_GPIOPORT, &gpio_init_struct);
 
-     gpio_bits_set(LCD_GPIOPORT, LCD_PINS_RST | LCD_PINS_DC | LCD_PINS_BLK);
 
- #endif
 
-  
 
- #else
 
-     // 使用软件SPI 且必定共用一个SPI
 
-     crm_periph_clock_enable(LCD_GPIOPORT_CRM, TRUE);
 
-  
 
-     gpio_init_type gpio_init_struct;
 
-     gpio_default_para_init(&gpio_init_struct);
 
-     gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
 
-     gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
 
-     gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
 
-     gpio_init_struct.gpio_pins = LCD_PINS_SCLK | LCD_PINS_MOSI | LCD_PINS_RST | LCD_PINS_DC | LCD_PINS_BLK | LCD_PINS_CS;
 
-     gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
 
-  
 
-     gpio_init(LCD_GPIOPORT, &gpio_init_struct);
 
-  
 
-     gpio_bits_set(LCD_GPIOPORT, LCD_PINS_SCLK | LCD_PINS_MOSI | LCD_PINS_RST | LCD_PINS_DC | LCD_PINS_BLK | LCD_PINS_CS);
 
- #endif
 
- }
 
-  
 
- #if LCD_USE_HARDWARE_SPI == 1 && LCD_HARDWARE_SPI_USE_DMA == 0
 
-  
 
- /**
 
-  
 
-   * [url=home.php?mod=space&uid=247401]@brief[/url]  spi configuration.
 
-   * @param  none
 
-   * @retval none
 
-   */
 
- void LCD_SPIx_init(void)
 
- {
 
-     spi_init_type spi_init_struct;
 
-  
 
-     spi_i2s_reset(LCD_SPIx);
 
-     crm_periph_clock_enable(LCD_SPIx_CRM, TRUE);
 
-     spi_default_para_init(&spi_init_struct);
 
-     spi_init_struct.master_slave_mode = SPI_MODE_MASTER;        // 设置SPI工作模式:主机模式
 
-     spi_init_struct.mclk_freq_division = LCD_SPI_SPEED;        // 288M / 8 = 36M
 
-     spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB; // 数据传输高位先行
 
-     spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;             // 设置SPI数据大小:8位帧结构
 
-     spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;   // 串行同步时钟空闲时SCLK位高电平
 
- #if LCD_SHARE_SPI_WITH_TOUCH_IC == 1
 
-     spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;        // 串行同步时钟空第二个时钟沿捕获
 
-     spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX; // 要接收触模信息所以是全双工
 
-     spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;     // 片选信号由软件管理
 
- #else
 
-     spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;        // 串行同步时钟空第二个时钟沿捕获
 
-     spi_init_struct.transmission_mode = SPI_TRANSMIT_HALF_DUPLEX_TX; // LCD只接收信息所以是单工
 
-     spi_init_struct.cs_mode_selection = SPI_CS_HARDWARE_MODE;        // 片选信号由硬件管理
 
-     #error "Hardware CS is is a piece of shit, DO NOT try!"
 
-     spi_hardware_cs_output_enable(LCD_SPIx, TRUE);
 
- #endif
 
-     spi_init(LCD_SPIx, &spi_init_struct);
 
-     spi_enable(LCD_SPIx, TRUE);
 
- }
 
-  
 
-  
 
-  
 
- #elif LCD_HARDWARE_SPI_USE_DMA == 1
 
-  
 
- // uint16_t LCD_SPIx_TX_buffer[LCD_SPI_TX_BUFFER_SIZE];
 
- // #if (LCD_SHARE_SPI_WITH_TOUCH_IC == 1)
 
- // uint16_t LCD_SPIx_RX_buffer[LCD_SPI_RX_BUFFER_SIZE];
 
- // #endif
 
-  
 
- void LCD_SPIx_init(void)
 
- {
 
-  
 
-     dma_init_type dma_init_struct;
 
-     spi_init_type spi_init_struct;
 
-     
 
-     /************** DMA 配置 *****************/
 
-  
 
-     /* LCD_SPI_TX_DMAx_CHy configuration */
 
-     // 时钟配置
 
-     crm_periph_clock_enable(LCD_SPI_TX_DMAx_CRM_CLOCK, TRUE);
 
-     dma_reset(LCD_SPI_TX_DMAx_CHy);
 
-     // DMA MUX 通道配置
 
-     dmamux_enable(LCD_SPI_TX_DMAx, TRUE);
 
-     dmamux_init(LCD_SPI_TX_DMAxMUX_CHy, LCD_SPI_TX_DMAMUX_REQ_ID);
 
-     // DMA 通道配置
 
-     dma_default_para_init(&dma_init_struct);
 
-     dma_init_struct.buffer_size = LCD_SPI_TX_BUFFER_SIZE;
 
-     dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
 
-     // dma_init_struct.memory_base_addr = (uint32_t)LCD_SPIx_TX_buffer;
 
-     dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
 
-     dma_init_struct.memory_inc_enable = TRUE;
 
-     dma_init_struct.peripheral_base_addr = (uint32_t)&(LCD_SPIx->dt);
 
-     // dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE; // 如果 MWIDTH 是16bit,但 PWIDTH 是8bit,方向是M2P,那么DMA只会搬运存MEM中每个半字的低8位,也即低地址处的字节。
 
-     dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
 
-     dma_init_struct.peripheral_inc_enable = FALSE;
 
-     dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
 
-     dma_init_struct.loop_mode_enable = FALSE; //是否循环模式
 
-     dma_init(LCD_SPI_TX_DMAx_CHy, &dma_init_struct);
 
-  
 
-     #if (LCD_SHARE_SPI_WITH_TOUCH_IC == 1)
 
-     /* LCD_SPI_TX_DMAx_CHy configuration */
 
-     // DMA MUX 通道配置
 
-     dmamux_init(LCD_SPI_RX_DMAxMUX_CHy, LCD_SPI_RX_DMAMUX_REQ_ID);
 
-     // DMA 通道配置
 
-     dma_default_para_init(&dma_init_struct);
 
-     dma_init_struct.buffer_size = LCD_SPI_RX_BUFFER_SIZE;
 
-     dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
 
-     // dma_init_struct.memory_base_addr = (uint32_t)LCD_SPIx_RX_buffer;
 
-     dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
 
-     dma_init_struct.memory_inc_enable = TRUE;
 
-     dma_init_struct.peripheral_base_addr = (uint32_t)&(LCD_SPIx->dt);
 
-     dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
 
-     dma_init_struct.peripheral_inc_enable = FALSE;
 
-     dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
 
-     dma_init_struct.loop_mode_enable = FALSE; //是否循环模式
 
-     dma_init(LCD_SPI_RX_DMAx_CHy, &dma_init_struct);
 
-     #else
 
-     // 不需要 RX buffer 和 RX DMA
 
-     #endif
 
-  
 
-     /************** SPI 配置 *****************/
 
-  
 
-     crm_periph_clock_enable(LCD_SPIx_CRM, TRUE);
 
-     spi_default_para_init(&spi_init_struct);
 
-     #if (LCD_SHARE_SPI_WITH_TOUCH_IC == 1)
 
-     spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
 
-     #else
 
-     spi_init_struct.transmission_mode = SPI_TRANSMIT_HALF_DUPLEX_TX;
 
-     #endif
 
-     spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
 
-     spi_init_struct.mclk_freq_division = LCD_SPI_SPEED;
 
-     spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
 
-     spi_init_struct.frame_bit_num = SPI_FRAME_16BIT;
 
-     spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
 
-     spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
 
-     spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
 
-  
 
-     spi_init(LCD_SPIx, &spi_init_struct);
 
-     spi_i2s_dma_transmitter_enable(LCD_SPIx, TRUE);
 
-     // spi_i2s_dma_receiver_enable(LCD_SPIx,TRUE);
 
-     spi_enable(LCD_SPIx, TRUE);
 
-  
 
-     #if (LCD_HARDWARE_SPI_TX_DMA_USE_INT == 1)
 
-     //中断配置
 
-     nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
 
-  
 
-     /* enable transfer full data intterrupt 当数据全部发送完毕后产生中断*/
 
-     dma_interrupt_enable(LCD_SPI_TX_DMAx_CHy, DMA_FDT_INT, TRUE);
 
-     /* LCD_SPI_TX_DMAx_CHy interrupt nvic init */
 
-     nvic_irq_enable(LCD_SPI_TX_DMAx_CHy_IRQn, 5, 0);
 
-     /* config flexible dma for LCD_SPI_TX_DMAxMUX_CHy 配置弹性映射 */
 
-     dma_flexible_config(LCD_SPI_TX_DMAx, LCD_SPI_TX_DMAxMUX_CHy, LCD_SPI_TX_DMAMUX_REQ_ID);
 
-  
 
-     #if (LCD_SHARE_SPI_WITH_TOUCH_IC == 1)
 
-     /* enable transfer full data intterrupt 当数据全部发送完毕后产生中断*/
 
-     dma_interrupt_enable(LCD_SPI_RX_DMAx_CHy, DMA_FDT_INT, TRUE);
 
-     /* LCD_SPI_RX_DMAx_CHy interrupt nvic init */
 
-     nvic_irq_enable(LCD_SPI_RX_DMAx_CHy_IRQn, 3, 0);
 
-     /* config flexible dma for LCD_SPI_RX_DMAxMUX_CHy 配置弹性映射 */
 
-     dma_flexible_config(LCD_SPI_TX_DMAx, LCD_SPI_RX_DMAxMUX_CHy, LCD_SPI_RX_DMAMUX_REQ_ID);
 
-     #endif
 
-     #endif
 
-     
 
- }
 
-  
 
- /**
 
-   * @brief  data transfer to LCD_SPIx using DMA
 
-   * @param  buf : buffer address
 
-   * @param  size : this uint32_t value should be less than 65535. Or otherwise size%0xFFFF is what finally takes effect.
 
-   * @retval none
 
-   */
 
- void LCD_SPI_data_send_use_DMA(const void *buf, uint32_t size)
 
- {
 
-     #if (LCD_HARDWARE_SPI_TX_DMA_USE_INT == 1)
 
-     // 在使用 SPI TX DMA 中断的情况下,如果此时DMA还在搬运,那么应该等DMA中断服务程序结束后再向DMA发送新的buf和size,否则DMA传输中断,屏幕收到数据不完整
 
-     if (LCD_SPI_TX_DMAx_CHy->ctrl_bit.chen == 1)
 
-     {
 
-         __WFI();
 
-     }
 
-     #endif
 
-     // 确保 LCD_SPIx 为16bit传输模式 且 频率为初始设定频率
 
-     if(LCD_SPIx->ctrl1_bit.fbn == SPI_FRAME_8BIT || LCD_SPIx->ctrl1_bit.mdiv_l != LCD_SPI_SPEED)
 
-     {
 
-         // 需要把SPI改为16bit模式 或 把频率改为设定频率
 
-  
 
-         // DMA搬运完成,但此时SPI还在发送,等待SPI通信忙结束
 
-         while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_TDBE_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Tx dt buf空 清零,说明还有数据在传输
 
-         {
 
-             // 等待主机数据发送完毕
 
-         }
 
-         while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_RDBF_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Rx dt buf满 清零,说明还有数据未发送
 
-         {
 
-             // 等待主机数据接收完毕
 
-         }
 
-         spi_i2s_data_receive(LCD_SPIx);
 
-         // SPI改为16bit模式
 
-         spi_frame_bit_num_set(LCD_SPIx, SPI_FRAME_16BIT);
 
-         // SPI时钟分频改为初始设定值
 
-         LCD_SPIx->ctrl1_bit.mdiv_l = LCD_SPI_SPEED;
 
-     }
 
-  
 
-     // 确保对应通道的 CHEN 位为 0,否则无法写入
 
-     dma_channel_enable(LCD_SPI_TX_DMAx_CHy, FALSE);
 
-     LCD_SPI_TX_DMAx_CHy->maddr = (uint32_t)buf;
 
-     LCD_SPI_TX_DMAx_CHy->dtcnt_bit.cnt = size; // 注意 dtcnt 是一个32位寄存器,但只有低16位是可用的
 
-     // 开启DMA搬运前拉低CS
 
-     LCD_CS_CLR();
 
-     // DMA开始搬运,随即SPI开始传输
 
-     dma_channel_enable(LCD_SPI_TX_DMAx_CHy, TRUE);
 
-     // =============================> 接收通道的DMA配置 <=============================
 
-     #if (LCD_SHARE_SPI_WITH_TOUCH_IC == 1)
 
-     dma_channel_enable(LCD_SPI_RX_DMAx_CHy, FALSE);
 
-     // 确保对应通道的 CHEN 位为 0,否则无法写入
 
-     // LCD_SPI_RX_DMAx_CHy->maddr = (uint32_t)LCD_SPIx_RX_buffer;
 
-     LCD_SPI_RX_DMAx_CHy->dtcnt_bit.cnt = size; // 注意 dtcnt 是一个32位寄存器,但只有低16位是可用的
 
-     dma_channel_enable(LCD_SPI_RX_DMAx_CHy, TRUE); // (在轮询结束或在中断服务程序的最后会关掉)
 
-     #endif
 
-  
 
-     #if LCD_HARDWARE_SPI_TX_DMA_USE_INT == 1
 
-     // 将在中断服务程序中完成 标志位清除、等待SPI发送结束并读一次数据(如果是全双工)、关闭DMA通道、拉高CS 的工作
 
-     #else
 
-     /*** 若不开DMA完成中断,则轮询DMAx_FDTy标志位 ***/
 
-     // while(spi_i2s_flag_get(LCD_SPIx,SPI_I2S_BF_FLAG) == SET){};
 
-     // while(dma_flag_get(DMA2_FDT1_FLAG) == RESET)
 
-     // {
 
-     // };
 
-     // dma_flag_clear(DMA2_FDT1_FLAG);
 
-     // LCD_CS_SET();
 
-     // // spi_i2s_dma_transmitter_enable(LCD_SPIx, FALSE);
 
-     // dma_channel_enable(LCD_SPI_TX_DMAx_CHy, FALSE);
 
-     // spi_i2s_data_receive(LCD_SPIx);
 
-     // // lv_disp_flush_complete();
 
-  
 
-     #endif
 
- }
 
- #if LCD_HARDWARE_SPI_TX_DMA_USE_INT == 1
 
- // 将在中断服务程序中完成 标志位清除、等待SPI发送结束并读一次数据(如果是全双工)、关闭DMA通道、拉高CS 的工作
 
-  
 
- void LCD_SPI_TX_DMAx_CHy_IRQHandler(void)
 
- {
 
-     /*DMA发送完成中断*/
 
-     if (dma_flag_get(LCD_SPI_TX_DMAx_FDTy_FLAG) == SET)
 
-     {
 
-         dma_channel_enable(LCD_SPI_TX_DMAx_CHy, FALSE);
 
-  
 
-         // DMA搬运完成,但此时SPI还在发送
 
-         while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_TDBE_FLAG) == RESET || spi_i2s_flag_get(LCD_SPIx, SPI_I2S_RDBF_FLAG) == SET || spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET)// Tx dt buf非空 或者 Rx dt buf满 或者 通信忙
 
-         {
 
-             spi_i2s_data_receive(LCD_SPIx);
 
-         }
 
-         while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_ROERR_FLAG) == SET || spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET)// Tx dt buf非空 或者 Rx dt buf满 或者 通信忙
 
-         {
 
-             spi_i2s_data_receive(LCD_SPIx);
 
-         }
 
-         spi_i2s_data_receive(LCD_SPIx); // !!!血泪教训!!全双工下DMA发完SPI后一定要读一次!!!
 
-         LCD_CS_SET();
 
-         // // DMA改回默认设置:MEM地址递增 (刷纯色的时候会改成FALSE)
 
-         // LCD_SPI_TX_DMAx_CHy->ctrl_bit.mincm = TRUE;
 
-         dma_flag_clear(LCD_SPI_TX_DMAx_FDTy_FLAG);
 
-     }
 
- }
 
-  
 
- #endif
 
-  
 
- void LCD_SPI_RX_DMAx_CHy_IRQHandler(void)
 
- {
 
-     /*DMA发送完成中断*/
 
-     if (dma_flag_get(LCD_SPI_RX_DMAx_FDTy_FLAG) == SET)
 
-     {
 
-         dma_flag_clear(LCD_SPI_RX_DMAx_FDTy_FLAG);
 
-         // LCD_SPI_RX_DMAx_CHy 将在发送数据的时候被再次使能
 
-         dma_channel_enable(LCD_SPI_RX_DMAx_CHy, FALSE);
 
-     }
 
- }
 
- #endif
 
-  
 
- /******************************************************************************
 
-      函数说明:LCD串行数据写入函数
 
-     入口数据:data  要写入的串行数据
 
-     返回值:  无
 
- ******************************************************************************/
 
- static void LCD_SPI_write_bus(uint16_t data)
 
- {
 
- #if (LCD_USE_HARDWARE_SPI == 1)
 
-     // #if (LCD_HARDWARE_SPI_USE_DMA == 1)
 
-     // LCD_SPI_data_send_use_DMA(&data, 1);
 
-     // #else
 
-     LCD_CS_CLR();
 
-     while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_TDBE_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Tx dt buf空 清零,说明还有数据在传输
 
-     {
 
-         // 等待主机数据发送完毕
 
-     }
 
-     spi_i2s_data_transmit(LCD_SPIx, data);
 
-     while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_RDBF_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Rx dt buf满 清零,说明还有数据未发送
 
-     {
 
-         // 等待主机数据接收完毕
 
-     }
 
-     spi_i2s_data_receive(LCD_SPIx);// 即使实际上没有用到 MISO,也需要读一次DT寄存器
 
-     // while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_TDBE_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Tx dt buf空 清零,说明还有数据在传输
 
-     // {
 
-     //     // 等待主机数据发送完毕
 
-     //     // 他说他自己发完了,其实他发完个屁
 
-     // }
 
-     LCD_CS_SET();
 
-     // #endif
 
- #else
 
-     uint8_t i;
 
-     LCD_CS_CLR();
 
-     for (i = 0; i < 8; i++) {
 
-         LCD_SCLK_CLR();
 
-         if (data & 0x80) { 
 
-             LCD_MOSI_SET();
 
-         } else {
 
-             LCD_MOSI_CLR();
 
-         }
 
-         LCD_SCLK_SET();
 
-         data <<= 1;
 
-     }
 
-     LCD_CS_SET();
 
- #endif
 
- }
 
-  
 
- /******************************************************************************
 
-      函数说明:LCD写入数据
 
-     入口数据:data 写入的数据
 
-     返回值:  无
 
- ******************************************************************************/
 
- void LCD_write_byte(uint8_t data_byte)
 
- {
 
-     // 确保 LCD_SPIx 为8bit传输模式
 
-     if(LCD_SPIx->ctrl1_bit.fbn == SPI_FRAME_16BIT)
 
-     {
 
-         // 需要把SPI改为16bit模式
 
-         // 等待SPI通信忙结束
 
-         while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_TDBE_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Tx dt buf空 清零,说明还有数据在传输
 
-         {
 
-             // 等待主机数据发送完毕
 
-         }
 
-         while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_RDBF_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Rx dt buf满 清零,说明还有数据未发送
 
-         {
 
-             // 等待主机数据接收完毕
 
-         }
 
-         spi_i2s_data_receive(LCD_SPIx);
 
-         // SPI改为8bit模式
 
-         spi_frame_bit_num_set(LCD_SPIx, SPI_FRAME_8BIT);
 
-     }
 
-     LCD_SPI_write_bus(data_byte);
 
- }
 
-  
 
- /******************************************************************************
 
-      函数说明:LCD写入数据
 
-     入口数据:data 写入的数据
 
-     返回值:  无
 
- ******************************************************************************/
 
- void LCD_write_half(uint16_t data_half)
 
- {
 
-     // 确保 LCD_SPIx 为16bit传输模式
 
-     if(LCD_SPIx->ctrl1_bit.fbn == SPI_FRAME_8BIT)
 
-     {
 
-         // 需要把SPI改为16bit模式
 
-  
 
-         // 等待SPI通信忙结束
 
-         while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_TDBE_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Tx dt buf空 清零,说明还有数据在传输
 
-         {
 
-             // 等待主机数据发送完毕
 
-         }
 
-         while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_RDBF_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Rx dt buf满 清零,说明还有数据未发送
 
-         {
 
-             // 等待主机数据接收完毕
 
-         }
 
-         spi_i2s_data_receive(LCD_SPIx);
 
-         // SPI改为16bit模式
 
-         spi_frame_bit_num_set(LCD_SPIx, SPI_FRAME_16BIT);
 
-     }
 
-     LCD_SPI_write_bus(data_half);
 
-  
 
- }
 
-  
 
- /******************************************************************************
 
-      函数说明:LCD写入命令
 
-     入口数据:data 写入的命令
 
-     返回值:  无
 
- ******************************************************************************/
 
- void LCD_write_cmd(uint8_t data_byte)
 
- {
 
-     #if (LCD_HARDWARE_SPI_TX_DMA_USE_INT == 1)
 
-     // 在使用 SPI TX DMA 中断的情况下,如果此时DMA还在搬运,那么应该等DMA中断服务程序结束,并且SPI当前帧发送结束后再把DC拉低,否则将导致cmd数据和data数据错位,屏幕卡死
 
-     if (LCD_SPI_TX_DMAx_CHy->ctrl_bit.chen == 1)
 
-     {
 
-     __WFI();
 
-     }
 
-     // DMA搬运完成,但此时SPI还在发送
 
-     while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_TDBE_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Tx dt buf空 清零,说明还有数据在传输
 
-     {
 
-         // 等待主机数据发送完毕
 
-     }
 
-     while (spi_i2s_flag_get(LCD_SPIx, SPI_I2S_RDBF_FLAG) == RESET && spi_i2s_flag_get(LCD_SPIx, SPI_I2S_BF_FLAG) == SET) // Rx dt buf满 清零,说明还有数据未发送
 
-     {
 
-         // 等待主机数据接收完毕
 
-     }
 
-     spi_i2s_data_receive(LCD_SPIx);
 
-     #endif
 
-     LCD_DC_CLR(); //写命令
 
-     LCD_write_byte(data_byte);
 
-     LCD_DC_SET(); //写数据
 
- }
 
-  
 
-  
 
- /**
 
-   * @brief  设置区域的左上角(起始)和右下角(结束)
 
-   * @param  x1 : 列起始坐标
 
-   * @param  y1 : 行起始坐标
 
-   * @param  x2 : 列结束坐标
 
-   * @param  y2 : 行结束坐标
 
-   * @retval none
 
-   */
 
- void LCD_addr_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
 
- {
 
-     // 列地址设置
 
-     LCD_write_cmd(0x2a); 
 
-     LCD_write_half(x1);
 
-     LCD_write_half(x2);
 
-     // 行地址设置
 
-     LCD_write_cmd(0x2b);
 
-     LCD_write_half(y1);
 
-     LCD_write_half(y2);
 
-     // 准备接收数据
 
-     LCD_write_cmd(0x2c); 
 
- }
 
-  
 
- /******************************************************************************
 
-      函数说明:LCD初始化函数
 
-     入口数据:无
 
-     返回值:  无
 
- ******************************************************************************/
 
- void LCD_init(void)
 
- {
 
- #if CHIP_USE_ST7789 == 0 //初始化ILI9341
 
-     {
 
-         LCD_RES_CLR(); //复位
 
-         delay_ms(100);
 
-         LCD_RES_SET();
 
-         delay_ms(100);
 
-  
 
-         LCD_BLK_SET(); //打开背光
 
-         delay_ms(100);
 
-  
 
-         //************* Start Initial Sequence **********//
 
-         LCD_write_cmd(0x11); // Sleep out
 
-         delay_ms(120);       // Delay 120ms
 
-         //************* Start Initial Sequence **********//
 
-         LCD_write_cmd(0xCF);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0xC1);
 
-         LCD_write_byte(0X30);
 
-         LCD_write_cmd(0xED);
 
-         LCD_write_byte(0x64);
 
-         LCD_write_byte(0x03);
 
-         LCD_write_byte(0X12);
 
-         LCD_write_byte(0X81);
 
-         LCD_write_cmd(0xE8);
 
-         LCD_write_byte(0x85);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0x79);
 
-         LCD_write_cmd(0xCB);
 
-         LCD_write_byte(0x39);
 
-         LCD_write_byte(0x2C);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0x34);
 
-         LCD_write_byte(0x02);
 
-         LCD_write_cmd(0xF7);
 
-         LCD_write_byte(0x20);
 
-         LCD_write_cmd(0xEA);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_cmd(0xC0);  // Power control
 
-         LCD_write_byte(0x1D); // VRH[5:0]
 
-         LCD_write_cmd(0xC1);  // Power control
 
-         LCD_write_byte(0x12); // SAP[2:0];BT[3:0]
 
-         LCD_write_cmd(0xC5);  // VCM control
 
-         LCD_write_byte(0x33);
 
-         LCD_write_byte(0x3F);
 
-         LCD_write_cmd(0xC7); // VCM control
 
-         LCD_write_byte(0x92);
 
-         LCD_write_cmd(0x3A); // Memory Access Control
 
-         LCD_write_byte(0x55);
 
-         LCD_write_cmd(0x36); // Memory Access Control
 
-         if (USE_HORIZONTAL == 0)
 
-             LCD_write_byte(0x08);
 
-         else if (USE_HORIZONTAL == 1)
 
-             LCD_write_byte(0xC8);
 
-         else if (USE_HORIZONTAL == 2)
 
-             LCD_write_byte(0x78);
 
-         else
 
-             LCD_write_byte(0xA8);
 
-         LCD_write_cmd(0xB1);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0x12);
 
-         LCD_write_cmd(0xB6); // Display Function Control
 
-         LCD_write_byte(0x0A);
 
-         LCD_write_byte(0xA2);
 
-  
 
-         LCD_write_cmd(0x44);
 
-         LCD_write_byte(0x02);
 
-  
 
-         LCD_write_cmd(0xF2); // 3Gamma Function Disable
 
-         LCD_write_byte(0x00);
 
-         LCD_write_cmd(0x26); // Gamma curve selected
 
-         LCD_write_byte(0x01);
 
-         LCD_write_cmd(0xE0); // Set Gamma
 
-         LCD_write_byte(0x0F);
 
-         LCD_write_byte(0x22);
 
-         LCD_write_byte(0x1C);
 
-         LCD_write_byte(0x1B);
 
-         LCD_write_byte(0x08);
 
-         LCD_write_byte(0x0F);
 
-         LCD_write_byte(0x48);
 
-         LCD_write_byte(0xB8);
 
-         LCD_write_byte(0x34);
 
-         LCD_write_byte(0x05);
 
-         LCD_write_byte(0x0C);
 
-         LCD_write_byte(0x09);
 
-         LCD_write_byte(0x0F);
 
-         LCD_write_byte(0x07);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_cmd(0XE1); // Set Gamma
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0x23);
 
-         LCD_write_byte(0x24);
 
-         LCD_write_byte(0x07);
 
-         LCD_write_byte(0x10);
 
-         LCD_write_byte(0x07);
 
-         LCD_write_byte(0x38);
 
-         LCD_write_byte(0x47);
 
-         LCD_write_byte(0x4B);
 
-         LCD_write_byte(0x0A);
 
-         LCD_write_byte(0x13);
 
-         LCD_write_byte(0x06);
 
-         LCD_write_byte(0x30);
 
-         LCD_write_byte(0x38);
 
-         LCD_write_byte(0x0F);
 
-         LCD_write_cmd(0x29); // Display on
 
-     }
 
- #else //初始化ST7789
 
-     {
 
-         LCD_RES_CLR(); //复位
 
-         delay_ms(100);
 
-         LCD_RES_SET();
 
-         delay_ms(100);
 
-         LCD_BLK_SET(); //打开背光
 
-         delay_ms(500);
 
-         LCD_write_cmd(0x11);
 
-         delay_ms(120); // Delay 120ms
 
-         //************* Start Initial Sequence **********//
 
-         //------------------------------display and color format setting--------------------------------//
 
-  
 
-         LCD_write_cmd(0X36); // Memory Access Control
 
-         if (USE_HORIZONTAL == 0)
 
-             LCD_write_byte(0x00);
 
-         else if (USE_HORIZONTAL == 1)
 
-             LCD_write_byte(0xC0);
 
-         else if (USE_HORIZONTAL == 2)
 
-             LCD_write_byte(0x70);
 
-         else
 
-             LCD_write_byte(0xA0);
 
-         LCD_write_cmd(0X3A);
 
-         LCD_write_byte(0X05);
 
-         //--------------------------------ST7789S Frame rate setting-------------------------
 
-  
 
-         LCD_write_cmd(0xb2);
 
-         LCD_write_byte(0x0c);
 
-         LCD_write_byte(0x0c);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0x33);
 
-         LCD_write_byte(0x33);
 
-         LCD_write_cmd(0xb7);
 
-         LCD_write_byte(0x35);
 
-         //---------------------------------ST7789S Power setting-----------------------------
 
-  
 
-         LCD_write_cmd(0xbb);
 
-         LCD_write_byte(0x35);
 
-         LCD_write_cmd(0xc0);
 
-         LCD_write_byte(0x2c);
 
-         LCD_write_cmd(0xc2);
 
-         LCD_write_byte(0x01);
 
-         LCD_write_cmd(0xc3);
 
-         LCD_write_byte(0x13);
 
-         LCD_write_cmd(0xc4);
 
-         LCD_write_byte(0x20);
 
-         LCD_write_cmd(0xc6);
 
-         LCD_write_byte(0x0f);
 
-         LCD_write_cmd(0xca);
 
-         LCD_write_byte(0x0f);
 
-         LCD_write_cmd(0xc8);
 
-         LCD_write_byte(0x08);
 
-         LCD_write_cmd(0x55);
 
-         LCD_write_byte(0x90);
 
-         LCD_write_cmd(0xd0);
 
-         LCD_write_byte(0xa4);
 
-         LCD_write_byte(0xa1);
 
-         //--------------------------------ST7789S gamma setting------------------------------
 
-         LCD_write_cmd(0xe0);
 
-         LCD_write_byte(0xd0);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0x06);
 
-         LCD_write_byte(0x09);
 
-         LCD_write_byte(0x0b);
 
-         LCD_write_byte(0x2a);
 
-         LCD_write_byte(0x3c);
 
-         LCD_write_byte(0x55);
 
-         LCD_write_byte(0x4b);
 
-         LCD_write_byte(0x08);
 
-         LCD_write_byte(0x16);
 
-         LCD_write_byte(0x14);
 
-         LCD_write_byte(0x19);
 
-         LCD_write_byte(0x20);
 
-         LCD_write_cmd(0xe1);
 
-         LCD_write_byte(0xd0);
 
-         LCD_write_byte(0x00);
 
-         LCD_write_byte(0x06);
 
-         LCD_write_byte(0x09);
 
-         LCD_write_byte(0x0b);
 
-         LCD_write_byte(0x29);
 
-         LCD_write_byte(0x36);
 
-         LCD_write_byte(0x54);
 
-         LCD_write_byte(0x4b);
 
-         LCD_write_byte(0x0d);
 
-         LCD_write_byte(0x16);
 
-         LCD_write_byte(0x14);
 
-         LCD_write_byte(0x21);
 
-         LCD_write_byte(0x20);
 
-         LCD_write_cmd(0x29);
 
-     }
 
- #endif
 
- }
- /* Define to prevent recursive inclusion -------------------------------------*/
 
- #ifndef __ST7789_H
 
- #define __ST7789_H
 
-  
 
- #ifdef __cplusplus
 
- extern "C" {
 
- #endif
 
-  
 
- /* includes ------------------------------------------------------------------*/
 
- #include "at32f435_437.h"
 
-  
 
- #include "systick.h"
 
-  
 
- /* micro and typedef ---------------------------------------------------------*/
 
-  
 
- #define USE_HORIZONTAL  0 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏
 
- #define CHIP_USE_ST7789 1 //设置芯片初始化 0为ILI9341  1为ST7789
 
-  
 
- #if USE_HORIZONTAL == 0 || USE_HORIZONTAL == 1
 
- #define LCD_W 240
 
- #define LCD_H 320
 
- #else
 
- #define LCD_W 320
 
- #define LCD_H 240
 
- #endif
 
-  
 
- //-----------------LCD端口定义----------------
 
-  
 
- /* 请按照以下逻辑修改宏定义:
 
-     1,使用硬件SPI?否则使用软件模拟时序。
 
-         若是,下一步;否则将配置为和触摸IC共用一个软件SPI。
 
-     2,判断触摸IC是否使用硬件SPI?
 
-         若是,下一步;否则LCD使用硬件SPI(本文件负责配置)而触摸IC使用软件SPI(不在本文件中配置)。
 
-     3,和触摸IC共用同一个SPI?否则使用两个硬件SPI。
 
-         若是,请指定SPIx,SPIx将设置成全双工模式,软件管理CS,触摸IC也使用此SPI,并下一步;
 
-         否则,请指定两个完全独立的SPI端口分别驱动LCD和触摸IC,硬件管理CS,下一步。
 
-     4,使用DMA?
 
-  
 
-  */
 
- #define LCD_USE_HARDWARE_SPI     1
 
- #define XPT2046_USE_HARDWARE_SPI 1
 
-  
 
- #if LCD_USE_HARDWARE_SPI == 1
 
- #include "at32f435_437_spi.h"
 
-  
 
- #if LCD_USE_HARDWARE_SPI == 1 && XPT2046_USE_HARDWARE_SPI == 1
 
- #define LCD_SHARE_SPI_WITH_TOUCH_IC 1 // 见 https://blog.csdn.net/m0_46882426/article/details/127568586?spm=1001.2014.3001.5501 ,共用SPI并软件管理CS是最优解,所以不要改动此宏
 
- #endif
 
-  
 
- #define LCD_HARDWARE_SPI_USE_DMA 1
 
- #define LCD_HARDWARE_SPI_TX_DMA_USE_INT 1
 
-  
 
- // SPI 通信速度选择
 
- #define LCD_SPI_USE_SPEED_LEVEL 1
 
-  
 
- // SPI 端口选择
 
- #if LCD_SHARE_SPI_WITH_TOUCH_IC == 1
 
- // 共用 LCD_SHARE_SPIx_NUM (该宏仅表示SPI序号),且使用软件管理CS
 
- #define LCD_SHARE_SPIx_NUM   2
 
- #define LCD_USE_SPIx_NUM     LCD_SHARE_SPIx_NUM
 
- #define XPT2046_USE_SPIx_NUM LCD_SHARE_SPIx_NUM
 
- #else
 
- // 使用独立的两个SPI,且使用硬件管理CS
 
- #define LCD_USE_SPIx_NUM     1
 
- #define XPT2046_USE_SPIx_NUM 2
 
- #endif
 
-  
 
- // 非SPI控制 GPIO定义
 
-  
 
- #define LCD_GPIOPORT     GPIOA
 
- #define LCD_GPIOPORT_CRM CRM_GPIOA_PERIPH_CLOCK
 
-  
 
- #define LCD_PINS_RST     GPIO_PINS_0
 
- #define LCD_PINS_DC      GPIO_PINS_1
 
- #define LCD_PINS_BLK     GPIO_PINS_8
 
- #define LCD_PINS_CS      GPIO_PINS_4
 
-  
 
- // DMA 控制器定义
 
- #if LCD_HARDWARE_SPI_USE_DMA == 1
 
- #include "at32f435_437_dma.h"
 
- #define LCD_SPI_TX_DMAx                DMA2
 
- #define LCD_SPI_TX_DMAx_CRM_CLOCK      CRM_DMA2_PERIPH_CLOCK
 
- #define LCD_SPI_TX_DMAx_CHy            DMA2_CHANNEL1
 
- #define LCD_SPI_TX_DMAxMUX_CHy         DMA2MUX_CHANNEL1
 
- #define LCD_SPI_TX_DMAMUX_REQ_ID       DMAMUX_DMAREQ_ID_SPI2_TX
 
- #define LCD_SPI_TX_DMAx_CHy_IRQn       DMA2_Channel1_IRQn
 
- #define LCD_SPI_TX_DMAx_CHy_IRQHandler DMA2_Channel1_IRQHandler
 
- #define LCD_SPI_TX_DMAx_FDTy_FLAG      DMA2_FDT1_FLAG
 
-  
 
- #define LCD_SPI_RX_DMAx_CHy            DMA2_CHANNEL2
 
- #define LCD_SPI_RX_DMAxMUX_CHy         DMA2MUX_CHANNEL2
 
- #define LCD_SPI_RX_DMAMUX_REQ_ID       DMAMUX_DMAREQ_ID_SPI2_RX
 
- #define LCD_SPI_RX_DMAx_CHy_IRQn       DMA2_Channel2_IRQn
 
- #define LCD_SPI_RX_DMAx_CHy_IRQHandler DMA2_Channel2_IRQHandler
 
- #define LCD_SPI_RX_DMAx_FDTy_FLAG      DMA2_FDT2_FLAG
 
-  
 
- // 定义 SPI 数据发送缓冲区长度。LCD_SPI_TX_DMAx_CHy 负责将该缓冲区内的数据搬运至 LCD_SPIx
 
- #define LCD_SPI_TX_BUFFER_SIZE 65535 // 设置宽度为半字后,DMA一次最多连续搬运65545个半字
 
- #define LCD_SPI_RX_BUFFER_SIZE 1024/2
 
- #endif
 
-  
 
- // SPI 控制端口自动定义
 
- #if LCD_USE_SPIx_NUM == 1 // DO NOT MODIFY!
 
-  
 
- #define LCD_SPIx SPI1
 
- // SPI1 位于 GPIOA 的 MUX5
 
- #define LCD_SPIx_CRM            CRM_SPI1_PERIPH_CLOCK
 
-  
 
- #define LCD_SPIx_GPIO           GPIOA
 
- #define LCD_SPIx_GPIO_CRM       CRM_GPIOA_PERIPH_CLOCK
 
- #define LCD_SPIx_MUX_SEL        GPIO_MUX_5
 
-  
 
- #define LCD_SPIx_CS_GPIO_PIN    GPIO_PINS_4
 
- #define LCD_SPIx_SCLK_GPIO_PIN  GPIO_PINS_5
 
- #define LCD_SPIx_MISO_GPIO_PIN  GPIO_PINS_6
 
- #define LCD_SPIx_MOSI_GPIO_PIN  GPIO_PINS_7
 
-  
 
- #define LCD_SPIx_CS_SOURCE      GPIO_PINS_SOURCE4
 
- #define LCD_SPIx_SCLK_SOURCE    GPIO_PINS_SOURCE5
 
- #define LCD_SPIx_MISO_SOURCE    GPIO_PINS_SOURCE6
 
- #define LCD_SPIx_MOSI_SOURCE    GPIO_PINS_SOURCE7
 
-  
 
- #define LCD_SPIx_EXT_IQRn       SPI1_IRQn
 
- #define LCD_SPIx_EXT_IQRHandler SPI1_IRQHandler
 
-  
 
- #elif LCD_USE_SPIx_NUM == 2 // DO NOT MODIFY!
 
-  
 
- #define LCD_SPIx               SPI2
 
- // SPI2 位于 GPIOA 的 MUX5
 
- #define LCD_SPIx_CRM           CRM_SPI2_PERIPH_CLOCK
 
-  
 
- #define LCD_SPIx_GPIO          GPIOA
 
- #define LCD_SPIx_GPIO_CRM      CRM_GPIOA_PERIPH_CLOCK
 
- #define LCD_SPIx_MUX_SEL       GPIO_MUX_5
 
-  
 
- #define LCD_SPIx_SCLK_GPIO_PIN GPIO_PINS_9
 
- #define LCD_SPIx_MOSI_GPIO_PIN GPIO_PINS_10
 
- #define LCD_SPIx_CS_GPIO_PIN   GPIO_PINS_11
 
- #define LCD_SPIx_MISO_GPIO_PIN GPIO_PINS_12
 
-  
 
- #define LCD_SPIx_SCLK_SOURCE   GPIO_PINS_SOURCE9
 
- #define LCD_SPIx_MOSI_SOURCE   GPIO_PINS_SOURCE10
 
- #define LCD_SPIx_CS_SOURCE     GPIO_PINS_SOURCE11
 
- #define LCD_SPIx_MISO_SOURCE   GPIO_PINS_SOURCE12
 
-  
 
- #define LCD_SPIx_EXT_IQRn      SPI2_I2S2EXT_IRQn
 
- #else
 
- #error the specified SPI (Macro "LCD_SPIx") is unknown!
 
- #endif
 
-  
 
- #if LCD_SHARE_SPI_WITH_TOUCH_IC == 1
 
- #define XPT2046_SPIx LCD_SPIx
 
- #endif
 
-  
 
- #else
 
-  
 
- #define LCD_GPIOPORT     GPIOA
 
- #define LCD_GPIOPORT_CRM CRM_GPIOA_PERIPH_CLOCK
 
-  
 
- #define LCD_PINS_SCLK    GPIO_PINS_5
 
- #define LCD_PINS_MOSI    GPIO_PINS_7
 
- #define LCD_PINS_RST     GPIO_PINS_0
 
- #define LCD_PINS_DC      GPIO_PINS_1
 
- #define LCD_PINS_BLK     GPIO_PINS_8
 
- #define LCD_PINS_CS      GPIO_PINS_4
 
-  
 
- #define LCD_SCLK_CLR()   gpio_bits_reset(LCD_GPIOPORT, LCD_PINS_SCLK)
 
- #define LCD_MOSI_CLR()   gpio_bits_reset(LCD_GPIOPORT, LCD_PINS_MOSI)
 
- #define LCD_CS_CLR()     gpio_bits_reset(LCD_GPIOPORT, LCD_PINS_CS)
 
-  
 
- #define LCD_SCLK_SET()   gpio_bits_set(LCD_GPIOPORT, LCD_PINS_SCLK)
 
- #define LCD_MOSI_SET()   gpio_bits_set(LCD_GPIOPORT, LCD_PINS_MOSI)
 
- #define LCD_CS_SET()     gpio_bits_set(LCD_GPIOPORT, LCD_PINS_CS)
 
-  
 
- #endif
 
-  
 
- #define LCD_RES_CLR() gpio_bits_reset(LCD_GPIOPORT, LCD_PINS_RST)
 
- #define LCD_DC_CLR()  gpio_bits_reset(LCD_GPIOPORT, LCD_PINS_DC)
 
- #define LCD_BLK_CLR() gpio_bits_reset(LCD_GPIOPORT, LCD_PINS_BLK)
 
-  
 
- #define LCD_RES_SET() gpio_bits_set(LCD_GPIOPORT, LCD_PINS_RST)
 
- #define LCD_DC_SET()  gpio_bits_set(LCD_GPIOPORT, LCD_PINS_DC)
 
- #define LCD_BLK_SET() gpio_bits_set(LCD_GPIOPORT, LCD_PINS_BLK)
 
-  
 
- #if LCD_SHARE_SPI_WITH_TOUCH_IC == 1
 
- #define LCD_CS_CLR() gpio_bits_reset(LCD_GPIOPORT, LCD_PINS_CS)
 
- #define LCD_CS_SET() gpio_bits_set(LCD_GPIOPORT, LCD_PINS_CS)
 
- #else
 
- // LCD_SPIx 的硬件管理CS将在 ST7789.c 中配置
 
- // XPT2046_SPIx 的硬件管理CS将在 XPT2046.c 中配置
 
- #endif
 
-  
 
- #if LCD_SPI_USE_SPEED_LEVEL == 1
 
- #define LCD_SPI_SPEED SPI_MCLK_DIV_8 // 288M / 8 = 36M
 
- #elif LCD_SPI_USE_SPEED_LEVEL == 2
 
- #define LCD_SPI_SPEED SPI_MCLK_DIV_16 // 288M / 16 = 18M
 
- #elif LCD_SPI_USE_SPEED_LEVEL == 3
 
- #define LCD_SPI_SPEED SPI_MCLK_DIV_32 // 288M / 32 = 9M
 
- #endif
 
-  
 
- /* function ------------------------------------------------------------------*/
 
-  
 
- void LCD_GPIO_init(void); // GPIO初始化
 
- void LCD_SPIx_init(void); // SPI初始化
 
- #if (LCD_HARDWARE_SPI_USE_DMA == 1)
 
- void LCD_SPI_data_send_use_DMA(const void *buf, uint32_t size);
 
- #endif
 
- void LCD_write_half(uint16_t data);                                    
 
- void LCD_addr_set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); 
 
- void LCD_init(void);                                                   
 
- void LCD_fill_color(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
 
-  
 
- #ifdef __cplusplus
 
- }
 
- #endif
 
-  
 
- #endif
- /**
 
-  * [url=home.php?mod=space&uid=288409]@file[/url] lv_port_disp_templ.c
 
-  *
 
-  */
 
- /*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
 
- #if 1
 
-  
 
- /*********************
 
-  *      INCLUDES
 
-  *********************/
 
- #include "lv_port_disp.h"
 
- #include <stdbool.h>
 
- #include "LCD/ST7789.h"
 
-  
 
- /*********************
 
-  *      DEFINES
 
-  *********************/
 
- #ifndef MY_DISP_HOR_RES
 
-     #define MY_DISP_HOR_RES    240
 
- #endif
 
-  
 
- #ifndef MY_DISP_VER_RES
 
-     #define MY_DISP_VER_RES    320
 
- #endif
 
-  
 
- /*-----------------------------
 
- * Create a buffer for drawing
 
- *----------------------------*/
 
-     /**
 
-      * LVGL requires a buffer where it internally draws the widgets.
 
-      * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
 
-      * The buffer has to be greater than 1 display row
 
-      *
 
-      * There are 3 buffering configurations:
 
-      * 1. Create ONE buffer:
 
-      *      LVGL will draw the display's content here and writes it to your display
 
-      *
 
-      * 2. Create TWO buffer:
 
-      *      LVGL will draw the display's content to a buffer and writes it your display.
 
-      *      You should use DMA to write the buffer's content to the display.
 
-      *      It will enable LVGL to draw the next part of the screen to the other buffer while
 
-      *      the data is being sent form the first buffer. It makes rendering and flushing parallel.
 
-      *
 
-      * 3. Double buffering
 
-      *      Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
 
-      *      This way LVGL will always provide the whole rendered screen in `flush_cb`
 
-      *      and you only need to change the frame buffer's address.
 
-      */
 
- #define BUFFER_METHOD 2
 
-  
 
-  
 
-  
 
- /**********************
 
-  *      TYPEDEFS
 
-  **********************/
 
- /**********************
 
-  *  STATIC PROTOTYPES
 
-  **********************/
 
- static void disp_init(void);
 
-  
 
- static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
 
- //static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
 
- //        const lv_area_t * fill_area, lv_color_t color);
 
-  
 
- /**********************
 
-  *  STATIC VARIABLES
 
-  **********************/
 
- /**********************
 
-  *      MACROS
 
-  **********************/
 
- /**********************
 
-  *   GLOBAL FUNCTIONS
 
-  **********************/
 
- void lv_port_disp_init(void)
 
- {
 
-     /*-------------------------
 
-      * Initialize your display
 
-      * -----------------------*/
 
-     disp_init();
 
-  
 
-     /*-----------------------------
 
-      * Create a buffer for drawing
 
-      *----------------------------*/
 
-     #if (BUFFER_METHOD == 1)
 
-     /* Example for 1) */
 
-     static lv_disp_draw_buf_t draw_buf_dsc_1;
 
-     static lv_color_t buf_1[MY_DISP_HOR_RES * 10];                          /*A buffer for 10 rows*/
 
-     lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10);   /*Initialize the display buffer*/
 
-     #elif (BUFFER_METHOD == 2)
 
-     /* Example for 2) */
 
-     static lv_disp_draw_buf_t draw_buf_dsc_2;
 
-     static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10];                        /*A buffer for 10 rows*/
 
-     static lv_color_t buf_2_2[MY_DISP_HOR_RES * 10];                        /*An other buffer for 10 rows*/
 
-     lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10);   /*Initialize the display buffer*/
 
-     #elif (BUFFER_METHOD == 3)
 
-     /* Example for 3) also set disp_drv.full_refresh = 1 below*/
 
-     static lv_disp_draw_buf_t draw_buf_dsc_3;
 
-     static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*A screen sized buffer*/
 
-     static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*Another screen sized buffer*/
 
-     lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2,
 
-                           MY_DISP_VER_RES * MY_DISP_HOR_RES);   /*Initialize the display buffer*/
 
-     #else
 
-         #error "the specified macro 'BUFFER_METHOD' is unknown!"
 
-     #endif
 
-  
 
-  
 
-     /*-----------------------------------
 
-      * Register the display in LVGL
 
-      *----------------------------------*/
 
-     static lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
 
-     lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/
 
-  
 
-     /*Set up the functions to access to your display*/
 
-  
 
-     /*Set the resolution of the display*/
 
-     disp_drv.hor_res = MY_DISP_HOR_RES;
 
-     disp_drv.ver_res = MY_DISP_VER_RES;
 
-  
 
-     /*Used to copy the buffer's content to the display*/
 
-     disp_drv.flush_cb = disp_flush;
 
-     /*Set a display buffer*/
 
-     #if (BUFFER_METHOD == 1)
 
-     disp_drv.draw_buf = &draw_buf_dsc_1;
 
-     #elif (BUFFER_METHOD == 2)
 
-     disp_drv.draw_buf = &draw_buf_dsc_2;
 
-     #else
 
-     disp_drv.draw_buf = &draw_buf_dsc_3;
 
-     #endif
 
-     #if (BUFFER_METHOD == 3)
 
-     /*Required for Example 3)*/
 
-     disp_drv.full_refresh = 1;
 
-     #endif
 
-     /* Fill a memory array with a color if you have GPU.
 
-      * Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.
 
-      * But if you have a different GPU you can use with this callback.*/
 
-     //disp_drv.gpu_fill_cb = gpu_fill;
 
-     /*Finally register the driver*/
 
-     lv_disp_drv_register(&disp_drv);
 
- }
 
- /**********************
 
-  *   STATIC FUNCTIONS
 
-  **********************/
 
- /*Initialize your display and the required peripherals.*/
 
- static void disp_init(void)
 
- {
 
-     LCD_GPIO_init();
 
-     #if LCD_USE_HARDWARE_SPI == 1
 
-     LCD_SPIx_init();
 
-     #endif
 
-     // 注意在此之前确保已经初始化 GPIO 和 SPI
 
-     LCD_init();
 
- }
 
- volatile bool disp_flush_enabled = true;
 
- /* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL
 
-  */
 
- void disp_enable_update(void)
 
- {
 
-     disp_flush_enabled = true;
 
- }
 
- /* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL
 
-  */
 
- void disp_disable_update(void)
 
- {
 
-     disp_flush_enabled = false;
 
- }
 
- /*Flush the content of the internal buffer the specific area on the display
 
-  *You can use DMA or any hardware acceleration to do this operation in the background but
 
-  *'lv_disp_flush_ready()' has to be called when finished.*/
 
- static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
 
- {
 
-     if(disp_flush_enabled)
 
-     {
 
-         /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
 
-         // int32_t x;
 
-         // int32_t y;
 
-         // for(y = area->y1; y <= area->y2; y++) {
 
-         //     for(x = area->x1; x <= area->x2; x++) {
 
-         //         /*Put a pixel to the display. For example:*/
 
-         //         /*put_px(x, y, *color_p)*/
 
-         //         color_p++;
 
-         //     }
 
-         // }
 
-         // 如果采用写点函数来做,刷屏会很慢,所以推荐的方式如下:
 
-         uint16_t  x1, y1, x2, y2;
 
-         uint16_t total_half;
 
-         x1 = area->x1;
 
-         y1 = area->y1;
 
-         x2 = area->x2;
 
-         y2 = area->y2;
 
-         
 
-         total_half = (x2 - x1 + 1) * (y2 - y1 + 1);
 
-         LCD_addr_set(x1, y1, x2, y2);
 
-         // st7789_cfg_dcx_set();
 
-         // st7789_cfg_spi_write((uint8_t*)color_p, total_half );
 
-         LCD_SPI_data_send_use_DMA((uint16_t *) color_p, total_half);
 
-     }
 
-     /*IMPORTANT!!!
 
-      *Inform the graphics library that you are ready with the flushing*/
 
-     lv_disp_flush_ready(disp_drv);
 
- }
 
- /*OPTIONAL: GPU INTERFACE*/
 
- /*If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color*/
 
- //static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
 
- //                    const lv_area_t * fill_area, lv_color_t color)
 
- //{
 
- //    /*It's an example code which should be done by your GPU*/
 
- //    int32_t x, y;
 
- //    dest_buf += dest_width * fill_area->y1; /*Go to the first line*/
 
- //
 
- //    for(y = fill_area->y1; y <= fill_area->y2; y++) {
 
- //        for(x = fill_area->x1; x <= fill_area->x2; x++) {
 
- //            dest_buf[x] = color;
 
- //        }
 
- //        dest_buf+=dest_width;    /*Go to the next line*/
 
- //    }
 
- //}
 
-  
 
-  
 
- #else /*Enable this file at the top*/
 
-  
 
- /*This dummy typedef exists purely to silence -Wpedantic.*/
 
- typedef int keep_pedantic_happy;
 
- #endif
- #include "at32f435_437_clock.h"
 
-  
 
- #include "systick.h"
 
- #include "usart.h"
 
- #include "LCD/XPT2046.h"
 
-  
 
- #include "lvgl.h"
 
- #include "examples/porting/lv_port_disp.h"
 
- #include "examples/porting/lv_port_indev.h"
 
- #include "examples/lv_examples.h"
 
-  
 
- #define LVGL_TICK         1
 
-  
 
- static void lvgl_init( void ) 
 
- {
 
-     lv_init();
 
-     lv_port_disp_init();        // 显示器初始化
 
-     lv_port_indev_init();       // 输入设备初始化
 
-     // lv_port_fs_init();          // 文件系统设备初始化
 
- }
 
-  
 
-  
 
- /**
 
-  * @brief  main function.
 
-  * @param  none
 
-  * @retval none
 
-  */
 
- int main()
 
- {
 
-  
 
-     system_clock_config();
 
-     delay_init();
 
-  
 
-         // LED init
 
-     gpio_init_type gpio_init_struct;
 
-     crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
 
-     gpio_default_para_init(&gpio_init_struct);
 
-     gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
 
-     gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
 
-     gpio_init_struct.gpio_mode           = GPIO_MODE_OUTPUT;
 
-     gpio_init_struct.gpio_pins           = GPIO_PINS_2;
 
-     gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;
 
-     gpio_init(GPIOD, &gpio_init_struct);
 
-  
 
-         // //USART init
 
-     uart_print_init(115200);
 
-  
 
-     printf("UART initialized successfully!\r\n");
 
-         // =============================> LCD app <=============================    
 
-         lvgl_init();
 
-  
 
-     lv_example_obj_2();
 
-  
 
-         while(1) {
 
-                 // 先调用 lv_tick_inc 再调用 lv_timer_handler
 
-                 lv_tick_inc(LVGL_TICK);
 
-                 lv_timer_handler();
 
-                 delay_ms(LVGL_TICK);
 
-         GPIOD->odt ^= GPIO_PINS_2;
 
-         }
 
- }
 
-  
 
-