读取adc

作者: 吴宪峰 | 来源:发表于2022-02-06 12:36 被阅读0次
    
    #include "gd32vf103.h"
    #include "systick.h"
    #include <stdint.h>
    #include "lcd/lcd.h"
    
    #define ANALOG_PORT GPIOA
    #define ANALOG_PIN GPIO_PIN_3
    #define ANALOG_CHANNEL ADC_CHANNEL_3
    
    #define RED_LED_PIN GPIO_PIN_13
    #define RED_LED_PORT GPIOC
    
    void init_ADC_example();
    
    int main(void)
    {
        uint16_t analog_read = 0;
    
        /* config ADC */
        /* 配置 ADC */
        init_ADC_example();
    
        Lcd_Init(); // init OLED
        LCD_Clear(BLACK);
        // 显示汉字“中景园”
        LCD_ShowChinese(24, 0, 0, 16, YELLOW);
        LCD_ShowChinese(48, 0, 1, 16, RED);
        LCD_ShowChinese(72, 0, 2, 16, GREEN);
        // 图型变量
        u16 x = 0;
        u16 y = 48;
    
        /* initiate the gpio for the red led on the longan board */
        /* 初始化 GPIO 用于闪烁红色 LED */
        rcu_periph_clock_enable(RCU_GPIOC);
        gpio_init(RED_LED_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, RED_LED_PIN);
    
        /* This loop generates a software based PWM signal which has a duty cycle based on the read analog value 
           (if you need an actual PWM signal though check the PWM example where it's done in hardware instead) */
        while (1)
        {
            /* Read analog value on pin */
            /* 读取引脚上的模拟值 */
            // analog_read = ADC_RDATA(ADC0);
            analog_read = adc_regular_data_read(ADC0);
    
            /* LCD 显示 */
            LCD_ShowNum(80, 16, analog_read,4, MAGENTA);
            LCD_DrawPoint(x, y - 10 * analog_read / 100, BLUE);
            if (x > 159)
            {
                LCD_Clear(BLACK);
                // LCD_DrawRectangle(0,40,159,80,WHITE);
                x = 0;
            }
            x++;
    
            /* Red LED on */
            /* 点亮 LED */
            // gpio_bit_write(RED_LED_PORT, RED_LED_PIN, 0);
    
            /* If ADC reads a high voltage delay for a longer time */
            /* 如果 ADC 读取高电压延迟较长时间 */
            delay_1us(analog_read);
    
            /* Red LED off */
            /* 关闭 LED */
            // gpio_bit_write(RED_LED_PORT, RED_LED_PIN, 1);
    
            /* Delay for longer if ADC reads a low voltage */
            /* 如果 ADC 读取低电压,则延迟更长 */
            // delay_1us(4096 - analog_read);
        }
    }
    
    void init_ADC_example()
    {
        /* enable GPIOC clock */
        /* 打开 GPIO_C 时钟 */
        rcu_periph_clock_enable(RCU_GPIOC);
        /* Initialize the GPIO that will be used for ADC. A0-A7 and B0-B1 are connected to an ADC-channel each. */
        /* 初始化将用于 ADC 的 GPIO。 A0-A7 和 B0-B1 分别连接到一个 ADC 通道 */
        gpio_init(ANALOG_PORT, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, ANALOG_PIN);
        /* enable ADC clock */
        /* 打开 ADC 时钟 */
        rcu_periph_clock_enable(RCU_ADC0);
    
        /* Select the clock frequency that will be used for the ADC core. Refer to README for more info on what to select. */
        /* 选择将用于 ADC 内核的时钟频率。有关选择内容的更多信息,请参阅自述文件 */
        // 108mhz 8分频 13mhz  采样周期 239.5+12.5 =252 个时钟周期 除以 13mhz = 19.38us 频率为 51587.3hz
        rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);
    
        /* Reset ADC0 configuration. GD32VF103 has two internal ADCs (ADC0, ADC1). */
        /* 重置 ADC_0 通道, 此芯片有两个 ADC 通道  */
        adc_deinit(ADC0);
    
        /* Set the ADCs to work independently. Refer to the manual for the different parallel modes available. */
        /* 将 ADC 设置为独立工作。有关可用的不同并行模式,请参阅手册 */
        adc_mode_config(ADC_MODE_FREE);
    
        /* Set the conversion mode to continuous. Continious mode lets the ADC take measurements continiously without
           an external trigger. */
        /* 将转换模式设置为连续。连续模式让 ADC 连续进行测量,而无需一个外部触发器。 */
        adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);
    
        /* Sets where padding is applied to the measurement. Data alignment right puts padding bits above MSB */
        /* 设置将填充应用于测量的位置。数据对齐右将填充位置于 MSB 之上 */
        adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);
    
        /* Selects how many channels to convert each time. This can be used to "queue" multiple channels. Here just one channel is selected. */
        /* 选择每次转换多少个频道。这可用于“排队”多个频道。这里只选择了一个频道 */
        adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1);
    
        /* Set the channel as the first "queued" conversion each time the ADC is activated. */
        /* 每次激活 ADC 时将通道设置为第一个“排队”转换,设置 adc 采周期*/
        adc_regular_channel_config(ADC0, 0, ANALOG_CHANNEL, ADC_SAMPLETIME_239POINT5);
        // 配置分辨率 12位
        adc_resolution_config(ADC0,ADC_RESOLUTION_12B);
    
        /* Since we are using continious conversion we do not want to use an external trigger. */
        /* 由于我们使用的是连续转换,我们不想使用外部触发器 */
        adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE);
        adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);
    
        /**
         * @brief ADC 校准过程
         * 内部的模拟校准通过设置 ADC_CTL1 寄存器的 RSTCLB 位来重置。
         * 1. 确保ADCON=1;
         * 2. 延迟14个ADCCLK以等待ADC稳定;
         * 3. 设置RSTCLB (可选的);
         * 4. 设置CLB=1;
         * 5. 等待直到CLB=0。
         */
        /* Enable ADC.*/
        /* 打开 ADC */
        adc_enable(ADC0); //  ADC_CTL1(adc_periph) |= (uint32_t)ADC_CTL1_ADCON;
    
        /* Let ADC stabilize */
        /* 让ADC稳定 */
        delay_1ms(1); // 第二步 等 ADC 稳定,最少14个 ADC 时钟周期
    
        /* Calibrates the ADC against an internal source. */
        /* 根据内部源校准 ADC */
        adc_calibration_enable(ADC0); // 第三、四、五步完成校准
    
        /* Start converting */
        /* 开始转换 */
        adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
    }
    

    相关文章

      网友评论

          本文标题:读取adc

          本文链接:https://www.haomeiwen.com/subject/pyeukrtx.html