介绍
抢占转换与序列转换不同,触发信号是来自电机系统的
抢占转换可以支持四个序列的转换
流程步骤
●挂上时钟 复用IO
board_init_adc_clock(HPM_ADC3, true);
ADC_Pin();
●设置ADC精度,分频时钟,模式,运行数据搬运到内存
adc16_get_default_config(&config);
config.res = 21;
config.adc_clk_div = 4;
config.conv_mode= adc16_conv_mode_preemption;
config.adc_ahb_en = true;
adc16_init(HPM_ADC3, &config);
●设置采样周期,设置通道
adc16_get_channel_default_config(&channel_config);
channel_config.sample_cycle = 20;
for(int i=0;i<sizeof(trig_adc_channel);i++)
{
channel_config.ch = trig_adc_channel[i];
adc16_init_channel(HPM_ADC3, &channel_config);
}
●设置抢占通道,设置转换完成是否启用中断,抢占触发源,开启触发源
pmt_config.trig_len = sizeof(trig_adc_channel);
pmt_config.trig_ch = APP_ADC16_PMT_TRIG_CH;//设置触发源
for (int i =0;i<pmt_config.trig_len;i++){
pmt_config.adc_ch[i]=trig_adc_channel[i];
pmt_config.inten[i] = false;
}
pmt_config.inten[pmt_config.trig_len-1] = true;
adc16_set_pmt_config(HPM_ADC3, &pmt_config);
adc16_set_pmt_queue_enable(HPM_ADC3, APP_ADC16_PMT_TRIG_CH, true);
●设置中断 设置DMA 地址,
adc16_init_pmt_dma(HPM_ADC3, core_local_mem_to_sys_address(APP_ADC16_CORE, (uint32_t)pmt_buff));
adc16_enable_interrupts(HPM_ADC3, APP_ADC16_PMT_IRQ_EVENT);
●设置互联管理器
TRGM_Init(HPM_TRGM0,APP_ADC16_HW_TRGM_OUT_PMT,APP_ADC16_HW_TRGM_IN);
void TRGM_Init(TRGM_Type *ptr,uint8_t output,uint8_t input)
{
trgm_output_t trgm_config ={0};
trgm_config.input = input;
trgm_config.invert = false;//是否翻转极性
trgm_config.type = trgm_output_same_as_input;//设置输出类型
trgm_output_config(ptr,output,&trgm_config);
}
●设置PWM
TRGM_Input_INit(2999);
void TRGM_Input_INit(uint32_t cmp)
{
pwm_cmp_config_t cmp_config[1] ={0};
pwm_config_t config ={0};
pwm_output_channel_t output_config ={0};
pwm_get_default_pwm_config(HPM_PWM0, &config);
config.invert_output = false;
config.enable_output =false;
config.dead_zone_in_half_cycle = 0;
pwm_set_reload(HPM_PWM0, 0, 5999);
pwm_set_start_count(HPM_PWM0, 0, 0);
pwm_get_default_cmp_config(HPM_PWM0,&cmp_config[0]);
cmp_config[0].cmp = cmp;
cmp_config[0].mode = pwm_cmp_mode_output_compare;
cmp_config[0].update_trigger =pwm_shadow_register_update_on_shlk;
if(status_success != pwm_setup_waveform(HPM_PWM0, 8, &config, 1, &cmp_config[0], 1))
{
printf("PWM0 set cmp error\n");
while(0);
}
pwm_issue_shadow_register_lock_event(HPM_PWM0);
pwm_start_counter(HPM_PWM0);
}
中断函数
void isr_adc16(void)
{
uint32_t status = adc16_get_status_flags(HPM_ADC3);//获取状态
adc16_clear_status_flags(BOARD_APP_ADC16_BASE, status);//清除标志位
if (ADC16_INT_STS_SEQ_CVC_GET(status))
{
seq_complete_flag = 1;
}
读取数据
void Preemption_Handle(void)
{
while (0==trig_complete_flag)
{
}
Pmt_Data(pmt_buff, sizeof(trig_adc_channel));
trig_complete_flag = 0;
}
void Pmt_Data(uint32_t *buff,uint8_t len)
{
adc16_pmt_dma_data_t *dam_cofig = (adc16_pmt_dma_data_t *)buff;
if(ADC16_IS_PMT_DMA_BUFF_LEN_INVLAID(len))
{
printf("Pmt data error\n");
}
for(int i=0;i<len;i++)
{
if(dam_cofig[i].cycle_bit)
{
printf("ADC3 -");
printf("adc_ch:%d -",dam_cofig[i].adc_ch);
printf("cycle_bit:%d -",dam_cofig[i].cycle_bit);
printf("seq_num:%d -",dam_cofig[i].seq_num);
printf("trig_ch:%d -",dam_cofig[i].trig_ch);
printf("result:%04x\n",dam_cofig[i].result);
dam_cofig[i].cycle_bit = 0;
}
}
}
主函数
int main(void)
{
/* Bsp initialization */
board_init();
printf("This is an ADC16 demo:\n");
preemption_Init();
/* Main loop */
while (1) {
channel_result_out_of_threshold();
Preemption_Handle();
}
}
这个测试是使用了PWM周期硬件触发ADC抢占转换的,对于软件触发我没有找到相关的API以及寄存器我也没有看到
对了关于DMA中的数据内容是这样的 里面不仅包涵了ADC采样数据还有ADC的通道,那个抢占位等等 序列模式也是和抢占模式一样的
综上就是我对ADC的一个学习,如有错误请大佬指出,我是想变强的小洛