目录
概述
本文主要介绍Renesas R7FA8D1BH (Cortex®-M85) ADC模块读取MCU内部Temperature sensor的值,笔者使用FSP配置ADC模块的参数,并生成基于KEIL的工程代码。还编写一个读取Temperature sensor的应用程序,以实现读取温度值的功能,并将读到的数据通过UART发送至控制台,以观察期数据的变化。
1 软硬件
1.1 软硬件环境信息
软硬件信息 | 版本信息 |
---|---|
Renesas MCU | R7FA8D1BH |
Keil | MDK ARM 5.38 |
FSP 版本 | 5.3.0 |
调试工具:N32G45XVL-STB | DAP-LINK |
1.2 开发板信息
笔者选择使用野火耀阳开发板_瑞萨RA8,该板块的主控MCU为R7FA8D1BHECBD,7FA8D1BHECBD的内核为ARM Contex-M85。
1.3 调试器信息
对于R7FA8D1BHECBD芯片,其使用的内核为Cortex®-M85 Core, ST-LINK-V2或者J-LINK-V9不支持下载和调试功能。笔者经过多次尝试,发现N32G45XVL-STB板卡上自带的DAP-LINK可以下载和调试R7FA8D1BHECBD。
下图为N32G45XVL-STB开发板实物图:
2 FSP和KEIL配置ADC
2.1 ADC硬件接口
温度传感器输出一个随温度变化的电压。该电压通过电路转换为数字值12位A/D转换器。要获得模具温度,将此值转换为温度。
2.2 FSP配置ADC
1)创建ADC模块
2)选择ADC单元选择
3) 配置通道号,使能Temperature Sensor
3 软件功能实现
3.1 FSP生成项目
在完成FSP的参数配置之后,就可以使用Generate Project生成项目代码,打开项目后在hal_data.c中已经生成了adc的相关代码。
3.2 FSP ADC模块库函数介绍
3.2.1 库函数列表
概述
ADC模块支持以下特性:1)12,14或16位最大分辨率取决于MCU
2)配置扫描包括:
多个模拟通道
温度传感器通道
电压传感器通道
3)可配置扫描启动触发器:
软件扫描触发器
硬件扫描触发器(例如,计时器过期)
外部扫描触发器从adtrn端口引脚
4)可配置扫描模式:
单扫描模式,其中每个触发器启动一次扫描
连续扫描模式,连续扫描所有通道
群组扫描模式,将通道分为A组和B组。群组可以配置不同的启动触发器,A组可以优先于B组。当A组优先于B组时,A组触发器暂停正在进行的B组扫描。5)支持添加和平均转换的样本
6)扫描完成时可选回调
7)取样和保持支撑
8)双层支持
9)具有中断和事件输出的硬件比较器
3.2.2 函数介绍
1)R_ADC_Open()
fsp_err_t R_ADC_Open ( adc_ctrl_t * p_ctrl,
adc_cfg_t const *const p_cfg
)
参数介绍
设置整个外设的操作模式、触发源、中断优先级和配置。如果中断被启用,该函数注册一个回调函数指针,以便在扫描完成时通知用户。
Return values
FSP_SUCCESS Module is ready for use. FSP_ERR_ASSERTION An input argument is invalid. FSP_ERR_ALREADY_OPEN The instance control structure has already been opened. FSP_ERR_IRQ_BSP_DISABLED A callback is provided, but the interrupt is not enabled. FSP_ERR_IP_CHANNEL_NOT_PRESENT The requested unit does not exist on this MCU. FSP_ERR_INVALID_HW_CONDITION The ADC clock must be at least 1 MHz
2)R_ADC_ScanCfg()
fsp_err_t R_ADC_ScanCfg ( adc_ctrl_t * p_ctrl,
void const *const p_channel_cfg
)
参数介绍
配置ADC扫描参数。通道特定设置在此函数中设置。将指向adc_channel_cfg_t的指针传递给p_channel_cfg。
请注意如果adc_channel_cfg_t::priority_group_a设置为ADC_GROUP_A_GROUP_B_CONTINUOUS_SCAN,则启动组B扫描。
Return values
FSP_SUCCESS Channel specific settings applied. FSP_ERR_ASSERTION An input argument is invalid. FSP_ERR_NOT_OPEN Unit is not open.
3)R_ADC_ScanStart()
fsp_err_t R_ADC_ScanStart ( adc_ctrl_t * p_ctrl )
根据R_ADC_Open调用中如何配置触发器,启动软件扫描或启用扫描的硬件触发器。如果单元配置为ELC或外部硬件触发,则此功能允许触发信号到达ADC单元。该函数不能控制触发器本身的生成。如果设备配置为软件触发,则此功能启动软件触发扫描。
Precondition
Call R_ADC_ScanCfg after R_ADC_Open before starting a scan.
On MCUs that support calibration, call R_ADC_Calibrate and wait for calibration to complete before starting a scan.
Return values
FSP_SUCCESS Scan started (software trigger) or hardware triggers enabled. FSP_ERR_ASSERTION An input argument is invalid. FSP_ERR_NOT_OPEN Unit is not open. FSP_ERR_NOT_INITIALIZED Unit is not initialized. FSP_ERR_IN_USE Another scan is still in progress (software trigger).
4)R_ADC_StatusGet()
fsp_err_t R_ADC_StatusGet ( adc_ctrl_t * p_ctrl,
adc_status_t * p_status
)
参数介绍
提供已启动的任何扫描进程的状态,包括由ELC或外部触发器启动的扫描以及支持校准的mcu上的校准扫描。
Return values
FSP_SUCCESS Module status stored in the provided pointer p_status FSP_ERR_ASSERTION An input argument is invalid. FSP_ERR_NOT_OPEN Unit is not open.
5)R_ADC_Read()
fsp_err_t R_ADC_Read ( adc_ctrl_t * p_ctrl,
adc_channel_t const reg_id,
uint16_t *const p_data
)
参数介绍
从单个通道或传感器读取转换结果。
Return values
FSP_SUCCESS Data read into provided p_data. FSP_ERR_ASSERTION An input argument is invalid. FSP_ERR_NOT_OPEN Unit is not open. FSP_ERR_NOT_INITIALIZED Unit is not initialized.
6) R_ADC_InfoGet()
fsp_err_t R_ADC_InfoGet ( adc_ctrl_t * p_ctrl,
adc_info_t * p_adc_info
)
返回最低配置通道的地址和为了读取配置通道的结果并返回ELC事件名称而要读取的总字节数。如果没有配置通道,则返回长度为0。还提供了温度传感器的斜率和传感器的校准数据,如果在这个MCU上可用。否则将返回无效的0xFFFFFFFF校准数据。
请注意
在组模式下,只返回组A的信息。目前不支持计算B组的信息。Return values
FSP_SUCCESS Information stored in p_adc_info. FSP_ERR_ASSERTION An input argument is invalid. FSP_ERR_NOT_OPEN Unit is not open.
4 读Temperature sensor
4.1 初始化ADC
代码第19行:初始化adc模块
代码第23行:使能adc转换通道
4.2 读取Temperature sensor值函数
代码第54行:启动ADC转换
代码第61行:获取ADC转换的状态
代码第65行:读取ADC的值
代码第72行:标定ADC Temperature sensor的值
代码104行:转换温度值
代码106行:打印温度数据到串口终端
4.3 源代码
/*
FILE NAME : bsp_adc.c
Description: adc interface
Author : [email protected]
Date : 2024/06/03
*/
#include "bsp_adc.h"
#include "hal_data.h"
#define ADC_EXAMPLE_CALIBRATION_DATA_RA6M1 (0x7D5)
#define ADC_EXAMPLE_VCC_MICROVOLT (3300000)
#define ADC_EXAMPLE_TEMPERATURE_RESOLUTION (12U)
#define ADC_EXAMPLE_REFERENCE_CALIBRATION_TEMPERATURE (127)
void adc_basic_init( void )
{
fsp_err_t err = FSP_SUCCESS;
/* Initializes the module. */
err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Enable channels. */
err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg);
assert(FSP_SUCCESS == err);
}
void adc_basic_get_value (uint16_t *result)
{
fsp_err_t err = FSP_SUCCESS;
adc_status_t status;
/* In software trigger mode, start a scan by calling R_ADC_ScanStart(). In other modes, enable external
* triggers by calling R_ADC_ScanStart(). */
(void) R_ADC_ScanStart(&g_adc0_ctrl);
/* Wait for conversion to complete. */
status.state = ADC_STATE_SCAN_IN_PROGRESS;
while (ADC_STATE_SCAN_IN_PROGRESS == status.state)
{
(void) R_ADC_StatusGet(&g_adc0_ctrl, &status);
}
/* Read converted data. */
err = R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_0, result);
assert(FSP_SUCCESS == err);
float voltage = (float)(((*result)*3.3)/4096);
printf(" ADC_CHANNEL_0: %d , voltage(v): %.02f\n", *result , voltage);
}
void adc_basic_get_temperature(int32_t *result)
{
fsp_err_t err = FSP_SUCCESS;
(void) R_ADC_ScanStart(&g_adc0_ctrl);
/* Wait for conversion to complete. */
adc_status_t status;
status.state = ADC_STATE_SCAN_IN_PROGRESS;
while (ADC_STATE_SCAN_IN_PROGRESS == status.state)
{
(void) R_ADC_StatusGet(&g_adc0_ctrl, &status);
}
/* Read converted data. */
uint16_t temperature_conversion_result;
err = R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_TEMPERATURE, &temperature_conversion_result);
assert(FSP_SUCCESS == err);
/* If the MCU does not provide calibration data, use the value in the hardware manual or determine it
* experimentally. */
/* Get Calibration data from the MCU if available. */
int32_t reference_calibration_data;
adc_info_t adc_info;
(void) R_ADC_InfoGet(&g_adc0_ctrl, &adc_info);
reference_calibration_data = (int32_t) adc_info.calibration_data;
/* NOTE: The slope of the temperature sensor varies from sensor to sensor. Renesas recommends calculating
* the slope of the temperature sensor experimentally.
*
* This example uses the typical slope provided in Table 52.38 "TSN characteristics" in the RA6M1 manual
* R01UM0011EU0050. */
int32_t slope_uv_per_c = BSP_FEATURE_ADC_TSN_SLOPE;
/* Formula for calculating temperature copied from section 44.3.1 "Preparation for Using the Temperature Sensor"
* of the RA6M1 manual R01UH0884EJ0100:
*
* In this MCU, the TSCDR register stores the temperature value (CAL127) of the temperature sensor measured
* under the condition Ta = Tj = 127 C and AVCC0 = 3.3 V. By using this value as the sample measurement result
* at the first point, preparation before using the temperature sensor can be omitted.
*
* If V1 is calculated from CAL127,
* V1 = 3.3 * CAL127 / 4096 [V]
*
* Using this, the measured temperature can be calculated according to the following formula.
*
* T = (Vs - V1) / Slope + 127 [C]
* T: Measured temperature (C)
* Vs: Voltage output by the temperature sensor when the temperature is measured (V)
* V1: Voltage output by the temperature sensor when Ta = Tj = 127 C and AVCC0 = 3.3 V (V)
* Slope: Temperature slope given in Table 52.38 / 1000 (V/C)
*/
int32_t v1_uv = (ADC_EXAMPLE_VCC_MICROVOLT >> ADC_EXAMPLE_TEMPERATURE_RESOLUTION) *
reference_calibration_data;
int32_t vs_uv = (ADC_EXAMPLE_VCC_MICROVOLT >> ADC_EXAMPLE_TEMPERATURE_RESOLUTION) *
temperature_conversion_result;
*result = (vs_uv - v1_uv) / slope_uv_per_c + ADC_EXAMPLE_REFERENCE_CALIBRATION_TEMPERATURE;
printf(" Temperature(C): %d \n", *result );
}
/* End of this file */
5 测试
5.1 主函数调用
代码第45行: 初始化ADC模块
代码第52行:调用adc端口读取温度值
5.2 下载代码和运行
编译代码,下载到板卡中。运行代码