概述

本文旨在介绍如何使用瑞萨 RA4L1 系列单片机的 SLCDC(Segment LCD Controller)模块,驱动段式 LCD 屏幕实现字符或图案的点亮显示。通过分析 LCD 屏幕的 COM/SEG 引脚分布关系,结合 FSP(中的 SLCDC 驱动 API(如 R_SLCDC_Write() 和 R_SLCDC_Modify()),实现对单个或多个数码管笔段的精确控制。文中以实际硬件为例,展示如何点亮指定数码管(如显示数字“1”或“3”),并解释段寄存器设置、位图控制方法以及显示时序,为后续 LCD 显示开发和调试提供参考。

最近在瑞萨RA的课程,需要样片的可以加qun申请:925643491。

在这里插入图片描述

视频教学

https://www.bilibili.com/video/BV1VHoUYGECR

RA4L1驱动LCD屏幕(2)----驱动LCD点亮

样品申请

https://www.wjx.top/vm/rCrkUrz.aspx

硬件准备

首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。
主控为R7FA4L1BD4CFP

在这里插入图片描述

参考程序

https://github.com/CoreMaker-lab/RA4L1_LCD

https://gitee.com/CoreMaker/RA4L1_LCD

源码下载

https://download.csdn.net/download/xinzuofang/91625983

LCD管脚对应

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

在这里插入图片描述
在这里插入图片描述

R_SLCDC_Open()函数

R_SLCDC_Open() 是 Renesas RA MCU 中 SLCDC(Segment LCD Controller)驱动程序的重要函数 。 为 LCD 驱动分配控制块 (slcdc_ctrl_t) 以及内部的资源,以确保 SLCDC 可以开始正常运行。 完成初始化后,使 LCD 驱动模块处于待启动状态,等待后续调用 R_SLCDC_Start() 函数真正启动 LCD 输出驱动波形。
在这里插入图片描述

    fsp_err_t err;
    /* Open SLCDC driver */
    err = R_SLCDC_Open(&g_slcdc0_ctrl, &g_slcdc0_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    /* When using internal boost mode this delay is required to allow the boost circuit to charge. See RA4M1 User's
     * Manual (R01UH0887EJ0100) 8.2.18 "Segment LCD Source Clock Control Register (SLCDSCKCR)" for details. */
    R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);

R_SLCDC_Start()函数

在调用 R_SLCDC_Open() 完成 SLCDC 初始化后,R_SLCDC_Start() 用于正式启动 LCD 驱动信号输出。调用此函数后,MCU 开始向 LCD 面板输出预配置的驱动波形和电压信号,LCD 显示正式开始工作。

    /* Start SLCDC output */
    err = R_SLCDC_Start(&g_slcdc0_ctrl);
    assert(FSP_SUCCESS == err);

R_SLCDC_Write()函数

R_SLCDC_Write() 的作用是向段式LCD控制器(SLCDC)写入一系列的数据,以控制LCD的显示内容。
数据被写入SLCDC内部的段数据寄存器中,从而控制LCD各段的亮灭状态。

在这里插入图片描述

例如在左方第一个数码管写入数字1。

在这里插入图片描述

点亮1B和1C,只涉及SEG11以及COM1,COM2。

在这里插入图片描述
在 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。

    //准备并写入段显示数据,第一个数码管显示1
    uint8_t segment_data_num1[] = {
    0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,
    0x00,0x6
    };
    R_SLCDC_Write(&g_slcdc0_ctrl, 0, segment_data_num1, sizeof(segment_data_num1));
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

在这里插入图片描述
在左方第二个数码管写入数字2。

在这里插入图片描述

点亮2A、2B、2D、2E、2G,涉及SEG15和SEG16以及COM1、COM2、COM3、COM4。

在这里插入图片描述

在 SLCDC (Segment LCD Controller) 驱动 LCD 数码管时,每个段 (SEGx) 需要与多个公共端 (COMx) 进行组合,以控制哪些段应该点亮。
从第15个段开始,由于只有4个COM,将4个数据写入SLCDC的段寄存器,驱动LCD显示对应图案或数字。
2G 段 和 2E 段 和 2D 段分别映射到:
● 2G → SEG15, COM1
● 2E → SEG15, COM2
● 2D → SEG15, COM3
要点亮 2G (COM1) 和 2E (COM2) 和 2D (COM3),所以需要设置:
● COM1 = 1(对应第 1 位)
● COM2 = 1(对应第 2 位)
● COM3 = 1(对应第 2 位)
● 其他 COM0 = 0
这里只有COM1和COM2和COM3需要驱动,对应十六进制为0xE。

从第16个段开始,由于只有4个COM,将4个数据写入SLCDC的段寄存器,驱动LCD显示对应图案或数字。
2A 段 和 2B 段 分别映射到:
● 2A → SEG16, COM0
● 2B → SEG16, COM1
要点亮 2A (COM0) 和 2B (COM1) ,所以需要设置:
● COM0 = 1(对应第 0 位)
● COM1 = 1(对应第 1 位)
● 其他 COM2 和 COM3 = 0
这里只有COM0和COM1需要驱动,对应十六进制为0x3。

下方代码R_SLCDC_Write中,15代表从 SEG0 开始写入数据,数组segment_data_num2长度sizeof(segment_data_num2),为2。在SEG15写入0xE以及SEG16写入0x3。

    //准备并写入段显示数据,第二个数码管显示2
    uint8_t segment_data_num2[] = {
    0xE,0x3};
    R_SLCDC_Write(&g_slcdc0_ctrl, 15, segment_data_num2, 2);
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

在这里插入图片描述

R_SLCDC_Modify()函数

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

在这里插入图片描述

例如在左方第三个数码管写入数字3。

在这里插入图片描述

点亮3A、3B、3C、3D、3G,涉及SEG22和SEG34以及COM1、COM2、COM3、COM4。

在这里插入图片描述在 SLCDC (Segment LCD Controller) 驱动 LCD 数码管时,每个段 (SEGx) 需要与多个公共端 (COMx) 进行组合,以控制哪些段应该点亮。
从第22个段开始,由于只有4个COM,将4个数据写入SLCDC的段寄存器,驱动LCD显示对应图案或数字。
3G 段 和 3D 段 分别映射到:
● 3G → SEG22, COM1
● 3D → SEG22, COM3
要点亮 3G (COM1) 和 3D (COM3) ,所以需要设置:
● COM1 = 1(对应第 1 位)
● COM3 = 1(对应第 3 位)
● 其他 COM0 和 COM2 = 0

这里只有COM1和COM3需要驱动,对应十六进制为0xA。

下面代码中,第二个参数为SEG索引号(22),第三个参数为要写入的值0xA,第四个参数为掩码0xF(表示我们仅修改该SEG寄存器低4位,对应使用的COM0–COM3位)。R_SLCDC_Modify 会据此将指定SEG寄存器的相应位置1或0,从而控制对应笔段的明暗。

    //准备并写入段显示数据,第三个数码管显示3
    R_SLCDC_Modify(&g_slcdc0_ctrl, 22, 0xA, 0xF);
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

在这里插入图片描述
在 SLCDC (Segment LCD Controller) 驱动 LCD 数码管时,每个段 (SEGx) 需要与多个公共端 (COMx) 进行组合,以控制哪些段应该点亮。
从第23个段开始,由于只有4个COM,将4个数据写入SLCDC的段寄存器,驱动LCD显示对应图案或数字。
3A 段 和 3B 段 和 3C 段分别映射到:
● 3A → SEG23, COM0
● 3B → SEG23, COM1
● 3C → SEG23, COM2
要点亮 3A (COM0) 和 3B (COM1) 和 3C (COM2),所以需要设置:
● COM0 = 1(对应第 0 位)
● COM1 = 1(对应第 1 位)
● COM2 = 1(对应第 2 位)
● 其他 COM3 = 0

这里只有COM0和COM1和COM2需要驱动,对应十六进制为0x7。
下面代码中,第二个参数为SEG索引号(22),第三个参数为要写入的值0x7,第四个参数为掩码0xF(表示我们仅修改该SEG寄存器低4位,对应使用的COM0–COM3位)。R_SLCDC_Modify 会据此将指定SEG寄存器的相应位置1或0,从而控制对应笔段的明暗。

    R_SLCDC_Modify(&g_slcdc0_ctrl, 23, 0x7, 0xF);
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

在这里插入图片描述

主程序

void hal_entry(void)
{
    /* TODO: add your own code here */


    fsp_err_t err;
    /* Open SLCDC driver */
    err = R_SLCDC_Open(&g_slcdc0_ctrl, &g_slcdc0_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    /* When using internal boost mode this delay is required to allow the boost circuit to charge. See RA4M1 User's
     * Manual (R01UH0887EJ0100) 8.2.18 "Segment LCD Source Clock Control Register (SLCDSCKCR)" for details. */
    R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
    /* Start SLCDC output */
    err = R_SLCDC_Start(&g_slcdc0_ctrl);
    assert(FSP_SUCCESS == err);

    /* Set Display Area of SLCDC driver.*/
//    err = R_SLCDC_SetDisplayArea(&g_slcdc0_ctrl, SLCDC_DISP_A);
//    assert(FSP_SUCCESS == err);
    //准备并写入段显示数据,第一个数码管显示1
    uint8_t segment_data_num1[] = {
    0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,
    0x00,0x6
    };
    R_SLCDC_Write(&g_slcdc0_ctrl, 0, segment_data_num1, sizeof(segment_data_num1));
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

    //准备并写入段显示数据,第二个数码管显示2
    uint8_t segment_data_num2[] = {
    0xE,0x3};
    R_SLCDC_Write(&g_slcdc0_ctrl, 15, segment_data_num2, sizeof(segment_data_num2));
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

    //准备并写入段显示数据,第三个数码管显示3
    R_SLCDC_Modify(&g_slcdc0_ctrl, 22, 0xA, 0xF);
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);
    R_SLCDC_Modify(&g_slcdc0_ctrl, 23, 0x7, 0xF);
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

    //准备并写入段显示数据,第四个数码管显示4
    R_SLCDC_Modify(&g_slcdc0_ctrl, 24, 0x3, 0xF);
    R_SLCDC_Modify(&g_slcdc0_ctrl, 29, 0x6, 0xF);
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

    //准备并写入段显示数据,第五个数码管显示5
    R_SLCDC_Modify(&g_slcdc0_ctrl, 30, 0xB, 0xF);
    R_SLCDC_Modify(&g_slcdc0_ctrl, 39, 0x5, 0xF);
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

    //准备并写入段显示数据,第六个数码管显示6
    R_SLCDC_Modify(&g_slcdc0_ctrl, 40, 0xF, 0xF);
    R_SLCDC_Modify(&g_slcdc0_ctrl, 41, 0x5, 0xF);
    R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

    while(1)
    {
        //清空0-41段
        uint8_t segment_data_num_off[41+1] ;
        for(int i=0;i<=41;i++)
            segment_data_num_off[i]=0;
        R_SLCDC_Write(&g_slcdc0_ctrl, 0, segment_data_num_off, sizeof(segment_data_num_off));
        R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

        //全部点亮
        uint8_t segment_data_num_on[41+1] ;
        for(int i=0;i<=41;i++)
            segment_data_num_on[i]=0xf;
        R_SLCDC_Write(&g_slcdc0_ctrl, 0, segment_data_num_on, sizeof(segment_data_num_on));
        R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);

        //准备并写入段显示数据,第一个数码管显示1
        R_SLCDC_Modify(&g_slcdc0_ctrl, 3, 0x0, 0xF);
        R_SLCDC_Modify(&g_slcdc0_ctrl, 11, 0x6, 0xF);

        //准备并写入段显示数据,第二个数码管显示2
        R_SLCDC_Modify(&g_slcdc0_ctrl, 15, 0xE, 0xF);
        R_SLCDC_Modify(&g_slcdc0_ctrl, 16, 0x3, 0xF);

        //准备并写入段显示数据,第三个数码管显示3
        R_SLCDC_Modify(&g_slcdc0_ctrl, 22, 0xA, 0xF);
        R_SLCDC_Modify(&g_slcdc0_ctrl, 23, 0x7, 0xF);

        //准备并写入段显示数据,第四个数码管显示4
        R_SLCDC_Modify(&g_slcdc0_ctrl, 24, 0x3, 0xF);
        R_SLCDC_Modify(&g_slcdc0_ctrl, 29, 0x6, 0xF);

        //准备并写入段显示数据,第五个数码管显示5
        R_SLCDC_Modify(&g_slcdc0_ctrl, 30, 0xB, 0xF);
        R_SLCDC_Modify(&g_slcdc0_ctrl, 39, 0x5, 0xF);

        //准备并写入段显示数据,第六个数码管显示6
        R_SLCDC_Modify(&g_slcdc0_ctrl, 40, 0xF, 0xF);
        R_SLCDC_Modify(&g_slcdc0_ctrl, 41, 0x5, 0xF);
        R_BSP_SoftwareDelay (2000, BSP_DELAY_UNITS_MILLISECONDS);


    }


#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐