瑞萨单片机论坛
直播中

EPTmachine

8年用户 1030经验值
擅长:可编程逻辑 嵌入式技术 存储技术 接口/总线/驱动 控制/MCU
私信 关注

【RA4L1-SENSOR】2、段码屏显示和ADC检测

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

1、硬件连接

开发板配套的段码屏和RA4L1芯片的连接原理图如下。

LCD_Interface_Config.png

LCD_Interface_Config.png

段码屏引脚 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寄存器中,实现对段码屏的显示控制。

SegLCD_Pin.png

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

Segment_LCD_Driver_Mode.png

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

Arduino_ADC_Input.png

2、工程配置

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

LCD_DriverCfg.png

LCD_PinCfg.png

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

ADC_Cfg.png

ADC_PinCfg.png

保存并生成代码后,即可使用SLCDC和ADC模块来实现“简易电压表功能”

关于RA4L1的断码屏使用和示例程序,可以在瑞萨官网找到相应的资料。

Segment_LCD_Example_code.png

3、功能实现

段码屏需要根据硬件进行编码,结合原理图中连接的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);
			
    }
...

程序的整体运行流程如下:
02_ADC_Get_Flow.png

4、实验效果

外部连接一个电位器到开发板,对电位器的活动触点的电压值进行采样(需要注意的是,有没有保护电路,不能让电位器的阻值过小引发短路)

实验效果如视频所示。

5、总结

瑞萨的SLDC模块可以直接驱动段码屏,可以减少外部段码屏驱动芯片以及电路,同时官方有详细的资料,方便开发相关的应用。

02_SLCDC_ADC实验效果

更多回帖

发帖
×
20
完善资料,
赚取积分