加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
  • 相关文件
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

【LPC845月饼板】+ 修改优化LCD驱动的分享

05/15 11:10
1675
阅读需 31 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

最近修改了LCD驱动,方便支持可以多屏显示以及坐标支持负坐标,超出显示范围时截取显示部分。

首先增加了一个屏幕数据结构体

typedef struct lcd_port_t
{
int16_t x;
int16_t y;
uint16_t w;
uint16_t h;
uint8_t buff[LCD_BUFF_SIZE * 2];
void ( * draw)(int16_t x1,int16_t y1,int16_t x2,int16_t y2,const uint8_t *pbuff);
void ( * setwindow)(int16_t x,int16_t y, int16_t width, int16_t height);
}lcd_port_t;

其中x,y标识这个lcd屏幕在画板上相对的偏移位置坐标,可以正负数据。

w,h标识这个lcd屏幕可以显示的宽度和高度。这2个值可以<=屏幕实际的宽度和高度。

buff是lcd绘图的内部缓存。

draw函数指针代表本LCD的绘图函数。

setwindow用于设置本LCD的允许显示的x,y相对坐标和w,h显示范围。

//LCD_CNT代表支持的屏幕个数。这里是1个。

lcd_port_t __spilcd[LCD_CNT] =
{
{
.x = 0,
.y = 0,
.w = LCD_W,
.h = LCD_H,
.draw = lcd_draw_image,
.setwindow = lcd_set_window,
},
};

下面是设置显示范围函数

void lcd_set_window(int16_t x,int16_t y, int16_t width, int16_t height)
{
__spilcd[0].x = x;
__spilcd[0].y = y;
__spilcd[0].w = width;
__spilcd[0].h = height;
}

最重要的绘图函数如下,后面所有绘图都基于这个绘图函数。

void lcd_draw_image(int16_t x1,int16_t y1,int16_t x2,int16_t y2,const uint8_t *pbuf)
{
int16_t i,j;
int16_t x_s,y_s,x_e, y_e;
uint8_t *ptr,*p;

if (pbuf == NULL) return;

//这里坐标减去屏幕相对坐标就是屏幕映射的显示坐标位置

x1 -= __spilcd[0].x;
x2 -= __spilcd[0].x;
y1 -= __spilcd[0].y;
y2 -= __spilcd[0].y;

if(x1 >= __spilcd[0].w) return;
else if(x1 >= 0) x_s = x1;
else x_s = 0;
if(x2 >= __spilcd[0].w) x_e = __spilcd[0].w - 1;
else if(x2 >= 0) x_e = x2;
else return;

if(y1 >= __spilcd[0].h) return;
else if(y1 >= 0) y_s = y1;
else y_s = 0;
if(y2 >= __spilcd[0].h) y_e = __spilcd[0].h - 1;
else if(y2 >= 0) y_e = y2;
else return;

ptr = (uint8_t *)pbuf + (y_s - y1) * 2 * (x2 - x1 + 1);
SPILCD_SetRegin(x_s, y_s, x_e, y_e);
for (i = y_s; i <= y_e; i++)
{
ptr += (x_s - x1) * 2;
p = __spilcd[0].buff;
for (j = x_s; j <= x_e; j++)
{
*p ++ = *ptr++;
*p ++ = *ptr++;
}
ptr += (x2 - x_e) * 2;
SPILCD_WriteMultiData(__spilcd[0].buff,(p - __spilcd[0].buff));
}
}

下面就是基于LCD屏驱动绘图的API

uint8_t lcd_line_buff[LCD_BUFF_SIZE * 2 * 2]; //长边的2倍缓存
void Lcd_DrawImage(int16_t x1,int16_t y1,int16_t x2,int16_t y2,const uint8_t *pbuf)
{
uint32_t i;
for(i=0;i<LCD_CNT;i++)
{
__spilcd[i].draw(x1,y1,x2,y2,pbuf);
}
}
void Lcd_DrawPoint(int16_t x,int16_t y,uint16_t color)
{
lcd_line_buff[0] = color>>8;
lcd_line_buff[1] = color;
Lcd_DrawImage(x,y,x,y,lcd_line_buff);
}

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;
uint8_t *p;

p = lcd_line_buff;
for(i=x1;i<=x2;i++)
{
*p ++ = color>>8;
*p ++ = color;
}
Lcd_DrawImage(x1,y1,x2,y1,lcd_line_buff);
}

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

p = lcd_line_buff;
for(i=y1;i<=y2;i++)
{
*p ++ = color>>8;
*p ++ = color;
}
Lcd_DrawImage(x1,y1,x1,y2,lcd_line_buff);
}

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_Fill(int16_t x1,int16_t y1,int16_t x2,int16_t y2, uint16_t color)
{
int i,j;
uint8_t *p;

for(j=y1;j<=y2;j++)
{
p = lcd_line_buff;
for(i=x1;i<=x2;i++)
{
*p ++ = color>>8;
*p ++ = color;
}
Lcd_DrawImage(x1,j,x2,j,lcd_line_buff);
}
}

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)
{
uint32_t i;
for(i=0;i<LCD_CNT;i++)
{
Lcd_Fill(__spilcd[i].x,__spilcd[i].y,__spilcd[i].w-1,__spilcd[i].h-1,color);
}
}

//字符点阵绘制
void Lcd_CharDot(int16_t x1, int16_t y1, uint16_t w, uint16_t h,const uint8_t *pbuf,uint16_t f_color,uint16_t b_color)
{
int16_t i,j;
uint8_t *p,*ptr;

if((pbuf == NULL)||(w == 0)||(h == 0)) return ;

ptr = (uint8_t *)pbuf;
for(i=0;i<h;i++)
{
p = lcd_line_buff;
for(j=0;j<w;)
{
if(*ptr & (0x80>>(j&0x07)))
{
*p ++ = f_color>>8;
*p ++ = f_color;
}else
{
*p ++ = b_color>>8;
*p ++ = b_color;
}
j++;
if(!(j&0x07))
{
ptr++;
}
}
Lcd_DrawImage(x1,y1+i,x1+w-1,y1+i,lcd_line_buff);
}
}

int32_t Disp0_DrawBitmap(int16_t x,int16_t y, int16_t width, int16_t height, const uint8_t *bitmap)
{
Lcd_DrawImage(x,y,x+width-1,y+height-1,bitmap);
return 0;
}

下面添加shell命令来测试各个API绘图函数:

#include "nr_micro_shell.h"

extern const unsigned char gImage_1[];

/* GLCD RGB color definitions */
#define GLCD_COLOR_BLACK 0x0000 /* 0, 0, 0 */
#define GLCD_COLOR_NAVY 0x000F /* 0, 0, 128 */
#define GLCD_COLOR_DARK_GREEN 0x03E0 /* 0, 128, 0 */
#define GLCD_COLOR_DARK_CYAN 0x03EF /* 0, 128, 128 */
#define GLCD_COLOR_MAROON 0x7800 /* 128, 0, 0 */
#define GLCD_COLOR_PURPLE 0x780F /* 128, 0, 128 */
#define GLCD_COLOR_OLIVE 0x7BE0 /* 128, 128, 0 */
#define GLCD_COLOR_LIGHT_GREY 0xC618 /* 192, 192, 192 */
#define GLCD_COLOR_DARK_GREY 0x7BEF /* 128, 128, 128 */
#define GLCD_COLOR_BLUE 0x001F /* 0, 0, 255 */
#define GLCD_COLOR_GREEN 0x07E0 /* 0, 255, 0 */
#define GLCD_COLOR_CYAN 0x07FF /* 0, 255, 255 */
#define GLCD_COLOR_RED 0xF800 /* 255, 0, 0 */
#define GLCD_COLOR_MAGENTA 0xF81F /* 255, 0, 255 */
#define GLCD_COLOR_YELLOW 0xFFE0 /* 255, 255, 0 */
#define GLCD_COLOR_WHITE 0xFFFF /* 255, 255, 255 */

static uint16_t g_color_f = GLCD_COLOR_WHITE,g_color_b = GLCD_COLOR_BLACK;
static int16_t g_x=0,g_y=0;

static uint16_t lcd_color_find(char *pstr)
{
if (!strcmp("black", pstr)) return GLCD_COLOR_BLACK;
else if (!strcmp("white", pstr)) return GLCD_COLOR_WHITE;
else if (!strcmp("red", pstr)) return GLCD_COLOR_RED;
else if (!strcmp("yellow", pstr)) return GLCD_COLOR_YELLOW;
else if (!strcmp("green", pstr)) return GLCD_COLOR_GREEN;
else if (!strcmp("blue", pstr)) return GLCD_COLOR_BLUE;
else if (!strcmp("purple", pstr)) return GLCD_COLOR_PURPLE;
else if (!strcmp("light", pstr)) return GLCD_COLOR_LIGHT_GREY;
else if (!strcmp("dark", pstr)) return GLCD_COLOR_DARK_GREY;
else return atoi(pstr);
}
/**
* @brief test command
*/

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_Fill(x1,y1,x1+x2-1,y1+y2-1,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=%04Xrn",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=%drn",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("display", &argv[argv[1]]))
{
if(argc == 5)
{
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
lcd_disp_str_at(x1,y1,&argv[argv[4]]);
}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,(uint8_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,(uint8_t *)gImage_1);
}else goto lcd_end;
}else goto lcd_end;
}else goto lcd_end;
return;
lcd_end:
printf("usage: lcd rn");
printf("lcd clear [color]rn");
printf("lcd fillrect x1 y1 w h [color]rn");
printf("lcd fillcircle x1 y1 r [color]rn");
printf("lcd hline x1 y1 w [color]rn");
printf("lcd vline x1 y1 h [color]rn");
printf("lcd circle x1 y1 r [color]rn");
printf("lcd rect x1 y1 w h [color]rn");
printf("lcd point x1 y1 [color]rn");
printf("lcd display x y string rn");
printf("lcd move x y rn");
printf("lcd image x y rn");
printf("lcd color f_color b_color rn");
}
NR_SHELL_CMD_EXPORT(lcd, shell_lcd, "lcd display test");

lpc845_mooncake.zip (5.9 MB, 点击下方附件下载)

  • lpc845_mooncake.zip

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
SN74LVC1G06DCKT 1 Texas Instruments Single 1.65-V to 5.5-V inverter with open-drain outputs 5-SC70 -40 to 125

ECAD模型

下载ECAD模型
$2.11 查看
XB3-24Z8PT-J 1 Digi International Inc Telecom Circuit, 1-Func, MODULE-20

ECAD模型

下载ECAD模型
$20.06 查看
PD69208T4ILQ-TR 1 Microsemi Corporation Power Supply Support Circuit,
暂无数据 查看

相关推荐

电子产业图谱