第二篇: 点亮屏幕

1.初始化IO口

初始化IO是最底层,我们就从最底层来看是如何一步一步把程序驱动起来的.

#ifndef BSP_LCD_H
#define BSP_LCD_H
#include "stm32f10x.h"

void bsp_spi_init(void);
void bsp_gpio_init(void);

u8 bsp_spi_write(u8 Byte);

#endif
#include "bsp_lcd.h"
/*******************************************************************

            此文件主要是对屏幕外设所接的引脚做初始化

*******************************************************************/

/******************************定义屏幕的IO接口*********************
PB13 : SPI时钟
PB15 : MOSI
PD9 : 复位
PD11 : 数据命令选择引脚
PD13 : 背光,这里没用PWM控制,直接接了IO口

*******************************************************************/

/*******************************************************************
函数功能:
    SPI初始化
参数:
返回值:
说明:
    这里只用到了SPI的MOSI,所以MISO没进行初始化
*******************************************************************/

void bsp_spi_init(void)
{
    SPI_InitTypeDef  SPI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
     
    //配置SPI2管脚
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
 
    
    //SPI2配置选项
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2 ,ENABLE);
       
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    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_2;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI2, &SPI_InitStructure);

    //使能SPI2
    SPI_Cmd(SPI2, ENABLE);   
}
/*******************************************************************
函数功能:
    对lcd其他三个引脚初始化
参数:
返回值:
说明:
    全部设为推完输出,
*******************************************************************/
void bsp_gpio_init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;          
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD ,ENABLE);    //使能GPIOB时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9| GPIO_Pin_11| GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
    GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化
    GPIO_SetBits(GPIOD,GPIO_Pin_9| GPIO_Pin_11| GPIO_Pin_13);    
}


/*******************************************************************
函数功能:
    SPI写函数
参数:
    Byte:写入一个字节
返回值:
    返回读到的值,这里没有初始化SPI的MISO,忽视返回值
说明:
*******************************************************************/
u8 bsp_spi_write(u8 Byte)
{
    while((SPI2->SR&SPI_I2S_FLAG_TXE)==RESET);        //等待发送区空      
    SPI2->DR=Byte;         //发送一个byte   
    while((SPI2->SR&SPI_I2S_FLAG_RXNE)==RESET);//等待接收完一个byte  
    return SPI2->DR;                   //返回收到的数据            
} 


2.初始化屏幕

初始化屏幕这一层向外暴露3个函数,一个初始化,一个画点,一个填充矩形区域.(在移植LVGL时需要调用填充矩形区域这个函数)

#ifndef DEV_LCD_H
#define DEV_LCD_H
#include "stm32f10x.h"
#include "bsp_lcd.h"

/***************************宏替换硬件操作函数********************************/

#define LCD_SPI_WRITE(data)                bsp_spi_write(data)
#define LCD_WRITE_REG_CMD()                GPIO_ResetBits(GPIOD, GPIO_Pin_11)     
#define LCD_WRITE_DATA_CMD()            GPIO_SetBits(GPIOD, GPIO_Pin_11)
#define LCD_RESET_CONTRL()                GPIO_ResetBits(GPIOD, GPIO_Pin_9)
#define LCD_SET_CONTRL()                GPIO_SetBits(GPIOD, GPIO_Pin_9)

/***************************************************************************/

/******************************寄存器地址   ********************************/
#define SET_X_CMD            0x2A
#define SET_Y_CMD            0x2B
#define WRITE_GRAM_CMD        0x2C
/***************************************************************************/

/***************************用宏定义一些重要的参数********************************/
//定义屏幕的大小
#define    LCD_W                240
#define    LCD_H                240


//画笔颜色
#define WHITE       0xFFFF
#define BLACK          0x0000      
#define BLUE           0x001F  
#define BRED        0XF81F
#define GRED                  0XFFE0
#define GBLUE                 0X07FF
#define RED         0xF800
#define MAGENTA     0xF81F
#define GREEN       0x07E0
#define CYAN        0x7FFF
#define YELLOW      0xFFE0
#define BROWN             0XBC40 //棕色
#define BRRED             0XFC07 //棕红色
#define GRAY              0X8430 //灰色
#define GRAY0       0xEF7D 
#define GRAY1       0x8410          //灰色1      00000 000000 00000
#define GRAY2       0x4208 
#define DARKBLUE           0X01CF    //深蓝色
#define LIGHTBLUE           0X7D7C    //浅蓝色  
#define GRAYBLUE            0X5458 //灰蓝色
#define LIGHTGREEN         0X841F //浅绿色
#define LIGHTGRAY     0XEF5B //浅灰色(PANNEL)
#define LGRAY                      0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE          0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE          0X2B12 //浅棕蓝色(选择条目的反色)

/***************************************************************************/



//LCD参数
typedef struct  
{                                            
    u16 width;                //LCD 宽度
    u16 height;                //LCD 高度
    u8  dir;                  //横屏还是竖屏控制:0,竖屏;1,横屏。    
    u16    write_gram_cmd;        //开始写gram指令
    u16 set_x_cmd;            //设置x坐标指令
    u16 set_y_cmd;            //设置y坐标指令    
    u8  x_offset;    
    u8    y_offset;
}lcd_dev_t; 




void dev_lcd_init(void);
void LCD_DrawPoint(u16 x,u16 y, u16 color);
void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color);

#endif

#include "dev_lcd.h"
/*******************************************************************

            此文件主要对屏幕初始化

*******************************************************************/
lcd_dev_t lcd_dev;        /*创建一个lcd设备*/

/*******************************************************************
函数功能:
    延时
参数:
返回值:
说明:
*******************************************************************/
static void lcd_delay_ms(u32 i)
{
    i = i * 4000;
    while(i--);
}
/*******************************************************************
函数功能:
    告诉ST7789要操作的寄存器的地址
参数:
返回值:
说明:
*******************************************************************/
void LCD_WR_REG(u8 data)
{      
    LCD_WRITE_REG_CMD();      
    LCD_SPI_WRITE(data);
}
/*******************************************************************
函数功能:
    告诉ST7789写入的是数据
参数:
返回值:
说明:
*******************************************************************/
void LCD_WR_DATA(u8 data)
{
    LCD_WRITE_DATA_CMD();
    LCD_SPI_WRITE(data);
}
/*******************************************************************
函数功能:
    LCD复位
参数:
返回值:
说明:
*******************************************************************/
void LCD_RESET(void)
{
    LCD_RESET_CONTRL();
    lcd_delay_ms(20);    
    LCD_SET_CONTRL();
    lcd_delay_ms(20);
}
/*******************************************************************
函数功能:
    向ST7789指定的寄存器中写入数据
参数:
返回值:
说明:
*******************************************************************/
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{    
    LCD_WR_REG(LCD_Reg);  
    LCD_SPI_WRITE(LCD_RegValue >> 8);      
    LCD_SPI_WRITE(LCD_RegValue);        
}
/*******************************************************************
函数功能:
    准备向gram中写入数据,也就是颜色信息
参数:
返回值:
说明:
*******************************************************************/
void LCD_Prepare_Write_GRAM(void)
{
    LCD_WR_REG(lcd_dev.write_gram_cmd);
}
/*******************************************************************
函数功能:
    写入一个16bit的数据
参数:
返回值:
说明:
*******************************************************************/
void Lcd_WriteData_16Bit(u16 Data)
{
    LCD_WRITE_DATA_CMD();  
    LCD_SPI_WRITE(Data >> 8);
    LCD_SPI_WRITE(Data);
}
/*******************************************************************
函数功能:
    设置显示窗口大小
参数:
    xStart,yStart,xEnd,yEnd:起始和结束的坐标
返回值:
说明:
*******************************************************************/
void LCD_SetWindows(u16 xStart, u16 yStart,u16 xEnd,u16 yEnd)
{    
    //设置起始点和结束点x轴的坐标
    LCD_WR_REG(lcd_dev.set_x_cmd);        
    LCD_WR_DATA((xStart+lcd_dev.x_offset)>>8);
    LCD_WR_DATA(xStart+lcd_dev.x_offset);        
    LCD_WR_DATA((xEnd+lcd_dev.x_offset)>>8);
    LCD_WR_DATA(xEnd+lcd_dev.x_offset);
    
    //设置起始点和结束点y轴的坐标
    LCD_WR_REG(lcd_dev.set_y_cmd);    
    LCD_WR_DATA((yStart+lcd_dev.y_offset)>>8);
    LCD_WR_DATA(yStart+lcd_dev.y_offset);        
    LCD_WR_DATA((yEnd+lcd_dev.y_offset)>>8);
    LCD_WR_DATA(yEnd+lcd_dev.y_offset);

    //开始写入GRAM    
    LCD_Prepare_Write_GRAM();            
} 
/*******************************************************************
函数功能:
    设置光标位置
参数:
    Xpos,Ypos:光标位置
返回值:
说明:
*******************************************************************/
void LCD_SetCursor(u16 Xpos, u16 Ypos)
  {                          
    LCD_SetWindows(Xpos,Ypos,Xpos,Ypos);    
}
/*******************************************************************
函数功能:
    LCD显示的方向
参数:
    Xpos,Ypos:光标位置
返回值:
说明:
*******************************************************************/
void LCD_direction(u8 direction)
{ 
            lcd_dev.set_x_cmd = SET_X_CMD;
            lcd_dev.set_y_cmd = SET_Y_CMD;
            lcd_dev.write_gram_cmd = WRITE_GRAM_CMD;
    switch(direction){          
        case 0:                                      
            lcd_dev.width = LCD_W;
            lcd_dev.height = LCD_H;    
            lcd_dev.x_offset = 0;
            lcd_dev.y_offset = 0;
            LCD_WriteReg(0x36, 0);//BGR==1,MY==0,MX==0,MV==0
        break;
        case 1:
            lcd_dev.width = LCD_H;
            lcd_dev.height = LCD_W;
            lcd_dev.x_offset = 0;
            lcd_dev.y_offset = 0;
            LCD_WriteReg(0x36,(1<<6)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
        break;
        case 2:                                      
            lcd_dev.width = LCD_W;
            lcd_dev.height = LCD_H;
      lcd_dev.x_offset=0;
            lcd_dev.y_offset = 80;            
            LCD_WriteReg(0x36,(1<<6)|(1<<7));//BGR==1,MY==0,MX==0,MV==0
        break;
        case 3:
            lcd_dev.width = LCD_H;
            lcd_dev.height = LCD_W;
            lcd_dev.x_offset = 80;
            lcd_dev.y_offset = 0;
            LCD_WriteReg(0x36,(1<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
        break;    
        default:break;
    }        
}
/*******************************************************************
函数功能:
    LCD初始化
参数:
返回值:
说明:
*******************************************************************/
void LCD_Clear(u16 Color)
{
  unsigned int i,m;  
    LCD_SetWindows(0,0,lcd_dev.width-1,lcd_dev.height-1);   

//    LCD_WRITE_DATA_CMD();
    for(i = 0; i < lcd_dev.height; i++)
    {
        for(m = 0; m < lcd_dev.width; m++)
        {    
//            LCD_SPI_WRITE(Color >> 8);
//            LCD_SPI_WRITE(Color);
            Lcd_WriteData_16Bit(Color);
        }
    }
} 
void dev_lcd_init(void)
{                                       
     LCD_RESET(); //LCD 复位
//************* ST7789初始化**********//    
    LCD_WR_REG(0x36); 
    LCD_WR_DATA(0x00);

    LCD_WR_REG(0x3A); 
    LCD_WR_DATA(0x05);

    LCD_WR_REG(0xB2);
    LCD_WR_DATA(0x0C);
    LCD_WR_DATA(0x0C);
    LCD_WR_DATA(0x00);
    LCD_WR_DATA(0x33);
    LCD_WR_DATA(0x33);

    LCD_WR_REG(0xB7); 
    LCD_WR_DATA(0x35);  

    LCD_WR_REG(0xBB);
    LCD_WR_DATA(0x19);

    LCD_WR_REG(0xC0);
    LCD_WR_DATA(0x2C);

    LCD_WR_REG(0xC2);
    LCD_WR_DATA(0x01);

    LCD_WR_REG(0xC3);
    LCD_WR_DATA(0x12);   

    LCD_WR_REG(0xC4);
    LCD_WR_DATA(0x20);  

    LCD_WR_REG(0xC6); 
    LCD_WR_DATA(0x0F);    

    LCD_WR_REG(0xD0); 
    LCD_WR_DATA(0xA4);
    LCD_WR_DATA(0xA1);

    LCD_WR_REG(0xE0);
    LCD_WR_DATA(0xD0);
    LCD_WR_DATA(0x04);
    LCD_WR_DATA(0x0D);
    LCD_WR_DATA(0x11);
    LCD_WR_DATA(0x13);
    LCD_WR_DATA(0x2B);
    LCD_WR_DATA(0x3F);
    LCD_WR_DATA(0x54);
    LCD_WR_DATA(0x4C);
    LCD_WR_DATA(0x18);
    LCD_WR_DATA(0x0D);
    LCD_WR_DATA(0x0B);
    LCD_WR_DATA(0x1F);
    LCD_WR_DATA(0x23);

    LCD_WR_REG(0xE1);
    LCD_WR_DATA(0xD0);
    LCD_WR_DATA(0x04);
    LCD_WR_DATA(0x0C);
    LCD_WR_DATA(0x11);
    LCD_WR_DATA(0x13);
    LCD_WR_DATA(0x2C);
    LCD_WR_DATA(0x3F);
    LCD_WR_DATA(0x44);
    LCD_WR_DATA(0x51);
    LCD_WR_DATA(0x2F);
    LCD_WR_DATA(0x1F);
    LCD_WR_DATA(0x1F);
    LCD_WR_DATA(0x20);
    LCD_WR_DATA(0x23);
    LCD_WR_REG(0x21); 
    LCD_WR_REG(0x11); 
    LCD_WR_REG(0x29); 
    
    LCD_direction(0);//设置LCD显示方向    
    LCD_Clear(WHITE);//清全屏白色

}
/*******************************************************************
函数功能:
    画点
参数:
    x,y坐标,color,点的颜色
返回值:
说明:
*******************************************************************/
void LCD_DrawPoint(u16 x, u16 y, u16 color)
{
    LCD_SetCursor(x, y);//设置光标位置 
    Lcd_WriteData_16Bit(color); 
}
/*******************************************************************
函数功能:
    在屏幕矩形范围内填充颜色
参数:
    
返回值:
说明:注意sx,sy要比ex,ey小
*******************************************************************/
void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
{      
    u16 i,j;            
    u16 width=ex-sx+1;         //得到填充的宽度
    u16 height=ey-sy+1;        //高度
    LCD_SetWindows(sx,sy,ex,ey);//设置显示窗口
    for(i=0;i<width;i++)
    {
        for(j=0;j<height;j++)
        {
            Lcd_WriteData_16Bit(color);    
        }            
    }
    LCD_SetWindows(0,0,lcd_dev.width-1,lcd_dev.height-1);//恢复窗口设置为全屏
}

3.UI函数

这一层主要调用设备层的画点和填充矩形区域,来完成一些复杂的画图功能.

#ifndef MID_UI_H
#define MID_UI_H
#include "dev_lcd.h"
#define LCD_DRAW_POINT(x, y, color)                        LCD_DrawPoint(x, y, color)
#define LCD_FILL_COLOR(x, y, x1, y1, color)                LCD_Fill(x, y, x1, y1, color)

void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2);

#endif
#include"mid_ui.h"


void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
{
    u16 t; 
    int xerr=0,yerr=0,delta_x,delta_y,distance; 
    int incx,incy,uRow,uCol; 

    delta_x=x2-x1; //计算坐标增量 
    delta_y=y2-y1; 
    uRow=x1; 
    uCol=y1; 
    if(delta_x>0)incx=1; //设置单步方向 
    else if(delta_x==0)incx=0;//垂直线 
    else {incx=-1;delta_x=-delta_x;} 
    if(delta_y>0)incy=1; 
    else if(delta_y==0)incy=0;//水平线 
    else{incy=-1;delta_y=-delta_y;} 
    if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
    else distance=delta_y; 
    for(t=0;t<=distance+1;t++ )//画线输出 
    {  
        LCD_DRAW_POINT(uRow,uCol, RED);//画点 
        xerr+=delta_x ; 
        yerr+=delta_y ; 
        if(xerr>distance) 
        { 
            xerr-=distance; 
            uRow+=incx; 
        } 
        if(yerr>distance) 
        { 
            yerr-=distance; 
            uCol+=incy; 
        } 
    }  
} 

4.调用函数实现画图

#include "stm32f10x.h"
#include "bsp_lcd.h"
#include "dev_lcd.h"
#include "mid_ui.h"

int main(void)
{    
    unsigned int i,m;
    bsp_spi_init();
    bsp_gpio_init();  
    dev_lcd_init();
    
    LCD_Fill(20,20,80, 80, RED);

    LCD_DrawLine(100, 20, 60, 200);

    while(1)
    {
    
    }
}

5.代码整体结构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

入门->放弃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值