瑞萨单片机william hill官网
直播中

hehung

8年用户 659经验值
擅长:嵌入式技术
私信 关注
[经验]

【瑞萨RA4系列开发板体验】6. ADC测量摇杆模块偏移量

之前发帖:
【瑞萨RA4系列开发板体验】1. 新建工程+按键控制LED
【瑞萨RA4系列开发板体验】2. KEIL环境搭建+STLINK调试+FreeRTOS使用
【瑞萨RA4系列开发板体验】3. KEIL下UART实现printf与scanf重定向
【瑞萨RA4系列开发板体验】4. PWM驱动LED
【瑞萨RA4系列开发板体验】5. 硬件IIC驱动OLED显示汉字

前言

本文的目的在与测试一下RA4M2的ADC功能,我会用一个摇杆模块来测试两路ADC的采集情况,本文实现如下功能:

  1. 本文基于KEIL开发环境;
  2. OLED会显示ADC的采集信息(OLED显示不是本文重点,请参考我上一篇文章);
  3. 摇杆模块有两路ADC信号,一路用于显示X轴,一路用于显示Y轴,用于表示当前摇杆所处的位置。

本文中实用到了所有驱动都能在我之前的文章中找到使用方法,有需要请参考。

硬件连接

查看原理图,了解芯片的ADC引脚的映射关系,我们才能接下来的工作。
RA4M2只有一路ADC,但是有很多通道。
本文中用到了ADC通道AN000以及AN001,分别连接到了P000引脚与P001引脚,如下图。1.png

RASC配置

知道了ADC的引脚映射关系,接下来就开始我们的驱动配置了,打开RASC,打开方式不细说,请参考我之前的文章。

使能ADC

如下图,选中Pins->Analog:ADC,使能ADC0,并且使能AN000以及AN001,如果需要使能其他的ADC,直接选中相应的引脚使能即可。2.png

ADC详细配置

使能了ADC引脚之后,开始配置ADC具体的采样功能,本文只进行了最基础的配置,其他的使用功能需要自行开发,如下图,新建ADC Stack。3.png

因为单片机只提供了一路ADC,这里需要将Unit写为0,使用12bit采样方式,右对齐,按照默认即可。
输入选择使能Channel0以及Channel1.4.png

输入回调函数的名字,这个函数需要我们自己实现。最后配置映射端口,其实无需我们自己编写会自动匹配。5.png

代码实现

我新建了一个app_adc.c以及app_adc.h,代码实现逻辑不细说,瑞萨已经封装的很好了,理解起来很简单。

app_adc.c

该文件中实现了adc的回调函数的实现,初始化,ADC开始转换函数,ADC转换状态获取,ADC转换结果获取。
这些函数都是我再封装了一层,主要是为了使用起来方便。下面说一下调用关系:

  1. 初始化,不细说,系统上电的时候需要做的工作;
  2. 在循环中作如下操作:
  3. 调用Adc_StartSample启动ADC转换;
  4. 调用Adc_ReadChannel获取ADC转换结果;
  5. 如果转换结果反馈状态为ADC_COMPLETED,则调用Adc_ReadChannel获取ADC转换结果。
/*
@hehung
2022-12-01
*/
#include "hal_data.h"
#include "app_adc.h"

#include <stdio.h>

volatile bool adc_scan_complete_flag = false;
volatile bool last_adc_scan_flag = true;

/* Callback function of ADC */
void adc_notification(adc_callback_args_t * p_args)
{
    (void)p_args;
    adc_scan_complete_flag = true;
}

void Adc_Init(void)
{
    fsp_err_t err = FSP_SUCCESS;
	
    /* Initializes the adc. */
    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);
}

/* ADC sampling */
void Adc_StartSample(void)
{
	if (false == adc_scan_complete_flag)
	{
		/* Enable scan triggering from ELC events. */
		(void)R_ADC_ScanStart(&g_adc0_ctrl);
	}
}

/* Get ADC sampling status */
e_Adc_StatusType Adc_GetStatus(void)
{
	if (true == adc_scan_complete_flag)
	{
		return ADC_COMPLETED;
	}
	else
	{	
		return ADC_ONGOING;
	}	
}

/* Read conversion result */
uint16_t Adc_ReadChannel(adc_channel_t channel)
{	
	fsp_err_t err = FSP_SUCCESS;
	uint16_t adc_value;
	
	err = R_ADC_Read(&g_adc0_ctrl, channel, &adc_value);
	assert(FSP_SUCCESS == err);
//	printf ("ADC%d: %d\n", channel, adc_value);
	
	adc_scan_complete_flag = false;
	
	return adc_value;
}

app_adc.h

/*
@hehung
2022-12-01
*/

#ifndef APP_ADC_H_
#define APP_ADC_H_

#include "stdint.h"
#include "hal_data.h"

typedef enum
{
	ADC_COMPLETED = 0,
	ADC_ONGOING
} e_Adc_StatusType;

extern void Adc_Init(void);
extern void Adc_StartSample(void);
extern e_Adc_StatusType Adc_GetStatus(void);
extern uint16_t Adc_ReadChannel(adc_channel_t channel);

#endif

主函数实现

没100毫秒采集一次ADC信息,并通过OLED显示出来X,Y坐标的偏移量,显示的是原ADC采样值,没有做计算处理。

void hal_entry(void)
{
	char adc_str[16];
	
	/* Initialize the uart for implement the 'printf' and 'scanf' */
	Uart_Init();
	/* Initialize the os and some tasks */
//	Task_Create();
	/* Initialize the I2c */
	I2c_Init();
	/* Initialize the OLED */
	OLED_Init();
	/* Initialize the ADC */
	Adc_Init();
	/* Initialize the DAC */
	Dac_Init();
	
	OLED_ShowString(12, 0, (const uint8_t*)"R7FA4M2AD3CFP", 16, 1);
//    OLED_ShowHzStringRow(32, 24, (const char*)"电子发烧友", 1);
    OLED_ShowString(0, 16, (const uint8_t*)"elecfans", 16, 1);
	OLED_ShowString(64, 16, (const uint8_t*)"|hehung", 16, 1);
    OLED_Refresh_Gram();
	
	while (1) 
	{
//		Adc_OutputVal(DAC_DAC0, 2000);
//		Adc_OutputVal(DAC_DAC1, 4000);
		Adc_StartSample();
		while (ADC_COMPLETED != Adc_GetStatus())
		{}
		sprintf(adc_str, "ADC X: %04d", Adc_ReadChannel(ADC_CHANNEL_0));
		OLED_ShowString(0, 32, (const uint8_t*)adc_str, 16, 1);	
		sprintf(adc_str, "ADC Y: %04d", Adc_ReadChannel(ADC_CHANNEL_1));
		OLED_ShowString(0, 48, (const uint8_t*)adc_str, 16, 1);	
		OLED_Refresh_Gram();
		R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
	}

#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

显示效果

6.png

视频演示效果见文章末尾视频

1

更多回帖

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