RA4L1芯片为仪表类应用提供段码屏驱动,便于仪表类应用开发。利用RA4L1自带的Segment LCD硬件驱动模块,用户只需要根据段码屏的COM引脚和Seg引脚的硬件连接配置进行相应的编码,在不同的Segment引脚对应的寄存器中写入编码值,即可控制段码屏的数字显示。
开发板配套的段码屏和RA4L1芯片的连接原理图如下。


| 段码屏引脚 | RA4L1引脚 | 引脚功能 |
|---|---|---|
| 1 | P111 | SEG2 |
| 2 | P112 | SEG3 |
| 3 | P700 | SEG11 |
| 4 | P413 | SEG15 |
| 5 | P412 | SEG16 |
| 6 | P307 | SEG22 |
| 7 | P306 | SEG23 |
| 8 | P305 | SEG24 |
| 9 | P113 | SEG29 |
| 10 | P114 | SEG30 |
| 11 | P106 | SEG39 |
| 12 | P105 | SEG40 |
| 13 | P104 | SEG41 |
| 14 | P303 | COM3 |
| 15 | P304 | COM2 |
| 16 | P208 | COM1 |
| 17 | P205 | COM0 |
根据段码屏的连接属性,对其控制进行编码。断码屏连接4个COM端,以Seg3为例,可以实现控制T1、T2、T3、T4的功能,编码时由低位至高位,COM1->COM4的顺序控制T1到T4的液晶管的亮灭。编码的结果写入到Seg3对应的Segment寄存器中,实现对段码屏的显示控制。

查看段码屏的驱动手册可知其驱动方式为1/3Bais,四分时。

开发板提供Arduino接口,使用其中的P510采集外部电位器的ADC信息。

在FSP配置工具中添加SLCDC的驱动,结合之前的硬件连接,设置相应的驱动参数和外设引脚。


同样地,配置ADC模块的参数、输入通道以及引脚如下


保存并生成代码后,即可使用SLCDC和ADC模块来实现“简易电压表功能”
关于RA4L1的断码屏使用和示例程序,可以在瑞萨官网找到相应的资料。

段码屏需要根据硬件进行编码,结合原理图中连接的Seg引脚,定义如下用于管理段码屏显示的常量。
const uint8_t medium_digit_start_addresses[6][2]=
{
{ 0x29, 0x28 }, // units digit is controlled by SLCD Data register 41 & 40
{ 0x27, 0x1E }, // tens digit is controlled by SLCD Data register 39 & 30
{ 0x1D, 0x18 }, // hundreds digit is controlled by SLCD Data register 29 & 24
{ 0x17, 0x16 }, // thousands digit is controlled by SLCD Data register 23 & 22
{ 0x10, 0x0F }, // ten-thousands digit is controlled by SLCD Data register 16 & 15
{ 0x0B, 0x03 } // hundred-thousands digit is controlled by SLCD Data register 11 & 3
};
const uint8_t medium_digit_data[10][2]=
{
{ 0x07, 0x0D }, // 0 digit is display by writing 0x0f and 0x0a to the appropriate medium_digit_start_addresses
{ 0x06, 0x00 }, // 1 digit is display by writing 0x06 and 0x00 to the appropriate medium_digit_start_addresses
{ 0x03, 0x0E }, // 2 digit is display by writing 0x0d and 0x06 to the appropriate medium_digit_start_addresses
{ 0x07, 0x0A }, // 3 digit is display by writing 0x0f and 0x04 to the appropriate medium_digit_start_addresses
{ 0x06, 0x03 }, // 4 digit is display by writing 0x06 and 0x0c to the appropriate medium_digit_start_addresses
{ 0x05, 0x0B }, // 5 digit is display by writing 0x0b and 0x0c to the appropriate medium_digit_start_addresses
{ 0x05, 0x0F }, // 6 digit is display by writing 0x0b and 0x0e to the appropriate medium_digit_start_addresses
{ 0x07, 0x00 }, // 7 digit is display by writing 0x0e and 0x00 to the appropriate medium_digit_start_addresses
{ 0x07, 0x0F }, // 8 digit is display by writing 0x0f and 0x0e to the appropriate medium_digit_start_addresses
{ 0x07, 0x0E } // 9 digit is display by writing 0x0f and 0x0c to the appropriate medium_digit_start_addresses
};
同时封装用于显示数字的函数如下:
/*******************************************************************************************************************//**
* [url=home.php?mod=space&uid=2666770]@Brief[/url] Performs writing Segment LCD's medium Digits with user requested value and DP settings .
* This is used for displaying the time information in this application along with colon icon
* @param[IN] None
* @retval FSP_SUCCESS Upon successful writing.
* @retval Any Other Error code apart from FSP_SUCCESS on Unsuccessful operation .
**********************************************************************************************************************/
fsp_err_t set_segments_medium_digits( uint32_t value, medium_dp_or_colon_t point_or_colon )
{
uint8_t temp_ten_thousands = (uint8_t)((value / 10000));
uint8_t temp_thousands = (uint8_t)((value % 10000) / 1000);
uint8_t temp_hundreds = (uint8_t)((value % 1000) / 100);
uint8_t temp_tens = (uint8_t)((value % 100) / 10);
uint8_t temp_units = (uint8_t)((value % 10) / 1);
fsp_err_t err;
// set / clear the decimal point
err = set_segments_icon_medium_dp_colon( point_or_colon );
if( value > 99999)
{
// Write an error message "E r r o r"
err = set_segments_icon_medium_dp_colon( DP_COLON_OFF );
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TEN_THOUSANDS][0], &medium_digit_error_data[0][0], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TEN_THOUSANDS][1], &medium_digit_error_data[0][1], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_THOUSANDS][0], &medium_digit_error_data[1][0], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_THOUSANDS][1], &medium_digit_error_data[1][1], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_HUNDREDS][0], &medium_digit_error_data[2][0], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_HUNDREDS][1], &medium_digit_error_data[2][1], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TENS][0], &medium_digit_error_data[3][0], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TENS][1], &medium_digit_error_data[3][1], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_UNITS][0], &medium_digit_error_data[4][0], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Write( &g_slcdc_ctrl, medium_digit_start_addresses[MN_UNITS][1], &medium_digit_error_data[4][1], 1);
CHECK_SEGMENT_WRITE_ERROR(err);
}
else
{
if( value > 9999 )
{
running_segment_data[MN_TEN_THOUSANDS][0] = running_segment_data[MN_TEN_THOUSANDS][0] & MED_DIGIT_MASK_4_2_1;
running_segment_data[MN_TEN_THOUSANDS][1] = running_segment_data[MN_TEN_THOUSANDS][1] & MED_DIGIT_MASK_8_4_2_1;
running_segment_data[MN_TEN_THOUSANDS][0] = (running_segment_data[MN_TEN_THOUSANDS][0] | medium_digit_data[temp_ten_thousands][0]);
running_segment_data[MN_TEN_THOUSANDS][1] = (running_segment_data[MN_TEN_THOUSANDS][1] | medium_digit_data[temp_ten_thousands][1]);
err = R_SLCDC_Modify(&g_slcdc_ctrl, (uint8_t)medium_digit_start_addresses[MN_TEN_THOUSANDS][0], (uint8_t)running_segment_data[MN_TEN_THOUSANDS][0], (uint8_t)~(uint8_t)MED_DIGIT_MASK_4_2_1);
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, (uint8_t)medium_digit_start_addresses[MN_TEN_THOUSANDS][1], (uint8_t)running_segment_data[MN_TEN_THOUSANDS][1], (uint8_t)~(uint8_t)MED_DIGIT_MASK_8_4_2_1);
CHECK_SEGMENT_WRITE_ERROR(err);
}
else
{
running_segment_data[MN_TEN_THOUSANDS][0] = (running_segment_data[MN_TEN_THOUSANDS][0] | CLEAR_WRITE_DATA);
running_segment_data[MN_TEN_THOUSANDS][1] = (running_segment_data[MN_TEN_THOUSANDS][1] | CLEAR_WRITE_DATA);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TEN_THOUSANDS][0], running_segment_data[MN_TEN_THOUSANDS][0], (uint8_t)~MED_DIGIT_MASK_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TEN_THOUSANDS][1], running_segment_data[MN_TEN_THOUSANDS][1], (uint8_t)~MED_DIGIT_MASK_8_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
}
if( value > 999 )
{
running_segment_data[MN_THOUSANDS][0] = running_segment_data[MN_THOUSANDS][0] & MED_DIGIT_MASK_4_2_1;
running_segment_data[MN_THOUSANDS][1] = running_segment_data[MN_THOUSANDS][1] & MED_DIGIT_MASK_8_4_2_1;
running_segment_data[MN_THOUSANDS][0] = (running_segment_data[MN_THOUSANDS][0] | medium_digit_data[temp_thousands][0]);
running_segment_data[MN_THOUSANDS][1] = (running_segment_data[MN_THOUSANDS][1] | medium_digit_data[temp_thousands][1]);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_THOUSANDS][0], running_segment_data[MN_THOUSANDS][0], (uint8_t)~MED_DIGIT_MASK_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_THOUSANDS][1], running_segment_data[MN_THOUSANDS][1], (uint8_t)~MED_DIGIT_MASK_8_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
}
else
{
running_segment_data[MN_THOUSANDS][0] = (running_segment_data[MN_THOUSANDS][0] | CLEAR_WRITE_DATA);
running_segment_data[MN_THOUSANDS][1] = (running_segment_data[MN_THOUSANDS][1] | CLEAR_WRITE_DATA);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_THOUSANDS][0], running_segment_data[MN_THOUSANDS][0], (uint8_t)~MED_DIGIT_MASK_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_THOUSANDS][1], running_segment_data[MN_THOUSANDS][1], (uint8_t)~MED_DIGIT_MASK_8_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
}
if( value > 99 )
{
running_segment_data[MN_HUNDREDS][0] = running_segment_data[MN_HUNDREDS][0] & MED_DIGIT_MASK_4_2_1;
running_segment_data[MN_HUNDREDS][1] = running_segment_data[MN_HUNDREDS][1] & MED_DIGIT_MASK_8_4_2_1;
running_segment_data[MN_HUNDREDS][0] = (running_segment_data[MN_HUNDREDS][0] | medium_digit_data[temp_hundreds][0]);
running_segment_data[MN_HUNDREDS][1] = (running_segment_data[MN_HUNDREDS][1] | medium_digit_data[temp_hundreds][1]);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_HUNDREDS][0], running_segment_data[MN_HUNDREDS][0], (uint8_t)~MED_DIGIT_MASK_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_HUNDREDS][1], running_segment_data[MN_HUNDREDS][1], (uint8_t)~MED_DIGIT_MASK_8_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
}
else
{
running_segment_data[MN_HUNDREDS][0] = (running_segment_data[MN_HUNDREDS][0] | CLEAR_WRITE_DATA);
running_segment_data[MN_HUNDREDS][1] = (running_segment_data[MN_HUNDREDS][1] | CLEAR_WRITE_DATA);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_HUNDREDS][0], running_segment_data[MN_HUNDREDS][0], (uint8_t)~MED_DIGIT_MASK_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_HUNDREDS][1], running_segment_data[MN_HUNDREDS][1], (uint8_t)~MED_DIGIT_MASK_8_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
}
if( value > 9 )
{
running_segment_data[MN_TENS][0] = running_segment_data[MN_TENS][0] & MED_DIGIT_MASK_4_2_1;
running_segment_data[MN_TENS][1] = running_segment_data[MN_TENS][1] & MED_DIGIT_MASK_8_4_2_1;
running_segment_data[MN_TENS][0] = (running_segment_data[MN_TENS][0] | medium_digit_data[temp_tens][0]);
running_segment_data[MN_TENS][1] = (running_segment_data[MN_TENS][1] | medium_digit_data[temp_tens][1]);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TENS][0], running_segment_data[MN_TENS][0], (uint8_t)~MED_DIGIT_MASK_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TENS][1], running_segment_data[MN_TENS][1], (uint8_t)~MED_DIGIT_MASK_8_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
}
else
{
running_segment_data[MN_TENS][0] = (running_segment_data[MN_TENS][0] | CLEAR_WRITE_DATA);
running_segment_data[MN_TENS][1] = (running_segment_data[MN_TENS][1] | CLEAR_WRITE_DATA);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TENS][0], running_segment_data[MN_TENS][0], (uint8_t)~MED_DIGIT_MASK_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_TENS][1], running_segment_data[MN_TENS][1], (uint8_t)~MED_DIGIT_MASK_8_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
}
running_segment_data[MN_UNITS][0] = running_segment_data[MN_UNITS][0] & MED_DIGIT_MASK_4_2_1;
running_segment_data[MN_UNITS][1] = running_segment_data[MN_UNITS][1] & MED_DIGIT_MASK_8_4_2_1;
// Write the Units
running_segment_data[MN_UNITS][0] = (running_segment_data[MN_UNITS][0] | medium_digit_data[temp_units][0]);
running_segment_data[MN_UNITS][1] = (running_segment_data[MN_UNITS][1] | medium_digit_data[temp_units][1]);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_UNITS][0], running_segment_data[MN_UNITS][0], (uint8_t)~MED_DIGIT_MASK_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
err = R_SLCDC_Modify( &g_slcdc_ctrl, medium_digit_start_addresses[MN_UNITS][1], running_segment_data[MN_UNITS][1], (uint8_t)~MED_DIGIT_MASK_8_4_2_1 );
CHECK_SEGMENT_WRITE_ERROR(err);
}
return err;
}
这样就可以实现在段码屏上显示ADC采样值的功能。ADC采样模块获取输入电压的代码如下。
//Output from ADC
static uint16_t voltage_out = RESET_VALUE;
...
while(true)
{
err = R_ADC_ScanStart(&g_adc_ctrl);
//Read voltage from ADC
err = R_ADC_Read (&g_adc_ctrl, ADC_CHANNEL_25, &voltage_out);
R_BSP_SoftwareDelay (COUNT_DELAY, BSP_DELAY_UNITS_MILLISECONDS);
set_segments_medium_digits(voltage_out,DP_COLON_OFF);
}
...
程序的整体运行流程如下:
外部连接一个电位器到开发板,对电位器的活动触点的电压值进行采样(需要注意的是,有没有保护电路,不能让电位器的阻值过小引发短路)
实验效果如视频所示。
瑞萨的SLDC模块可以直接驱动段码屏,可以减少外部段码屏驱动芯片以及电路,同时官方有详细的资料,方便开发相关的应用。
更多回帖