测试使用开发板硬件SPI方式来驱动单色LCD显示屏。
一、硬件部分
测试使用芯片内部的LPSPI1接口,对应的电路图如下
需要调整R60电阻到B端,连接到P2.13端口上。
二、配置SPI
在Config Tools软件中配置SPI端口和时钟
2.1、配置SPI端口
2.2、配置SPI时钟
三、程序部分
3.1、spi.c
#include "main.h"
void init_spi(void)
{
uint32_t srcClock_Hz;
lpspi_master_config_t masterConfig;
/*Master config*/
LPSPI_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate = TRANSFER_BAUDRATE;
masterConfig.whichPcs = EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT;
masterConfig.pcsToSckDelayInNanoSec = 1000000000U / (masterConfig.baudRate * 2U);
masterConfig.lastSckToPcsDelayInNanoSec = 1000000000U / (masterConfig.baudRate * 2U);
masterConfig.betweenTransferDelayInNanoSec = 1000000000U / (masterConfig.baudRate * 2U);
srcClock_Hz = LPSPI_MASTER_CLK_FREQ;
LPSPI_MasterInit(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterConfig, srcClock_Hz);
}
uint8_t spi1_writedat(uint8_t dat)
{
uint8_t srcBuff[2];
uint8_t destBuff[2];
srcBuff[0]=dat;
lpspi_transfer_t masterXfer;
/*Start master transfer*/
masterXfer.txData = srcBuff;
masterXfer.rxData = destBuff;
masterXfer.dataSize = 1;
masterXfer.configFlags =
EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;
LPSPI_MasterTransferBlocking(EXAMPLE_LPSPI_MASTER_BASEADDR, &masterXfer);
return destBuff[0];
}
3.2、spi.h
#ifndef __SPI_H
#define __SPI_H
#define LPSPI_MASTER_CLK_FREQ (CLOCK_GetLpspiClkFreq(1))
#define EXAMPLE_LPSPI_MASTER_BASEADDR (LPSPI1)
#define EXAMPLE_LPSPI_MASTER_PCS_FOR_INIT (kLPSPI_Pcs0)
#define EXAMPLE_LPSPI_MASTER_PCS_FOR_TRANSFER (kLPSPI_MasterPcs0)
#define TRANSFER_SIZE 64U
#define TRANSFER_BAUDRATE 50000000U
void init_spi(void);
uint8_t spi1_writedat(uint8_t dat);
#endif
3.3、fun_jlx12864.c
#include "main.h"
#include "lcd_jlx12864g/fun_jlx12864g_font.h"
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
volatile static uint8_t lcdGram[128][8];
void lcd_writebyte(uint8_t dat)
{
spi1_writedat(dat);
}
void lcd_jlx12864g_write_cmd(uint8_t cmd)
{
uint8_t i=0;
lcd_jlx12864g_cs_l();
lcd_jlx12864g_rs_l();
lcd_writebyte(cmd);
}
void lcd_jlx12864g_write_dat(uint8_t dat)
{
uint8_t i=0;
lcd_jlx12864g_cs_l();
lcd_jlx12864g_rs_h();
lcd_writebyte(dat);
}
void lcd_refreshGram(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
lcd_jlx12864g_write_cmd (0xb0+i); //write page
lcd_jlx12864g_write_cmd (0x00);
lcd_jlx12864g_write_cmd (0x10);
for(n=0;n<128;n++)
lcd_jlx12864g_write_dat(lcdGram[n][i]);
}
}
void lcd_clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
for(n=0;n<128;n++)
lcdGram[n][i]=0X00;
lcd_refreshGram();
}
void lcd_drawPoint(uint8_t x,uint8_t y,uint8_t t)
{
uint8_t pos,bx,temp=0;
if(x>127||y>63)return;
pos=7-y/8;
bx=y%8;
temp=1<<(7-bx);
if(t)lcdGram[x][pos]|=temp;
else lcdGram[x][pos]&=~temp;
}
//读点
//x:0~127
//y:0~63
uint8_t lcd_readPoint(uint8_t x,uint8_t y)
{
uint8_t pos,bx,temp=0x00;
//x = 127-x;
y = 63-y;
pos=y/8;
bx=y%8;
temp=1<<bx;
if(temp&lcdGram[x][pos]) return 1;
return 0;
}
//x1,y1,x2,y2 填充区域的对角坐标
//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63
//dot:0,清空;1,填充
void lcd_fill(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t dot)
{
uint8_t x,y;
for(x=x1;x<=x2;x++)
for(y=y1;y<=y2;y++)
lcd_drawPoint(x,y,dot);
// oled_refreshGram();//更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//f_w:字宽
//f_h:字高
//mode:0,反白显示;1,正常显示
void lcd_showChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t f_w,uint8_t f_h,uint8_t mode)
{
uint8_t temp,t,t1;
uint8_t y0=y;
uint8_t csize=(f_h/8+((f_h%8)?1:0))*f_w;
chr=chr-' ';
for(t=0;t<csize;t++)
{
if(f_w==6&&f_h==8)temp=asc2_0608[chr][t];
else if(f_w==6&&f_h==12)temp=asc2_0612[chr][t];
else if(f_w==12&&f_h==24)temp=asc2_1224[chr][t];
else return;
for(t1=0;t1<8;t1++)
{
if(temp&0x80)lcd_drawPoint(x,y,mode);
else lcd_drawPoint(x,y,!mode);
temp<<=1;
y++;
if((y-y0)==f_h)
{
y=y0;
x++;
break;
}
}
}
}
//m^n函数
uint32_t mypow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//f_w:字宽
//f_h:字高
//mode:模式 0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void lcd_showNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t f_w,uint8_t f_h)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/mypow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
lcd_showChar(x+(f_w)*t,y,' ',f_w,f_h,1);
continue;
}
else
enshow=1;
}
lcd_showChar(x+(f_w)*t,y,temp+'0',f_w,f_h,1);
}
}
//显示字符串
//x,y:起点坐标
//f_w:字宽
//f_h:字高
//*p:字符串起始地址
void lcd_showString(uint8_t x,uint8_t y,const uint8_t *p,uint8_t f_w,uint8_t f_h)
{
while((*p<='~')&&(*p>=' '))
{
if(x>(128-(f_w))){x=0;y+=f_h;}
if(y>(64-f_h)){y=x=0;lcd_clear();}
lcd_showChar(x,y,*p,f_w,f_h,1);
x+=f_w;
p++;
}
}
//显示图片
//x,y:起点坐标
//p_w:图片宽(单位像素)
//p_h:图片高(单位像素)
//*p:图片起始地址
void lcd_showPicture(uint8_t x,uint8_t y,const uint8_t *p,uint8_t p_w,uint8_t p_h)
{
uint8_t temp,i,col,row;
uint8_t y0=y;
uint8_t width=p_w;
if(x+p_w>128)width=128-p_w;//实际显示宽度
uint8_t high=p_h;
if(y+p_h>64)high=64-p_h;//实际显示高度
uint8_t exp_col_bytes=(p_h/8+((p_h%8)?1:0));//显示一列的字节数
uint8_t act_col_bytes=(high/8+((high%8)?1:0));//实际显示一列的字节数
for(row=0;row<width;row++)//列++
{
for(col=0;col<act_col_bytes;col++)//显示一列
{
temp = p[col+row*exp_col_bytes];
for(i=0;i<8;i++)
{
if(temp&0x80)lcd_drawPoint(x,y,1);
else lcd_drawPoint(x,y,0);
temp<<=1;
y++;
if((y-y0)==high)
{
y=y0;
x++;
break;
}
}
}
}
}
void init_lcd_jlx12864g(void)
{
lcd_jlx12864g_cs_h();
lcd_jlx12864g_rst_l();
SysTick_Delay_ms(200);
lcd_jlx12864g_rst_h();
SysTick_Delay_ms(200);
lcd_jlx12864g_write_cmd(0xe2);
lcd_jlx12864g_write_cmd(0x2c);
lcd_jlx12864g_write_cmd(0x2e);
lcd_jlx12864g_write_cmd(0x2f);
lcd_jlx12864g_write_cmd(0x23);
lcd_jlx12864g_write_cmd(0x81);
lcd_jlx12864g_write_cmd(0x28);
lcd_jlx12864g_write_cmd(0xa2);
lcd_jlx12864g_write_cmd(0xc0);
lcd_jlx12864g_write_cmd(0xa0);
lcd_jlx12864g_write_cmd(0x40);
lcd_jlx12864g_write_cmd(0xaf);
lcd_clear();
//lcd_jlx12864g_bk_on();
}
3.4、main.c
#include "main.h"
int main(void)
{
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
BOARD_InitBootPeripherals();
printf("zhang\r\n");
SysTick_Init();
init_led();
//init_key();
//OLED_Init();
//oled_test();
init_spi();
init_lcd_jlx12864g();
lcd_showString(0,0, (uint8_t*)"MCXA156_BOARD_TEST",6,12);
lcd_showString(0,13,(uint8_t*)"MCU:MCXA156",6,12);
lcd_showString(0,26,(uint8_t*)"JLX12864G-SPI",6,12);
lcd_showString(0,39,(uint8_t*)"2026-03-08",6,12);
lcd_refreshGram();
while (1)
{
SysTick_Delay_ms(200);
led_red_tog();
}
}
四、运行结果
下载程序后,显示屏显示如下
引用: Gen_X 发表于 2026-3-9 19:27 可款我也用,价格很有优势, 但不是很稳定,有时启动初始化失败。
这个还没有发现。
引用: lugl4313820 发表于 2026-3-10 07:30 这个屏看起来有点年代感了,大佬存货多呀!
从旧的东东上面拆的屏幕,做的LCD模块。