芯源半导体CW32
直播中

郭学深

3年用户 35经验值
擅长:嵌入式技术,处理器/DSP,控制/MCU
私信 关注
[经验]

【CW32饭盒派开发板试用体验】+ LCD 绘图显示测试

饭盒派带有一块1.77寸的液晶屏,160*128点阵大小。下面就来测试一下LCD的绘图功能。
参考例程的LCD驱动重新写了绘图相关的函数API。LCD驱动使用的是模拟SPI驱动接口。
下面看看LCD的驱动吧:
LCD的初始化部分

//LCD Init For 1.44Inch LCD Panel with ST7735R.
void Lcd_Init(void)
{
    unsigned int i;
    
    LCD_GPIO_Init();
    //Reset before LCD Init.
    LCD_RST_CLR;
    Delay_ms(100);
    LCD_RST_SET;
    Delay_ms(1);
    
    //LCD Init For 1.44Inch LCD Panel with ST7735R.
    Lcd_WriteIndex(0x11);//Sleep exit 
    Delay_ms (120);
    
    //ST7735R Frame Rate
    Lcd_WriteIndex(0xB1); 
    Lcd_WriteData(0x01); 
    Lcd_WriteData(0x2C); 
    Lcd_WriteData(0x2D); 

    Lcd_WriteIndex(0xB2); 
    Lcd_WriteData(0x01); 
    Lcd_WriteData(0x2C); 
    Lcd_WriteData(0x2D); 

    Lcd_WriteIndex(0xB3); 
    Lcd_WriteData(0x01); 
    Lcd_WriteData(0x2C); 
    Lcd_WriteData(0x2D); 
    Lcd_WriteData(0x01); 
    Lcd_WriteData(0x2C); 
    Lcd_WriteData(0x2D); 
    
    Lcd_WriteIndex(0xB4); //Column inversion 
    Lcd_WriteData(0x07); 
    
    //ST7735R Power Sequence
    Lcd_WriteIndex(0xC0); 
    Lcd_WriteData(0xA2); 
    Lcd_WriteData(0x02); 
    Lcd_WriteData(0x84); 
    Lcd_WriteIndex(0xC1); 
    Lcd_WriteData(0xC5); 

    Lcd_WriteIndex(0xC2); 
    Lcd_WriteData(0x0A); 
    Lcd_WriteData(0x00); 

    Lcd_WriteIndex(0xC3); 
    Lcd_WriteData(0x8A); 
    Lcd_WriteData(0x2A); 
    Lcd_WriteIndex(0xC4); 
    Lcd_WriteData(0x8A); 
    Lcd_WriteData(0xEE); 
    
    Lcd_WriteIndex(0xC5); //VCOM 
    Lcd_WriteData(0x0E); 
    
    Lcd_WriteIndex(0x36); //MX, MY, RGB mode 
    Lcd_WriteData(0xC0); 
    
    //ST7735R Gamma Sequence
    Lcd_WriteIndex(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_WriteIndex(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_WriteIndex(0x2a);
    Lcd_WriteData(0x00);
    Lcd_WriteData(0x00);
    Lcd_WriteData(0x00);
    Lcd_WriteData(0x7f);

    Lcd_WriteIndex(0x2b);
    Lcd_WriteData(0x00);
    Lcd_WriteData(0x00);
    Lcd_WriteData(0x00);
    Lcd_WriteData(0x9f);
    
    Lcd_WriteIndex(0xF0); //Enable test command  
    Lcd_WriteData(0x01); 
    Lcd_WriteIndex(0xF6); //Disable ram power save mode 
    Lcd_WriteData(0x00); 
    
    Lcd_WriteIndex(0x3A); //65k mode 
    Lcd_WriteData(0x05); 
    
    Lcd_WriteIndex(0x29);//Display on
}


/*************************************************
函数名:LCD_Set_Region
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:xy起点和终点
返回值:无
*************************************************/
void Lcd_SetRegion(unsigned int x_start,unsigned int y_start,unsigned int x_end,unsigned int y_end)
{
    Lcd_WriteIndex(0x2a);
    Lcd_WriteData(0x00);
    Lcd_WriteData(x_start);
    Lcd_WriteData(0x00);
    Lcd_WriteData(x_end);

    Lcd_WriteIndex(0x2b);
    Lcd_WriteData(0x00);
    Lcd_WriteData(y_start);
    Lcd_WriteData(0x00);
    Lcd_WriteData(y_end);
    
    Lcd_WriteIndex(0x2c);
}

LCD绘图部分API,重新写了,支持负坐标轴显示。

/*************************************************
函数名:LCD_DrawPoint
功能:画一个点
入口参数:无
返回值:无
*************************************************/
uint8_t lcd_line_buff[LCD_Y_MAX * 2];   //长边的2倍缓存

void Lcd_DrawPoint(int16_t x,int16_t y,uint16_t color)
{
    if((x >= LCD_X_MAX)||(y >= LCD_Y_MAX)||(x<0)||(y<0))  return ;
    Lcd_SetRegion(x,y,x+1,y);
    LCD_WriteData_16Bit(color);
}

//取模方式 水平扫描 从左到右 低位在前
void Lcd_DrawImage(int16_t x1,int16_t y1,int16_t x2,int16_t y2,const uint16_t *pbuf)
{
    int16_t i,j;
    int16_t x_s,y_s,x_e, y_e;
    uint8_t *ptr,*p;

    if(x1 >= LCD_X_MAX) return;
    else if(x1 > 0)    x_s = x1;
    else x_s = 0;
    
    if(y1 >= LCD_Y_MAX) return;
    else if(y1 > 0)    y_s = y1;
    else y_s = 0;
    
    if(x2 >= LCD_X_MAX)  x_e  = LCD_X_MAX - 1;
    else if(x2 > 0) x_e = x2;
    else return;
    
    if(y2 >= LCD_Y_MAX)  y_e  = LCD_Y_MAX - 1;
    else if(y2 > 0) y_e = y2;
    else return;

    if (pbuf)
    {
        ptr = (uint8_t *)pbuf + (y_s - y1) * 2 * LCD_X_MAX;
        LCD_CS_CLR;
        Lcd_SetRegion(x_s, y_s, x_e, y_e);
        for (i = y_s; i <= y_e; i++)
        {
            ptr += (x_s - x1) * 2;
            p = lcd_line_buff;
            for (j = x_s; j <= x_e; j++)
            {
                *p ++ = *ptr++;
                *p ++ = *ptr++;
            }
            ptr += (x2 - x_e) * 2;
            Lcd_WriteBuff(lcd_line_buff,(p - lcd_line_buff));
        }
        LCD_CS_SET;
    }
}

void Lcd_Fill(int16_t x1,int16_t y1,int16_t x2,int16_t y2, uint16_t color)
{
    int16_t i,j;
    int16_t x_s,y_s,x_e, y_e;
    uint8_t *p;

    if(x1 >= LCD_X_MAX) return;
    else if(x1 > 0)    x_s = x1;
    else x_s = 0;
    
    if(y1 >= LCD_Y_MAX) return;
    else if(y1 > 0)    y_s = y1;
    else y_s = 0;
    
    if(x2 >= LCD_X_MAX)  x_e  = LCD_X_MAX - 1;
    else if(x2 > 0) x_e = x2;
    else return;
    
    if(y2 >= LCD_Y_MAX)  y_e  = LCD_Y_MAX - 1;
    else if(y2 > 0) y_e = y2;
    else return;
    
    LCD_CS_CLR;
    Lcd_SetRegion(x_s, y_s, x_e, y_e);
    for (i = y_s; i <= y_e; i++)
    {
        p = lcd_line_buff;
        for (j = x_s; j <= x_e; j++)
        {
            *p ++ = color>>8;
            *p ++ = color;
        }
        Lcd_WriteBuff(lcd_line_buff,(p - lcd_line_buff));
    }
    LCD_CS_SET;
}

void Lcd_FillRect(int16_t x_start, int16_t y_start, uint16_t width, uint16_t height, uint16_t color)
{
    if((width <= 0)||(height <= 0))    return;
    Lcd_Fill(x_start,y_start,x_start+width-1,y_start+height-1,color);
}

void Lcd_DrawCircle(int16_t x0, int16_t y0, uint16_t r,uint16_t color)
{
    int a, b;
    int di;
    
    if(r <= 0)  return;
    else if(r == 1)
    {
        Lcd_DrawPoint(x0, y0, color);
        return;
    }
    a = 0;
    b = r;
    di = 3 - (r << 1);
    while (a <= b)
    {
        Lcd_DrawPoint(x0 - b, y0 - a, color);
        Lcd_DrawPoint(x0 + b, y0 - a, color);
        
        Lcd_DrawPoint(x0 - b, y0 + a, color);
        Lcd_DrawPoint(x0 + b, y0 + a, color);
        
        Lcd_DrawPoint(x0 - a, y0 - b, color);
        Lcd_DrawPoint(x0 + a, y0 - b, color);
        
        Lcd_DrawPoint(x0 - a, y0 + b, color);
        Lcd_DrawPoint(x0 + a, y0 + b, color);
        
        Lcd_DrawPoint(x0 - b, y0 - a, color);
        a++;
        //Bresenham
        if (di < 0)di += 4 * a + 6;
        else
        {
            di += 10 + 4 * (a - b);
            b--;
        }
        Lcd_DrawPoint(x0 + a, y0 + b, color);
    }
}

void Lcd_DrawHLine(int16_t x1, int16_t y1, int16_t x2,uint16_t color)
{
    int16_t i;
    int16_t x_s,x_e;
    uint8_t *p;
    
    if((y1 >= LCD_Y_MAX)||(y1 < 0)) return;
    
    if(x1 >= LCD_X_MAX) return;
    else if(x1 > 0)    x_s = x1;
    else x_s = 0;
    
    if(x2 >= LCD_X_MAX)  x_e  = LCD_X_MAX - 1;
    else if(x2 > 0) x_e = x2;
    else return;
    
    LCD_CS_CLR;
    Lcd_SetRegion(x_s, y1, x_e, y1);
    p = lcd_line_buff;
    for (i = x_s; i <= x_e; i++)
    {
        *p ++ = color>>8;
        *p ++ = color;
    }
    Lcd_WriteBuff(lcd_line_buff,(p - lcd_line_buff));
    LCD_CS_SET;
}

void Lcd_DrawVLine(int16_t x1, int16_t y1, int16_t y2,uint16_t color)
{
    int16_t i;
    int16_t y_s, y_e;
    uint8_t *p;

    if((x1 >= LCD_X_MAX)||(x1 < 0)) return;
    
    if(y1 >= LCD_Y_MAX) return;
    else if(y1 > 0)    y_s = y1;
    else y_s = 0;
    
    if(y2 >= LCD_Y_MAX)  y_e  = LCD_Y_MAX - 1;
    else if(y2 > 0) y_e = y2;
    else return;
    
    LCD_CS_CLR;
    Lcd_SetRegion(x1, y_s, x1, y_e);
    p = lcd_line_buff;
    for (i = y_s; i <= y_e; i++)
    {
        *p ++ = color>>8;
        *p ++ = color;
    }
    Lcd_WriteBuff(lcd_line_buff,(p - lcd_line_buff));
    LCD_CS_SET;
}

void Lcd_DrawRect(int16_t x1,int16_t y1,int16_t x2,int16_t y2,uint16_t color)
{
  Lcd_DrawHLine(x1, y1, x2, color);
  Lcd_DrawHLine(x1, y2, x2, color);
  Lcd_DrawVLine(x1, y1, y2, color);
  Lcd_DrawVLine(x2, y1, y2, color);
}

void Lcd_FillCircle(int16_t x0, int16_t y0, uint16_t r,uint16_t color)
{
    int a, b;
    int di;

    if(r <= 0)  return;
    else if(r == 1)
    {
        Lcd_DrawPoint(x0, y0, color);
        return;
    }
    a = 0;
    b = r;
    di = 3 - (r << 1);
    while (a <= b)
    {
        Lcd_DrawHLine(x0 - b, y0 - a, x0 + b, color);
        Lcd_DrawHLine(x0 - a, y0 + b, x0 + a, color);
        Lcd_DrawHLine(x0 - a, y0 - b, x0 + a, color);
        Lcd_DrawHLine(x0 - b, y0 + a, x0 + b, color);
        
        Lcd_DrawPoint(x0 - b, y0 - a, color);
        a++;
        //Bresenham
        if (di < 0)di += 4 * a + 6;
        else
        {
            di += 10 + 4 * (a - b);
            b--;
        }
        Lcd_DrawPoint(x0 + a, y0 + b, color);
    }
}

void Lcd_Clear(uint16_t color)
{
    Lcd_Fill(0,0,LCD_X_MAX-1,LCD_Y_MAX-1,color);
}

上篇已经移植了串口shell,这次LCD显示也加上了 用shell控制绘图API命令了。

void shell_lcd(char argc, char *argv)
{
    int color;
    int x1,y1,x2,y2;
    if (argc > 1)
    {
        if (!strcmp("clear", &argv[argv[1]]))
        {
            if(argc == 3)
            {
                color = lcd_color_find(&argv[argv[2]]);
            }else if(argc == 2)
            {
                color = g_color_b;
            }else goto lcd_end;
            Lcd_Clear(color);
        }else if (!strcmp("fillrect", &argv[argv[1]]))
        {
            if(argc == 6)
            {
                color = g_color_f;
            }else if(argc == 7)
            {
                color = lcd_color_find(&argv[argv[6]]);
            }else goto lcd_end;
            x1 = atoi(&argv[argv[2]]);
            y1 = atoi(&argv[argv[3]]);
            x2 = atoi(&argv[argv[4]]);
            y2 = atoi(&argv[argv[5]]);
            if(x2 && y2)    Lcd_FillRect(x1,y1,x2,y2,color);
            else printf("w h must > 0");
        }else if (!strcmp("fillcircle", &argv[argv[1]]))
        {
            if(argc == 5)
            {
                color = g_color_f;
            }else if(argc == 6)
            {
                color = lcd_color_find(&argv[argv[5]]);
            }else goto lcd_end;
            x1 = atoi(&argv[argv[2]]);
            y1 = atoi(&argv[argv[3]]);
            x2 = atoi(&argv[argv[4]]);  //r
            if(x2)  Lcd_FillCircle(x1,y1,x2,color);
            else printf("r must > 0");
        }else if (!strcmp("vline", &argv[argv[1]]))
        {
            if(argc == 5)
            {
                color = g_color_f;
            }else if(argc == 6)
            {
                color = lcd_color_find(&argv[argv[5]]);
            }else goto lcd_end;
            x1 = atoi(&argv[argv[2]]);
            y1 = atoi(&argv[argv[3]]);
            y2 = atoi(&argv[argv[4]]);
            if(y2)  Lcd_DrawVLine(x1,y1,y1+y2-1,color);
            else printf("h must > 0");
        }else if (!strcmp("hline", &argv[argv[1]]))
        {
            if(argc == 5)
            {
                color = g_color_f;
            }else if(argc == 6)
            {
                color = lcd_color_find(&argv[argv[5]]);
            }else goto lcd_end;
            x1 = atoi(&argv[argv[2]]);
            y1 = atoi(&argv[argv[3]]);
            x2 = atoi(&argv[argv[4]]);
            if(x2)  Lcd_DrawHLine(x1,y1,x1+x2-1,color);
            else printf("w  must > 0");
        }else if (!strcmp("circle", &argv[argv[1]]))
        {
            if(argc == 5)
            {
                color = g_color_f;
            }else if(argc == 6)
            {
                color = lcd_color_find(&argv[argv[5]]);
            }else goto lcd_end;
            x1 = atoi(&argv[argv[2]]);
            y1 = atoi(&argv[argv[3]]);
            x2 = atoi(&argv[argv[4]]);  //r
            if(x2)   Lcd_DrawCircle(x1,y1,x2,color);
            else printf("r must > 0");
        }else if (!strcmp("rect", &argv[argv[1]]))
        {
            if(argc == 6)
            {
                color = g_color_f;
            }else if(argc == 7)
            {
                color = lcd_color_find(&argv[argv[6]]);
            }else goto lcd_end;
            x1 = atoi(&argv[argv[2]]);
            y1 = atoi(&argv[argv[3]]);
            x2 = atoi(&argv[argv[4]]);
            y2 = atoi(&argv[argv[5]]);
            if(x2 && y2)    Lcd_DrawRect(x1,y1,x1+x2-1,y1+y2-1,color);
            else printf("w h must > 0");
        }else if (!strcmp("point", &argv[argv[1]]))
        {
            if(argc == 4)
            {
                color = g_color_f;
            }else if(argc == 5)
            {
                color = lcd_color_find(&argv[argv[4]]);
            }else goto lcd_end;
            x1 = atoi(&argv[argv[2]]);
            y1 = atoi(&argv[argv[3]]);
            Lcd_DrawPoint(x1,y1,color);
        }else if (!strcmp("color", &argv[argv[1]]))
        {
            if(argc == 2)
            {
                printf("f_color=%04X,b_color=%04X\r\n",g_color_f,g_color_b);
            }else if(argc == 4)
            {
                g_color_f = lcd_color_find(&argv[argv[2]]);
                g_color_b = lcd_color_find(&argv[argv[3]]);
            }else goto lcd_end;
        }else if (!strcmp("move", &argv[argv[1]]))
        {
            if(argc == 2)
            {
                printf("x=%d,y=%d\r\n",g_x,g_y);
            }else if(argc == 4)
            {
                g_x = atoi(&argv[argv[2]]);
                g_y = atoi(&argv[argv[3]]);
            }else goto lcd_end;
        }else if (!strcmp("image", &argv[argv[1]]))
        {
            if(argc == 2)
            {
                Lcd_DrawImage(g_x,g_y,g_x+39,g_y+39,(uint16_t *)gImage_1);
            }else if(argc == 4)
            {
                x1 = atoi(&argv[argv[2]]);
                y1 = atoi(&argv[argv[3]]);
                Lcd_DrawImage(x1,y1,x1+39,y1+39,(uint16_t *)gImage_1);
            }else goto lcd_end;
        }else goto lcd_end;
    }else goto lcd_end;
    return;
lcd_end:
    printf("usage: lcd  clear/fillrect/fillcircle/hline/vline/circle/rect/point/color/move/image \r\n");
    printf("lcd clear                    [color]\r\n");
    printf("lcd fillrect     x1 y1 w  h  [color]\r\n");
    printf("lcd fillcircle   x1 y1 r     [color]\r\n");
    printf("lcd hline        x1 y1 w     [color]\r\n");
    printf("lcd vline        x1 y1    h  [color]\r\n");
    printf("lcd circle       x1 y1 r     [color]\r\n");
    printf("lcd rect         x1 y1 w  h  [color]\r\n");
    printf("lcd point        x1 y1       [color]\r\n");
    printf("lcd move         x  y             \r\n");
    printf("lcd image        x  y             \r\n");
    printf("lcd color        f_color  b_color \r\n");

}
NR_SHELL_CMD_EXPORT(lcd, shell_lcd, "lcd display test");

可以通过串口shell控制显示。

image.png

下面是main中初始化测试显示函数

int main(void)
{
    RCC_Configuration();
    SysTick_Config(SystemCoreClock/1000);
    UART_Configuration();
    GPIO_Configuration(CW_GPIOA, GPIO_PIN_7 | GPIO_PIN_8, 0x3);   //LED灯
    Lcd_Init();
    printf("uart test out\r\n");
    
    
    Lcd_Fill(0,0,LCD_X_MAX-1,LCD_Y_MAX-1,GLCD_COLOR_RED);
    Delay_ms(100);
    Lcd_Fill(0,0,LCD_X_MAX-1,LCD_Y_MAX-1,GLCD_COLOR_GREEN);
    Delay_ms(100);
    Lcd_Fill(0,0,LCD_X_MAX-1,LCD_Y_MAX-1,GLCD_COLOR_BLUE);
    Delay_ms(100);
    Lcd_DrawImage(10,10,49,49,(uint16_t *)gImage_1);
    Lcd_DrawCircle(80,80,40,GLCD_COLOR_RED);
    Lcd_FillRect(52,52,56,56,GLCD_COLOR_GREEN);
    Lcd_FillCircle(2,90,20,GLCD_COLOR_YELLOW);
    Lcd_DrawRect(50,50,110,110,GLCD_COLOR_WHITE); 
    Lcd_FillCircle(60,120,20,GLCD_COLOR_YELLOW);
    shell_init();
    while (1)
    {
        if(shell_uart_rx.read_i != shell_uart_rx.write_i)
        {
            shell(shell_uart_rx.buff[shell_uart_rx.read_i++]);
            shell_uart_rx.read_i &= 0x7f;
        }
    }
}

显示效果如下:

lcd显示

更多回帖

发帖
×
20
完善资料,
赚取积分