第四周-GD32F4XX的配置和函数归纳(4)

GD32F4XX的配置和函数归纳(4)

1.分析了ADC的例程,看看其中的配置是如何实现的


1.ADC 温度传感器

#include "gd32f4xx.h"
#include "gd32f450z_eval.h"
#include "systick.h"
#include <stdio.h>

float temperature;
float vref_value;
float battery_value;

void rcu_config(void);
void adc_config(void);

int main(void)
{
    /* system clocks configuration */
    rcu_config();
    /* ADC configuration */
    adc_config();
    /* USART configuration */
    gd_eval_com_init(EVAL_COM0);
    /* configure systick */
    systick_config();

    while(1){
        /* ADC software trigger enable */
        adc_software_trigger_enable(ADC0,ADC_INSERTED_CHANNEL);
        /* delay a time in milliseconds */
        delay_1ms(2000);
        /* value convert  */
        temperature = (1.42-ADC_IDATA0(ADC0)*3.3/4096)*1000/4.35+25;
        vref_value = (ADC_IDATA1(ADC0)*3.3/4096);
        battery_value = (ADC_IDATA2(ADC0)*4*3.3/4096);
        /* value print */
        printf(" the temperature data is %2.0f degrees Celsius\r\n",temperature);
        printf(" the reference voltage data is %5.3fV \r\n",vref_value);
        printf(" the battery voltage is %5.3fV \r\n",battery_value);
        printf(" \r\n");
    }
}

1.1 RCU配置

RCU的配置,使能外设时钟函数rcu_periph_clock_enable(),这个函数是将输入的外设时钟给打开。
ADC时钟的配置adc_clock_config(),配置adc的时钟,一个有八种分频方式,调用两种时钟源
这是常用的两个配置语句,给出官方备注以便后面使用

void rcu_config(void)
{
    /* enable ADC clock */
    rcu_periph_clock_enable(RCU_ADC0);
    /* config ADC clock */
    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);
}
/*!
    \brief      enable the peripherals clock
    \param[in]  periph: RCU peripherals, refer to rcu_periph_enum
                only one parameter can be selected which is shown as below:
      \arg        RCU_GPIOx (x=A,B,C,D,E,F,G,H,I): GPIO ports clock
      \arg        RCU_CRC: CRC clock
      \arg        RCU_BKPSRAM: BKPSRAM clock
      \arg        RCU_TCMSRAM: TCMSRAM clock
      \arg        RCU_DMAx (x=0,1): DMA clock
      \arg        RCU_IPA: IPA clock
      \arg        RCU_ENET: ENET clock
      \arg        RCU_ENETTX: ENETTX clock
      \arg        RCU_ENETRX: ENETRX clock
      \arg        RCU_ENETPTP: ENETPTP clock
      \arg        RCU_USBHS: USBHS clock
      \arg        RCU_USBHSULPI: USBHSULPI clock
      \arg        RCU_DCI: DCI clock
      \arg        RCU_TRNG: TRNG clock
      \arg        RCU_USBFS: USBFS clock
      \arg        RCU_EXMC: EXMC clock
      \arg        RCU_TIMERx (x=0,1,2,3,4,5,6,7,8,9,10,11,12,13): TIMER clock
      \arg        RCU_WWDGT: WWDGT clock
      \arg        RCU_SPIx (x=0,1,2,3,4,5): SPI clock
      \arg        RCU_USARTx (x=0,1,2,5): USART clock
      \arg        RCU_UARTx (x=3,4,6,7): UART clock
      \arg        RCU_I2Cx (x=0,1,2): I2C clock
      \arg        RCU_CANx (x=0,1): CAN clock
      \arg        RCU_PMU: PMU clock
      \arg        RCU_DAC: DAC clock
      \arg        RCU_RTC: RTC clock
      \arg        RCU_ADCx (x=0,1,2): ADC clock
      \arg        RCU_SDIO: SDIO clock
      \arg        RCU_SYSCFG: SYSCFG clock
      \arg        RCU_TLI: TLI clock
      \arg        RCU_CTC: CTC clock
      \arg        RCU_IREF: IREF clock
    \param[out] none
    \retval     none
*/
/*!
    \brief      configure the ADC clock for all the ADCs
    \param[in]  prescaler: configure ADCs prescaler ratio
                only one parameter can be selected which is shown as below:
      \arg        ADC_ADCCK_PCLK2_DIV2: PCLK2 div2
      \arg        ADC_ADCCK_PCLK2_DIV4: PCLK2 div4
      \arg        ADC_ADCCK_PCLK2_DIV6: PCLK2 div6
      \arg        ADC_ADCCK_PCLK2_DIV8: PCLK2 div8
      \arg        ADC_ADCCK_HCLK_DIV5: HCLK div5
      \arg        ADC_ADCCK_HCLK_DIV6: HCLK div6
      \arg        ADC_ADCCK_HCLK_DIV10: HCLK div10
      \arg        ADC_ADCCK_HCLK_DIV20: HCLK div20
    \param[out] none
    \retval     none
*/

1.2 ADC配置

这里调用了很多adc.c和adc.h的变量和函数,总体配置思路如下:
1.先将ADC0配置成注入通道,采样率设置为3
2.配置三个内部传感器(温度传感器,内部参考电压 VREFINT和外部电池电压 VBAT)的采样率
3.关闭外部触发源
4.设置数据对齐方式为右对齐
5.将ADC0转换模式调为扫描模式
6.使能三个内部传感器
7.使能ADC0
8.校准三个内部传感器

void adc_config(void)
{
    /* ADC channel length config */
    adc_channel_length_config(ADC0,ADC_INSERTED_CHANNEL,3);
    /* ADC temperature sensor channel config */
    adc_inserted_channel_config(ADC0,0,ADC_CHANNEL_16,ADC_SAMPLETIME_480);
    /* ADC internal reference voltage channel config */
    adc_inserted_channel_config(ADC0,1,ADC_CHANNEL_17,ADC_SAMPLETIME_480);
    /* ADC 1/4 voltate of external battery config */
    adc_inserted_channel_config(ADC0,2,ADC_CHANNEL_18,ADC_SAMPLETIME_480);
    /* ADC external trigger enable */
    adc_external_trigger_config(ADC0,ADC_INSERTED_CHANNEL,DISABLE);
    /* ADC data alignment config */
    adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);
    /* ADC SCAN function enable */
    adc_special_function_config(ADC0,ADC_SCAN_MODE,ENABLE);
    /* ADC Vbat channel enable */
    adc_channel_16_to_18(ADC_VBAT_CHANNEL_SWITCH,ENABLE);
    /* ADC temperature and Vrefint enable */
    adc_channel_16_to_18(ADC_TEMP_VREF_CHANNEL_SWITCH,ENABLE);    
    /* enable ADC interface */
    adc_enable(ADC0);
    /* ADC calibration and reset calibration */
    adc_calibration_enable(ADC0);
}

1.3 com口初始化配置

com端口配置是以下函数,主要步骤是:使能串口控制器,再将端口连接到串口控制器的读写端,再将读写设置成推挽模式,最后将串口控制器配置完成即可。

gd_eval_com_init(uint32_t com)

1.4 系统配置

系统配置函数内有两部:建立1000hz的系统时钟和将其配置为最强的中断优先级。

systick_config();

2. ADC0 和 ADC1 跟随模式

与上面不同的是:
1.TIMER1_CH1 作为 ADC0 和 ADC1 的触发源,而上个例程是直接调用
2.ADC0 和 ADC1 的值通过 DMA 传送给 adc_value[0]和 adc_value[1],使用两个ADC,并且采用规则通道(规则通道相比注入通道而言,是一直进行的而不需要中断重新进入)
得到adc_value[0]和 adc_value[1]值后,根据TIMER上升沿,更新数据。
在这里插入图片描述

int main(void)
{
    /* system clocks configuration */
    rcu_config();
    /* GPIO configuration */
    gpio_config();
    /* TIMER configuration */
    timer_config();
    /* DMA configuration */
    dma_config();
    /* ADC configuration */
    adc_config();
    /* configure COM port */
    gd_eval_com_init(EVAL_COM0);
    /* configure systick */
    systick_config();

    while(1){
        delay_1ms(2000);
        printf(" the data adc_value[0] is %08X \r\n",adc_value[0]);
        printf(" the data adc_value[1] is %08X \r\n",adc_value[1]);
        printf("\r\n");
    }
}

2.1 dma配置

它的主要思路是,先初始化所需要的dma1的第一个通道(该芯片一共2个dma,每个有8通道);再依次配置dma.c中设置好的结构体变量
在这里插入图片描述
配置好结构体变量后,再将结构体的参数配置到dma1的第一个通道,用下面函数,最后一步是使能该通道。

dma_single_data_mode_init(DMA1,DMA_CH0,DMA_SUBPERI0)
void dma_config(void)
{
    /* ADC_DMA_channel configuration */
    dma_single_data_parameter_struct dma_single_data_parameter;
    
    /* ADC_DMA_channel deinit */
    dma_deinit(DMA1,DMA_CH0);
    
    /* initialize DMA single data mode */
    dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_SYNCDATA);
    dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_single_data_parameter.memory0_addr = (uint32_t)(adc_value);
    dma_single_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;
    dma_single_data_parameter.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
    dma_single_data_parameter.direction = DMA_PERIPH_TO_MEMORY;
    dma_single_data_parameter.number = 2;
    dma_single_data_parameter.priority = DMA_PRIORITY_HIGH;
    dma_single_data_mode_init(DMA1,DMA_CH0,&dma_single_data_parameter);
    /* DMA channel 0 peripheral select */
    dma_channel_subperipheral_select(DMA1,DMA_CH0,DMA_SUBPERI0);

    /* enable DMA channel */
    dma_channel_enable(DMA1,DMA_CH0);
}

2.2 ADC0/1规则通道下的配置

第一个函数是将其ADC0/1设置为跟随模式:
在这里插入图片描述
后面再将ADC0/1设置为右对齐和扫描模式,配置为规则通道,设置采样率,再分别将ADC0/1进行使能和校准。与上例子不同的是,这里采用timer 0 cc1作为触发源。

void adc_config(void)
{
    /* configure the ADC sync mode */
    adc_sync_mode_config(ADC_DAUL_REGULAL_FOLLOW_UP);
    adc_sync_dma_config(ADC_SYNC_DMA_MODE1);  //模式1
    adc_sync_dma_request_after_last_enable(); //dma使用完就禁用
    /* ADC data alignment config */
    adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);
    adc_data_alignment_config(ADC1,ADC_DATAALIGN_RIGHT);
    /* ADC scan mode function enable */
    adc_special_function_config(ADC0,ADC_SCAN_MODE,ENABLE);
    adc_special_function_config(ADC1,ADC_SCAN_MODE,ENABLE);
    
    /* ADC channel length config */
    adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,2);
    adc_channel_length_config(ADC1,ADC_REGULAR_CHANNEL,2);
    /* ADC regular channel config */
    adc_regular_channel_config(ADC0,0,ADC_CHANNEL_13,ADC_SAMPLETIME_480);
    adc_regular_channel_config(ADC0,1,ADC_CHANNEL_15,ADC_SAMPLETIME_480);
    adc_regular_channel_config(ADC1,1,ADC_CHANNEL_13,ADC_SAMPLETIME_480);
    adc_regular_channel_config(ADC1,0,ADC_CHANNEL_15,ADC_SAMPLETIME_480);
    /* ADC external trigger enable */
    adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,EXTERNAL_TRIGGER_RISING);
    adc_external_trigger_config(ADC1,ADC_REGULAR_CHANNEL,EXTERNAL_TRIGGER_DISABLE);
    adc_external_trigger_source_config(ADC0,ADC_REGULAR_CHANNEL,ADC_EXTTRIG_REGULAR_T1_CH1);
    
    /* enable ADC interface */
    adc_enable(ADC0);
    /* ADC calibration and reset calibration */
    adc_calibration_enable(ADC0);
    /* enable ADC interface */
    adc_enable(ADC1);
    /* ADC calibration and reset calibration */
    adc_calibration_enable(ADC1);
}

2.3 TIMER配置

先设置初始外设和输出外设的结构体参数
在这里插入图片描述
在这里插入图片描述
再设置PWM的模式
在这里插入图片描述

void timer_config(void)
{
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    /* TIMER1 configuration */
    timer_initpara.prescaler         = 19999;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 9999;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER1,&timer_initpara);

    /* CH1 configuration in PWM mode0 */
    timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
    timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
    timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
    timer_channel_output_config(TIMER1,TIMER_CH_1,&timer_ocintpara);

    timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_1,3999);
    timer_channel_output_mode_config(TIMER1,TIMER_CH_1,TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER1,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);
    
    /* enable TIMER1 */
    timer_enable(TIMER1);
}

3. ADC0和ADC1规则并行模式

只需要将上个例程ADC配置的跟随模式改为规则模式即可:

    /* ADC channel length config */
    adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,2);
    adc_channel_length_config(ADC1,ADC_REGULAR_CHANNEL,2);
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值