[MM32硬件]【灵动微电子MM32F5330测评】5.SPI+DMA驱动ST7735彩色LCD

一、SPI初始化
1、SPI_InitStruct.SPI_BaudRatePrescaler设置越小,SPI频率越高,16好像是极限了,不能再小了。
2、SPI1用于驱动板上的flash了,所以驱动LCD要用SPI2。

复制
void LCD_SPI_Configure(void)

{

    GPIO_InitTypeDef GPIO_InitStruct;

    SPI_InitTypeDef  SPI_InitStruct;



    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

        

    SPI_StructInit(&SPI_InitStruct);

    SPI_InitStruct.SPI_Mode      = SPI_Mode_Master;

    SPI_InitStruct.SPI_DataSize  = SPI_DataSize_8b;

    SPI_InitStruct.SPI_DataWidth = 8;

    SPI_InitStruct.SPI_CPOL      = SPI_CPOL_Low;

    SPI_InitStruct.SPI_CPHA      = SPI_CPHA_1Edge;

    SPI_InitStruct.SPI_NSS       = SPI_NSS_Soft;

    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;

    SPI_InitStruct.SPI_FirstBit  = SPI_FirstBit_MSB;

    SPI_Init(SPI2, &SPI_InitStruct);

                

                

        

    SPI_BiDirectionalLineConfig(SPI2, SPI_Direction_Rx);

    SPI_BiDirectionalLineConfig(SPI2, SPI_Direction_Tx);

        

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

        

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource12,  GPIO_AF_5);        //SPI2_NSS  PB12

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13,  GPIO_AF_5);        //SPI2_SCK  PB13

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource14,  GPIO_AF_5);        //SPI2_MISO PB14

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15,  GPIO_AF_5);        //SPI2_MOSI PB15

                

                

    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_15;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOB, &GPIO_InitStruct);

                

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_14;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_IPU;

    GPIO_Init(GPIOB, &GPIO_InitStruct);

                

                

    SPI_Cmd(SPI2, ENABLE);

                

                

   //初始化LCD_DC、LCD_RST、LCD_LED

    GPIO_StructInit(&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_1|GPIO_Pin_10|GPIO_Pin_11;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;

    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;

    GPIO_Init(GPIOB, &GPIO_InitStruct);

                

}

二、DMA设置
1、首先申请一个内存做为DMA的源地址:
之所以申请256*16个地址,是因为ST7735是一个128*128分辨率的LCD,一行128个点,由于是彩屏,每个点color值用2个字节,一行就是256个字节;另外一个汉字点阵是16*16,所以申请256*16这么一个空间,可以显示一行汉字。

复制
#define DMABUFFERSIZE         256*16

uint8_t DMA_TxBuffer[DMABUFFERSIZE];

2、DMA向发送SPI2数据
1)DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->TXREG);
DMA_PeripheralBaseAddr外设地址要这么设置,可以从DMA_TxBuffer地址发送到SPI2

2)DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
外设地址是固定的

3)DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;源地址每次要增加,这样可以保障DMA_TxBuffer里的数据都发送给SPI2.

4)DMA_Cmd(DMA1_Channel4, ENABLE);
DMA_Cmd(DMA1_Channel5, ENABLE);
根据数据手册DAM channel要这么设置
 


 

复制
void SPI_TxData_DMA_Polling(uint8_t *Buffer, uint16_t Length)

{

    DMA_InitTypeDef  DMA_InitStruct;



    uint8_t DataCache = 0;



    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);



    DMA_DeInit(DMA1_Channel4);

    DMA_DeInit(DMA1_Channel5);



    DMA_StructInit(&DMA_InitStruct);

    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->RXREG);

    DMA_InitStruct.DMA_MemoryBaseAddr     = (uint32_t)&DataCache;

    DMA_InitStruct.DMA_DIR                = DMA_DIR_PeripheralSRC;

    DMA_InitStruct.DMA_BufferSize         = Length;

    DMA_InitStruct.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;

    DMA_InitStruct.DMA_MemoryInc          = DMA_MemoryInc_Disable;

    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

    DMA_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;

    DMA_InitStruct.DMA_Mode               = DMA_Mode_Normal;

    DMA_InitStruct.DMA_Priority           = DMA_Priority_VeryHigh;

    DMA_InitStruct.DMA_M2M                = DMA_M2M_Disable;

    DMA_InitStruct.DMA_Auto_Reload        = DMA_Auto_Reload_Disable;

    DMA_Init(DMA1_Channel4, &DMA_InitStruct);



    DMA_StructInit(&DMA_InitStruct);

    DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->TXREG);

    DMA_InitStruct.DMA_MemoryBaseAddr     = (uint32_t)Buffer;

    DMA_InitStruct.DMA_DIR                = DMA_DIR_PeripheralDST;

    DMA_InitStruct.DMA_BufferSize         = Length;

    DMA_InitStruct.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;

    DMA_InitStruct.DMA_MemoryInc          = DMA_MemoryInc_Enable;

    DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

    DMA_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;

    DMA_InitStruct.DMA_Mode               = DMA_Mode_Normal;

    DMA_InitStruct.DMA_Priority           = DMA_Priority_VeryHigh;

    DMA_InitStruct.DMA_M2M                = DMA_M2M_Disable;

    DMA_InitStruct.DMA_Auto_Reload        = DMA_Auto_Reload_Disable;

    DMA_Init(DMA1_Channel5, &DMA_InitStruct);



    DMA_Cmd(DMA1_Channel4, ENABLE);

    DMA_Cmd(DMA1_Channel5, ENABLE);



    SPI_DMACmd(SPI2, ENABLE);



    while (RESET == DMA_GetFlagStatus(DMA1_FLAG_TC4))

    {

    }



    while (RESET == DMA_GetFlagStatus(DMA1_FLAG_TC5))

    {

    }



    SPI_DMACmd(SPI2, DISABLE);



    DMA_Cmd(DMA1_Channel4, DISABLE);

    DMA_Cmd(DMA1_Channel5, DISABLE);

}

3、对源数据控制函数:
把DMA+SPI发送函数包装下:

复制
void SPI_LCD_TxBuffer(uint8_t *Buffer, uint16_t Length)

{

    if (Length)

    {

        SPI_TxData_DMA_Polling(Buffer, Length);

    }

}

发送16行到LCD

复制
//16行

void sendOneLineDataDMA(void)

{

        LCD_CS_RESET();

        LCD_DC_SET();

        SPI_LCD_TxBuffer(DMA_TxBuffer,DMABUFFERSIZE);

        LCD_CS_SET();

}

DMA方式清屏,

复制
void GUI_Clear(uint16_t Color)     //清屏

{

        uint16_t i,j;

        

  ST7735_SetWindow(0, 0, X_MAX_PIXEL, Y_MAX_PIXEL);



        for(i=0;i<DMABUFFERSIZE/2;i++){

                DMA_TxBuffer[i*2]=Color>>8;

                DMA_TxBuffer[i*2+1]=Color&0xFF;

        }

        



        for(i=0;i<Y_MAX_PIXEL/16;i++)

        {

                        sendOneLineDataDMA();



        }

        

}


DMA_TxBuffer上画点,相当于在128*16区域设置每个点的颜色值

复制
void Gui_DrawPoint_DMA(uint16_t x,uint16_t y,uint16_t Data)

{

    DMA_TxBuffer[2*x+y*256]=Data>>8;

    DMA_TxBuffer[2*x+y*256+1]=Data;



}

用一个颜色值将整个源数据填满

复制
void set_DMA_TxBuffer(uint16_t Data)

{

        uint16_t i,j;

        for(i=0;i<16;i++)

        {

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

                {

                                Gui_DrawPoint_DMA(j,i,Data);

                }

        }

}

4、DMA方式发送汉字、ASCII

复制
void GUI_WriteCN16x16DMA(uint16_t x, uint16_t y,const uint8_t *cn, uint16_t wordColor, uint16_t backColor)

{

    uint16_t i, j, mx,my,wordByte;

    uint16_t zm;

    uint16_t color;

    uint8_t wordNum;



    mx=x;

    my=y;

    while (*cn != '\0')

    {

            

            if(mx>119){

        ST7735_SetWindow(0,my,X_MAX_PIXEL,16);

        sendOneLineDataDMA();

        mx=x;

        my+=16;

        memset(DMA_TxBuffer,0,sizeof(DMA_TxBuffer));

            }

            if(*cn<128){

        wordNum = *cn - 32;



        

        for (wordByte=0; wordByte<16; wordByte++)

        {

            color = Font_Data[wordNum].dat[wordByte];

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

            {

                if ((color&0x80) == 0x80)

                {

                    Gui_DrawPoint_DMA(mx+j,(my+wordByte)%16,wordColor);



                }

                else

                {



                    Gui_DrawPoint_DMA(mx+j,(my+wordByte)%16,backColor);

                }

                color <<= 1;

            }

        }

        cn++;

        mx +=8;

        }

        else

        {



            zm=*cn;

            zm<<=8;

            zm|=*(cn+1);



            getMatrix(zm);



                for(i=0; i<32; i++)

                {   //MSK的位数

                    color=MatrixBuff[i];

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

                    {

                        if((color&0x80)==0x80)

                        {



                            Gui_DrawPoint_DMA(mx+j+(i%2)*8,i/2,wordColor);

                        }

                        else

                        {



                            Gui_DrawPoint_DMA(mx+j+(i%2)*8,i/2,backColor);

                        }

                        color<<=1;

                    }//for(j=0;j<8;j++)结束

                }





        cn += 2;

        mx += 16;

                    }

    }

               

    ST7735_SetWindow(0,my,X_MAX_PIXEL, 16);

    sendOneLineDataDMA();

               

    set_DMA_TxBuffer(backColor);

    my+=16;

    while(my<(Y_MAX_PIXEL)){

            ST7735_SetWindow(0,my,X_MAX_PIXEL, 16);

            sendOneLineDataDMA();

            my+=16;

    }

               

}



5、实验:

复制
void ST7735_Init(void)

{

        char buf[16];

        LCD_LED_SET();

        

        LCD_SPI_Configure();

        

        ST7735_HardReset();

        ST7735_SendInitStr();

        GUI_Clear(COLOR_Red);

        sprintf(buf,"%d ",maxPage);

        GUI_WriteCN16x16(20,20,buf,COLOR_Red,COLOR_Black);

        PLATFORM_DelayMS(1000);

        GUI_Clear(COLOR_Blue);

        GUI_WriteCN16x16(20,20,buf,COLOR_Red,COLOR_Black);

        PLATFORM_DelayMS(1000);

        GUI_Clear(COLOR_Green);

        GUI_WriteCN16x16(20,20,buf,COLOR_Red,COLOR_Black);

        PLATFORM_DelayMS(1000);

}

三、演示效果
 


四、源码

 

 mini-f53330_USART_Polling.rar (188.6 KB)。
---------------------
作者:sujingliang
链接:https://bbs.21ic.com/icview-3387586-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值