学习目标
- 了解ADC开发流程
- 掌握采样方式
- 能够使用ADC进行芯片内部通道进行采样
-
学习内容
GD32F4的ADC
特点:
16个外部模拟输入通道;
- 1个内部温度传感通道(VSENSE);
- 1个内部参考电压输入通道(VREFINT);
- 1个外部监测电池VBAT供电引脚输入通道。
ADC开发流程
- ADC配置
- ADC采样
ADC配置
GPIO配置
主要配置GPIO的模式和引脚信息,如果ADC采样需要通过引脚进行,则需要配置。主频配置
采样的频率配置。adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
分辨率和数据对齐配置
分辨率为采样精度,可选为12位,10位,8位,6位。
不同分辨率,取值精度范围不同:
*
左对齐与右对齐,表示的是采样的数据,如何存储到寄存器的。我们获取的是寄存器存储的值。详见《GD32F4xx_User_Manual_Rev2.8_CN.pdf》14.4.7
规则配置
规则包含:
- 常规规则
- 插入规则
模式配置
Continuous Mode(连续模式)
定义:在连续模式下,一旦 ADC 被启动,它会不断地对选定的通道进行采样和转换,直到显式停止。
用途:这个模式适用于需要持续监测某个信号的场合,比如读取一个模拟传感器的持续输出。
特点:一旦开始,ADC 会连续不断地进行转换操作,无需每次转换都重新启动。
Scan Mode(扫描模式)
定义:在扫描模式下,ADC 按照预设的顺序自动扫描多个通道,并对每个通道进行一次采样和转换。
用途:这个模式适用于需要周期性地监测多个通道(例如多个传感器)的场合。
特点:ADC 在一系列通道上进行顺序采样,每个通道都被转换一次,然后整个序列可以重复进行,如果结合连续模式使用。
- 扫描模式
- 运行模式:连续or单次
- 插入序列自动转换模式
我们这里的模式并非是多选一的结构,而是多选多,自由搭配方式
模式 | 开启 | 关闭 |
---|---|---|
扫描模式 | ||
连续模式 | ||
插入序列自动转换模式 |
校准ADC
// 校准ADC
adc_calibration_enable(ADC0);
ADC采样
- 数据转换操作。这个是ADC电路实现的,我们主要是去触发它进行数据转换。
- 转换状态。电路在转换过程中,会修改相应寄存器状态。我们可以通过判断寄存器状态来知道转换的进度。
-
需求:采样芯片温度
读取芯片的温度。芯片内置温度采样电路,可以通过ADC进行采样。
初始化
static void ADC_config() {
/******************** ADC config **********************/
// 配置时钟
rcu_periph_clock_enable(RCU_ADC0);
// 重置
adc_deinit();
// 配置主频
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
////////// 采样配置
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); // 分辨率
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
//////////// 规则配置
adc_channel_16_to_18(ADC_TEMP_VREF_CHANNEL_SWITCH, ENABLE);
// 配置通道和通道数量
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_16, ADC_SAMPLETIME_15);
adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 1);
/////////// 模式配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);// 取消扫描模式
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);//取消连续模式
// 打开ADC
adc_enable(ADC0);
// 校准ADC
adc_calibration_enable(ADC0);
delay_1ms(100);
}
获取采样
static void ADC_get() {
// 触发ADC采样
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
// 等待ADC采样并且转化完成
while(RESET == adc_flag_get(ADC0, ADC_FLAG_EOC));
adc_flag_clear(ADC0, ADC_FLAG_EOC);
// 获取采样结果数据
uint16_t value = adc_routine_data_read(ADC0);
// 将ADC结果转化为温度值
float temperature = ((1.4 - 3.3 * value / 4096 )/ 4.4) * 1000 + 25;
printf("value: %d %f\r\n", value, temperature);
}
- 通过软触发调用adc进行采样。
- adc的规则通道为常规通道,通过
adc_routine_data_read
读取数据
完整代码
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart0.h"
void Usart0_recv(uint8_t *data, uint32_t len) {
printf("recv: %s\r\n", data);
}
static void ADC_config() {
/****************** GPIO config *********************/
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOE);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3);
// 3. 配置GPIO 模式的操作方式
gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_3);
/******************** ADC config **********************/
// 配置时钟
rcu_periph_clock_enable(RCU_ADC0);
// 重置
adc_deinit();
// 配置主频
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
////////// 采样配置
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); // 分辨率
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
//////////// 规则配置
adc_channel_16_to_18(ADC_TEMP_VREF_CHANNEL_SWITCH, ENABLE);
// 配置通道和通道数量
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_16, ADC_SAMPLETIME_15);
adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 1);
/////////// 模式配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);// 取消扫描模式
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);//取消连续模式
// 打开ADC
adc_enable(ADC0);
// 校准ADC
adc_calibration_enable(ADC0);
delay_1ms(100);
}
static void ADC_get() {
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
while(RESET == adc_flag_get(ADC0, ADC_FLAG_EOC));
adc_flag_clear(ADC0, ADC_FLAG_EOC);
uint16_t value = adc_routine_data_read(ADC0);
float temperature = ((1.4 - 3.3 * value / 4096 )/ 4.4) * 1000 + 25;
printf("temp: %d %f\r\n", value, temperature);
}
int main(void)
{
// 系统时钟初始化
systick_config();
Usart0_init();
ADC_config();
while(1) {
ADC_get();
delay_1ms(1000);
}
}
单次运行模式
- 每次采样,都需要触发
需求:电位器
初始化
static void ADC_config() {
/****************** GPIO config *********************/
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOA);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
/******************** ADC config **********************/
// 配置时钟
rcu_periph_clock_enable(RCU_ADC0);
// 重置
adc_deinit();
// 配置主频
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
////////// 采样配置
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); // 分辨率
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
//////////// 规则配置
// 配置通道和通道数量
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_15);
adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 1);
/////////// 模式配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);// 取消扫描模式
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);//取消连续模式
// 打开ADC
adc_enable(ADC0);
// 校准ADC
adc_calibration_enable(ADC0);
delay_1ms(100);
}
-
获取采样
static void ADC_get() {
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
while(RESET == adc_flag_get(ADC0, ADC_FLAG_EOC));
adc_flag_clear(ADC0, ADC_FLAG_EOC);
uint16_t value = adc_routine_data_read(ADC0);
float vol = value * 3.3 / 4096;
printf("value: %d %f\r\n", value, vol);
}
通过软触发调用adc进行采样。
- adc的规则通道为常规通道,通过
adc_routine_data_read
读取数据完整代码
```cinclude “gd32f4xx.h”
include “systick.h”
include
include “main.h”
include “Usart0.h”
// PA0: 电位器
void Usart0_recv(uint8_t *data, uint32_t len) { printf(“recv: %s\r\n”, data); }
static void ADC_config() { /** GPIO config */ // 1. 时钟初始化 rcu_periph_clock_enable(RCU_GPIOA); // 2. 配置GPIO 输入输出模式 gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
/******************** ADC config **********************/
// 配置时钟
rcu_periph_clock_enable(RCU_ADC0);
// 重置
adc_deinit();
// 配置主频
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
////////// 采样配置
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); // 分辨率
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
//////////// 规则配置
// 配置通道和通道数量
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_15);
adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 1);
/////////// 模式配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);// 取消扫描模式
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);//取消连续模式
// 打开ADC
adc_enable(ADC0);
// 校准ADC
adc_calibration_enable(ADC0);
delay_1ms(100);
}
static void ADC_get() { adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
while(RESET == adc_flag_get(ADC0, ADC_FLAG_EOC));
adc_flag_clear(ADC0, ADC_FLAG_EOC);
uint16_t value = adc_routine_data_read(ADC0);
float vol = value * 3.3 / 4096;
printf("value: %d %f\r\n", value, vol);
}
int main(void) { // 系统时钟初始化 systick_config(); Usart0_init(); ADC_config();
while(1) {
ADC_get();
delay_1ms(1000);
}
}
<a name="bcPJU"></a>
### 多通道采样
需要同时采样芯片内部的温度和外部电位器的电压。
<a name="aL05f"></a>
#### 初始化
```c
static void ADC_config() {
/****************** GPIO config *********************/
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOA);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
/******************** ADC config **********************/
// 配置时钟
rcu_periph_clock_enable(RCU_ADC0);
// 重置
adc_deinit();
// 配置主频
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
////////// 采样配置
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); // 分辨率
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
/////////// 模式配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);// 扫描模式
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);//取消连续模式
// 打开ADC
adc_enable(ADC0);
// 校准ADC
adc_calibration_enable(ADC0);
delay_1ms(100);
}
获取采样
static void ADC_get_temperature() {
// 配置通道
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_16, ADC_SAMPLETIME_15);
// 触发转换
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
while(RESET == adc_flag_get(ADC0, ADC_FLAG_EOC));
adc_flag_clear(ADC0, ADC_FLAG_EOC);
uint16_t value = adc_routine_data_read(ADC0);
float temperature = ((1.4 - 3.3 * value / 4096 )/ 4.4) + 25;
printf("temp: %d %f\r\n", value, temperature);
}
static void ADC_get_vol() {
// 配置通道
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_15);
// 触发转换
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
while(RESET == adc_flag_get(ADC0, ADC_FLAG_EOC));
adc_flag_clear(ADC0, ADC_FLAG_EOC);
uint16_t value = adc_routine_data_read(ADC0);
float vol = value * 3.3 / 4096;
printf("vol: %d %f\r\n", value, vol);
}
完整代码
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "Usart0.h"
void Usart0_recv(uint8_t *data, uint32_t len) {
printf("recv: %s\r\n", data);
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
}
static void ADC_config() {
/****************** GPIO config *********************/
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOA);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
/******************** ADC config **********************/
// 配置时钟
rcu_periph_clock_enable(RCU_ADC0);
// 重置
adc_deinit();
// 配置主频
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
////////// 采样配置
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); // 分辨率
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
/////////// 模式配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);// 扫描模式
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);//取消连续模式
// 打开ADC
adc_enable(ADC0);
// 校准ADC
adc_calibration_enable(ADC0);
delay_1ms(100);
}
static void ADC_get_temperature() {
// 配置通道
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_16, ADC_SAMPLETIME_15);
// 触发转换
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
while(RESET == adc_flag_get(ADC0, ADC_FLAG_EOC));
adc_flag_clear(ADC0, ADC_FLAG_EOC);
uint16_t value = adc_routine_data_read(ADC0);
float temperature = ((1.4 - 3.3 * value / 4096 )/ 4.4) + 25;
printf("temp: %d %f\r\n", value, temperature);
}
static void ADC_get_vol() {
// 配置通道
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_0, ADC_SAMPLETIME_15);
// 触发转换
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
while(RESET == adc_flag_get(ADC0, ADC_FLAG_EOC));
adc_flag_clear(ADC0, ADC_FLAG_EOC);
uint16_t value = adc_routine_data_read(ADC0);
float vol = value * 3.3 / 4096;
printf("vol: %d %f\r\n", value, vol);
}
int main(void)
{
// 系统时钟初始化
systick_config();
Usart0_init();
ADC_config();
while(1) {
ADC_get_temperature();
ADC_get_vol();
delay_1ms(1000);
}
}
多通道采样DMA
现在需要采样数据,采集多路数据,采用DMA的方式帮助我们搬运数据
初始化
static void ADC_config() {
/****************** GPIO config *********************/
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOA);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
/******************** ADC config **********************/
// 配置时钟
rcu_periph_clock_enable(RCU_ADC0);
// 重置
adc_deinit();
// 配置主频
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
////////// 采样配置
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); // 分辨率
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
//////////// 规则配置
// 配置通道和通道数量
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_16, ADC_SAMPLETIME_15);
adc_routine_channel_config(ADC0, 1, ADC_CHANNEL_0, ADC_SAMPLETIME_15);
adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 2);
/////////// 模式配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);// 扫描模式
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);//取消连续模式
// DMA
adc_dma_request_after_last_enable(ADC0);
adc_dma_mode_enable(ADC0);
// 打开ADC
adc_enable(ADC0);
// 校准ADC
adc_calibration_enable(ADC0);
delay_1ms(100);
// 触发采样
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
}
ADC初始化,需要配置DMA模式开启
uint16_t buff[2] = {0};
static void DMA_config() {
uint32_t dmax = DMA1;
uint32_t dmax_rcu = RCU_DMA1;
uint32_t dmax_ch = DMA_CH0;
uint32_t damx_sub = DMA_SUBPERI0;
uint32_t dmax_dirction = DMA_PERIPH_TO_MEMORY;
uint32_t dmax_src = (uint32_t)(&ADC_RDATA(ADC0));
uint32_t dmax_src_inc = DMA_PERIPH_INCREASE_DISABLE;
uint32_t dmax_src_width = DMA_PERIPH_WIDTH_16BIT;
uint32_t dmax_src_len = 2;
uint32_t dmax_dst = (uint32_t)(buff);
uint32_t dmax_dst_inc = DMA_MEMORY_INCREASE_ENABLE;
/**************** DMA p2m *******************/
// 时钟
rcu_periph_clock_enable(dmax_rcu);
// 重置dma
dma_deinit(dmax, dmax_ch);
//////// dma 配置
dma_single_data_parameter_struct dsdps;
dma_single_data_para_struct_init(&dsdps);
// 方向
dsdps.direction = DMA_PERIPH_TO_MEMORY;
// 内存: dst
dsdps.memory0_addr = dmax_dst;
dsdps.memory_inc = dmax_dst_inc;
// 外设: src
dsdps.periph_addr = dmax_src;
dsdps.periph_inc = dmax_src_inc;
// 数据长度
dsdps.number = dmax_src_len;
// dst数据宽度
dsdps.periph_memory_width = dmax_src_width;
// 传输优先级
dsdps.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_single_data_mode_init(dmax, dmax_ch, &dsdps);
//////// 配置 dma 子连接
dma_channel_subperipheral_select(dmax, dmax_ch, damx_sub);
dma_circulation_enable(dmax, dmax_ch);
// 默认开启接收
dma_flag_clear(dmax, dmax_ch, DMA_FLAG_FTF);
dma_channel_enable(dmax, dmax_ch);
}
-
采样数据获取
static void ADC_get() {
uint16_t value = buff[0];
float temperature = ((1.4 - 3.3 * value / 4096 )/ 4.4) + 25;
printf("temp: 0x%04X %f\r\n", value, temperature);
value = buff[1];
float vol = value * 3.3 / 4096;
printf("vol: 0x%04X %f\r\n", value, vol);
buff[0] = 0;
buff[1] = 0;
}
使用了DMA后,就不必去ADC寄存器中取数据,可以直接到内存中获取。
运行模式
连续运行模式
连续运行模式,只需要触发一次采样,ADC后续会自动帮助进行采样。
对应的配置为:adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);//连续模式
扫描模式
扫描模式,是在多个通道需要同时采样的情况下使用的,确保每个通道都能够获得数据。
如果是多个通道采样时,不配置扫描模式,则只会读取第一个序列的数据:
连续运行+扫描模式
完整代码
```c
include “gd32f4xx.h”
include “systick.h”
include
include “main.h”
include “Usart0.h”
void Usart0_recv(uint8_t *data, uint32_t len) { printf(“recv: %s\r\n”, data);
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
}
static void ADC_config() { /** GPIO config */ // 1. 时钟初始化 rcu_periph_clock_enable(RCU_GPIOA); // 2. 配置GPIO 输入输出模式 gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOA);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
/******************** ADC config **********************/
// 配置时钟
rcu_periph_clock_enable(RCU_ADC0);
// 重置
adc_deinit();
// 配置主频
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
////////// 采样配置
adc_resolution_config(ADC0, ADC_RESOLUTION_12B); // 分辨率
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
//////////// 规则配置
// 配置通道和通道数量
adc_routine_channel_config(ADC0, 0, ADC_CHANNEL_16, ADC_SAMPLETIME_15);
adc_routine_channel_config(ADC0, 1, ADC_CHANNEL_0, ADC_SAMPLETIME_15);
adc_routine_channel_config(ADC0, 2, ADC_CHANNEL_1, ADC_SAMPLETIME_15);
adc_channel_length_config(ADC0, ADC_ROUTINE_CHANNEL, 3);
/////////// 模式配置
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);// 扫描模式
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ENABLE);//取消连续模式
// DMA
adc_dma_request_after_last_enable(ADC0);
adc_dma_mode_enable(ADC0);
// 打开ADC
adc_enable(ADC0);
// 校准ADC
adc_calibration_enable(ADC0);
delay_1ms(100);
// 触发采样
adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
}
uint16_t buff[2] = {0};
static void DMA_config() { uint32_t dmax = DMA1; uint32_t dmax_rcu = RCU_DMA1; uint32_t dmax_ch = DMA_CH0; uint32_t damx_sub = DMA_SUBPERI0;
uint32_t dmax_dirction = DMA_PERIPH_TO_MEMORY;
uint32_t dmax_src = (uint32_t)(&ADC_RDATA(ADC0));
uint32_t dmax_src_inc = DMA_PERIPH_INCREASE_DISABLE;
uint32_t dmax_src_width = DMA_PERIPH_WIDTH_16BIT;
uint32_t dmax_src_len = 3;
uint32_t dmax_dst = (uint32_t)(buff);
uint32_t dmax_dst_inc = DMA_MEMORY_INCREASE_ENABLE;
/**************** DMA p2m *******************/
// 时钟
rcu_periph_clock_enable(dmax_rcu);
// 重置dma
dma_deinit(dmax, dmax_ch);
//////// dma 配置
dma_single_data_parameter_struct dsdps;
dma_single_data_para_struct_init(&dsdps);
// 方向
dsdps.direction = DMA_PERIPH_TO_MEMORY;
// 内存: dst
dsdps.memory0_addr = dmax_dst;
dsdps.memory_inc = dmax_dst_inc;
// 外设: src
dsdps.periph_addr = dmax_src;
dsdps.periph_inc = dmax_src_inc;
// 数据长度
dsdps.number = dmax_src_len;
// dst数据宽度
dsdps.periph_memory_width = dmax_src_width;
// 传输优先级
dsdps.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_single_data_mode_init(dmax, dmax_ch, &dsdps);
//////// 配置 dma 子连接
dma_channel_subperipheral_select(dmax, dmax_ch, damx_sub);
dma_circulation_enable(dmax, dmax_ch);
// 默认开启接收
dma_flag_clear(dmax, dmax_ch, DMA_FLAG_FTF);
dma_channel_enable(dmax, dmax_ch);
}
static void ADC_get() { uint16_t value = buff[0]; float temperature = ((1.4 - 3.3 * value / 4096 )/ 4.4) + 25; printf(“temp: 0x%04X %f\r\n”, value, temperature);
value = buff[1];
float vol = value * 3.3 / 4096;
printf("vol: 0x%04X %f\r\n", value, vol);
buff[0] = 0;
buff[1] = 0;
}
int main(void) { // 系统时钟初始化 systick_config(); Usart0_init(); ADC_config(); DMA_config();
while(1) {
ADC_get();
delay_1ms(1000);
}
练习题
- 使用ADC进行采样芯片温度
- 使用ADC进行采样电位器
- 使用ADC进行采样NTC温度