3线硬件SPI+DMA驱动 HX8347 TFT屏-快速显示文字

本文实现DMA快速显示文字

汉字点阵通常是16*16点阵,那么用DMA一次性显示汉字,应该至少申请480*16个字节的空间,用于显示一行文字,其中480是屏幕一行用DMA驱动所需内存。

一、 源码

HX8347.h

#ifndef USER_HX8347_H_
#define USER_HX8347_H_

#define SPI_hardware
#define SPI_hardware_dma

#define Buf_Size 480*16

#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);
void Gui_DrawFont_GBK16_DMA(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s);

#endif /* USER_HX8347_H_ */

HX8347.c

cpp 复制代码
#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<Buf_Size;){
        TxData[j] = color>>8;
        TxData[j+1] = color;
     j += 2;
    }

    for(j = 0 ; j<320/(Buf_Size/480) ; 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_DrawPoint_DMA(unsigned int x,unsigned int y,unsigned int Data)
{
    //LCD_SetWindow(x,y,x+1,y+1);
    //LCD_WriteData_16Bit(Data);

    TxData[2*x+y*480]=Data>>8;
    TxData[2*x+y*480+1]=Data;

}

void DMA_BUFFER_RESET(unsigned int bc)
{
    unsigned int j;
    for(j=0 ;j<Buf_Size;){
        TxData[j] = bc>>8;
        TxData[j+1] = bc;
     j += 2;
    }
}

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;
        }

    }
}


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

    DMA_BUFFER_RESET(bc);       //清缓存
    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_DMA(x+j,y+i,fc);
                        else
                        {
                            if (fc!=bc) Gui_DrawPoint_DMA(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_DMA(x+j,y+i,fc);
                                else {
                                    if (fc!=bc) Gui_DrawPoint_DMA(x+j,y+i,bc);
                                }
                            }
                        for(j=0;j<8;j++)
                            {
                                if(hz16[k].Msk[i*2+1]&(0x80>>j))   Gui_DrawPoint_DMA(x+j+8,y+i,fc);
                                else
                                {
                                    if (fc!=bc) Gui_DrawPoint_DMA(x+j+8,y+i,bc);
                                }
                            }
                    }
                }
              }
            s+=2;x+=16;
        }

    }

    LCD_SetWindow(0,y0,239,y0+16);
    LCD_CS_CLR;
    SPI_WriteData(0x72);


    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;

}

main.c

cpp 复制代码
/********************************** (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)
    {

        Delay_Ms(1000);
        FillRect_DMA(GREEN);
        Gui_DrawFont_GBK16_DMA(0,5,BLACK,GREEN,"HELLO world");
        Gui_DrawFont_GBK16_DMA(0,25,RED,GREEN,"LCD OK DISPLAY");
        Gui_DrawFont_GBK16_DMA(0,45,RED,GREEN,"智能物联红外测温系统通过人数");
        Gui_DrawFont_GBK16_DMA(0,65,RED,GREEN,"报警人数人体温度环境表面距离");
        Gui_DrawFont_GBK16_DMA(0,85,RED,GREEN,"网络连接中.温度气象站雨量风速");
        Gui_DrawFont_GBK16_DMA(0,105,RED,GREEN,"创新实验平台℃");
        Delay_Ms(2000);
        FillRect_DMA(RED);
        Delay_Ms(1000);
        FillRect_DMA(BLUE);
        Gui_DrawFont_GBK16_DMA(0,5,WHITE,BLUE,"HELLO world");
        Gui_DrawFont_GBK16_DMA(0,25,WHITE,BLUE,"LCD OK DISPLAY");
        Gui_DrawFont_GBK16_DMA(0,45,WHITE,BLUE,"智能物联红外测温系统通过人数");
        Gui_DrawFont_GBK16_DMA(0,65,WHITE,BLUE,"报警人数人体温度环境表面距离");
        Gui_DrawFont_GBK16_DMA(0,85,WHITE,BLUE,"网络连接中.温度气象站雨量风速");
        Gui_DrawFont_GBK16_DMA(0,105,WHITE,BLUE,"创新实验平台℃");
        Delay_Ms(1000);
        FillRect_DMA(YELLOW);
        Delay_Ms(1000);
        FillRect(0, 0, 239, 63, RED );


        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、增加了 Gui_DrawPoint_DMA(unsigned int x,unsigned int y,unsigned int Data)向DMA内存画点的功能

void Gui_DrawPoint_DMA(unsigned int x,unsigned int y,unsigned int Data)

{

TxData[2*x+y*480]=Data>>8;

TxData[2*x+y*480+1]=Data;

}

2、增加了void DMA_BUFFER_RESET(unsigned int bc),用于清空DMA内存

void DMA_BUFFER_RESET(unsigned int bc)

{

unsigned int j;

for(j=0 ;j<Buf_Size;){

TxData[j] = bc>>8;

TxData[j+1] = bc;

j += 2;

}

}

3、增加了Gui_DrawFont_GBK16_DMA(unsigned int x, unsigned int y, unsigned int fc, unsigned int bc,unsigned char *s)。用于处理字符串并以DMA方式输出到屏幕。

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

{

unsigned char i,j;

unsigned short k,x0,y0;

x0=x;

y0=y;

x=0;

y=0;

DMA_BUFFER_RESET(bc); //清缓存

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_DMA(x+j,y+i,fc);

else

{

if (fc!=bc) Gui_DrawPoint_DMA(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_DMA(x+j,y+i,fc);

else {

if (fc!=bc) Gui_DrawPoint_DMA(x+j,y+i,bc);

}

}

for(j=0;j<8;j++)

{

if(hz16[k].Msk[i*2+1]&(0x80>>j)) Gui_DrawPoint_DMA(x+j+8,y+i,fc);

else

{

if (fc!=bc) Gui_DrawPoint_DMA(x+j+8,y+i,bc);

}

}

}

}

}

s+=2;x+=16;

}

}

LCD_SetWindow(0,y0,239,y0+16);

LCD_CS_CLR;

SPI_WriteData(0x72);

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;

}

三、总结

1、申请的DMA空间为480*16,对应于屏幕是一个240*16的长条空间。也就是每次向屏幕刷一个 240*16范围,对应文字就是一行。改变起始位置,就可以在其他地方再刷一行。

DMA快速显示文字

相关推荐
重生之我是数学王子2 小时前
点亮核心板小灯 STM32U575
stm32·单片机·嵌入式硬件
end_SJ2 小时前
初学stm32 --- 定时器中断
stm32·单片机·嵌入式硬件
南城花随雪。3 小时前
单片机:实现数码管动态显示(0~99999999)74hc138驱动(附带源码)
单片机·嵌入式硬件
南城花随雪。5 小时前
单片机:实现信号发生器(附带源码)
单片机·嵌入式硬件
灵槐梦6 小时前
【速成51单片机】2.点亮LED
c语言·开发语言·经验分享·笔记·单片机·51单片机
三月七(爱看动漫的程序员)7 小时前
HiQA: A Hierarchical Contextual Augmentation RAG for Multi-Documents QA---附录
人工智能·单片机·嵌入式硬件·物联网·机器学习·语言模型·自然语言处理
新晨单片机设计8 小时前
【087】基于51单片机智能宠物喂食器【Proteus仿真+Keil程序+报告+原理图】
嵌入式硬件·51单片机·proteus·宠物·ad原理图
大风起兮128 小时前
STM32HAL库中RTC闹钟设置时分秒,年月日
stm32·嵌入式硬件
超能力MAX9 小时前
IIC驱动EEPROM
单片机·嵌入式硬件·fpga开发
QQ5471760529 小时前
stm32实现回调功能
stm32·单片机·嵌入式硬件