HPM6700系列—ADC序列转换

介绍

ADC有四个转换模式:读取转换,周期转换,序列转换,抢占转换

      

  序列转换是可以将几个通道的数据按照顺序逐一去转换,  例如 通道 1 2 3 可以将转换顺序设置为3 1 2,最多一次可以转换十六个通道。序列转换还能通过软件、硬件触发转换与连续转换,将转换数据搬运到DMA中,另外这里的DMA用法也与其他的MCU不同,不需要配置地址自增这些。

配置步骤

 ● 挂上时钟,复用IO口

  board_init_adc_clock(HPM_ADC3, true);
  HPM_IOC->PAD[IOC_PAD_PE29].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK;

● 配置精度,ADC时钟分频,模式,同步系统时钟,是否使能数据到DMA

  adc16_get_default_config(&config_t);
  config_t.res = 21;
  config_t.adc_ahb_en =true;
  config_t.adc_clk_div = 4U;
  config_t.conv_mode = adc16_conv_mode_sequence;
  config_t.sel_sync_ahb = (clk_adc_src_ahb0 == clock_get_source(clock_adc3)?true:false);
  if(adc16_init(HPM_ADC3,&config_t)!=status_success)
  {
    printf("ADC3_sequnce Init error\n");
    while(1);
  }

●配置通道,采样时间

  adc16_get_channel_default_config(&channel_config);
  channel_config.sample_cycle = 20;
  for(int i=0;i<sizeof(seq_adc_channel);i++)
  {
    channel_config.ch = seq_adc_channel[i];
    adc16_init_channel(HPM_ADC3, &channel_config);
  }

●配置序列通道数量,序列自动转换,序列硬件转换,序列软件转换,序列转换,序列转换完成后进入是否进入中断

  seq_config.seq_len = sizeof(seq_adc_channel);
  seq_config.restart_en = false;//不使能自动转换
  seq_config.cont_en  = true;//使能转换
  seq_config.hw_trig_en = true;//使能硬件触发转换
  seq_config.sw_trig_en = false;//不使能软件触发

  for (int i =0; i<seq_config.seq_len;i++) {
      seq_config.queue[i].ch = seq_adc_channel[i];//配置通道
      seq_config.queue[i].seq_int_en = false;//不使能本次转换完成后中断
  }
  seq_config.queue[seq_config.seq_len-1].seq_int_en = true;//最后一个完成后进入中断
  adc16_set_seq_config(HPM_ADC3, &seq_config);

 ●DMA配置,配置DMA搬运内存,内存大小,是否完成DMA进入中断。

  dma_config.start_addr = (uint32_t *)core_local_mem_to_sys_address(HPM_CORE0, (uint32_t)seq_buff);
  dma_config.buff_len_in_4bytes = sizeof(seq_buff);
  dma_config.stop_en = false;
  dma_config.stop_pos = 0;

  adc16_init_seq_dma(HPM_ADC3, &dma_config);

 ●设置中断 设置序列转换完成中断,设置抢占优先级

  adc16_enable_interrupts(HPM_ADC3, adc16_event_seq_single_complete);
  intc_m_enable_irq_with_priority(IRQn_ADC3, 1);

  ●设置互联管理器,由于我是使用硬件触发ADC序列转换,需要用互联管理器来链接一个硬件触发ADC,这里使用的是PWM。

  TRGM_Init(HPM_TRGM0,TRGM_TRGOCFG_ADC3_STRGI,HPM_TRGM0_INPUT_SRC_PWM0_CH8REF);
  TRGM_Input_INit(2999);
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);
} 
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;

      if (ADC16_INT_STS_WDOG_GET(status) & APP_ADC16_CH_WDOG_EVENT)//判断是否是同一个
      {
        adc16_disable_interrupts(BOARD_APP_ADC16_BASE, APP_ADC16_CH_WDOG_EVENT);
        trig_complete_flag = ADC16_INT_STS_WDOG_GET(status)&(1<<2);//取出通道值
      }

}

测试

void sequence_handler(void)
{
#if defined(ADC_SOC_NO_HW_TRIG_SRC) || defined(__ADC16_USE_SW_TRIG)
    /* SW trigger */
    adc16_trigger_seq_by_sw(BOARD_APP_ADC16_BASE);
#endif

    while (seq_complete_flag == 0) {

    }

    /* Process data */
    process_seq_data(seq_buff, APP_ADC16_SEQ_START_POS, sizeof(seq_adc_channel));

    /* Clear the flag */
    seq_complete_flag = 0;
}
hpm_stat_t process_seq_data(uint32_t *buff, int32_t start_pos, uint32_t len)
{
    adc16_seq_dma_data_t *dma_data = (adc16_seq_dma_data_t *)buff;

    if (ADC16_IS_SEQ_DMA_BUFF_LEN_INVLAID(len)) {//检查序列有效性
        return status_invalid_argument;
    }

    for (uint32_t i = start_pos; i < start_pos + len; i++) {
        printf("Sequence Mode - %s - ", BOARD_APP_ADC16_NAME);
        printf("Cycle Bit: %02d - ",   dma_data[i].cycle_bit);
        printf("Sequence Number:%02d - ", dma_data[i].seq_num);
        printf("ADC Channel: %02d - ",  dma_data[i].adc_ch);
        printf("Result: 0x%04x\n", dma_data[i].result);
    }
    return status_success;
}

 main函数

int main(void)
{
    /* Bsp initialization */
    adc16_config_t config;
    board_init();
    printf("This is an ADC16 demo:\n");
    Sequence_Init();
    /* Main loop */
     while (1) {
        channel_result_out_of_threshold();
        sequence_handler();
            //sequeue_Handler();
    }
       
}

综上,是我了解ADC序列转换的情况,如有错误请大佬指出!!

                                                                                                          我是一个想变强的小洛!
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值