3线硬件SPI+DMA驱动 HX8347 TFT屏

3线硬件SPI+DMA驱动 HX8347 TFT屏,实现用DMA清屏。

a81c5161c51b4678bbb7adaeaebc35ee.jpg

参考:基于stm32 标准库spi驱动st7789彩屏TFT(使用DMA)-技术天地-深圳市修德电子有限公司

一、源码

HX8347.h

#ifndef USER_HX8347_H_
#define USER_HX8347_H_

#define SPI_hardware
#define SPI_hardware_dma

#define Buf_Size 480

#define X_MAX_PIXEL 240
#define Y_MAX_PIXEL 320

#define RED     0xf800
#define GREEN   0x07e0
#define BLUE    0x001f
#define WHITE   0xffff
#define BLACK   0x0000
#define YELLOW  0xFFE0
#define GRAY0   0xEF7D      //灰色0 3165 00110 001011 00101
#define GRAY1   0x8410          //灰色1      00000 000000 00000
#define GRAY2   0x4208          //灰色2  1111111111011111

#ifdef SPI_hardware
    #define LCD_CS          GPIO_Pin_0  // CS:PA0
    #define LCD_SDA         GPIO_Pin_7  // SDA:PA7  SPI1 //硬件SPI实现,不用人工处理
    #define LCD_SCL         GPIO_Pin_5  // SCL:PA5  SPI1 //硬件SPI实现,不用人工处理
    #define LCD_RST         GPIO_Pin_4  // RST:PA4
#else
    #define LCD_CS          GPIO_Pin_0  // CS:PA0
    #define LCD_SDA         GPIO_Pin_1  // SDA:PA1
    #define LCD_SCL         GPIO_Pin_3  // SCL:PA3
    #define LCD_RST         GPIO_Pin_4  // RST:PA4
#endif

#define LCD_SCL_SET GPIO_WriteBit(GPIOA, LCD_SCL,Bit_SET)
#define LCD_SDA_SET GPIO_WriteBit(GPIOA, LCD_SDA,Bit_SET)
#define LCD_CS_SET  GPIO_WriteBit(GPIOA, LCD_CS,Bit_SET)
#define LCD_RST_SET GPIO_WriteBit(GPIOA, LCD_RST,Bit_SET)


#define LCD_SCL_CLR GPIO_WriteBit(GPIOA, LCD_SCL,Bit_RESET)
#define LCD_SDA_CLR GPIO_WriteBit(GPIOA, LCD_SDA,Bit_RESET)
#define LCD_CS_CLR  GPIO_WriteBit(GPIOA, LCD_CS,Bit_RESET)
#define LCD_RST_CLR GPIO_WriteBit(GPIOA, LCD_RST,Bit_RESET)


void LCD_GPIO_Init(void);
void Lcd_WriteIndex(unsigned char Index);
void Lcd_WriteData(unsigned char Data);
void LCD_WriteData_16Bit(unsigned int Data);
void Lcd_Write_REG(unsigned char Index,unsigned char Data);
void LCD_Init(void);
void Lcd_Clear(unsigned int Color);
void FillRect(u16 x1, u16 y1, u16 x2, u16 y2, u16 color);
void FillRect_DMA(u16 color);

void Gui_DrawFont_GBK16(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc, unsigned char *s);

#endif /* USER_HX8347_H_ */

HX8347.c

#include "debug.h"
#include "HX8347.h"
#include "font.h"


extern unsigned char TxData[];
extern void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);

void LCD_GPIO_Init(void)
{
   GPIO_InitTypeDef GPIO_InitStructure = {0};

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
#ifdef SPI_hardware
   GPIO_InitStructure.GPIO_Pin = LCD_CS|LCD_RST;
#else
   GPIO_InitStructure.GPIO_Pin = LCD_SCL|LCD_SDA|LCD_CS|LCD_RST;
#endif
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
}


//向SPI总线传输一个8位数据

void  SPI_WriteData(unsigned char Data)
{
#ifdef SPI_hardware

     SPI_I2S_SendData( SPI1, Data);
     while( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) == RESET );
     //Delay_Us(1);

     uint32_t i;

     SysTick->SR &= ~(1 << 0);
     i = 8;

     SysTick->CMP = i;
     SysTick->CTLR |= (1 << 4);
     SysTick->CTLR |= (1 << 5) | (1 << 0);

     while((SysTick->SR & (1 << 0)) != (1 << 0))
         ;
     SysTick->CTLR &= ~(1 << 0);

#else
    unsigned char i=0;
    for(i=8;i>0;i--)
    {
      if(Data&0x80)
          LCD_SDA_SET; //输出数据
      else LCD_SDA_CLR;

      LCD_SCL_CLR;
      LCD_SCL_SET;
      Data<<=1;
    }
#endif
}

//向液晶屏写一个8位指令

void Lcd_WriteIndex(unsigned char Index)
{
   //SPI 写命令时序开始
   LCD_CS_CLR;
   SPI_WriteData(0x70);
   SPI_WriteData(Index);

   LCD_CS_SET;
}



//向液晶屏写一个8位数据

void Lcd_WriteData(unsigned char Data)
{
   LCD_CS_CLR;

   SPI_WriteData(0x72);
   SPI_WriteData(Data);

   LCD_CS_SET;
}


//向液晶屏写一个16位数据
void LCD_WriteData_16Bit(unsigned int Data)
{
   LCD_CS_CLR;
   SPI_WriteData(0x72);
   SPI_WriteData(Data>>8);
   SPI_WriteData(Data);
   LCD_CS_SET;
}

void Lcd_Write_REG(unsigned char Index,unsigned char Data)
{
    Lcd_WriteIndex(Index);
    Lcd_WriteData(Data);
}

void Lcd_Reset(void)
{
    LCD_RST_CLR;
    Delay_Ms(50);
    LCD_RST_SET;
    Delay_Ms(50);
}





//  set region to paint
void LCD_SetWindow(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{

    //SC
    Lcd_Write_REG(0x02,x1>>8);       // Column address start2
    Lcd_Write_REG(0x03,(u8)x1);          // Column address start1
    //EC
    Lcd_Write_REG(0x04,x2>>8);       // Column address end2
    Lcd_Write_REG(0x05,(u8)x2);          // Column address end1
    //SP
    Lcd_Write_REG(0x06,y1>>8);       // Row address start2
    Lcd_Write_REG(0x07,(u8)y1);          // Row address start1
    //EP
    Lcd_Write_REG(0x08,y2>>8);       // Row address end2
    Lcd_Write_REG(0x09,(u8)y2);          // Row address end1
    //写0x22到index register,那么下次send data就会直接被写到graphic ram
    Lcd_WriteIndex(0x22);
}



void FillRect(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
{
    LCD_SetWindow(x1, y1,x2,y2);
    x2 = x2 - x1 + 1;
    y2 = y2 - y1 + 1;

    LCD_CS_CLR;
    SPI_WriteData(0x72);

    for(x1 = x2; x1 != 0 ; x1--)
    {
        for (y1 = y2;y1 != 0 ;y1--)
        {
            SPI_WriteData(color>>8);
            SPI_WriteData(color);
        }
    }

    LCD_CS_SET;
}


void FillRect_DMA(u16 color)
{
    int16_t j;
    LCD_SetWindow(0, 0,239,319);

    LCD_CS_CLR;
    SPI_WriteData(0x72);

    for(j=0 ;j<480;){
        TxData[j] = color>>8;
        TxData[j+1] = color;
     j += 2;
    }

    for(j = 0 ; j<320 ; j++){
        SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);
        MYDMA_Enable(DMA1_Channel3);

        while(1){
            if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET)
            {
                DMA_ClearFlag(DMA1_FLAG_TC3);
                break;
            }
        }

    }
    LCD_CS_SET;
}


void LCD_Init(void)
{
    //LCD_GPIO_Init();
    Lcd_Reset();

    Lcd_Write_REG(0x18,0x88);        //UADJ 75Hz
    Lcd_Write_REG(0x19,0x01);        //OSC_EN='1', start Osc
    //Power Voltage Setting
    Lcd_Write_REG(0x1B,0x1e); //VRH=4.60V   0x1e
    Lcd_Write_REG(0x1C,0x04); //AP Crosstalk    04
    Lcd_Write_REG(0x1A,0x01); //BT (VGH~15V,VGL~-10V,DDVDH~5V)   0x01
    Lcd_Write_REG(0x24,0x21); //VMH 27   0x38
    Lcd_Write_REG(0x25,0x5F); //VML




    //VCOM offset
    Lcd_Write_REG(0x23,0x8C); //for Flicker adjust
    Lcd_Write_REG(0x1F,0x88);// GAS=1, VOMG=00, PON=0, DK=1, XDK=0, DVDH_TRI=0, STB=0
    Delay_Ms(50);
    Lcd_Write_REG(0x1F,0x80);// GAS=1, VOMG=00, PON=0, DK=0, XDK=0, DVDH_TRI=0, STB=0
    Delay_Ms(50);
    Lcd_Write_REG(0x1F,0x90);// GAS=1, VOMG=00, PON=1, DK=0, XDK=0, DVDH_TRI=0, STB=0
    Delay_Ms(50);
    Lcd_Write_REG(0x1F,0xD0);// GAS=1, VOMG=10, PON=1, DK=0, XDK=0, DDVDH_TRI=0, STB=0
    Delay_Ms(50);
    //Display ON Setting
    Lcd_Write_REG(0x28,0x38);   //GON=1, DTE=1, D=1000
    Delay_Ms(50);
    Lcd_Write_REG(0x28,0x3C);   //GON=1, DTE=1, D=1100
    Lcd_Write_REG(0x36,0x09);   //REV, BGR
    Lcd_Write_REG(0x17,0x05);  //16BIT/PIXEL


    //Gamma 2.2 Setting
    Lcd_Write_REG(0x40,0x00); //
    Lcd_Write_REG(0x41,0x00); //
    Lcd_Write_REG(0x42,0x00); //
    Lcd_Write_REG(0x43,0x11); //
    Lcd_Write_REG(0x44,0x0e); //
    Lcd_Write_REG(0x45,0x23); //
    Lcd_Write_REG(0x46,0x08); //
    Lcd_Write_REG(0x47,0x53); //
    Lcd_Write_REG(0x48,0x03); //
    Lcd_Write_REG(0x49,0x11); //
    Lcd_Write_REG(0x4A,0x18); //
    Lcd_Write_REG(0x4B,0x1a); //
    Lcd_Write_REG(0x4C,0x16); //
    Lcd_Write_REG(0x50,0x1c); //
    Lcd_Write_REG(0x51,0x31); //
    Lcd_Write_REG(0x52,0x2e); //
    Lcd_Write_REG(0x53,0x3f); //
    Lcd_Write_REG(0x54,0x3f); //
    Lcd_Write_REG(0x55,0x3f); //
    Lcd_Write_REG(0x56,0x2c); //
    Lcd_Write_REG(0x57,0x77); //
    Lcd_Write_REG(0x58,0x09); //
    Lcd_Write_REG(0x59,0x05); //
    Lcd_Write_REG(0x5A,0x07); //
    Lcd_Write_REG(0x5B,0x0e); //
    Lcd_Write_REG(0x5C,0x1c); //
    Lcd_Write_REG(0x5D,0x88); //


     Delay_Ms(100);
     FillRect(0, 0, 239, 319, RED );
}


/*************************************************
函数名:LCD_DrawPoint
功能:画一个点
入口参数:无
返回值:无
*************************************************/
void Gui_DrawPoint(unsigned int x,unsigned int y,unsigned int Data)
{
    LCD_SetWindow(x,y,x+1,y+1);
    LCD_WriteData_16Bit(Data);
}


void Gui_DrawFont_GBK16(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s)
{
    unsigned char i,j;
    unsigned short k,x0;
    x0=x;
    while(*s)
    {

        if((*s) < 128)
        {
            k=*s;
            if (k==13)
            {
                x=x0;
                y+=16;
            }
            else
            {
                if (k>32) k-=32; else k=0;

                for(i=0;i<16;i++)
                for(j=0;j<8;j++)
                    {
                        if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
                        else
                        {
                            if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                        }
                    }
                x+=8;
            }
            s++;
        }

        else
        {


            for (k=0;k<hz16_num;k++)
            {
              if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1)))
              {

                    for(i=0;i<16;i++)
                    {
                        for(j=0;j<8;j++)
                            {
                                if(hz16[k].Msk[i*2]&(0x80>>j))  Gui_DrawPoint(x+j,y+i,fc);
                                else {
                                    if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                                }
                            }
                        for(j=0;j<8;j++)
                            {
                                if(hz16[k].Msk[i*2+1]&(0x80>>j))    Gui_DrawPoint(x+j+8,y+i,fc);
                                else
                                {
                                    if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);
                                }
                            }
                    }
                }
              }
            s+=2;x+=16;
        }

    }
}

main.c

/********************************** (C) COPYRIGHT *******************************
* File Name          : main.c
* Author             : WCH
* Version            : V1.0.0
* Date               : 2021/06/06
* Description        : Main program body.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for 
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/

/*
 *@Note
 GPIO routine:
 PA0 push-pull output.

*/

#include "debug.h"
#include "HX8347.h"

/* Global define */


/* Global Variable */

unsigned char TxData[Buf_Size]={0};
u16 DMA1_MEM_LEN;

/*********************************************************************
 * @fn      GPIO_Toggle_INIT
 *
 * @brief   Initializes GPIOA.0
 *
 * @return  none
 */
void GPIO_Toggle_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}


void SPI_1Lines_HalfDuplex_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure={0};
    SPI_InitTypeDef SPI_InitStructure={0};


    RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1|RCC_APB2Periph_GPIOA, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;         //在空闲状态下,时钟线保持高电平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;        //数据在时钟的上升沿被传输。
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init( SPI1, &SPI_InitStructure );

    SPI_Cmd( SPI1, ENABLE );
}


//使能dma1的通道3,因为spi输出对应的是此通道
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
  DMA_Cmd(DMA_CHx, DISABLE );
  DMA_SetCurrDataCounter(DMA1_Channel3,DMA1_MEM_LEN);
  DMA_Cmd(DMA_CHx, ENABLE);
}

/*********************************************************************
 * @fn      DMA_Tx_Init
 *
 * @brief   Initializes the DMAy Channelx configuration.
 *
 * @param   DMA_CHx - x can be 1 to 7.
 *          ppadr - Peripheral base address.
 *          memadr - Memory base address.
 *          bufsize - DMA channel buffer size.
 *
 * @return  none
 */
void DMA_Tx_Init( DMA_Channel_TypeDef* DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize)
{
    DMA_InitTypeDef DMA_InitStructure={0};

    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );

    DMA_DeInit(DMA_CHx);
    DMA1_MEM_LEN=bufsize;

    DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
    DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = bufsize;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init( DMA_CHx, &DMA_InitStructure );
}

/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main(void)
{
    u8 i = 0;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);	
    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );

    printf("GPIO Toggle TEST\r\n");
    GPIO_Toggle_INIT();

    LCD_GPIO_Init();
#ifdef SPI_hardware
    printf("SPI_HARDWARE");
    SPI_1Lines_HalfDuplex_Init();
#ifdef SPI_hardware_dma
    printf("SPI_HARDWARE_DMA");
    DMA_Tx_Init( DMA1_Channel3, (u32)&SPI1->DATAR, (u32)TxData, Buf_Size );
    DMA_Cmd( DMA1_Channel3, ENABLE );
#endif
#else
    printf("SPI_SOFTWARE");
#endif
    LCD_Init();


    GPIO_WriteBit(GPIOB, GPIO_Pin_13,Bit_RESET);



    while(1)
    {
        //下面用的是SPI+DMA

        Delay_Ms(1000);
        FillRect_DMA(GREEN);
        Delay_Ms(1000);
        FillRect_DMA(GREEN);
        Delay_Ms(1000);
        FillRect_DMA(BLUE);
        Delay_Ms(1000);
        FillRect_DMA(YELLOW);
        Delay_Ms(1000);
        FillRect(0, 0, 239, 63, RED );

        //下面用的硬件SPI

        Gui_DrawFont_GBK16(15,5,BLACK,GRAY0,"HELLO world");
        Gui_DrawFont_GBK16(15,25,RED,GRAY0,"LCD OK DISPLAY");
        Gui_DrawFont_GBK16(15,45,RED,GRAY0,"智能物联红外测温系统通过人数");
        Gui_DrawFont_GBK16(15,65,RED,GRAY0,"报警人数人体温度环境表面距离");
        Gui_DrawFont_GBK16(15,85,RED,GRAY0,"网络连接中.温度气象站雨量风速");
        Gui_DrawFont_GBK16(15,105,RED,GRAY0,"创新实验平台℃");

        Delay_Ms(1000);
        GPIO_WriteBit(GPIOB, GPIO_Pin_13, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
        printf( "GPIOB:%d\r\n", i);


        FillRect(0, 0, 239, 319, RED );
        Delay_Ms(1000);
        FillRect(0, 0, 239, 319, GREEN );
        Delay_Ms(1000);
        FillRect(0, 0, 239, 319, BLUE );
        FillRect(50, 50, 100, 100, RED );




    }
}

二、说明

1、DMA初始化:

void DMA_Tx_Init( DMA_Channel_TypeDef* DMA_CHx, u32 ppadr, u32 memadr, u16 bufsize)
{
    DMA_InitTypeDef DMA_InitStructure={0};

    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );

    DMA_DeInit(DMA_CHx);
    DMA1_MEM_LEN=bufsize;

    DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
    DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = bufsize;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init( DMA_CHx, &DMA_InitStructure );
}

2、用DMA主要是清屏:

void FillRect_DMA(u16 color)
{
    int16_t j;
    LCD_SetWindow(0, 0,239,319);

    LCD_CS_CLR;
    SPI_WriteData(0x72);

    for(j=0 ;j<480;){
        TxData[j] = color>>8;
        TxData[j+1] = color;
     j += 2;
    }

    for(j = 0 ; j<320 ; j++){
        SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,ENABLE);
        MYDMA_Enable(DMA1_Channel3);                //传输

        while(1){
            if(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=RESET)
            {
                DMA_ClearFlag(DMA1_FLAG_TC3);
                break;
            }
        }

    }
    LCD_CS_SET;
}
 

 

为了使用DMA申请了一个480字节的空间,就是屏幕上一行所需空间(240*2):

unsigned char TxData[Buf_Size]={0}; 

清屏过程就是每次DMA发送480个字节清一行,然后循环320次清掉整个屏幕。

如果改变 TxData的值,可以向屏幕发送一些字符、图画什么的。需要写一个改变TxData内容的函数。

3、可以考虑为DMA申请更大的内存空间,那样就可以一次传更多的数据。但是240*320*2=153600=150KB空间,一般单片机没有这么大的SRAM,怎么都需要分屏传输。

SPI+DMA

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/127283.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于表面电势的AlGaN/GaN MODFET紧凑模型

标题&#xff1a;A Surface-Potential-Based Compact Model for AlGaN/GaN MODFETs 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;11年&#xff09; 摘要 - 本文首次构建了基于表面势&#xff08;SP&#xff09;的AlGaN/GaN调制掺杂场效应晶体管&#…

说说地址栏输入 URL 敲下回车后发生了什么?

面试官&#xff1a;说说地址栏输入 URL 敲下回车后发生了什么? 一、简单分析 简单的分析&#xff0c;从输入 URL到回车后发生的行为如下&#xff1a; URL解析DNS 查询TCP 连接HTTP 请求响应请求页面渲染 二、详细分析 URL解析 首先判断你输入的是一个合法的 URL 还是一个…

C++初阶(九)内存管理

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、C/C内存分布1、选择题2、填空题3、sizeof 和 strlen 区别&#xff1f;4、总结 二、 C语言…

19.8 Boost Asio 异或加密传输

异或加密是一种对称加密算法&#xff0c;通常用于加密二进制数据。异或操作的本质是对两个二进制数字进行比较&#xff0c;如果它们相同则返回0&#xff0c;如果不同则返回1。异或加密使用一把密钥将明文与密文进行异或运算&#xff0c;从而产生密文。同时&#xff0c;使用相同…

数字马力笔试面试复盘

笔试——10月9日19&#xff1a;00 单选&#xff1a;30题 16.如何获取AJAX 请求的响应状态码? A通过AJAX对象的 statusCode 属性获取 B通过AJAX对象的responseText 属性获取C通过AJAX对象的status 属性获取 D通过AJAX对象的responseCode属性获取 答案&#xff1a;可以通过AJAX…

Python学习笔记--枚举类的使用

一、枚举类的使用 实际开发中&#xff0c;我们离不开定义常量&#xff0c;当我们需要定义常量时&#xff0c;其中一个办法是用大写变量通过整数来定义&#xff0c;例如月份&#xff1a; JAN 1 FEB 2 MAR 3 ... NOV 11 DEC 12当然这样做简单快捷&#xff0c;缺点是类型是…

paddleOcr训练一个属于自己的模型

自己配置开发环境的时候踩了不少坑&#xff0c;现在记录下来&#xff0c;以后需要了可以直接找到现成的代码&#xff0c;也希望能够帮到有需要的小伙伴 目录 &#xff08;一&#xff09;、运行环境搭建1、Anaconda部分Anaconda安装Anaconda创建虚拟环境指令Anaconda Prompt工作…

xilinx primitives(原语)

Xilinx的原语分为10类&#xff0c;包括&#xff1a;计算组件&#xff0c;IO端口组件&#xff0c;寄存器/锁存器&#xff0c;时钟组件&#xff0c;处理器组件&#xff0c;移位寄存器&#xff0c;配置和检测组件&#xff0c;RAM/ROM组件&#xff0c;Slice/CLB组件&#xff0c;G-t…

微信号绑定50个开发者小程序以后超额如何删除不用的

我们在开发微信小程序的时候&#xff0c;当前开发者工具登录的必须是该小程序的开发者才能进行小程序的开发&#xff0c;添加开发者的步骤是&#xff1a; 添加开发者 1、进入微信开放平台&#xff0c;然后扫码进入管理平台 2、找到下图所示位置 3:、输入要添加的微信账号&am…

工商银行卡安全码怎么看

工商银行的安全码&#xff0c;作为一项至关重要的安全措施&#xff0c;旨在保护用户的银行账户和交易安全。为了查看工商银行的安全码用户需要按照以下步骤操作&#xff1a; 首先&#xff0c;用户需要使用电脑或手机访问工商银行的网上银行平台。在平台首页&#xff0c;用户需要…

Git 入门使用

一、Git 入门 1.1 Git简介 Git是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。Git是由Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。 Git是目前世界上最先进的分布式版本控制系统&#xff0c;没有之一&a…

千城千站系统源码+SEO关键词推广优化 万能通用版 带完整的搭建教程

大家好啊&#xff0c;源码小编来给大家分享一款超级好用的千城千站系统源码。其实最近大家会发现做SEO排名做的最好的就是千城千站系统&#xff0c;排名好&#xff0c;流量高&#xff0c;其实这都是用千城千站系统做的。而这一套系统搭建起来十分简单&#xff0c;只要把里面的内…

LCD英文字模库(16x8)模拟测试程序

字模 字模&#xff0c;就是把文字符号转换为LCD能识别的像素点阵信息。 电子发烧友可能都熟悉字模的用途。就是调用者通过向LCD模块发送字模数据&#xff0c;LCD根据字模数据在LCD面板上相应的像素描绘出图形或文字。 现在&#xff0c;大部分的LCD都内置了字模库&#xff0c…

【脑源成像】术前癫痫的电源成像 评价:现状与未来展望

Electric source imaging for presurgical epilepsy evaluation: current status and future prospects 术前癫痫的电源成像 评价:现状与未来展望论文下载&#xff1a;算法程序下载&#xff1a;摘要1 项目介绍1.1. 选择要综述的文章2. 电源成像的基本原理4. ESI的实践方面4.1脑…

Nodejs沙箱绕过

目录 JavaScript和Nodejs介绍 沙箱&#xff08;sandbox&#xff09; 简单的介绍一下vm模块 下面介绍几种绕过方式 方法1&#xff1a;利用Function构造函数沙箱逃逸&#xff0c;执行命令 方法2&#xff1a;利用argument.callee.caller实现 方法3&#xff1a;利用ES6的 pro…

虚幻引擎 5.1 中全新的增强型输入操作系统

教程链接 https://www.youtube.com/watch?vCYiHNbAIp4s 前提 虚幻引擎5.1之后&#xff0c;项目设置里的input选项&#xff0c;默认会有一条警告&#xff0c;告知旧的input系统已经不能用了。 做法 在content文件夹下新建一个input按钮 input文件夹里面分成两部分内容 1.…

Java必考面试题,谈谈你对 Spring AOP 的理解

大家好&#xff0c;我是伍六七。 今天我们来学习 Spring 框架中最重要的概念之一&#xff1a;AOP。 这是一个 Java 程序员必考的面试题&#xff0c;大家好好理解。我们开始正文。 AOP 的概念 Spring AOP 是 Java 程序员们面试经常被问到的一个问题&#xff0c;但 AOP&#…

高等数学教材啃书汇总重难点(三)微分中值定理与导数的应用

本章节包含多个知识点&#xff0c;一些列微分中值定理是考研证明题的重头戏&#xff0c;而洛必达和泰勒展开则是方法论的天花板难度&#xff0c;虽然对于小题的考察难度较低&#xff0c;整体上仍需重点复习 首先是考研大纲包含的内容&#xff1a; 1.理解并会用罗尔(Rolle)定理、…

万字详解Java的三大特性:封装 | 继承 | 多态

前言&#xff1a;面向对象程序设计的三大特征就是&#xff1a;封装&#xff0c;继承&#xff0c;多态。在前文介绍了类和对象后&#xff0c;我们就可以继而学习什么是封装&#xff0c;怎么用类的子类来实现继承和多态 目录 一.面向对象的特性 1.封装性 2.继承性 3.多态性…

Find My行李箱|苹果Find My技术与行李箱结合,智能防丢,全球定位

行李箱&#xff0c;亦称旅行箱、拉杆箱。是出门时所携带用以放置物品的箱子&#xff0c;它是行李的其中一种类型。通常行李箱是用来放置旅途上所需要的衣物、个人护理用品、纪念品和贵重物品。旅游出差我们离不开行李箱&#xff0c;可是一旦行李箱丢失将造成很大不便&#xff0…