一塊晶聯訊3.5吋TFT屏,用STC8H8K64S開通了SPI模式驅動成功。速度比晶聯訊公司提供的模擬SPI驅動快很多,想要再提高刷新率,就要開通DMA
模式了。手冊上說STC8H8K64S支持DMA_SPI傳輸模式。但是我是小白不會弄,網上也少有可直接引用的例程(大多是STM32的)。所以肯請高手大佬幫我完善下面的程序。謝謝。
/* 開通SPI模式驅動TFT屏的串行程序:
型號:JLX350-01901-BN、橫屏;
驅動 IC:ST7796S;
解決Keil的OxFD_BUG
1.使用HexEditor編輯Keil安裝目錄下的/keil/c51/bin/c51.exe文件,
搜索80FBFD改成80FBFF,如果使用匯編則修改A51.exe.
2.使用曉奇工作室出品的補丁程序ccKeilVxx.exe。下載后放在/keil/c51/bin/目錄下運行即可。
KeilC51 0xFD BUG補丁 ccKeilVxx.exe下載
*/
#include <STC8H.H>
#include "string.h"
#define ulong unsigned long
#define uint unsigned int
#define uchar unsigned char
//液晶屏IC 所需要的信號線的接口定義
sbit C_S = P2^2;//液晶片選CS,P1.4為單片機SPI總線的SS引腳,通過MSTR位配置為IO模式
sbit R_ESET = P0^3; //液晶RESET引腳,接單片機IO引腳
sbit C_D = P0^4;//液晶D/CX引腳,數據/命令控制,接單片機IO引腳
//以下2個引腳的連接。因接單片機默認硬件SPI引腳,只需要在SPCTL中使能即可,不需程序中定義
//sbit SDI = P2^3; 液晶SDI引腳,主機寫到液晶,接單片機MOSI引腳P1.5
//sbit SCL = P2^5; 液晶SCL時鐘引腳,接單片機SCLK時鐘引腳P1.7
#define red 0xf800 //定義紅色
#define blue 0x001f //定義藍色
#define green 0x07e0 //定義綠色
#define white 0xffff //定義白色
struct typFNT_GBK16
{
char Index[2];//記錄漢字的編碼
uchar Msk[32];//記錄漢字的字模
}typFNT_GBK16;//字表結構體,16*16的漢字庫
struct typFNT_GBK16 code F16x16[]= //逐行式,順向
{
"產",0x02,0x00,0x01,0x00,0x7f,0xfc,0x00,0x00,0x08,0x20,0x04,0x20,0x04,0x40,0x3f,0xfe, /* 116 */
0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x80,0x00,
"全",0x01,0x00,0x01,0x00,0x02,0x80,0x04,0x40,0x08,0x20,0x10,0x10,0x2f,0xe8,0xc1,0x06, /* 129 */
0x01,0x00,0x01,0x00,0x1f,0xf0,0x01,0x00,0x01,0x00,0x01,0x00,0x7f,0xfc,0x00,0x00,
"面",0x00,0x00,0xff,0xfe,0x02,0x00,0x02,0x00,0x04,0x00,0x3f,0xf8,0x24,0x48,0x24,0x48, /* 130 */
0x27,0xc8,0x24,0x48,0x24,0x48,0x27,0xc8,0x24,0x48,0x24,0x48,0x3f,0xf8,0x20,0x08,
"提",0x10,0x00,0x11,0xfc,0x11,0x04,0x11,0x04,0xfd,0xfc,0x11,0x04,0x11,0x04,0x15,0xfc, /* 131 */
0x18,0x00,0x33,0xfe,0xd0,0x20,0x11,0x20,0x11,0x3c,0x11,0x20,0x52,0xa0,0x24,0x7e,
"升",0x01,0x20,0x07,0xa0,0x3c,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0xff,0xfe, /* 132 */
0x04,0x20,0x04,0x20,0x04,0x20,0x08,0x20,0x08,0x20,0x10,0x20,0x20,0x20,0x40,0x20,
"新",0x10,0x00,0x08,0x04,0x7f,0x78,0x00,0x40,0x22,0x40,0x14,0x40,0xff,0x7e,0x08,0x48, /* 134 */
0x08,0x48,0x7f,0x48,0x08,0x48,0x2a,0x48,0x49,0x48,0x88,0x88,0x28,0x88,0x11,0x08,
"質",0x00,0x7c,0x3f,0xc0,0x20,0x40,0x20,0x40,0x3f,0xfe,0x20,0x40,0x20,0x40,0x27,0xfc, /* 135 */
0x24,0x04,0x24,0x44,0x24,0x44,0x24,0x44,0x24,0xb4,0x41,0x08,0x46,0x04,0x98,0x02,
"生",0x01,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x3f,0xfc,0x21,0x00,0x41,0x00,0x81,0x00, /* 136 */
0x01,0x00,0x3f,0xf8,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xff,0xfe,0x00,0x00,
"力",0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x7f,0xf8,0x02,0x08,0x02,0x08,0x02,0x08, /* 137 */
0x02,0x08,0x04,0x08,0x04,0x08,0x08,0x08,0x08,0x08,0x10,0x88,0x20,0x50,0x40,0x20,
};
//函數
void Delay_us(int value)////延時函數_us
{
while (value)
value--;
}
void Delay_ms(int value)////延時函數_ms
{
while (value--){
Delay_us(999);
value--;
}
}
void SPI_Init()
{
P_SW1 = (P_SW1 & ~0x0c) | 0x04; //SPI: SS(P2.2), MOSI(P2.3), MISO(P2.4), SCLK(P2.5)
//SPI初始化
SPDAT = 0;
SPCTL = 0xd0; //設置1101,0000; SPI控制寄存器
SPSTAT = 0xc0; //標志位寫1清零 (SPSTAT)SPI狀態寄存器 //
}
void LCD_Writ_Bus(char a)
{ //數據寫入函數 8位
C_S = 0;
SPDAT = a;//開始傳輸
while(!(SPSTAT&0x80)); // 等待SPIF = 1,傳輸完成
SPSTAT = 0xc0;
C_S = 1;
}
void transfer_command(char cmd)//8 bit
{
C_D = 0;
LCD_Writ_Bus(cmd);
}
void transfer_data(char com_data)//8 bit
{
C_D = 1;
LCD_Writ_Bus(com_data);
}
void transfer_data_16(int a)//16位數據,分兩次,每次送8位
{
C_D = 1;
LCD_Writ_Bus(a>>8);
LCD_Writ_Bus(a);
}
void lcd_initial()
{
R_ESET=1;
Delay_ms(100);
R_ESET=0;
Delay_ms(200);
R_ESET=1;
Delay_ms(50);
//************* Start Initial Sequence **********//
transfer_command(0x11); //Sleep Out
Delay_ms(200);
transfer_command(0xf0); //
transfer_data(0xc3); //enable command 2 part 1
transfer_command(0xf0);
transfer_data(0x96); //enable command 2 part 2
transfer_command(0x36); //內存數據訪問控制
transfer_data(0x28); //0x28橫屏顯示,0x48豎屏顯示; 0xe8,顛倒順序
// transfer_data(0xe8); //
transfer_command(0x3a); //16bit pixel
transfer_data(0x55);
transfer_command(0xb4);
transfer_data(0x01);
transfer_command(0xb7);
transfer_data(0xc6);
transfer_command(0xf0);
transfer_data(0x69);
Delay_ms(120);
//transfer_command(0x21); //IPS必須加這條指令
transfer_command(0x29); //Display ON
transfer_command(0x2c); // 寫數據開始
}
//定義窗口坐標:開始坐標(XS,YS)以及窗口大小(x_total,y_total)
void lcd_address(int XS,int YS,int x_total,int y_total)
{
int XE,YE;
XE=XS+x_total-1;
YE=YS+y_total-1;
transfer_command(0x2a); // 設置 X 開始及結束的地址
transfer_data_16(XS); // X 開始地址(16位)
transfer_data_16(XE); // X 結束地址(16位)
transfer_command(0x2b); // 設置 Y 開始及結束的地址
transfer_data_16(YS); // Y 開始地址(16位)
transfer_data_16(YE); // Y 結束地址(16位)
transfer_command(0x2c); // 寫數據開始
}
void mono_transfer_data_16(int mono_data,int font_color,int back_color)
{
int i;
for(i=0;i<8;i++)
{
if(mono_data&0x80)
{
transfer_data_16(font_color); //當數據是1時,顯示字體顏色
}
else
{
transfer_data_16(back_color); //當數據是0時,顯示底色
}
mono_data<<=1;
}
}
//全屏顯示一種顏色
void display_color(uint color_data)
{
int i,j;
lcd_address(0,0,480,320);
for(i=0;i<480;i++)
{
for(j=0;j<320;j++)
{
transfer_data_16(color_data);
}
}
}
// //顯示結構體字庫的16x16純漢字
void display_hanzi_16x16(int x,int y,uchar *text,int font_color,int back_color)
{
uint j,k,m;// i,
uint address;
uint WordNum;//記錄字表的字數
j = 0;
WordNum=sizeof(F16x16)/sizeof(typFNT_GBK16);//算出數組漢字的數量
while(text[j]>128) // >0x7f即說明不是 ASCII 碼字符 //'\0' 字符串結束標志
{
address = 1;
for(m=0;m<WordNum;m++)//遍歷查表,尋出字模
{
if((F16x16[m].Index[0]==*(text))&&(F16x16[m].Index[1]==*(text+1)))//Index[0]指漢字的GBK編碼的低8位,Index[1]是高8位
{
address = j * 16;
break;
}
}
if(address != 1)// 顯示漢字
{
lcd_address(x,y,16,16);
for(k = 0; k <32; k++)
{
mono_transfer_data_16(F16x16[m].Msk[k],font_color,back_color);
address++;
}
text+=2;
}
else //顯示空白字符
{
lcd_address(x,y,16,16);
for(k = 0; k < 32; k++)
{
mono_transfer_data_16(0x00,font_color,back_color);
}
text+=2;
}
x=x+16;
if(x > 480-16)
{
x=0;
y+=18;
}
}
}
void main(void)
{
P0M0=0; P0M1=0; P1M0=0; P1M1=0;P2M0=0x00; P2M1=0x00;
SPI_Init();//
lcd_initial();
display_color(blue);
while(1)
{
display_hanzi_16x16(58, 6,"全面提升新質生產力", white, blue);
}
}
|