先楫半导体HPMicro
直播中

jf_67024233

2年用户 282经验值
擅长:电源/新能源 模拟技术 测量仪表 接口/总线/驱动
私信 关注
[资料]

【先楫HPM5361EVK开发板试用体验】先楫HPM5361EVK开发板测试 16 位高精度 ADC

HPM5300系列MCU是上海先楫半导体推出的一款高性能RISC-V内核通用微控制器。

HPM5300系列RISC-VCPU主频高达480MHz,内置288KBSRAM和1MB Flash,并提供48~100脚LOFP和OFN等封装,为工业自动化,新能源及汽车等应用提供了丰富的算力和高效的控制能力。

HPM5300EVK提供了一系列HPM5300微控制器外设的接口,包括一个ADC输入SMA接口和一个先楫标准的电机控制及传感器接口。HPM5300EVK同时集成了1个2x20 pin IO扩展接口,连接了HPM5300 MCU的大部分IO,供用户自由评估。HPM5300EVK集成了板载调试器,同时提供了一个标准JTAG接口可以连接JLINK、DAPLINK等调试器。

12.jpg

11.jpg

可以通过依次配置 SEQ_QUE0 到 SEQ_QUE15 寄存器来指定转换序列的目标输入通道。SEQ_QUE0 [CHAN_NUM] 位域用于配置序列转换触发后的第一次转换的通道序号,SEQ_QUE1 [CHNUM] 位域配置第二次转换的通道序号,以此类推,SEQ_QUE15 [CHNUM] 位配置第16次转换的通道序号。此外,需要配置 SEQ_CFG0 [SEQ_LEN] 位来指定转换序列的长度,ADC的转换序列最长可达16个通道。序列的开始转换可以通过软件或硬件触发实现:

通过软件触发:首先将 SEQ_CFG0 [SW_TRIG_EN] 位置1,然后将 SEQ_CFG0 [SW_TRIG] 位置1,即可触发序列转换。
通过硬件触发:将 SEQ_CFG0 [HW_TRIG_EN] 位置1,当触发引脚(STRGI)上检测到上升沿时,即可触发序列转换。
一旦触发,ADC将按照顺序根据 SEQ_QUE0 的配置开始转换输入通道。转换完成后,标志位 INT_STS [SEQ_CVC](转换完成)将被置为1。此时:

如果 SEQ_CFG0 [CONT_EN] 位置1,ADC将自动根据 SEQ_QUE1 的配置开始下一次转换,直到达到指定的序列长度 SEQ_QUEn。
如果 SEQ_CFG0 [CONT_EN] 位清零,ADC将等待下一次软件或硬件触发才会开始下一个通道的转换。
当ADC完成整个序列的转换(长度由 SEQ_CFG0 [SEQ_LEN] 位设置)后,标志位 INT_STS [SEQ_CMPT](序列转换完成)将被置为1。此时:

如果 SEQ_CFG0 [RESTART_EN] 位置1且 SEQ_CFG0 [CONT_EN] 位置1,ADC将自动根据 SEQ_QUEx 的配置,从 SEQ_QUE0 开始连续依次转换。
如果 SEQ_CFG0 [RESTART_EN] 位置0且 SEQ_CFG0 [CONT_EN] 位置1,ADC将在下一次软件或硬件触发后连续转换直到整个序列完成。
如果 SEQ_CFG0 [CONT_EN] 位置0,无论 SEQ_CFG0 [RESTART_EN] 位置1还是0,ADC将在下一次软件或硬件触发后重新根据 SEQ_QUEx 的配置开始转换。
如果在ADC序列转换过程中接收到新的序列转换触发信号,ADC将忽略该触发。如果是通过软件触发序列转换,INT_STS [SEQ_SW_CFLCT] 位将被置为1。如果是由 STRGI 引发的硬件触发序列转换,INT_STS [SEQ_HW_CFLCT] 位将被置为1。

ADC序列转换模式支持内置DMA,可以直接将转换结果写入用户指定的内存缓冲区。用户可以通过 SEQ_DMA_ADDR 寄存器配置目标地址,并通过 SEQ_DMA_CFG [BUF_LEN] 设置数据区域的长度,从而为ADC的序列转换结果配置一个循环缓冲区。

抢占转换模式:

ADC支持抢占转换模式,这是优先级最高的转换模式,适用于对电机控制系统中实时性要求较高的情况,需要在指定时间对指定通道进行转换。

ADC支持12组抢占转换序列,触发信号来自芯片的片上互联模块,共有12个抢占触发源。这些抢占转换序列可以通过寄存器CONFIGx进行配置。抢占转换是通过硬件触发实现的,当PTRGIxA、PTRGIxB或PTRGIxC上出现上升沿时,会触发相应的抢占序列xA、xB或xC。首先,用户需要通过CONFIGx寄存器的[TRIG_LEN]位来配置抢占转换的序列长度,最多可以设置为4,即每个触发最多可以触发一次长度为4的转换。可以通过CONFIGx寄存器配置抢占转换的转换顺序。通过配置寄存器的[CHAN0]、[CHAN1]、[CHAN2]和[CHAN3]位域,依次配置触发后的第1、2、3、4次转换的AD输入通道号码。

一旦抢占转换开始,ADC会根据[TRIG_LEN]的配置连续进行转换,完成整个抢占序列。在抢占序列的第x次转换完成后,如果CONFIGx寄存器的[INTENx]位置为1,INT_STS[TRIG_CMPT]标志位会被置为1。如果相应的中断控制位也被置为1,ADC会生成中断。在ADC抢占转换过程中,如果接收到新的抢占转换触发信号,ADC不会响应新的触发。但是,根据触发源是软件还是硬件,INT_STS[TRIG_SW_CFLICT]标志位或INT_STS[TRIG_HW_CFLICT]标志位会被置为1,表示发生了抢占转换触发冲突。如果对应的中断控制位也被置为1,ADC会产生中断报警。

如果多个不同的抢占转换同时触发,ADC会按照以下优先顺序进行响应:较小组号的抢占转换优先,例如PTRGI0A优先于PTRGI1A;同一组中,xA优先于xB,xB优先于xC,例如PTRGI0A优先于PTRGI0B。同时,INT_STS[PTCHWCFLICT]标志位会被置为1。

ADC抢占转换模式也支持内置DMA,可以直接将转换结果写入用户指定的内存缓冲区中。
9.jpg

测试代码及过程:

首先是硬件初始化和配置时钟,这里我们的程序采用ADC0的11通道进行测试,查看芯片的数据手册可以看到ADC0_IN11所在端口是在PB08

复制

int main(void)
{    uint8_t conv_mode;    /* Bsp initialization */
    board_init();    /* ADC pin initialization */
    board_init_adc16_pins();    /* ADC clock initialization */
    board_init_adc16_clock(BOARD_APP_ADC16_BASE, true);
    printf("This is an ADC16 demo:\n");
    /* Get a conversion mode from a console window */
    conv_mode = get_adc_conv_mode();    /* ADC16 common initialization */
    init_common_config(conv_mode);    /* ADC16 read patter and DMA initialization */
    switch (conv_mode) {
        case adc16_conv_mode_oneshot:
            init_oneshot_config();            break;
        case adc16_conv_mode_period:
            init_period_config();            break;
        case adc16_conv_mode_sequence:
            init_sequence_config();            break;
        case adc16_conv_mode_preemption:
            init_preemption_config();            break;
        default:
            break;
    }    /* Main loop */
    while (1) {
        board_delay_ms(1000);
        channel_result_out_of_threshold_handler();        if (conv_mode == adc16_conv_mode_oneshot) {
            oneshot_handler();        } else if (conv_mode == adc16_conv_mode_period) {
            period_handler();        } else if (conv_mode == adc16_conv_mode_sequence) {
            sequence_handler();        } else if (conv_mode == adc16_conv_mode_preemption) {
            preemption_handler();        } else {
            printf("Conversion mode is not supported!\n");
        }    }}
它首先初始化了一些硬件和ADC相关的配置,然后从控制台获取了一个转换模式,并根据不同的转换模式进行不同的初始化操作。接着进入一个主循环,每隔1秒进行一次延时,然后根据不同的转换模式调用不同的处理函数进行处理。如果转换模式不被支持,会输出一个错误信息。整体来说,这段代码是一个ADC16的演示程序,根据不同的转换模式进行不同的处理。

代码总共配置了四种转换模式,根据选择的模式进行初始化

复制

hpm_stat_t init_common_config(adc16_conversion_mode_t conv_mode){    adc16_config_t cfg;    /* initialize an ADC instance */
    adc16_get_default_config(&cfg);    cfg.res            = adc16_res_16_bits;    cfg.conv_mode      = conv_mode;    cfg.adc_clk_div    = adc16_clock_divider_4;    cfg.sel_sync_ahb   = (clk_adc_src_ahb0 == clock_get_source(BOARD_APP_ADC16_CLK_NAME)) ? true : false;
    if (cfg.conv_mode == adc16_conv_mode_sequence ||
        cfg.conv_mode == adc16_conv_mode_preemption) {        cfg.adc_ahb_en = true;
    }    /* adc16 initialization */
    if (adc16_init(BOARD_APP_ADC16_BASE, &cfg) == status_success) {
        /* enable irq */
        intc_m_enable_irq_with_priority(BOARD_APP_ADC16_IRQn, 1);
        return status_success;
    } else {
        printf("%s initialization failed!\n", BOARD_APP_ADC16_NAME);
        return status_fail;
    }}

采样精度设置为16位,时钟预分频为4分频模式。

这里我只测试了读取转换模式,模式配置和处理函数如下:

复制

void init_oneshot_config(void)
{    adc16_channel_config_t ch_cfg;    /* get a default channel config */
    adc16_get_channel_default_config(&ch_cfg);    /* initialize an ADC channel */
    ch_cfg.ch           = BOARD_APP_ADC16_CH_1;    ch_cfg.sample_cycle = 20;
    adc16_init_channel(BOARD_APP_ADC16_BASE, &ch_cfg);    adc16_set_nonblocking_read(BOARD_APP_ADC16_BASE);#if defined(ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT) && ADC_SOC_BUSMODE_ENABLE_CTRL_SUPPORT
    /* enable oneshot mode */
    adc16_enable_oneshot_mode(BOARD_APP_ADC16_BASE);#endif
}void oneshot_handler(void)
{    uint16_t result;    if (adc16_get_oneshot_result(BOARD_APP_ADC16_BASE, BOARD_APP_ADC16_CH_1, &result) == status_success) {
        if (adc16_is_nonblocking_mode(BOARD_APP_ADC16_BASE)) {
            adc16_get_oneshot_result(BOARD_APP_ADC16_BASE, BOARD_APP_ADC16_CH_1, &result);        }        printf("Oneshot Mode - %s [channel %02d] - Result: 0x%04x\n", BOARD_APP_ADC16_NAME, BOARD_APP_ADC16_CH_1, result);
    }}

结果处理函数:

复制

hpm_stat_t adc16_get_oneshot_result(ADC16_Type *ptr, uint8_t ch, uint16_t *result)
{    uint32_t bus_res;    /* Check the specified channel number */
    if (ADC16_IS_CHANNEL_INVALID(ch)) {
        return status_invalid_argument;
    }    bus_res = ptr->BUS_RESULT[ch];    *result = ADC16_BUS_RESULT_CHAN_RESULT_GET(bus_res);
    if (ADC16_BUF_CFG0_WAIT_DIS_GET(ptr->BUF_CFG0)) {
        if (!ADC16_BUS_RESULT_VALID_GET(bus_res)) {
            return status_fail;
        }    }    return status_success;
}

14.jpg

5.jpg

6.jpg

7.jpg

4.jpg

 总的来说先楫HPM5361EVK的ADC功能非常出色!它提供了高精度、高性能和可靠性,能够准确地转换模拟信号为数字数据。其高分辨率和低噪声特性使其在各种应用中表现出色。开发板的两个16位的高精度ADC可以满足大多数实际工程需要,同时四种采样模式也可以满足不同用户的需求,先楫HPM5361EVK开发板值得大家认真了解和测试的一款开发板。

更多回帖

发帖
×
20
完善资料,
赚取积分