饭盒派带有一块1.77寸的液晶屏,160*128点阵大小。下面就来测试一下LCD的绘图功能。
参考例程的LCD驱动重新写了绘图相关的函数API。LCD驱动使用的是模拟SPI驱动接口。
下面看看LCD的驱动吧:
LCD的初始化部分
void Lcd_Init(void)
{
unsigned int i;
LCD_GPIO_Init();
LCD_RST_CLR;
Delay_ms(100);
LCD_RST_SET;
Delay_ms(1);
Lcd_WriteIndex(0x11);
Delay_ms (120);
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);
Lcd_WriteData(0x07);
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);
Lcd_WriteData(0x0E);
Lcd_WriteIndex(0x36);
Lcd_WriteData(0xC0);
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);
Lcd_WriteData(0x01);
Lcd_WriteIndex(0xF6);
Lcd_WriteData(0x00);
Lcd_WriteIndex(0x3A);
Lcd_WriteData(0x05);
Lcd_WriteIndex(0x29);
}
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,重新写了,支持负坐标轴显示。
uint8_t lcd_line_buff[LCD_Y_MAX * 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++;
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++;
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]]);
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]]);
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控制显示。
下面是main中初始化测试显示函数
int main(void)
{
RCC_Configuration();
SysTick_Config(SystemCoreClock/1000);
UART_Configuration();
GPIO_Configuration(CW_GPIOA, GPIO_PIN_7 | GPIO_PIN_8, 0x3);
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;
}
}
}
显示效果如下: