使用SPI驱动单色LCD显示屏。
一、硬件部分
使用芯片的SPI0接口,使用的引脚如下

二、配置SPI
2.1、配置spi0引脚

2.2、配置spi0参数

三、程序部分
3.1、fun_spi.c
#include "hal_data.h"
#include "spi/fun_spi.h"
volatile bool g_transfer_complete = false;
void spi0_callback(spi_callback_args_t *p_args)
{
if(p_args->event == SPI_EVENT_TRANSFER_COMPLETE)
{
g_transfer_complete = true;
}
}
bool SPIWaitgtc(void)
{
unsigned short wTimeout = 100;
while(!g_transfer_complete && wTimeout)
{
R_BSP_SoftwareDelay(1u, BSP_DELAY_UNITS_MICROSECONDS);
wTimeout--;
}
g_transfer_complete = false;
if(g_transfer_complete==false && wTimeout==0)
return false;
return true;
}
3.2、fun_jlx12864g.c
#include "hal_data.h"
#include "spi/fun_spi.h"
#include "lcd/fun_jlx12864g_font.h"
#include "lcd/fun_jlx12864g.h"
volatile static uint8_t lcdGram[128][8];
void lcd_writebyte(uint8_t dat)
{
R_SPI_Write(&g_spi0_ctrl,&dat,1,SPI_BIT_WIDTH_8_BITS);
SPIWaitgtc();
}
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);
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;
}
uint8_t lcd_readPoint(uint8_t x,uint8_t y)
{
uint8_t pos,bx,temp=0x00;
y = 63-y;
pos=y/8;
bx=y%8;
temp=1<<bx;
if(temp&lcdGram[x][pos]) return 1;
return 0;
}
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);
}
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;
}
}
}
}
uint32_t mypow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
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);
}
}
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++;
}
}
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)
{
fsp_err_t err = FSP_SUCCESS;
err = R_SPI_Open(&g_spi0_ctrl,&g_spi0_cfg);
assert(FSP_SUCCESS == err);
R_BSP_SoftwareDelay(500u, BSP_DELAY_UNITS_MILLISECONDS);
lcd_jlx12864g_cs_h();
lcd_jlx12864g_rst_l();
R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS);
lcd_jlx12864g_rst_h();
R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS);
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();
}
3.3、fun_jlx12864.h
#ifndef __12864G_H
#define __12864G_H
#define LCD_JLX12864G_CS_PIN BSP_IO_PORT_03_PIN_01
#define LCD_JLX12864G_RST_PIN BSP_IO_PORT_03_PIN_02
#define LCD_JLX12864G_RS_PIN BSP_IO_PORT_03_PIN_06
#define lcd_jlx12864g_cs_l() R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_JLX12864G_CS_PIN, BSP_IO_LEVEL_LOW)
#define lcd_jlx12864g_cs_h() R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_JLX12864G_CS_PIN, BSP_IO_LEVEL_HIGH)
#define lcd_jlx12864g_rs_l() R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_JLX12864G_RS_PIN, BSP_IO_LEVEL_LOW)
#define lcd_jlx12864g_rs_h() R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_JLX12864G_RS_PIN, BSP_IO_LEVEL_HIGH)
#define lcd_jlx12864g_rst_l() R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_JLX12864G_RST_PIN, BSP_IO_LEVEL_LOW)
#define lcd_jlx12864g_rst_h() R_IOPORT_PinWrite(&g_ioport_ctrl, LCD_JLX12864G_RST_PIN, BSP_IO_LEVEL_HIGH)
void lcd_refreshGram(void);
void lcd_clear(void) ;
void lcd_drawPoint(uint8_t x,uint8_t y,uint8_t t);
uint8_t lcd_readPoint(uint8_t x,uint8_t y);
void lcd_fill(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t dot);
void lcd_showChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t f_w,uint8_t f_h,uint8_t mode);
uint32_t mypow(uint8_t m,uint8_t n);
void lcd_showNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t f_w,uint8_t f_h);
void lcd_showString(uint8_t x,uint8_t y,const uint8_t *p,uint8_t f_w,uint8_t f_h);
void lcd_showPicture(uint8_t x,uint8_t y,const uint8_t *p,uint8_t p_w,uint8_t p_h);
void init_lcd_jlx12864g(void);
#endif
3.4、hal_entry.c
#include "hal_data.h"
#include "led/fun_led.h"
#include "uart/fun_uart.h"
#include "adc/fun_adc.h"
#include "oled/fun_oled.h"
#include "lcd/fun_jlx12864g.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
/*******************************************************************************************************************//**
* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
* is called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void)
{
uint8_t num=0;
/* TODO: add your own code here */
init_led();
init_lcd_jlx12864g();
lcd_showString(0,0, (uint8_t*)"RA6M4_BOARD_TEST",6,12);
lcd_showString(0,13,(uint8_t*)"MCU:R7FA6M4AF",6,12);
lcd_showString(0,26,(uint8_t*)"JLX12864G-SPI",6,12);
lcd_showString(0,39,(uint8_t*)"2025-08-10",6,12);
lcd_refreshGram();
while(1)
{
lcd_showNum(0,52,num++,4,6,12);
lcd_refreshGram();
R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
led1_on();
led2_off();
led3_on();
R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
led1_off();
led2_on();
led3_off();
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
四、运行结果