先辑 HPM6E80 学习笔记 -ADC抢占模式采样(PWMV2计数器中心点触发采样)
2、ADC采样频率需要4分频,因为clk_adc_src_ahb0为200MHZ,ADC时钟频率最大为50MHZ。PWMv2发生器上桥导通中间点产生PWM1_TRG_0 ,50us触发ADC0,1,2抢占采样启动。1、需要注意ADC如果是作为电机系统使用,需要将时钟源配置为。2、内置DMA,可以直接把ADC转换结果写入内存,配置方便。抢占采样完成后,触发ADC0抢占采样完成中断,计算采样值。
一、硬件资源
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;
}
}
更多推荐



所有评论(0)