打印
[产品应用]

CW32点亮1.44寸TFT(ST7735S)

[复制链接]
68|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
CW_SPI配置
首先可以很方便的从手册上看见CW32的SPI引脚



我用的是非触摸的屏幕 所以只配置使用了SCK(时钟引脚)和MOSI(主机输出从机输入)
从手册上可以看到单工单发/主机模式下,MOSI和SCK引脚需配置为数字/推挽输出/复用



这里就贴一下SPI的配置代码

        SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_TxOnly;        //单工只发
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                        //主机模式
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //八位数据
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                                //时钟极性-默认高电平
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                        //时钟触发模式 第二个边沿开始
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                        //软件片选
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//fspi = 64MHz/4 = 16MHz
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
        SPI_InitStructure.SPI_Speed = SPI_Speed_Low;                        //低速模式
       
        SPI_Init(CW_SPI2, &SPI_InitStructure);
        SPI_Cmd(CW_SPI2, ENABLE);
LCD配置
上面讲到了SPI的配置,下面就该讲讲屏幕使用到的引脚以及初始化了
首先,屏幕有8个引脚,他们分别为 GND VCC SCL SDA RES DC CS BL
GND/VCC:电源正负极
SCL:时钟引脚,接CW32的SPI_SCK 即PA02
SDA:数据输入引脚,接CW32的SPI_MOSI 即 PA01
RES:屏幕复位引脚,低电平复位 接PA03
DC:数据/命令选择引脚,低电平发送命令,高电平发送数据 接PA04
CS:片选信号,低电平选中 接PA05(使用的软件片选)
BL:背光引脚,用于控制屏幕亮度 接PA06
使用到的引脚都是GPIOA端口且都是推挽输出,所以初始化代码如下
        PA01_AFx_SPI2MOSI(); //引脚复用
        PA02_AFx_SPI2SCK();  //引脚复用
       
        GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
       
        GPIO_InitStructure.Pins = LSCL|LSDA|LRES|LDC|LCS|LBL;
        GPIO_Init(CW_GPIOA, &GPIO_InitStructure);

然后就是LCD初始化配置了(可以在屏幕的数据手册上找到),太长了,所以一会放最下面。


这里补充一下SPI的写函数
void LCD_WriteCmd(uint8_t cmd)
{
        LCS_CLR;                                                                        //开始通信
        LDC_CLR;                                                                        //指令
        SPI_SendData(CW_SPI2, cmd);
        while(!SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE));//等待本次发送完成
        LCS_SET;                                                                        //结束通信
}

void LCD_WriteData(uint8_t data)
{
        LCS_CLR;                                                                        //开始通信
        LDC_SET;                                                                        //数据
        SPI_SendData(CW_SPI2, data);
        while(!SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE));//等待本次发送完成
        LCS_SET;                                                                        //结束通信
}

void LCD_Write2Byte(uint16_t data)
{
        LCS_CLR;                                                                        //开始通信
        LDC_SET;                                                                        //数据
        SPI_SendData(CW_SPI2, (uint8_t)(data>>8));
        while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);//等待本次发送完成
        SPI_SendData(CW_SPI2, (uint8_t)data);
        while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);//等待本次发送完成
        LCS_SET;                                                                        //结束通信
}



最后贴一下所有代码
LCD.C

#include "lcd.h"
#include "font.h"
#include "math.h"

void LCD_Delay(void)
{
        uint16_t i = 0xfff;
        while(i--);
}

void LCD_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef SPI_InitStructure;
       
        __RCC_SPI2_CLK_ENABLE();
        __RCC_GPIOA_CLK_ENABLE();
       
        PA01_AFx_SPI2MOSI();
        PA02_AFx_SPI2SCK();
       
        //将 SPIx_SCK、SPIx_MOSI 和 SPIx_CS 配置为推挽复用输出模式
        //SPIx_MISO 引脚配置为浮空输入、复用模式
        GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
        GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
       
        GPIO_InitStructure.Pins = LSCL|LSDA|LRES|LDC|LCS|LBL;
        GPIO_Init(CW_GPIOA, &GPIO_InitStructure);

        SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_TxOnly;        //单工只发
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                        //主机模式
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //八位数据
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                                //时钟极性-默认高电平
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                        //时钟触发模式 第二个边沿开始
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                        //软件片选
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//fspi = 64MHz/4 = 16MHz
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
        SPI_InitStructure.SPI_Speed = SPI_Speed_Low;                        //低速模式
       
        SPI_Init(CW_SPI2, &SPI_InitStructure);
        SPI_Cmd(CW_SPI2, ENABLE);
       
        LCS_SET;                //片选失能
        LBL_SET;                //打开背光
        LDC_SET;
}

void LCD_Rest()
{
        LRES_CLR;
        LCD_Delay();
        LRES_SET;
        LCD_Delay();
}

void LCD_WriteCmd(uint8_t cmd)
{
        LCS_CLR;                                                                        //开始通信
        LDC_CLR;                                                                        //指令
        SPI_SendData(CW_SPI2, cmd);
        while(!SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE));//等待本次发送完成
        LCS_SET;                                                                        //结束通信
}

void LCD_WriteData(uint8_t data)
{
        LCS_CLR;                                                                        //开始通信
        LDC_SET;                                                                        //数据
        SPI_SendData(CW_SPI2, data);
        while(!SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE));//等待本次发送完成
        LCS_SET;                                                                        //结束通信
}

void LCD_Write2Byte(uint16_t data)
{
        LCS_CLR;                                                                        //开始通信
        LDC_SET;                                                                        //数据
        SPI_SendData(CW_SPI2, (uint8_t)(data>>8));
        while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);//等待本次发送完成
        SPI_SendData(CW_SPI2, (uint8_t)data);
        while(SPI_GetFlagStatus(CW_SPI2, SPI_FLAG_TXE) == RESET);//等待本次发送完成
        LCS_SET;                                                                        //结束通信
}

void LCD_Init(void)
{       
        LCD_Config();

        LCD_Rest();
       
        LCD_WriteCmd(0x11);//Sleep exit
        LCD_WriteCmd(0xB1);
        LCD_WriteData(0x01);
        LCD_WriteData(0x2C);
        LCD_WriteData(0x2D);
        LCD_WriteCmd(0xB2);
        LCD_WriteData(0x01);
        LCD_WriteData(0x2C);
        LCD_WriteData(0x2D);
        LCD_WriteCmd(0xB3);
        LCD_WriteData(0x01);
        LCD_WriteData(0x2C);
        LCD_WriteData(0x2D);
        LCD_WriteData(0x01);
        LCD_WriteData(0x2C);
        LCD_WriteData(0x2D);
        LCD_WriteCmd(0xB4); //Column inversion
        LCD_WriteData(0x07);
        LCD_WriteCmd(0xC0);
        LCD_WriteData(0xA2);
        LCD_WriteData(0x02);
        LCD_WriteData(0x84);
        LCD_WriteCmd(0xC1);
        LCD_WriteData(0xC5);
        LCD_WriteCmd(0xC2);
        LCD_WriteData(0x0A);
        LCD_WriteData(0x00);
        LCD_WriteCmd(0xC3);
        LCD_WriteData(0x8A);
        LCD_WriteData(0x2A);
        LCD_WriteCmd(0xC4);
        LCD_WriteData(0x8A);
        LCD_WriteData(0xEE);
        LCD_WriteCmd(0xC5); //VCOM
        LCD_WriteData(0x0E);
        LCD_WriteCmd(0x36); //MX, MY, RGB mode
        LCD_WriteData(0xC8);
        LCD_WriteCmd(0xe0);
        LCD_WriteData(0x0f);
        LCD_WriteData(0x1a);
        LCD_WriteData(0x0f);
        LCD_WriteData(0x18);
        LCD_WriteData(0x2f);
        LCD_WriteData(0x28);
        LCD_WriteData(0x20);
        LCD_WriteData(0x22);
        LCD_WriteData(0x1f);
        LCD_WriteData(0x1b);
        LCD_WriteData(0x23);
        LCD_WriteData(0x37);
        LCD_WriteData(0x00);        
        LCD_WriteData(0x07);
        LCD_WriteData(0x02);
        LCD_WriteData(0x10);
        LCD_WriteCmd(0xe1);
        LCD_WriteData(0x0f);
        LCD_WriteData(0x1b);
        LCD_WriteData(0x0f);
        LCD_WriteData(0x17);
        LCD_WriteData(0x33);
        LCD_WriteData(0x2c);
        LCD_WriteData(0x29);
        LCD_WriteData(0x2e);
        LCD_WriteData(0x30);
        LCD_WriteData(0x30);
        LCD_WriteData(0x39);
        LCD_WriteData(0x3f);
        LCD_WriteData(0x00);
        LCD_WriteData(0x07);
        LCD_WriteData(0x03);
        LCD_WriteData(0x10);  
        LCD_WriteCmd(0x2a);
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        LCD_WriteData(0x7f);
        LCD_WriteCmd(0x2b);
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        LCD_WriteData(0x00);
        LCD_WriteData(0x9f);
        LCD_WriteCmd(0xF0); //Enable test command  
        LCD_WriteData(0x01);
        LCD_WriteCmd(0xF6); //Disable ram power save mode
        LCD_WriteData(0x00);
        LCD_WriteCmd(0x3A); //65k mode
        LCD_WriteData(0x05);
        LCD_WriteCmd(0x29);//Display on       
       
        LCD_Clear(BLACK);
}

//设置写入范围
void setRegion(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1 )
{
        LCD_WriteCmd(0x2a);
        LCD_Write2Byte(x0+2);
        LCD_Write2Byte(x1+2);
        // Y轴
        LCD_WriteCmd(0x2b);
        LCD_Write2Byte(y0+3);
        LCD_Write2Byte(y1+3);
        // 写入命令
        LCD_WriteCmd(0x2c);
}

//设置光标位置
void setPoint(uint8_t x, uint8_t y)
{
        LCD_WriteCmd(0x2a);
        LCD_Write2Byte(x+2);
        // Y轴
        LCD_WriteCmd(0x2b);
        LCD_Write2Byte(y+3);
        // 写入命令
        LCD_WriteCmd(0x2c);
}
void LCD_Clear( uint16_t color )
{
        uint16_t area = MAX_H * MAX_W;
        setRegion(0,0,MAX_W - 1,MAX_H - 1);
        while(area--) LCD_Write2Byte(color);
}

void LCD_ClearPart(uint8_t x0,uint8_t y0, uint8_t x1,uint8_t y1, uint16_t color )
{
        uint16_t area = (y1 - y0) * (x1 - x0);
        setRegion(x0,y0,x1,y1);
        while(area--) LCD_Write2Byte(color);
}

void LCD_DrawPoint(uint8_t x, uint8_t y, uint16_t color)
{
        setPoint(x,y);
        LCD_Write2Byte(color);
}

/**************************************
        函数名:LCD_ShowChar
        函数作用:显示一个字符(无背景色)
        参数:x/y->显示坐标
                                size->字符大小 6/8/12 分别对应 6*12/8*16/12*24
                                color->颜色 0x0000-0xffff
                                ch->需要显示的字符
        注意:字符类型取列行式
**************************************/
void LCD_ShowChar(uint8_t x, uint8_t y, uint8_t size, uint16_t color, uint8_t chr)
{
        uint8_t i,j,n;
       
        uint8_t N = (size + 3) / 4; //获取一个字符对应的高度
       
        for(n=0; n<N; n++)
        {
                for(j=0;j<size;j++)
                {
                        for(i=0;i<8;i++)
                        {
                                if(size == 6)
                                {
                                        if((0x01<<i)&F6x12[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
                                }
                                else if(size == 8)
                                {
                                        if((0x01<<i)&F8x16[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
                                }
                                else if(size == 12)
                                {
                                        if((0x01<<i)&F12x24[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
                                }
                        }
                }
        }
}

void LCD_ShowStr(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint8_t *str)
{
        uint8_t i;
        for(i=0; str != '\0'; i++)
        {
                LCD_ShowChar(x,y,size,color,str);
                x += size;
                if((x + size) > MAX_W)
                {
                        x = 0;
                        y += 2 * size;
                }
        }
}

/**************************************
        函数名:LCD_ShowChar
        函数作用:显示一个字符(带背景色)
        参数:x/y->显示坐标
                                size->字符大小 6/8/12 分别对应 6*12/8*16/12*24
                                color->颜色 0x0000-0xffff
                                ch->需要显示的字符
        注意:字符类型取列行式
**************************************/
void LCD_ShowBChar(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint16_t BackColor, uint8_t chr)
{
        uint8_t i,j,n;
        uint8_t N = (size + 3) / 4; //获取一个字符对应的高度
       
        for(n=0; n<N; n++)
        {
                for(j=0;j<size;j++)
                {
                        for(i=0;i<8;i++)
                        {
                                if(size == 6)
                                {
                                        if((0x01<<i)&F6x12[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
                                        else LCD_DrawPoint(x+j,y+n*8+i,BackColor);
                                }
                                else if(size == 8)
                                {
                                        if((0x01<<i)&F8x16[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
                                        else LCD_DrawPoint(x+j,y+n*8+i,BackColor);
                                }
                                else if(size == 12)
                                {
                                        if((0x01<<i)&F12x24[chr - ' '][n*size+j]) LCD_DrawPoint(x+j,y+n*8+i,color);
                                        else LCD_DrawPoint(x+j,y+n*8+i,BackColor);
                                }
                        }
                }
        }
}

void LCD_ShowBStr(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint16_t BackColor,uint8_t *str)
{
        uint8_t i;
        for(i=0; str != '\0'; i++)
        {
                LCD_ShowBChar(x,y,size,color, BackColor,str);
                x += size;
                if((x + size) > MAX_W)
                {
                        x = 0;
                        y += 2 * size;
                }
        }
}

void LCD_ShowBMP(uint8_t x, uint8_t y,uint8_t w, uint8_t h, const uint8_t bmp[], uint16_t color)
{
        uint8_t i,j,n,N;
        N = h/8;
        if(h%8 != 0) N += 1;
       
        for(n=0;n<N;n++)
        {
                for(j=0;j<w;j++)
                {
                        for(i=0;i<8;i++)
                        {
                                if((bmp[n*w+j] >> i) & 0x01) LCD_DrawPoint(x+j,y+i,color);
                        }
                }
                y += 8;
        }
}

void LCD_DrawLine(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint16_t color)   
{
int dx,             // difference in x's
    dy,             // difference in y's
    dx2,            // dx,dy * 2
    dy2,
    x_inc,          // amount in pixel space to move during drawing
    y_inc,          // amount in pixel space to move during drawing
    error,          // the discriminant i.e. error i.e. decision variable
    index;          // used for looping

        setPoint(x0,y0);
        dx = x1-x0;//计算x距离
        dy = y1-y0;//计算y距离

        if (dx>=0)
        {
                x_inc = 1;
        }
        else
        {
                x_inc = -1;
                dx = -dx;  
        }
       
        if (dy>=0)
        {
                y_inc = 1;
        }
        else
        {
                y_inc = -1;
                dy = -dy;
        }

        dx2 = dx << 1;
        dy2 = dy << 1;

        if (dx > dy)
        {
                error = dy2 - dx;
                for (index=0; index <= dx; index++)
                {
                        LCD_DrawPoint(x0,y0,color);
                        if (error >= 0)
                        {
                                error-=dx2;
                                y0+=y_inc;
                        }
                        error+=dy2;
                        x0+=x_inc;
                }
        }
        else
        {
                error = dx2 - dy;
                for (index=0; index <= dy; index++)
                {
                        LCD_DrawPoint(x0,y0,color);
                        if (error >= 0)
                        {
                                error-=dy2;
                                x0+=x_inc;
                        }
                        error+=dx2;
                        y0+=y_inc;
                }
        }
}

void LCD_DrawCricle(uint8_t x,uint8_t y,uint8_t r,uint16_t color)
{
        int dy,dx;
        dx=r;
        dy=0;
        while(dy<r)
        {
                if(dx>=dy)
                {
                        LCD_DrawPoint(x+dx,y-dy,color);
                        LCD_DrawPoint(x-dx,y-dy,color);
                        LCD_DrawPoint(x+dx,y+dy,color);
                        LCD_DrawPoint(x-dx,y+dy,color);
                       
                        LCD_DrawPoint(y+dy,y-dx,color);
                        LCD_DrawPoint(y-dy,y-dx,color);
                        LCD_DrawPoint(y+dy,y+dx,color);
                        LCD_DrawPoint(y-dy,y+dx,color);
                }
                dy++;
                dx=sqrt((double)r*r-dy*dy);
        }
}

void LCD_FullCircle(uint8_t x, uint8_t y, uint8_t r, uint16_t color)
{
        uint16_t dx,dy,dr=r;
        for(dy=y - dr;dy<y +dr;dy++)
        {
                for(dx=x - dr;dx<x+dr;dx++)
                {
                        if(((dx-x)*(dx-x)+(dy-y)*(dy-y)) <= dr*dr)
                        {
                                LCD_DrawPoint(dx,dy,color);
                        }
                }
        }
}




下面是LCD.h文件

#ifndef __LCD_H
#define __LCD_H

#include "cw32f030.h"
#include "cw32f030.h"
#include "cw32f030_spi.h"
#include "cw32f030_gpio.h"
#include "cw32f030_rcc.h"

#define RED                        0xf800
#define GREEN                0x07e0
#define BLUE                0x001f
#define YELLOW        0xffe0
#define BLACK                0x0000
#define WHITE                0xffff

#define MAX_W                128
#define MAX_H                128

//CW_SPI2
#define LSCL        GPIO_PIN_2
#define LSDA        GPIO_PIN_1
#define LRES        GPIO_PIN_3
#define LDC                GPIO_PIN_4
#define LCS                GPIO_PIN_5
#define LBL                GPIO_PIN_6

#define LCS_SET        CW_GPIOA->BSRR = LCS
#define LCS_CLR        CW_GPIOA->BRR = LCS

#define LDC_SET        CW_GPIOA->BSRR = LDC
#define LDC_CLR        CW_GPIOA->BRR = LDC

#define LRES_SET        CW_GPIOA->BSRR = LRES
#define LRES_CLR        CW_GPIOA->BRR = LRES

#define LBL_SET        CW_GPIOA->BSRR = LBL
#define LBL_CLR        CW_GPIOA->BRR = LBL

void LCD_Init(void );                                        // LCD初始化
void LCD_Clear(uint16_t color ) ;
void LCD_ClearPart(uint8_t x0,uint8_t y0, uint8_t x1,uint8_t y1, uint16_t color );
void LCD_ShowChar(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint8_t chr);
void LCD_ShowBChar(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint16_t BackColor, uint8_t chr);
void LCD_ShowStr(uint8_t x, uint8_t y, uint8_t size, uint16_t color, uint8_t *str);
void LCD_ShowBStr(uint8_t x, uint8_t y, uint8_t size, uint16_t color,uint16_t BackColor,uint8_t *str) ;
void LCD_ShowBMP(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t bmp[], uint16_t color);
void LCD_DrawLine(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1,uint16_t color);
void LCD_DrawPoint(uint8_t x, uint8_t y, uint16_t color);
void LCD_DrawCricle(uint8_t x,uint8_t y,uint8_t r,uint16_t color);
void LCD_FullCircle(uint8_t x,uint8_t y,uint8_t r,uint16_t color);
void LCD_DrawCurve(uint32_t* data,uint8_t x);
#endif




我觉得font.h就没必要补充了
自己取字模的时候注意一下配置就行(列行式,C51格式)



————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_45813999/article/details/131538800

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

106

帖子

0

粉丝