工作模式
1、初始化单路ADC,开启转化,轮训等待转换完成,输出转化完成寄存器值。
问题
1、ADC中断无法正常启用
在ADC配置函数中加入中断配置语句开启ADC中断,无法找到相应的中断处理函数。
与ADC相关的中断处理函数只有ADC_CMP_IRQHandler()
定义此中断函数后,开启ADC转换确实可以触发此中断服务函数,但是中断标志无法清除,会不断触发中断。
请求大神帮忙解答!!!!!
2、多个ADC都要读取如何配置,配置完成如何读取数据
请求大神帮忙解答!!!!!
中断配置:
使能ADC中断
// adc_interrupt_enable(ADC_INT_EOC);
配置ADC中断优先级
// nvic_irq_enable(ADC_CMP_IRQn, 0, 0);
中断处理函数:
void ADC_CMP_IRQHandler()
{
printf("ADC_CMP_IRQHandler\r\n");
if(adc_interrupt_flag_get(ADC_INT_FLAG_EOC))
{
// 清除ADC规则组转换结束中断标志
adc_interrupt_flag_clear(ADC_INT_FLAG_EOC);
}
}
头文件 adc.h
#ifndef __ADC_H__
#define __ADC_H__
void get_adc_val_PA0();
void get_adc_val_PA1();
#endif
源文件 adc.c
#include "gd32f3x0.h"
#include "systick.h"
#include <stdio.h>
#include "jlink_log.h"
//ADC配置结构体
typedef struct
{
// ADC通道
uint8_t adc_channel;
// ADC引脚PORT
uint32_t gpio_periph;
// ADC引脚PIN
uint32_t pin;
// ADC引脚时钟
rcu_periph_enum gpio_clock;
} struct_adc_config;
//ID1
struct_adc_config adc_config_PA0 =
{
.adc_channel = ADC_CHANNEL_0,
.gpio_periph = GPIOA,
.pin = GPIO_PIN_0,
.gpio_clock = RCU_GPIOA,
};
//ID2
struct_adc_config adc_config_PA1 =
{
.adc_channel = ADC_CHANNEL_1,
.gpio_periph = GPIOA,
.pin = GPIO_PIN_1,
.gpio_clock = RCU_GPIOA,
};
/*!
\brief 初始化ADC
\param[in] adc_config ADC配置结构体
\param[out] none
\retval none
*/
static void init_adc(struct_adc_config adc_config)
{
/* 启用GPIO时钟功能 */
rcu_periph_clock_enable(adc_config.gpio_clock);
/* 启用ADC时钟功能 */
rcu_periph_clock_enable(RCU_ADC);
/* 配置ADC时钟预分频 APB2=25M 6分频后ADC时钟约为4M*/
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
/* 设置GPIO模式 */
gpio_mode_set(adc_config.gpio_periph, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, adc_config.pin);
/* 配置 ADC 为连续模式(扫描模式只在 DMA 模式下使用) */
adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);
/* 配置 ADC 的触发方式 此处设置为软件触发 */
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
/* ADC 对齐设置为右对齐 */
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
/* 配置通道数 */
adc_channel_length_config(ADC_REGULAR_CHANNEL, 1U);
/* 配置使用哪一个 ADC 通道 */
adc_regular_channel_config(0U, adc_config.adc_channel, ADC_SAMPLETIME_55POINT5);
// 开启 ADC 的常规通道组
adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
使能ADC中断
// adc_interrupt_enable(ADC_INT_EOC);
配置ADC中断优先级
// nvic_irq_enable(ADC_CMP_IRQn, 0, 0);
/* 使能ADC */
adc_enable();
delay_1ms(1U);
/* 校准和复位校准 ADC*/
adc_calibration_enable();
}
/*!
\brief 获取ADC值
\param[in] *adc_val ADC值存储地址
\param[out] 0--获取成功,其他值获取失败
\retval none
*/
static int get_adc_val(uint16_t *adc_val)
{
// 清除转换标志位
adc_flag_clear(ADC_FLAG_STRC | ADC_FLAG_EOC);
//软件触发 ADC 转换开始
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
// 轮训等待转换完成
for(int i = 0; i < 1000; i++)
{
if(SET == adc_flag_get(ADC_FLAG_STRC))
{
if(SET == adc_flag_get(ADC_FLAG_EOC))
{
*adc_val = adc_regular_data_read();
adc_flag_clear(ADC_FLAG_STRC | ADC_FLAG_EOC);
printf("i:%d\r\n", i);
return 0;
}
else
{
continue;
}
}
delay_1ms(1);
}
//获取ADC值超时返回失败
printf("get ADC val overtimer\r\n");
return -1;
}
/*!
\brief 获取PA0 ADC值
\param[in] *adc_val ADC值存储地址
\param[out] 0--获取成功,其他值获取失败
\retval none
*/
int get_adc_val_PA0(uint16_t *adc_val)
{
printf("get_adc_val_PA0\r\n");
init_adc(adc_config_PA0);
return get_adc_val(adc_val);
}
/*!
\brief 获取PA1 ADC值
\param[in] *adc_val ADC值存储地址
\param[out] 0--获取成功,其他值获取失败
\retval none
*/
int get_adc_val_PA1(uint16_t *adc_val)
{
printf("get_adc_val_PA1\r\n");
init_adc(adc_config_PA1);
return get_adc_val(adc_val);
}
main.c
#include "adc.h"
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
/* system clocks configuration */
rcu_config();
/* systick configuration */
systick_config();
uint16_t adc_val;
get_adc_val_PA0(&adc_val);
printf("get_adc_val_PA0: 0%d\r\n", adc_value);
get_adc_val_PA1(&adc_val);
printf("get_adc_val_PA1: 0%d\r\n", adc_value);
while(1) {}
}