这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 【瑞萨RA4L1开发板】:成功驱动板载的LCD显示屏

共2条 1/1 1 跳转至

【瑞萨RA4L1开发板】:成功驱动板载的LCD显示屏

高工
2025-05-14 16:45:43     打赏

LCD段码屏(又称段式LCD或段码显示屏)是一种常见的液晶显示技术,主要用于显示简单的数字、字符或固定图形。以下是其核心特点和工作原理的详细说明:

一:LCD基本知识分享:

1. 基本结构

分段显示:屏幕由多个独立的“段”(Segment)组成,每个段对应显示内容的一部分(如数字的某一段笔画、符号或简单图标)。

背电极(COM)与段电极(SEG):通过交叉矩阵控制,每个段的亮灭由对应的电极信号决定。

固定图案:显示内容需预先设计(如计算器、电子表上的数字),无法动态变化。

2. 工作原理

驱动方式:采用静态驱动或动态驱动(多路复用),通过施加电压改变液晶排列,控制光线透过与否。

对比度高:通常为单色(如蓝底白字、黑底灰字),依赖背光或环境光。

低功耗:仅在切换段状态时耗电,适合电池供电设备。

3:RA4L1板载的LCD资料:

液晶显示(LCD)是嵌入式系统中常见的人机交互方式,广泛应用于工业控制、智能家电、医疗设备和消费电子产品。Renesas RA4L1 微控制器(MCU)内置 Segment LCD Controller (SLCDC),可直接驱动 静态、1/2、1/3、1/4 Bias 的段式 LCD 显示屏,无需额外的 LCD 驱动芯片。这种集成方案不仅降低了硬件成本,还简化了设计。

Renesas RA4L1 的 SLCDC 模块提供了一种高效、低功耗、低成本的 LCD 显示方案。通过 FSP 提供的 r_slcdc 驱动,开发者可以快速初始化 LCD,轻松控制显示内容。在实际项目中,合理配置 COM/SEG 引脚、优化时钟和对比度设置,可以进一步提升 LCD 显示效果。

开发板图片如下所示:

1.png

二:开发板资料

要将 LCD 屏幕的引脚正确映射到 RA MCU 的 SLCDC(Segment LCD Controller)驱动引脚,需要按照 LCD 的 COM(公共端) 和 SEG(段) 分配关系,将其连接到 MCU 的相应 SLCDC 引脚。LCD映射到 MCU 的 SLCDC 驱动引脚

5.png

通过上图,一个数码管驱动需要两个位选来确定,这种和数码管驱动有点区别,大家在驱动的时候,需要格外的注意;

原理图如下所示:

2.png

打开fsp配置,对所使用的IO口进行配置

4.png

系统时钟的配置如下所示:

3.png

三:代码的编写:

3.1底层驱动函数如下:

以第一个数码管驱动做简单的结合扫

在 SLCDC (Segment LCD Controller) 驱动 LCD 数码管时,每个段 (SEGx) 需要与多个公共端 (COMx) 进行组合,以控制哪些段应该点亮。

从第11个段开始,由于只有4个COM,将4个数据写入SLCDC的段寄存器,驱动LCD显示对应图案或数字。

1B 段 和 1C 段 分别映射到:

● 1B → SEG11, COM1

● 1C → SEG11, COM2

要点亮 1B (COM1) 和 1C (COM2),所以需要设置:

● COM1 = 1(对应第 1 位)

● COM2 = 1(对应第 2 位)

● 其他 COM0 和 COM3 = 0

这里只有COM1和COM2需要驱动,对应十六进制为0x6,驱动代码如下所示。

下方代码R_SLCDC_Write中,0代表从 SEG0 开始写入数据,数组segment_data_num1长度sizeof(segment_data_num1),为11。在SEG11写入0x6。

用计算器的二进值确定一下,断码需要点亮时,发送的数据;

R_SLCDC_Write()函数:

R_SLCDC_Write() 的作用是向段式LCD控制器(SLCDC)写入一系列的数据,以控制LCD的显示内容。

数据被写入SLCDC内部的段数据寄存器中,从而控制LCD各段的亮灭状态。

fsp_err_t R_SLCDC_Write (slcdc_ctrl_t * const p_ctrl,
uint8_t const        start_segment,
uint8_t const      * p_data,
uint8_t const        segment_count)
{
slcdc_instance_ctrl_t * p_instance_ctrl = (slcdc_instance_ctrl_t *) p_ctrl;

fsp_err_t err = FSP_SUCCESS;

#if (SLCDC_CFG_PARAM_CHECKING_ENABLE)
FSP_ASSERT(p_instance_ctrl);
FSP_ASSERT(p_data);
FSP_ERROR_RETURN(SLCDC_CLOSED != p_instance_ctrl->open, FSP_ERR_NOT_OPEN);

if ((BSP_FEATURE_SLCDC_MAX_NUM_SEG <= start_segment) ||
(((uint8_t) (BSP_FEATURE_SLCDC_MAX_NUM_SEG)) < (start_segment + segment_count)))
{
return FSP_ERR_INVALID_ARGUMENT;
}

#else
FSP_PARAMETER_NOT_USED(p_instance_ctrl);
#endif

/* Display data is stored in the LCD segment data register array */
for (uint8_t seg = start_segment; (seg - start_segment) < segment_count; seg++)
{
R_SLCDC->SEG[seg] = *p_data;
p_data++;
}

return err;
}

这里我所使用的驱动函数是:

R_SLCDC_Modify() 是用于修改单个段寄存器中的部分位的函数,属于 SLCDC 驱动的精细控制接口。

fsp_err_t R_SLCDC_Modify (slcdc_ctrl_t * const p_ctrl,
uint8_t const        segment,
uint8_t const        data,
uint8_t const        data_mask)
{
slcdc_instance_ctrl_t * p_instance_ctrl = (slcdc_instance_ctrl_t *) p_ctrl;

#if (SLCDC_CFG_PARAM_CHECKING_ENABLE)
FSP_ASSERT(p_instance_ctrl);
FSP_ERROR_RETURN(SLCDC_CLOSED != p_instance_ctrl->open, FSP_ERR_NOT_OPEN);

if (BSP_FEATURE_SLCDC_MAX_NUM_SEG <= segment)
{
return FSP_ERR_INVALID_ARGUMENT;
}

#else
FSP_PARAMETER_NOT_USED(p_instance_ctrl);
#endif

/* Mask and write data to segment */
R_SLCDC->SEG[segment] = (R_SLCDC->SEG[segment] & (uint8_t) (~(data_mask))) | data;

return FSP_SUCCESS;
}

修改底层的驱动函数代码如下所示:

void OneDisNumber(char number)
{
switch (number)
{
case 0 :           //准备并写入段显示数据,第一个数码管显示0
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0xD, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x7, 0xF);
break ;
case 1 :           //准备并写入段显示数据,第一个数码管显示1
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0x0, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x6, 0xF);
break ;
case 2 :           //准备并写入段显示数据,第一个数码管显示2
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0xE, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x3, 0xF);
break ;
case 3 :           //准备并写入段显示数据,第一个数码管显示3
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0xA, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x7, 0xF);
break ;
case 4 :           //准备并写入段显示数据,第一个数码管显示4
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0x3, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x6, 0xF);
break ;
case 5 :           //准备并写入段显示数据,第一个数码管显示5
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0xB, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x5, 0xF);
break ;
case 6 :           //准备并写入段显示数据,第一个数码管显示6
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0xF, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x5, 0xF);
break ;
case 7 :           //准备并写入段显示数据,第一个数码管显示7
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0x0, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x7, 0xF);
break ;
case 8 :           //准备并写入段显示数据,第一个数码管显示8
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0xF, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x7, 0xF);
break ;
case 9 :           //准备并写入段显示数据,第一个数码管显示9
R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0xB, 0xF);
R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x7, 0xF);
break ;
default :
break ;
}
}

在主程序添加,对一个第一个数码管的驱动显示部分:

data++;
if(data >=10) data = 0 ;
OneDisNumber(data);
SencoendDisNumber(data);
R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

实物测试图如下所示:

8.png


院士
2025-05-15 09:45:00     打赏
2楼

楼主 要是有时间,可以拿示波器点一下seg和com引脚。



共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]