开发板上带有一个段式LCD屏,可以用来显示数字,正好可以搭配RA4L1自带的SLCDC外设使用,SLCDC外设更能比较强大,可直接驱动 静态、1/2、1/3、1/4 的段式 LCD 显示屏,无需额外的LCD驱动芯片,实现对单个或多个数码管笔段的精确控制。

先学习下LCD屏的知识

SEG(Segment):控制 LCD 具体显示的段,经常使用
COM(Common):LCD 的 公共信号,决定哪个段被驱动
经常使用数码管的会很熟悉
下面来学习下如何配置SLCDC外设

在原理图中找到LCD对应的引脚,后面根据这个绑定引脚


这里选择 4x Slice或者Custom都可以 带的LCD一共有4个COM
剩下引脚太多了,就不截图了,对照原理图中选择即可

下面还要配置SLCDC的其他属性

这里需要配置的就时框出来的

Source:时钟源选择,提供了LOCO、SOSC、MOSC、HOCO多种选择
Divisor:时钟分频
Bias Method:偏置方法选择
分段lcd需要交流电压驱动,以防止液晶材料随着时间的推移而变质。偏置有助于有效地分配电压水平,在保持良好对比度的同时降低功耗。偏置模式是由多路复用LCD中施加电压电平的比率来定义的。偏置电平的数量取决于LCD的多路复用方案。
根据硬件设计和选择的LCD模块,可以使用FSP配置器配置偏置模式。RA4L1提供了使用FSP配置器的1/2、1/3和1/4偏置方法。
Timeslice:时间片
时间片的个数(N)与复用比(1:N)直接相关,其中N为COM的个数。更高的多路复用允许更多的显示段,而使用更少的引脚。
可以参考下面这张图

Waveform:波形模式 可选择波形A和波形B
当使用分段LCD控制器时,波形a和波形B表示用于控制液晶显示的不同驱动方案。这些波形定义了如何将电压施加到LCD段和公共终端,以正确驱动显示器而不会引起直流偏置问题。

Drive Method:驱动方式

Default Contrast:对比度
分段 LCD 控制器中的对比度调整通过控制
公共 (COM) 电极和段式 (SEG) 电极之间的电压差。适当的对比度
调整可确保清晰、锐利和无闪烁的显示作。
• 对比度由施加在液晶材料上的偏置电压控制。
• 更高的电压→更暗的段(对比度更高)。
• 电压较低→段较轻(对比度较低)。
配置完了,下面就开始写代码了
用到的API就这8个


要想在第一位显示数字1,要选中1B 1C,即向SEG15写入0x06
R_SLCDC_Open(&g_slcdc0_ctrl,&g_slcdc0_cfg);
R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
R_SLCDC_Start(&g_slcdc0_ctrl);
uint8_t data = 0x06;
R_SLCDC_Write(&g_slcdc0_ctrl, 11, &data, 1);

要想在第六位显示数字0,要选中6A 6B 6C 6D 6E 6F,即向SEG40写入0x0D ,向SEG41写入0x07
R_SLCDC_Open(&g_slcdc0_ctrl,&g_slcdc0_cfg);
R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
R_SLCDC_Start(&g_slcdc0_ctrl);
uint8_t data = 0x0d;
R_SLCDC_Write(&g_slcdc0_ctrl, 40, &data, 1);
data = 0x07;
R_SLCDC_Write(&g_slcdc0_ctrl, 41, &data, 1);

以此类推,就能实现各个位置显示任意数字
下面提供在任意位置显示数字的函数
#define LCDSEG_F 0x01
#define LCDSEG_G 0x02
#define LCDSEG_E 0x04
#define LCDSEG_D 0x08
#define LCDSEG_A 0x10
#define LCDSEG_B 0x20
#define LCDSEG_C 0x40
#define CHAR_0 LCDSEG_A+LCDSEG_B+LCDSEG_C+LCDSEG_D+LCDSEG_E+LCDSEG_F
#define CHAR_1 LCDSEG_B+LCDSEG_C
#define CHAR_2 LCDSEG_A+LCDSEG_B+LCDSEG_D+LCDSEG_E+LCDSEG_G
#define CHAR_3 LCDSEG_A+LCDSEG_B+LCDSEG_C+LCDSEG_D+LCDSEG_G
#define CHAR_4 LCDSEG_B+LCDSEG_C+LCDSEG_F+LCDSEG_G
#define CHAR_5 LCDSEG_A+LCDSEG_C+LCDSEG_D+LCDSEG_F+LCDSEG_G
#define CHAR_6 LCDSEG_A+LCDSEG_C+LCDSEG_D+LCDSEG_E+LCDSEG_F+LCDSEG_G
#define CHAR_7 LCDSEG_A+LCDSEG_B+LCDSEG_C
#define CHAR_8 LCDSEG_A+LCDSEG_B+LCDSEG_C+LCDSEG_D+LCDSEG_E+LCDSEG_F+LCDSEG_G
#define CHAR_9 LCDSEG_A+LCDSEG_B+LCDSEG_C+LCDSEG_D+LCDSEG_F+LCDSEG_G
const uint8_t DisTable[] = {
CHAR_0, (CHAR_0 >> 4),
CHAR_1, (CHAR_1 >> 4),
CHAR_2, (CHAR_2 >> 4),
CHAR_3, (CHAR_3 >> 4),
CHAR_4, (CHAR_4 >> 4),
CHAR_5, (CHAR_5 >> 4),
CHAR_6, (CHAR_6 >> 4),
CHAR_7, (CHAR_7 >> 4),
CHAR_8, (CHAR_8 >> 4),
CHAR_9, (CHAR_9 >> 4),
};
const uint8_t SegTable[] = {
3,11,
15,16,
22,23,
24,29,
30,39,
40,41
};
uint32_t Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y --)
{
Result *= X;
}
return Result;
}
void LCD_ShowSingleNum(uint8_t pos,uint8_t num)
{
R_SLCDC_Write(&g_slcdc0_ctrl, SegTable[(pos-1)*2],&(DisTable[num*2]) , 1);
R_SLCDC_Write(&g_slcdc0_ctrl, SegTable[(pos-1)*2 + 1],&(DisTable[num*2 + 1]) , 1);
}
void LCD_ShowNum(uint8_t pos,uint32_t num,uint8_t len)
{
if(len > 6)return;
for(uint8_t i = 0;i < len;i++)
{
LCD_ShowSingleNum(pos,num / Pow(10, len - i - 1) % 10);
pos++;
}
}
最后展示效果