GD32F103学习笔记(8)——ADC接口使用
一、简介
ADC(Analog-to-Digital Converter),即模拟-数字转换器,可以将连续变化的模拟信号转换为离散的数字信号,进而使用数字电路进行处理,称之为数字信号处理。
GD32F103 系列有 3 个 ADC,精度为 12 位,每个 ADC 最多有 18 个多路复用通道,可以转换来自 16个外部通道和 2 个内部通道的模拟信号。模拟看门狗允许应用程序来检测输入电压是否超出用户设定的高低阈值。各种通道的 A/D 转换可以配置成单次、连续、扫描或间断转换模式。ADC 转换的结果可以按照左对齐或右对齐的方式存储在 16 位数据寄存器中。
二、API说明
以下 ADC 接口位于 GD32F10x_Firmware_Library_V2.2.2\Firmware\GD32F10x_standard_peripheral\Include\gd32f10x_adc.h。
2.1 adc_mode_config
功能 | 配置ADC同步模式 |
---|---|
函数定义 | void adc_mode_config(uint32_t mode) |
参数 | mode:ADC运行模式 |
返回 | 无 |
mode:ADC运行模式,详细列表如下:
值 | 含义 |
---|---|
ADC_MODE_FREE | 所有ADC运行于独立模式 |
ADC_DAUL_REGULAL_PARALLEL_INSERTED_PARALLEL | ADC0和ADC1运行在规则并行+注入并行组合模式 |
ADC_DAUL_REGULAL_PARALLEL_INSERTED_ROTATION | ADC0和ADC1运行在规则并行+交替触发组合模式 |
ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_FAST | ADC0和ADC1运行在注入并行+快速交叉组合模式 |
ADC_DAUL_INSERTED_PARALLEL_REGULAL_FOLLOWUP_SLOW | ADC0和ADC1运行在注入并行+慢速交叉组合模式 |
ADC_DAUL_INSERTED_PARALLEL | ADC0和ADC1运行在注入并行模式 |
ADC_DAUL_REGULAL_PARALLEL | ADC0和ADC1运行在规则并行模式 |
ADC_DAUL_REGULAL_FOLLOWUP_FAST | ADC0和ADC1运行在快速交叉模式 |
ADC_DAUL_REGULAL_FOLLOWUP_SLOW | ADC0和ADC1运行在慢速交叉模式 |
ADC_DAUL_INSERTED_TRIGGER_ROTATION | ADC0和ADC1运行在交替触发模式 |
2.2 adc_special_function_config
功能 | 使能或除能ADC特殊功能 |
---|---|
函数定义 | void adc_special_function_config(uint32_t adc_periph, uint32_t function, ControlStatus newvalue) |
参数 |
adc_periph:ADCx(x=0,1,2) function:功能配置 newvalue:功能使能ENABLE/除能DISABLE |
返回 | 无 |
function:功能配置,详细列表如下:
值 | 含义 |
---|---|
ADC_SCAN_MODE | 扫描模式选择 |
ADC_INSERTED_CHANNEL_AUTO | 注入组自动转换 |
ADC_CONTINUOUS_MODE | 连续模式选择 |
2.3 adc_data_alignment_config
功能 | 配置ADCx数据对齐方式 |
---|---|
函数定义 | void adc_data_alignment_config(uint32_t adc_periph, uint32_t data_alignment) |
参数 |
adc_periph:ADCx(x=0,1,2) data_alignment:数据对齐方式选择 |
返回 | 无 |
data_alignment:数据对齐方式选择,详细列表如下:
值 | 含义 |
---|---|
ADC_DATAALIGN_RIGHT | LSB对齐 |
ADC_DATAALIGN_LEFT | MSB对齐 |
2.4 adc_channel_length_config
功能 | 配置规则通道组或注入通道组的长度 |
---|---|
函数定义 | void adc_channel_length_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t length) |
参数 |
adc_periph:ADCx(x=0,1,2) adc_channel_group:通道组选择 length:通道长度,规则通道组为1-16,注入通道组为1-4 |
返回 | 无 |
adc_channel_group:通道组选择,详细列表如下:
值 | 含义 |
---|---|
ADC_REGULAR_CHANNEL | 规则通道组 |
ADC_INSERTED_CHANNE | 注入通道组 |
2.5 adc_external_trigger_source_config
功能 | 配置ADC外部触发源 |
---|---|
函数定义 | void adc_external_trigger_source_config(uint32_t adc_periph, uint8_t adc_channel_group, uint32_t external_trigger_source) |
参数 |
adc_periph:ADCx(x=0,1,2) adc_channel_group:通道组选择 external_trigger_source:规则通道组或注入通道组触发源 |
返回 | 无 |
external_trigger_source:规则通道组或注入通道组触发源,详细列表如下:
值 | 含义 |
---|---|
ADC0_1_EXTTRIG_REGULAR_T0_CH0 | TIMER0 CH0事件(规则组) |
ADC0_1_EXTTRIG_REGULAR_T0_CH1 | TIMER0 CH1事件(规则组) |
ADC0_1_EXTTRIG_REGULAR_T0_CH2 | TIMER0 CH2事件(规则组) |
ADC0_1_EXTTRIG_REGULAR_T1_CH1 | TIMER1 CH1事件(规则组) |
ADC0_1_EXTTRIG_REGULAR_T2_TRGO | TIMER2 TRGO事件(规则组) |
ADC0_1_EXTTRIG_REGULAR_T3_CH3 | TIMER3 CH3事件(规则组) |
ADC0_1_EXTTRIG_REGULAR_T7_TRGO | TIMER7 TRGO事件(规则组) |
ADC0_1_EXTTRIG_REGULAR_EXTI_11 | 外部中断线11(规则组) |
ADC0_1_2_EXTTRIG_REGULAR_NONE | 软件触发(规则组) |
ADC2_EXTTRIG_REGULAR_T2_CH0 | TIMER2 CH0事件(规则组) |
ADC2_EXTTRIG_REGULAR_T1_CH2 | TIMER1 CH2事件(规则组) |
ADC2_EXTTRIG_REGULAR_T0_CH2 | TIMER0 CH2事件(规则组) |
ADC2_EXTTRIG_REGULAR_T7_CH0 | TIMER7 CH0事件(规则组) |
ADC2_EXTTRIG_REGULAR_T7_TRGO | TIMER7 TRGO事件(规则组) |
ADC2_EXTTRIG_REGULAR_T4_CH0 | TIMER4 CH0事件(规则组) |
ADC2_EXTTRIG_REGULAR_T4_CH2 | TIMER4 CH2事件(规则组) |
ADC0_1_EXTTRIG_INSERTED_T0_TRGO | TIMER0 TRGO事件(注入组) |
ADC0_1_EXTTRIG_INSERTED_T0_CH3 | TIMER0 CH3事件(注入组) |
ADC0_1_EXTTRIG_INSERTED_T1_TRGO | TIMER1 TRGO事件(注入组) |
ADC0_1_EXTTRIG_INSERTED_T1_CH0 | TIMER1 CH0事件(注入组) |
ADC0_1_EXTTRIG_INSERTED_T2_CH3 | TIMER2 CH3事件(注入组) |
ADC0_1_EXTTRIG_INSERTED_T3_TRGO | TIMER3 TRGO事件(注入组) |
ADC0_1_EXTTRIG_INSERTED_EXTI_15 | 外部中断线15(注入组) |
ADC0_1_EXTTRIG_INSERTED_T7_CH3 | TIMER7 CH3事件(注入组) |
ADC0_1_2_EXTTRIG_INSERTED_NONE | 软件触发(注入组) |
ADC2_EXTTRIG_INSERTED_T0_TRGO | TIMER0 TRGO事件(注入组) |
ADC2_EXTTRIG_INSERTED_T0_CH3 | TIMER0 CH3事件(注入组) |
ADC2_EXTTRIG_INSERTED_T3_CH2 | TIMER3 CH2事件(注入组) |
ADC2_EXTTRIG_INSERTED_T7_CH1 | TIMER7 CH1事件(注入组) |
ADC2_EXTTRIG_INSERTED_T7_CH3 | TIMER7 CH3事件(注入组) |
ADC2_EXTTRIG_INSERTED_T4_TRGO | TIMER4 TRGO事件(注入组) |
ADC2_EXTTRIG_INSERTED_T4_CH3 | TIMER4 CH3事件(注入组) |
2.6 adc_external_trigger_config
功能 | 配置ADC外部触发 |
---|---|
函数定义 | void adc_external_trigger_config(uint32_t adc_periph, uint8_t adc_channel_group, ControlStatus newvalue) |
参数 |
adc_periph:ADCx(x=0,1,2) adc_channel_group:通道组选择 newvalue:通道使能ENABLE/禁能DISABLE |
返回 | 无 |
2.7 adc_enable
功能 | 使能ADCx外设 |
---|---|
函数定义 | void adc_enable(uint32_t adc_periph) |
参数 | adc_periph:ADCx(x=0,1,2) |
返回 | 无 |
2.8 adc_calibration_enable
功能 | ADCx校准复位 |
---|---|
函数定义 | void adc_calibration_enable(uint32_t adc_periph) |
参数 | adc_periph:ADCx(x=0,1,2) |
返回 | 无 |
2.9 adc_regular_channel_config
功能 | 配置ADC规则通道组 |
---|---|
函数定义 | void adc_regular_channel_config(uint32_t adc_periph, uint8_t rank, uint8_t adc_channel, uint32_t sample_time) |
参数 |
adc_periph:ADCx(x=0,1,2) rank:规则组通道序列,取值范围为0~15 adc_channel:ADC通道x(x=0…17)(只有ADC0,可取值x=16和17) sample_time:采样时间 |
返回 | 无 |
sample_time:采样时间,详细列表如下:
值 | 含义 |
---|---|
ADC_SAMPLETIME_1POINT5 | 1.5周期 |
ADC_SAMPLETIME_7POINT5 | 7.5周期 |
ADC_SAMPLETIME_13POINT5 | 13.5周期 |
ADC_SAMPLETIME_28POINT5 | 28.5周期 |
ADC_SAMPLETIME_41POINT5 | 41.5周期 |
ADC_SAMPLETIME_55POINT5 | 55.5周期 |
ADC_SAMPLETIME_71POINT5 | 71.5周期 |
ADC_SAMPLETIME_239POINT5 | 239.5周期 |
2.10 adc_software_trigger_enable
功能 | ADC软件触发使能 |
---|---|
函数定义 | void adc_software_trigger_enable(uint32_t adc_periph, uint8_t adc_channel_group) |
参数 |
adc_periph:ADCx(x=0,1,2) channel_group:通道组选择 |
返回 | 无 |
2.11 adc_flag_get
功能 | 获取ADC标志位 |
---|---|
函数定义 | FlagStatus adc_flag_get(uint32_t adc_periph, uint32_t adc_flag) |
参数 |
adc_periph:ADCx(x=0,1,2) adc_flag:ADC标志位 |
返回 | SET或RESET |
adc_flag:ADC标志位,详细列表如下:
值 | 含义 |
---|---|
ADC_FLAG_WDE | 模拟看门狗事件标志位 |
ADC_FLAG_EOC | 组转换结束标志位 |
ADC_FLAG_EOIC | 注入通道组转换结束标志位 |
ADC_FLAG_STIC | 注入通道组转换开始标志位 |
ADC_FLAG_STRC | 规则通道组转换开始标志位 |
2.12 adc_flag_clear
功能 | 清除ADC标志位 |
---|---|
函数定义 | void adc_flag_clear(uint32_t adc_periph, uint32_t adc_flag) |
参数 |
adc_periph:ADCx(x=0,1,2) adc_flag:ADC标志位 |
返回 | 无 |
2.13 adc_regular_data_read
功能 | 读ADC规则组数据寄存器 |
---|---|
函数定义 | uint16_t adc_regular_data_read(uint32_t adc_periph) |
参数 | adc_periph:ADCx(x=0,1,2) |
返回 | ADC转换值(0-0xFFFF) |
2.14 adc_interrupt_flag_get
功能 | 获取ADC中断标志位 |
---|---|
函数定义 | FlagStatus adc_interrupt_flag_get(uint32_t adc_periph, uint32_t adc_interrupt) |
参数 |
adc_periph:ADCx(x=0,1,2) adc_interrupt:ADC中断标志位 |
返回 | SET或RESET |
adc_interrupt:ADC中断标志位,详细列表如下:
值 | 含义 |
---|---|
ADC_INT_WDE | 模拟看门狗中断标志位 |
ADC_INT_EOC | 组转换结束中断标志位 |
ADC_INT_EOIC | 注入通道组转换结束中断标志位 |
2.15 adc_interrupt_flag_clear
功能 | 清除ADC中断标志位 |
---|---|
函数定义 | void adc_interrupt_flag_clear(uint32_t adc_periph, uint32_t adc_interrupt) |
参数 |
adc_periph:ADCx(x=0,1,2) adc_interrupt:ADC中断标志位 |
返回 | 无 |
2.16 adc_interrupt_enable
功能 | ADC中断使能 |
---|---|
函数定义 | void adc_interrupt_enable(uint32_t adc_periph, uint32_t adc_interrupt) |
参数 |
adc_periph:ADCx(x=0,1,2) adc_interrupt:ADC中断标志位 |
返回 | 无 |
三、ADC电压采集
3.1 电压输入范围
ADC 输入范围为:VREF−≤VIN≤VREF+V_{REF-} ≤ V_{IN} ≤ V_{REF+}VREF−≤VIN≤VREF+。由 VREF-、VREF+ 、VDDA 、VSSA、这四个外部引脚决定。
我们在设计原理图的时候一般把 VSSA 和 VREF-接地,把 VREF+和 VDDA 接 3V3,得到 ADC 的输入电压范围为:0~3.3V
。
如果我们想让输入的电压范围变宽,去到可以测试负电压或者更高的正电压,我们可以在外部加一个电压调理电路,把需要转换的电压抬升或者降压到 0~3.3V,这样 ADC 就可以测量。
3.2 ADC通道选择
GD32 的 ADC 多达 18 个通道,其中外部的 16 个通道就是框图中的 ADCx_IN0、ADCx_IN1…ADCx_IN5。这 16 个通道对应着不同的 IO 口,具体是哪一个 IO 口可以从手册查询到。其中 ADC0/1/2 还有内部通道:ADC0 的通道 16 连接到了芯片内部的温度传感器,Vrefint 连接到了通道 17。ADC1 的模拟通道 16 和 17 连接到了内部的 VSS。ADC2 的模拟通道 9、14、15、16 和 17 连接到了内部的 VSS。
ADC0 | ADC1 | ADC2 | |
---|---|---|---|
通道0 | PA0 | PA0 | PA0 |
通道1 | PA1 | PA1 | PA1 |
通道2 | PA2 | PA2 | PA2 |
通道3 | PA3 | PA3 | PA3 |
通道4 | PA4 | PA4 |
PF6
|
通道5 | PA5 | PA5 |
PF7
|
通道6 | PA6 | PA6 |
PF8
|
通道7 | PA7 | PA7 |
PF9
|
通道8 | PB0 | PB0 |
PF10
|
通道9 | PB1 | PB1 | 连接内部VSS |
通道10 | PC0 | PC0 | PC0 |
通道11 | PC1 | PC1 | PC1 |
通道12 | PC2 | PC2 | PC2 |
通道13 | PC3 | PC3 | PC3 |
通道14 | PC4 | PC4 | 连接内部VSS |
通道15 | PC5 | PC5 | 连接内部VSS |
通道16 |
连接内部温度传感器Vsense
|
连接内部VSS | 连接内部VSS |
通道17 |
连接内部参考电压输入Vrefint
|
连接内部VSS | 连接内部VSS |
3.3 编程要点
- 初始 ADC 用到的 GPIO
- 设置 ADC 的工作参数并初始化
- 设置 ADC 工作时钟
- 设置 ADC 转换通道顺序及采样时间
- 配置使能 ADC 转换完成中断,在中断/轮询内读取转换完数据
- 使能 ADC
- 使能软件触发 ADC 转换
ADC 转换结果数据使用中断/轮询方式读取,这里没有使用 DMA 进行数据传输。
3.4 ADC初始化
使用到 GPIO 时候都必须开启对应的 GPIO 时钟,GPIO 用于 AD 转换功能必须配置为模拟输入模式。
ADC 工作参数具体配置为:独立模式、单通道采集不需要扫描、启动连续转换、使用内部软件触发无需外部触发事件、使用右对齐数据格式、转换通道为 1。
rcu_adc_clock_config()
函数用来配置 ADC 的工作时钟,接收一个参数,设置的是 PCLK2 的分频系数,ADC 的时钟最大不能超过 14M。
adc_enable()
函数控制 ADC 转换启动。最后,进行 ADC 校准。
/*------------------时钟配置------------------*/
// GPIO时钟使能
rcu_periph_clock_enable(RCU_GPIOC);
// ADC时钟使能
rcu_periph_clock_enable(RCU_ADC1);
// ADC时钟8分频,最大14MHz
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);/*------------------ADC GPIO配置------------------*/
// 必须为模拟输入
gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_3);/*------------------ADC工作模式配置------------------*/
// 只使用一个ADC,属于独立模式
adc_mode_config(ADC_MODE_FREE);
// 多通道用扫描模式
// adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE);
// 单通道用连续转换模式
adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE);// 结果转换右对齐
adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);
// 转换通道1个
adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 1);// 不用外部触发转换,软件开启即可
adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);
adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);// 使能ADC
adc_enable(ADC1);
delay_1ms(1); // 等待1ms
// 使能ADC校准
adc_calibration_enable(ADC1);
3.5 获取ADC转化值
adc_regular_channel_config()
函数用来绑定 ADC 通道的转换顺序和时间。它接收 4 个形参,第一个形参选择 ADC 外设,可为 ADC0、ADC1 或 ADC2;第二个形参为通道的转换顺序,可选为 1 到 16;第三个形参通道选择,总共可选 18 个通道;第四个形参为采样周期选择,采样周期越短,ADC 转换数据输出周期就越短但数据精度也越低,采样周期越长,ADC 转换数据输出周期就越长同时数据精度越高。
调用 adc_software_trigger_enable()
函数进行软件触发 ADC 开始转换。
adc_regular_data_read()
函数是获取 ADC 转换结果值的库函数,只有一个形参为 ADC 外设,可选为 ADC0、ADC1 或 ADC2,该函数还返回一个 16 位的 ADC 转换结果值。
uint16_t adcValue = 0;// 配置ADC通道转换顺序,采样时间为55.5个时钟周期
adc_regular_channel_config(ADC1, 0, ADC_CHANNEL_13, ADC_SAMPLETIME_55POINT5);
// 由于没有采用外部触发,所以使用软件触发ADC转换
adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); while(!adc_flag_get(ADC1, ADC_FLAG_EOC)); // 等待采样完成
adc_flag_clear(ADC1, ADC_FLAG_EOC); // 清除结束标志adcValue = adc_regular_data_read(ADC1); // 读取ADC数据
3.6 ADC中断初始化
利用 ADC 转换完成中断可以非常方便的保证我们读取到的数据是转换完成后的数据而不用担心该数据可能是 ADC 正在转换时“不稳定”的数据。我们使用 adc_interrupt_enable()
函数使能 ADC 转换完成中断,并在中断服务函数中读取转换结果数据。
// 使能ADC中断
nvic_irq_enable(ADC0_1_IRQn, 0, 0);
// 清除ADC规则组转换结束中断标志
adc_interrupt_flag_clear(ADC1, ADC_INT_FLAG_EOC);
// 使能ADC规则组转换结束中断
adc_interrupt_enable(ADC1, ADC_INT_EOC);
3.7 ADC中断处理函数
我们使能了 ADC 转换完成中断,在 ADC 转换完成后就会进入中断服务函数,我们在中断服务函数内直接读取 ADC 转换结果保存在变量(在 main.c 中定义)中。
extern uint16_t adcValue;
/*!\brief this function handles ADC0 and ADC1 interrupt\param[in] none\param[out] none\retval none
*/
void ADC0_1_IRQHandler(void)
{adc_interrupt_flag_clear(ADC1, ADC_INT_FLAG_EOC); // 清除ADC规则组转换结束中断标志adcValue = adc_regular_data_read(ADC1); // 读取ADC数据
}
ADC 中断处理函数名称要与 ADC外设 相对应,可在 startup_gd32f10x_hd.s
启动文件中查看:
; /* external interrupts handler */DCD WWDGT_IRQHandler ; 16:Window Watchdog TimerDCD LVD_IRQHandler ; 17:LVD through EXTI Line detectDCD TAMPER_IRQHandler ; 18:Tamper Interrupt DCD RTC_IRQHandler ; 19:RTC through EXTI LineDCD FMC_IRQHandler ; 20:FMCDCD RCU_IRQHandler ; 21:RCUDCD EXTI0_IRQHandler ; 22:EXTI Line 0DCD EXTI1_IRQHandler ; 23:EXTI Line 1DCD EXTI2_IRQHandler ; 24:EXTI Line 2DCD EXTI3_IRQHandler ; 25:EXTI Line 3DCD EXTI4_IRQHandler ; 26:EXTI Line 4DCD DMA0_Channel0_IRQHandler ; 27:DMA0 Channel 0DCD DMA0_Channel1_IRQHandler ; 28:DMA0 Channel 1DCD DMA0_Channel2_IRQHandler ; 29:DMA0 Channel 2DCD DMA0_Channel3_IRQHandler ; 30:DMA0 Channel 3DCD DMA0_Channel4_IRQHandler ; 31:DMA0 Channel 4DCD DMA0_Channel5_IRQHandler ; 32:DMA0 Channel 5 DCD DMA0_Channel6_IRQHandler ; 33:DMA0 Channel 6DCD ADC0_1_IRQHandler ; 34:ADC0 and ADC1DCD USBD_HP_CAN0_TX_IRQHandler ; 35:USBD and CAN0 TXDCD USBD_LP_CAN0_RX0_IRQHandler ; 36:USBD and CAN0 RX0DCD CAN0_RX1_IRQHandler ; 37:CAN0 RX1DCD CAN0_EWMC_IRQHandler ; 38:CAN0 EWMCDCD EXTI5_9_IRQHandler ; 39:EXTI Line 5 to EXTI Line 9DCD TIMER0_BRK_IRQHandler ; 40:TIMER0 BreakDCD TIMER0_UP_IRQHandler ; 41:TIMER0 UpdateDCD TIMER0_TRG_CMT_IRQHandler ; 42:TIMER0 Trigger and CommutationDCD TIMER0_Channel_IRQHandler ; 43:TIMER0 Channel Capture CompareDCD TIMER1_IRQHandler ; 44:TIMER1DCD TIMER2_IRQHandler ; 45:TIMER2DCD TIMER3_IRQHandler ; 46:TIMER3DCD I2C0_EV_IRQHandler ; 47:I2C0 EventDCD I2C0_ER_IRQHandler ; 48:I2C0 ErrorDCD I2C1_EV_IRQHandler ; 49:I2C1 EventDCD I2C1_ER_IRQHandler ; 50:I2C1 ErrorDCD SPI0_IRQHandler ; 51:SPI0DCD SPI1_IRQHandler ; 52:SPI1DCD USART0_IRQHandler ; 53:USART0DCD USART1_IRQHandler ; 54:USART1DCD USART2_IRQHandler ; 55:USART2DCD EXTI10_15_IRQHandler ; 56:EXTI Line 10 to EXTI Line 15DCD RTC_Alarm_IRQHandler ; 57:RTC Alarm through EXTI LineDCD USBD_WKUP_IRQHandler ; 58:USBD WakeUp from suspend through EXTI LineDCD TIMER7_BRK_IRQHandler ; 59:TIMER7 Break InterruptDCD TIMER7_UP_IRQHandler ; 60:TIMER7 Update InterruptDCD TIMER7_TRG_CMT_IRQHandler ; 61:TIMER7 Trigger and Commutation InterruptDCD TIMER7_Channel_IRQHandler ; 62:TIMER7 Channel Capture Compare DCD ADC2_IRQHandler ; 63:ADC2DCD EXMC_IRQHandler ; 64:EXMCDCD SDIO_IRQHandler ; 65:SDIODCD TIMER4_IRQHandler ; 66:TIMER4DCD SPI2_IRQHandler ; 67:SPI2DCD UART3_IRQHandler ; 68:UART3DCD UART4_IRQHandler ; 69:UART4DCD TIMER5_IRQHandler ; 70:TIMER5DCD TIMER6_IRQHandler ; 71:TIMER6DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel4
四、ADC多通道轮询读取
4.1 board_adc.c
/********************************************************************** INCLUDES*/
#include "gd32f10x.h"
#include "systick.h"#include "board_adc.h"/********************************************************************** PUBLIC FUNCTIONS*/
/**@brief ADC驱动初始化@param 无@return 无
*/
void ADC_Init(void)
{/*------------------时钟配置------------------*/// GPIO时钟使能rcu_periph_clock_enable(RCU_GPIOC);// ADC时钟使能rcu_periph_clock_enable(RCU_ADC1);// ADC时钟8分频,最大14MHzrcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);/*------------------ADC GPIO配置------------------*/// 必须为模拟输入gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_3);gpio_init(GPIOC, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_4);/*------------------ADC工作模式配置------------------*/// 只使用一个ADC,属于独立模式adc_mode_config(ADC_MODE_FREE);// 多通道用扫描模式adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE);// 单通道用连续转换模式
// adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE);// 结果转换右对齐adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);// 转换通道1个adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 1);// 不用外部触发转换,软件开启即可adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);// 使能ADCadc_enable(ADC1);delay_1ms(1); // 等待1ms// 使能ADC校准adc_calibration_enable(ADC1);
}/**@brief ADC读取@param channel -[in] ADC通道@return ADC采样值
*/
uint16_t ADC_Read(uint8_t channel)
{uint16_t adcValue = 0;// 配置ADC通道转换顺序,采样时间为55.5个时钟周期adc_regular_channel_config(ADC1, 0, channel, ADC_SAMPLETIME_55POINT5);// 由于没有采用外部触发,所以使用软件触发ADC转换adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL); while(!adc_flag_get(ADC1, ADC_FLAG_EOC)); // 等待采样完成adc_flag_clear(ADC1, ADC_FLAG_EOC); // 清除结束标志adcValue = adc_regular_data_read(ADC1); // 读取ADC数据return adcValue;
}/****************************************************END OF FILE****************************************************/
4.2 board_adc.h
#ifndef _BOARD_ADC_H_
#define _BOARD_ADC_H_/********************************************************************** INCLUDES*/
#include "gd32f10x_adc.h"/********************************************************************** DEFINITIONS*//********************************************************************** API FUNCTIONS*/
void ADC_Init(void);
uint16_t ADC_Read(uint8_t channel);#endif /* _BOARD_ADC_H_ */
4.3 main.c
#include <stdio.h>
#include "gd32f10x.h"
#include "systick.h"#include "board_adc.h"
#include "board_usart.h"static volatile uint16_t s_adcValue = 0;
static volatile uint16_t s_volValue = 0;
static volatile uint16_t s_adcValue2 = 0;
static volatile uint16_t s_volValue2 = 0;int main(void)
{systick_config();//系统主频108MHZ,采用外部晶振,由两个宏决定(__SYSTEM_CLOCK_108M_PLL_HXTAL与HXTAL_VALUE)ADC_Init();USART_Init();while(1){s_adcValue = ADC_Read(ADC_CHANNEL_13); // 读取ADC采样值printf("adc1_13: %d ", s_adcValue);s_volValue = s_adcValue * 3300 / 4095; // 转换成电压值printf("vol: %d\r\n", s_volValue);s_adcValue2 = ADC_Read(ADC_CHANNEL_14); // 读取ADC采样值printf("adc1_14: %d ", s_adcValue2);s_volValue2 = s_adcValue2 * 3300 / 4095; // 转换成电压值printf("vol: %d\r\n", s_volValue2);delay_1ms(500);}
}
串口打印添加查看:GD32F103学习笔记(7)——USART串口使用
查看打印:
4.4 工程代码
百度网盘:https://pan.baidu.com/s/1pMFKeyZDeIZ1ejBfpc-Y0Q?pwd=lp1j 提取码:lp1j
五、ADC单通道中断读取
5.1 board_adc.c
/********************************************************************** INCLUDES*/
#include "gd32f10x.h"
#include "systick.h"#include "board_adc.h"/********************************************************************** PUBLIC FUNCTIONS*/
/**@brief ADC驱动初始化@param 无@return 无
*/
void ADC_Init(void)
{/*------------------时钟配置------------------*/// GPIO时钟使能rcu_periph_clock_enable(RCU_GPIOA);// ADC时钟使能rcu_periph_clock_enable(RCU_ADC1);// ADC时钟8分频,最大14MHzrcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8);/*------------------ADC GPIO配置------------------*/// 必须为模拟输入gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_0);/*------------------ADC工作模式配置------------------*/// 只使用一个ADC,属于独立模式adc_mode_config(ADC_MODE_FREE);// 多通道用扫描模式
// adc_special_function_config(ADC1, ADC_SCAN_MODE, ENABLE);// 单通道用连续转换模式adc_special_function_config(ADC1, ADC_CONTINUOUS_MODE, ENABLE);// 结果转换右对齐adc_data_alignment_config(ADC1, ADC_DATAALIGN_RIGHT);// 转换通道1个adc_channel_length_config(ADC1, ADC_REGULAR_CHANNEL, 1);// 配置ADC通道转换顺序,采样时间为55.5个时钟周期adc_regular_channel_config(ADC1, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_55POINT5);// 不用外部触发转换,软件开启即可adc_external_trigger_source_config(ADC1, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);adc_external_trigger_config(ADC1, ADC_REGULAR_CHANNEL, ENABLE);// 使能ADCadc_enable(ADC1);delay_1ms(1); // 等待1ms// 使能ADC校准adc_calibration_enable(ADC1);// 使能ADC中断nvic_irq_enable(ADC0_1_IRQn, 1, 1);// 清除ADC规则组转换结束中断标志adc_interrupt_flag_clear(ADC1, ADC_INT_FLAG_EOC);// 使能ADC规则组转换结束中断adc_interrupt_enable(ADC1, ADC_INT_EOC);// 由于没有采用外部触发,所以使用软件触发ADC转换adc_software_trigger_enable(ADC1, ADC_REGULAR_CHANNEL);
}/**@brief ADC读取@param 无@return ADC采样值
*/
uint16_t ADC_Read(void)
{ adc_interrupt_flag_clear(ADC1, ADC_INT_FLAG_EOC); // 清除ADC规则组转换结束中断标志return adc_regular_data_read(ADC1); // 读取ADC数据
}/****************************************************END OF FILE****************************************************/
5.2 board_adc.h
#ifndef _BOARD_ADC_H_
#define _BOARD_ADC_H_/********************************************************************** INCLUDES*/
#include "gd32f10x_adc.h"/********************************************************************** DEFINITIONS*//********************************************************************** API FUNCTIONS*/
void ADC_Init(void);
uint16_t ADC_Read(void);#endif /* _BOARD_ADC_H_ */
5.3 gd32f10x_it.c
/*!\file gd32f10x_it.c\brief interrupt service routines\version 2014-12-26, V1.0.0, firmware for GD32F10x\version 2017-06-20, V2.0.0, firmware for GD32F10x\version 2018-07-31, V2.1.0, firmware for GD32F10x\version 2020-09-30, V2.2.0, firmware for GD32F10x
*//*Copyright (c) 2020, GigaDevice Semiconductor Inc.Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32f10x_it.h"
#include "systick.h"#include "board_adc.h"/*!\brief this function handles NMI exception\param[in] none\param[out] none\retval none
*/
void NMI_Handler(void)
{}/*!\brief this function handles HardFault exception\param[in] none\param[out] none\retval none
*/
void HardFault_Handler(void)
{/* if Hard Fault exception occurs, go to infinite loop */while(1){}
}/*!\brief this function handles MemManage exception\param[in] none\param[out] none\retval none
*/
void MemManage_Handler(void)
{/* if Memory Manage exception occurs, go to infinite loop */while(1){}
}/*!\brief this function handles BusFault exception\param[in] none\param[out] none\retval none
*/
void BusFault_Handler(void)
{/* if Bus Fault exception occurs, go to infinite loop */while(1){}
}/*!\brief this function handles UsageFault exception\param[in] none\param[out] none\retval none
*/
void UsageFault_Handler(void)
{/* if Usage Fault exception occurs, go to infinite loop */while(1){}
}/*!\brief this function handles SVC exception\param[in] none\param[out] none\retval none
*/
void SVC_Handler(void)
{}/*!\brief this function handles DebugMon exception\param[in] none\param[out] none\retval none
*/
void DebugMon_Handler(void)
{}/*!\brief this function handles PendSV exception\param[in] none\param[out] none\retval none
*/
void PendSV_Handler(void)
{}/*!\brief this function handles SysTick exception\param[in] none\param[out] none\retval none
*/
void SysTick_Handler(void)
{delay_decrement();
}/*!\brief this function handles USART RBNE interrupt request and TBE interrupt request\param[in] none\param[out] none\retval none
*/
void USART0_IRQHandler(void)
{unsigned char data;if(RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)){data = usart_data_receive(USART0);usart_data_transmit(USART0, (uint8_t)data);while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));//发送完成判断}
}extern uint16_t adcValue;
/*!\brief this function handles ADC0 and ADC1 interrupt\param[in] none\param[out] none\retval none
*/
void ADC0_1_IRQHandler(void)
{adcValue = ADC_Read();
}
5.4 main.c
#include <stdio.h>
#include "gd32f10x.h"
#include "systick.h"#include "board_adc.h"
#include "board_usart.h"volatile uint16_t adcValue = 0;
volatile uint16_t volValue = 0;int main(void)
{systick_config();//系统主频108MHZ,采用外部晶振,由两个宏决定(__SYSTEM_CLOCK_108M_PLL_HXTAL与HXTAL_VALUE)ADC_Init();USART_Init();while(1){printf("adc1_0: %d ", adcValue);volValue = adcValue * 3300 / 4095; // 转换成电压值printf("vol: %d\r\n", volValue);delay_1ms(500);}
}
串口打印添加查看:GD32F103学习笔记(7)——USART串口使用
查看打印:
5.5 工程代码
百度网盘:https://pan.baidu.com/s/1pMFKeyZDeIZ1ejBfpc-Y0Q?pwd=lp1j 提取码:lp1j
• 由 Leung 写于 2022 年 4 月 20 日
• 参考:15. GD32F103C8T6入门教程-adc单通道轮训采集
19. GD32F103C8T6入门教程-adc使用教程6-外部中断线11触发adc0
GD32F103学习笔记(8)——ADC接口使用相关推荐
- PhalAPI学习笔记 ——— 第二章接口服务请求
PhalAPI学习笔记 --- 第二章接口服务请求 前言 接口服务请求 接口服务请求案例 自定义接口路由 开启匹配路由 配置路由规则 nginx apache 服务请求 结束语 前言 公司业务需要转学 ...
- STM32F407霸天虎HAL库学习笔记——使用ADC采集MQ135的数据并通过OLED显示
STM32F407霸天虎HAL库学习笔记--使用ADC采集MQ135的数据并通过OLED显示 一.软件准备 二.硬件准备 三.CubeMX配置 四.Keil MQ135.c MQ135.h main函 ...
- 学习笔记二:接口与继承(内部类)
学习笔记参考来源 java学习路线-推荐链接:java-接口与继承-内部类 学习笔记难免出错 望多指正!!! 什么是内部类呢? 什么是内部类?定义很简单 内部类就是定义在另一个类中的类 内部类的分类 ...
- 31 天重构学习笔记9. 提取接口
摘要:由于最近在做重构的项目,所以对重构又重新进行了一遍学习和整理,对31天重构最早接触是在2009年10月份,由于当时没有订阅Sean Chambers的blog,所以是在国外的社区上闲逛的时候链接 ...
- LTE学习笔记三:接口协议
上一笔记说明了LTE网络的网元组成,网元之间的联系是通过标准化的接口.接下来学习LTE终端和网络的空中接口Uu.基站之间的X2接口.基站与核心网之间的S1接口,以及LTE接口协议栈和以往无线制式相比的 ...
- STM32学习笔记(七) ADC模数转换测电平(普通和DMA模式)
嵌入式系统在微控制领域(温度,湿度,压力检测,四轴飞行器)中占据着重要地位,这些功能的实现是由微处理器cpu(如stm32)和传感器以及控制器共同完成的,而连接他们,使它们能够互相正常交流的正是本小节 ...
- 《如何了解软件的设计》学习笔记0——模型-接口-实现
如何理解软件的设计?一套流程:模型-接口-实现. 模型 找类与类之间的关系,绘制整体图,这个步骤就是找模型.有个整体地图. 接口 类中的各方法就是接口. 接口反映模型. 实现 类中方法的函数体就是实现 ...
- STM32学习笔记一一ADC
前言: 为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长. github:my github 注:博客所涉及的关于 stm32 的代码 ...
- [apifox学习笔记]在所有接口中添加登录后获取的token(有图示)
如何在所有的接口添加token 写在前面 在登录接口调通的基础上 在登录接口添加后置操作提取token作为环境变量 在项目概览中选择Auth和Bearer Token类型并赋值环境变量token 我们 ...
最新文章
- Wireshark分析器分析数据流过程
- HDU 2094 产生冠军 (map容器)
- WEB前端 vue学习一使用 vue-cli 搭建项目
- New Distinct Substrings(后缀数组)
- [css] 在页面上隐藏元素的方法有哪些?
- jsp示例-response页面重定向
- 漂亮的个人团队介绍网页模板
- 网站压力测试工具,不用安装,在线进行【强烈推荐】
- 软件架构入门及分类——微服务架构
- html中电子邮件地址怎么写,电子邮件地址怎么写
- 法人 法人代表和法定代表人的区别
- swing api 文档
- 微信公众账号怎么快速增加粉丝
- unity调试手机游戏(Android)【模拟器+真机】+设置运行时游戏横屏
- 全志T3开发板——嵌入式入门学习测试教程(7)
- Microsoft Edge 中的ie浏览器图标、右击新标签页打开功能的关闭方法
- UniRx之操作符详解-ReactiveX语法
- 我的第二本译作《精通OpenStack》上架啦:书籍介绍和译者序
- 32位驱动模式写保护开关
- vue中使用axios post上传头像/图片并实时显示到页面
热门文章
- 大型网站seo布局怎么做
- h5游戏间接转换为微信小游戏
- 最新流浪猫流浪狗H5完整运营源码下载/可封装APP
- php 直接显示缩略图,PHP自动生成缩略图函数的源码示例
- web前端本科未拿到学位证_您是否需要计算机科学学位才能成为成功的Web开发人员...
- C 碎片八 结构体amp;枚举amp;联合
- H5活动邀请函用这个就可以了
- 【毕业设计】基于深度学习的图像超分辨率重建 - opencv python cnn
- vc 2005 express使用
- [企业权限管理项目](二)环境搭建