瑞萨单片机论坛
直播中

qiao

未满1年用户 11经验值
擅长:嵌入式技术 控制/MCU
私信 关注
[经验]

【瑞萨RA6E2】ADC数据采集与数码管显示

概述

项目简介

本报告基于瑞萨RA6E2评估板,实现了一个完整的ADC数据采集与显示系统。通过板载ADC通道采集模拟信号,将采集到的数字量通过动态扫描方式在4位数码管上实时显示,展示了RA6E2在模拟信号处理和显示控制方面的强大能力。


一、硬件设计与连接

1.1 硬件组件

  • 主控板 :瑞萨RA6E2评估板
  • 显示模块 :8位(启用4位)74HC595共阳极数码管
  • 输入信号 :电位器(提供0-3.3V可调电压)
  • 连接方式 :使用杜邦线连接开发板与数码管模块

1.2 引脚分配

功能 RA6E2引脚 对应74HC595引脚 说明
数据线(DIO) P400 DS 串行数据输入
时钟线(SCLK) P401 SHCP 移位寄存器时钟
锁存线(RCLK) P402 STCP 存储寄存器时钟
ADC输入 AN0 - 模拟信号输入

1.3 电路连接示意图

text

RA6E2开发板          数码管模块
   P400    ------>    DS (数据)
   P401    ------>    SHCP (时钟)
   P402    ------>    STCP (锁存)
   3.3V    ------>    VCC
   GND     ------>    GND
   AN0     <------    电位器中间引脚

二、软件开发环境

2.1 开发工具

  • IDE : Keil MDK
  • 配置工具 : Renesas Advanced Smart Configurator

2.2 环境配置步骤

  1. 使用e2 studio创建新工程,选择R7FA6E2BH芯片0-3.png

  2. 配置ADC模块:

    • 选择ADC通道0

    • 设置12位分辨率
      00-9.png

      屏幕截图(30).png

      屏幕截图(31).png

  3. 生成工程代码并导入Keil MDK


三、软件设计与实现

3.1 核心代码实现

c

#include "hal_data.h"

/* 数码管驱动引脚定义 */
#define SEG_DIO BSP_IO_PORT_04_PIN_00  // 数据输入引脚
#define SEG_SCLK BSP_IO_PORT_04_PIN_01 // 移位寄存器时钟
#define SEG_RCLK BSP_IO_PORT_04_PIN_02 // 存储寄存器时钟(锁存)

/* 全局变量 */
fsp_err_t err = FSP_SUCCESS;
volatile bool g_scan_complete_flag = false;
uint16_t g_seg_data = 0;

/* 共阳极数码管段码表 (0-9, A-F, '-', 全灭) */
const uint8_t g_seg_table[] = {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, // 0-9
    0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E, 0xBF, 0xFF              // A-F, '-', 全灭
};

/**
 * [url=home.php?mod=space&uid=2666770]@Brief[/url] ADC回调函数
 * [url=home.php?mod=space&uid=3142012]@param[/url] p_args 回调参数
 * [url=home.php?mod=space&uid=1902110]@NOTE[/url] ADC扫描完成时自动调用,设置完成标志
 */
void adc_callback(adc_callback_args_t * p_args)
{
    FSP_PARAMETER_NOT_USED(p_args);
    g_scan_complete_flag = true;
}

/**
 * @brief ADC初始化
 * @note 配置并启动ADC模块
 */
void adc_init(void)
{
    /* 打开ADC设备 */
    err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg);
    assert(FSP_SUCCESS == err);
    
    /* 配置ADC扫描参数 */
    err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg);
    assert(FSP_SUCCESS == err);
    
    /* 开始ADC扫描 */
    R_ADC_ScanStart(&g_adc0_ctrl);
}

/**
 * @brief 读取ADC通道值
 * @param channel ADC通道号
 * [url=home.php?mod=space&uid=1141835]@Return[/url] ADC转换结果(0-4095)
 */
uint16_t adc_read(adc_channel_t channel)
{
    uint16_t adc_value = 0;
    
    /* 等待ADC转换完成 */
    g_scan_complete_flag = false;
    while (!g_scan_complete_flag)
    {
        /* 空循环等待中断 */
    }
    
    /* 读取ADC转换结果 */
    err = R_ADC_Read(&g_adc0_ctrl, channel, &adc_value);
    assert(FSP_SUCCESS == err);
    
    return adc_value;
}

/**
 * @brief 向数码管发送数据
 * @param segment 段码数据
 * @param position 位选数据
 * @note 使用软件SPI协议控制74HC595
 */
void seg_send_data(uint8_t segment, uint8_t position)
{
    uint8_t data[2] = {segment, position};
    
    /* 拉低锁存信号,准备接收数据 */
    R_IOPORT_PinWrite(&g_ioport_ctrl, SEG_RCLK, BSP_IO_LEVEL_LOW);
    
    /* 发送两个字节数据 */
    for (uint8_t i = 0; i < 2; i++)
    {
        /* 逐位发送数据 */
        for (uint8_t j = 0; j < 8; j++)
        {
            /* 拉低时钟,准备数据位 */
            R_IOPORT_PinWrite(&g_ioport_ctrl, SEG_SCLK, BSP_IO_LEVEL_LOW);
            
            /* 发送数据位(从高位开始) */
            bsp_io_level_t bit_level = (data[i] & (0x80 >> j)) ? 
                                      BSP_IO_LEVEL_HIGH : BSP_IO_LEVEL_LOW;
            R_IOPORT_PinWrite(&g_ioport_ctrl, SEG_DIO, bit_level);
            
            /* 拉高时钟,锁存数据位 */
            R_IOPORT_PinWrite(&g_ioport_ctrl, SEG_SCLK, BSP_IO_LEVEL_HIGH);
        }
    }
    
    /* 拉高锁存信号,输出数据到并行端口 */
    R_IOPORT_PinWrite(&g_ioport_ctrl, SEG_RCLK, BSP_IO_LEVEL_HIGH);
}

/**
 * @brief 数码管动态扫描显示
 * @note 采用动态扫描方式,每次显示一位数字
 */
void seg_display(void)
{
    static uint16_t digit_value = 1;     // 当前位数权重
    static uint8_t digit_position = 0;   // 当前显示位置
    
    /* 计算当前位的数字 */
    uint8_t number = (g_seg_data / digit_value) % 10;
    
    /* 在第2位(从0开始)显示小数点 */
    uint8_t segment_data = (digit_position == 1) ? 
                          (g_seg_table[number] & 0x7F) : g_seg_table[number];
    
    /* 位选信号(共阳极,低电平选中) */
    uint8_t position_data = (uint8_t)(1 << digit_position);
    
    /* 发送显示数据 */
    seg_send_data(segment_data, position_data);
    
    /* 更新显示位置和位数权重 */
    digit_position = (digit_position + 1) % 4;
    digit_value = (digit_position == 0) ? 1 : digit_value * 10;
}

/**
 * @brief 主程序入口
 */
void hal_entry(void)
{
    /* 初始化数码管控制引脚 */
    R_IOPORT_PinCfg(&g_ioport_ctrl, SEG_DIO, 
                    IOPORT_CFG_PORT_DIRECTION_OUTPUT);
    R_IOPORT_PinCfg(&g_ioport_ctrl, SEG_SCLK, 
                    IOPORT_CFG_PORT_DIRECTION_OUTPUT);
    R_IOPORT_PinCfg(&g_ioport_ctrl, SEG_RCLK, 
                    IOPORT_CFG_PORT_DIRECTION_OUTPUT);
    
    /* 初始化ADC */
    adc_init();
    
    /* 主循环 */
    while (1)
    {
        static uint32_t adc_sample_counter = 0;
        
        /* 每1000次显示刷新采样一次ADC(软件定时) */
        if (++adc_sample_counter >= 1000)
        {
            adc_sample_counter = 0;
            
            /* 读取ADC并转换为电压值(0-330对应0-3.30V) */
            uint16_t adc_raw = adc_read(ADC_CHANNEL_0);
            g_seg_data = adc_raw * 330 / 4095;
        }
        
        /* 刷新数码管显示 */
        seg_display();
        
        /* 短暂延时,控制刷新频率 */
        R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
    }
}

3.2 关键算法说明

  1. ADC数据处理
    • 12位ADC原始值(0-4095)转换为电压值(0-330)
    • 对应实际电压0-3.30V,分辨率为0.01V(MAX 0.8mV)
  2. 动态扫描原理
    • 每次只点亮一位数码管
    • 快速循环刷新(约1ms每位)
    • 利用视觉暂留效应实现稳定显示
  3. 软件SPI协议
    • 模拟74HC595的串行输入时序
    • 先发送位码,再发送段码

3.3 实物演示

  • 系统整体连接照片
    微信图片_20251127001615.jpg
  • 功能演示视频

实物演示

更多回帖

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