一個(gè)1.69寸SPI接口的液晶顯示模塊,有320*240=76800個(gè)點(diǎn),每個(gè)點(diǎn)有2個(gè)字節(jié)表示RGB的顏色,所以需要153.6K個(gè)字節(jié)的數(shù)據(jù)來刷新全屏,如果SPI口輸出數(shù)據(jù)不是高速并且不緊密排列的話,刷新就會比較慢,有從下到下的肉眼可見的刷新過程,現(xiàn)就是希望使用數(shù)據(jù)緩沖區(qū)(我理解這就是顯存的概念吧)來快速刷新顯示區(qū)域。
原始的單個(gè)字符的顯示程序:
/******************************************************************************
函數(shù)說明:顯示單個(gè)字符
入口數(shù)據(jù):x,y顯示坐標(biāo)
num 要顯示的字符
fc 字的顏色
bc 字的背景色
sizey 字號
mode: 0非疊加模式 1疊加模式
返回值: 無
******************************************************************************/
void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{
uint8_t temp,sizex,t,m=0;
uint16_t i,TypefaceNum;//一個(gè)字符所占字節(jié)大小
uint16_t x0=x;
sizex=sizey/2;
TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey;
num=num-' '; //得到偏移后的值
LCD_Address_Set(x,y,x+sizex-1,y+sizey-1); //設(shè)置光標(biāo)位置
for(i=0;i<TypefaceNum;i++)
{
if(sizey==12)temp=ascii_1206[num][i]; //調(diào)用6x12字體
else if(sizey==16)temp=ascii_1608[num][i]; //調(diào)用8x16字體
else if(sizey==24)temp=ascii_2412[num][i]; //調(diào)用12x24字體
else if(sizey==32)temp=ascii_3216[num][i]; //調(diào)用16x32字體
else return;
for(t=0;t<8;t++)
{
if(!mode)//非疊加模式
{
if(temp&(0x01<<t))LCD_WR_DATA(fc); //每一個(gè)點(diǎn)發(fā)送2個(gè)字節(jié)數(shù)據(jù)
else LCD_WR_DATA(bc);
m++;
if(m%sizex==0)
{
m=0;
break;
}
}
else//疊加模式
{
if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//畫一個(gè)點(diǎn)
x++;
if((x-x0)==sizex)
{
x=x0;
y++;
break;
}
}
}
}
}
由if(temp&(0x01<<t))LCD_WR_DATA(fc); //每一個(gè)點(diǎn)發(fā)送2個(gè)字節(jié)數(shù)據(jù)
else LCD_WR_DATA(bc);
這幾句說明每個(gè)點(diǎn),由SPI發(fā)送2個(gè)字節(jié)的數(shù)據(jù)出去,而且是一邊計(jì)算數(shù)據(jù),一邊發(fā)送數(shù)據(jù),速度較慢,可以肉眼可見的逐字顯示的。
改用緩沖區(qū)顯示單個(gè)字符:文章來源:http://www.zghlxwxcb.cn/news/detail-809135.html
void LCD_ShowChar_new(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode)
{
uint8_t temp,sizex,t,m=0;
uint16_t i,TypefaceNum;//一個(gè)字符所占字節(jié)大小
uint16_t x0=x;
sizex=sizey/2;
TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey;
num=num-' '; //得到偏移后的值
//LCD_Address_Set(x,y,x+sizex-1,y+sizey-1); //設(shè)置光標(biāo)位置
//uint8_t data[TypefaceNum * 2 * 8]; //=========
static uint8_t data[1024]; //=========重要,用靜態(tài)變量,或者用全局變量,一個(gè)字符作為一個(gè)緩沖區(qū)
uint16_t xx = 0;
for(i=0; i<TypefaceNum; i++)
{
if(sizey==12)temp=ascii_1206[num][i]; //調(diào)用6x12字體
else if(sizey==16)temp=ascii_1608[num][i]; //調(diào)用8x16字體
else if(sizey==24)temp=ascii_2412[num][i]; //調(diào)用12x24字體
else if(sizey==32)temp=ascii_3216[num][i]; //調(diào)用16x32字體
else return;
for(t=0;t<8;t++)
{
if(!mode)//非疊加模式 帶緩沖區(qū),實(shí)現(xiàn)快顯示功能
{
if(temp&(0x01<<t))
{
data[xx++] = fc>>8;
data[xx++] = fc;
// data[i*2*8 + t] == fc<<8;
// data[i*2*8 + t + 1] == fc;
// LCD_WR_DATA(fc);
}
else
{
data[xx++] = bc>>8;
data[xx++] = bc;
// data[i*2*8 + t] == bc<<8;
// data[i*2*8 + t + 1] == bc;
// LCD_WR_DATA(bc);
}
m++;
if(m%sizex==0)
{
m=0;
break;
}
}
else//疊加模式
{
if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//畫一個(gè)點(diǎn)
x++;
if((x-x0)==sizex)
{
x=x0;
y++;
break;
}
}
}
}
while(HAL_SPI_GetState(&hspi1)==HAL_SPI_STATE_BUSY_TX); //等待SPI發(fā)送完成
LCD_Address_Set(x,y,x+sizex-1,y+sizey-1); //設(shè)置光標(biāo)位置
//while(HAL_SPI_GetState(&hspi1)==HAL_SPI_STATE_BUSY_TX); //等待SPI發(fā)送完成
HAL_SPI_Transmit_DMA(&hspi1, &data, TypefaceNum * 2 * 8); //這句有嚴(yán)重問題,會死機(jī),OK
// while(HAL_SPI_GetState(&hspi1)==HAL_SPI_STATE_BUSY_TX); //等待SPI發(fā)送完成
}
使用緩沖區(qū)的方法還是和全屏刷新一樣,先把數(shù)據(jù)都放在數(shù)組,然后一次性SPI口發(fā)送出去。
緩沖區(qū)的大小是按照32字體大小的字符來計(jì)算,32字體是 16*32=512個(gè)點(diǎn),1024個(gè)字節(jié),所以使用data是1024個(gè)字節(jié)的緩沖區(qū),這個(gè)緩沖區(qū)必須是靜態(tài)或者全局的(這個(gè)問題困擾了我好久,一開始就是顯示不正常,或者死機(jī)),我的理解是SPI要取數(shù)據(jù)發(fā)送,但緩沖區(qū)沒有了,被系統(tǒng)回收了。
使用緩沖區(qū)后,字符顯示都是直接顯示,不再是一個(gè)一個(gè)字符逐個(gè)顯示的感覺了文章來源地址http://www.zghlxwxcb.cn/news/detail-809135.html
到了這里,關(guān)于STM32使用1.69寸液晶顯示模塊使用緩沖區(qū)實(shí)現(xiàn)快速刷新全屏顯示字符串功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!