一、硬件资源
1、16位ADC采样,最大2M采样率
2、内置DMA,可以直接把ADC转换结果写入内存,配置方便
3、支持多种外部触发源,触发采样
4、单个抢占转换队列可达12个,每个队列最大4个通道。
5、PWMV2的触发配置见之前的文章
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、调试问题
1、需要注意ADC如果是作为电机系统使用,需要将时钟源配置为
clock_set_adc_source(clock_adc0, clk_adc_src_ahb0);这是电机系统专用时钟
2、ADC采样频率需要4分频,因为clk_adc_src_ahb0为200MHZ,ADC时钟频率最大为50MHZ
3、互联管理器需要注意输入信号和输出信号和实际需要的信号匹配
4、发现当在DEBUG时,查看多个寄存器会导致SEGGER卡死,未解决。
在这里插入图片描述

三、调试代码
#include “Bsp_Adc.h”

/*
默认时钟 AHB0 —200MHZ,需4分频至50MHZ
PF6- ADC0-14
PF8- ADC1-10
PF19- ADC2-11

PWMv2发生器上桥导通中间点产生PWM1_TRG_0 ,50us触发ADC0,1,2抢占采样启动
抢占采样完成后,触发ADC0抢占采样完成中断,计算采样值

*/

ATTR_PLACE_AT_FAST_RAM uint32_t pmt_buff[20] = {0};

ATTR_PLACE_AT_FAST_RAM float ADC_Time, ADC_U_V, ADC_V_V, ADC_W_V = 0.0f;

void Bsp_ADC16_Init(void)
{

uint32_t freq;

adc16_config_t cfg;
adc16_channel_config_t ch_cfg;
adc16_pmt_config_t pmt_cfg;
trgm_output_t trgm_output_cfg;

ADC_Time = 0.0f;
ADC_U_V = 0.0f;
ADC_V_V = 0.0f;
ADC_W_V = 0.0f;
//使能ADC 时钟
clock_add_to_group(clock_adc0, 0);
clock_add_to_group(clock_adc1, 0);
clock_add_to_group(clock_adc2, 0);

//选择ADC时钟为AHB0 --电机系统统一时钟
clock_set_adc_source(clock_adc0, clk_adc_src_ahb0);
clock_set_adc_source(clock_adc1, clk_adc_src_ahb0);
clock_set_adc_source(clock_adc2, clk_adc_src_ahb0);

//获取ADC时钟
freq = clock_get_frequency(clock_adc0);

/* 初始化为IO口为模拟量输入 */
HPM_IOC->PAD[IOC_PAD_PF06].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK;
HPM_IOC->PAD[IOC_PAD_PF08].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK;
HPM_IOC->PAD[IOC_PAD_PF19].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK;

//ADC基本配置
cfg.res                = adc16_res_16_bits;
cfg.conv_mode          = adc16_conv_mode_preemption; //抢占模式
cfg.adc_clk_div        = adc16_clock_divider_4; //规定最大时钟50MHZ 时钟4分频
cfg.wait_dis           = true;
cfg.sel_sync_ahb       = true;
cfg.port3_realtime     = false;
cfg.adc_ahb_en         = true;
adc16_init(HPM_ADC0, &cfg);
adc16_init(HPM_ADC1, &cfg);
adc16_init(HPM_ADC2, &cfg);

//ADC 通道基本配置
ch_cfg.ch                 = 14; //ADC通道14
ch_cfg.sample_cycle       = 10; //ADC采样时长10个周期,转换周期21个, //20NS*10 = 200NS 
ch_cfg.sample_cycle_shift = 0;
ch_cfg.thshdh             = 0xffff;
ch_cfg.thshdl             = 0x0000;
ch_cfg.wdog_int_en        = false;
adc16_init_channel(HPM_ADC0, &ch_cfg);

//ADC 通道基本配置
ch_cfg.ch				  = 10; //ADC通道10
ch_cfg.sample_cycle 	  = 10; //ADC采样时长10个周期,转换周期21个, //20NS*10 = 200NS 
ch_cfg.sample_cycle_shift = 0;
ch_cfg.thshdh			  = 0xffff;
ch_cfg.thshdl			  = 0x0000;
ch_cfg.wdog_int_en		  = false;
adc16_init_channel(HPM_ADC1, &ch_cfg);

//ADC 通道基本配置
ch_cfg.ch				  = 11; //ADC通道11
ch_cfg.sample_cycle 	  = 10; //ADC采样时长10个周期,转换周期21个, //20NS*10 = 200NS 
ch_cfg.sample_cycle_shift = 0;
ch_cfg.thshdh			  = 0xffff;
ch_cfg.thshdl			  = 0x0000;
ch_cfg.wdog_int_en		  = false;
adc16_init_channel(HPM_ADC2, &ch_cfg);

//抢占转换配置

pmt_cfg.trig_len = 1;  //抢占转换长度
pmt_cfg.trig_ch = ADC16_CONFIG_TRG0A;  //抢占转换队列

for (int i = 0; i < pmt_cfg.trig_len; i++) {
   pmt_cfg.adc_ch[i] = 14;  //抢占转换通道
   pmt_cfg.inten[i] = false; //本次转换完成不触发, TRIG_COMPT 标志位置 1
}

pmt_cfg.inten[pmt_cfg.trig_len - 1] = true; //最后一次抢占通道转换完成,TRIG_COMPT 标志位置 1

adc16_set_pmt_config(HPM_ADC0, &pmt_cfg); //抢占配置

//抢占转换配置

pmt_cfg.trig_len = 1;  //抢占转换长度
pmt_cfg.trig_ch = ADC16_CONFIG_TRG0A;  //抢占转换队列

for (int i = 0; i < pmt_cfg.trig_len; i++) {
   pmt_cfg.adc_ch[i] = 10;  //抢占转换通道
   pmt_cfg.inten[i] = false; //本次转换完成不触发, TRIG_COMPT 标志位置 1
}

pmt_cfg.inten[pmt_cfg.trig_len - 1] = true; //最后一次抢占通道转换完成,TRIG_COMPT 标志位置 1

adc16_set_pmt_config(HPM_ADC1, &pmt_cfg); //抢占配置

//抢占转换配置

pmt_cfg.trig_len = 1;  //抢占转换长度
pmt_cfg.trig_ch = ADC16_CONFIG_TRG0A;  //抢占转换队列

for (int i = 0; i < pmt_cfg.trig_len; i++) {
   pmt_cfg.adc_ch[i] = 11;  //抢占转换通道
   pmt_cfg.inten[i] = false; //本次转换完成不触发, TRIG_COMPT 标志位置 1
}

pmt_cfg.inten[pmt_cfg.trig_len - 1] = true; //最后一次抢占通道转换完成,TRIG_COMPT 标志位置 1

adc16_set_pmt_config(HPM_ADC2, &pmt_cfg); //抢占配置
//抢占转换队列使能
adc16_enable_pmt_queue(HPM_ADC0, ADC16_CONFIG_TRG0A);
adc16_enable_pmt_queue(HPM_ADC1, ADC16_CONFIG_TRG0A);
adc16_enable_pmt_queue(HPM_ADC2, ADC16_CONFIG_TRG0A);

/* 为抢占模式设置DMA起始地址,ADC采样有自己的内部DMA */
adc16_init_pmt_dma(HPM_ADC0, core_local_mem_to_sys_address(HPM_CORE0, (uint32_t)pmt_buff));
adc16_init_pmt_dma(HPM_ADC1, core_local_mem_to_sys_address(HPM_CORE0, (uint32_t)&pmt_buff[1]));
adc16_init_pmt_dma(HPM_ADC2, core_local_mem_to_sys_address(HPM_CORE0, (uint32_t)&pmt_buff[2]));

//互联管理器初始化,将PWM0_TRGO_0,信号路由到ADCX_TRG0A上
trgm_output_cfg.invert = false;
trgm_output_cfg.type = trgm_output_same_as_input; //输入信号和输出信号一致

trgm_output_cfg.input  = HPM_TRGM0_INPUT_SRC_PWM1_TRGO_0; //输入信号PWM1_TRGO0
//输出信号:ADC抢占转换队列_0A
trgm_output_config(HPM_TRGM0, TRGM_TRGOCFG_ADCX_PTRGI0A, &trgm_output_cfg);


//抢占转换完成标志位中断使能
adc16_enable_interrupts(HPM_ADC0, adc16_event_trig_complete);
intc_m_enable_irq_with_priority(IRQn_ADC0, 1);

}

//注册ADC0中断函数
SDK_DECLARE_EXT_ISR_M(IRQn_ADC0, isr_adc16_0);
void isr_adc16_0(void)
{
uint32_t status;

status = adc16_get_status_flags(HPM_ADC0);

ADC_Time += 0.00005f;

/* Clear status */
adc16_clear_status_flags(HPM_ADC0, status);

if (ADC16_INT_STS_SEQ_CVC_GET(status)) {
    /* Set flag to read memory data */
  //  seq_complete_flag = 1;
}

if (ADC16_INT_STS_TRIG_CMPT_GET(status)) {

//低16位为数据,高16位为附加信息
	ADC_U_V = (pmt_buff[0] & 0xffff) / 65535.0f * 3.3f;
	ADC_V_V = (pmt_buff[1] & 0xffff) / 65535.0f * 3.3f;
	ADC_W_V = (pmt_buff[2] & 0xffff) / 65535.0f * 3.3f;
    
}

}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐