模拟量:反应真实世界中的物理量(比如温度,压力,长度)模拟量通常是通过电压,电流等信号来表示。
数字量:通常是0和1来表示某个物理量的变化。
1. 分为并联比较,逐次逼近,计数型,双积分型。
Vin 大于 Vr 输出1 ,Vin 小于 Vr 输出0. 而Vin可以设置0~8v。每个比较器的Vr通过分压算出来。就可以控制比较器的输出。
上图是输出8位怎么输出三位呢。
利用D触发的当控制端 = 1 ,数据输入等于数据输出。
利用D触发的当控制端 = 0,保持数据输出不变。
如下电路就只输出三位的组合。
一次一次接近所需的值。如下未知砝码的重量。先用权重大的。慢慢加砝码。直到两边平衡。
VIN相当于待测量的值.于VDAC去比较。如果大于或者小于就去调整逐次逼近电路。
直到VIN = VDAC。B1,B2.....Bn的值就是模数的转换结果。
GD32的框图
STM32的框图
分为规则通道与注入通道。并且规则通道最多可以16个。注入通道最多4个。规则通道只有一个数据寄存器。而注入每个都有单独的数据寄存器。当EOC标志位1。说明ADC转换完成。并且可以触发中断。要想成功转换还必须设置ADC的触发源。比如:软件触发。
分为单次运行,连续运行,扫描运行,间断运行。
单次转换模式:在这种模式下,ADC 仅进行一次转换。一旦转换完成,ADC 将停止工作。这是最基本的模式,适用于只需要一次转换的应用。
连续转换模式:在这种模式下,ADC 连续不断地进行转换。每次转换完成后,ADC 会自动启动下一次转换。这种模式适用于需要连续监测的应用,例如连续采集传感器数据。
扫描模式:在这种模式下,ADC 会按照预设的顺序对多个通道进行转换。每次转换完成后,ADC 会继续进行下一次转换,直到完成所有通道的转换。这种模式适用于需要定期监测多个通道的应用。
间断运行模式:这种模式下,ADC 会在预定的时间间隔内进行转换。在转换完成后,ADC 会停止工作,直到下一次预定的时间到达。这种模式适用于需要定期进行转换,但转换频率较低的应用。
14. adc_interrupt_flag_get
光敏电阻与可调电阻的P7的3,1引脚。获取PA4,PA5的电压。根据分压求出光敏电阻与可调电阻
的电阻值。
resister_adc.h
#ifndef _RESISTER_ADC
#define _RESISTER_ADC
#include "gd32f10x.h"
#include "systick.h"
void resister_adc_init(void);
void gpio_config(void);
void adc_config(void);
uint16_t read_adc0_data(uint8_t adc_channel); // 读取ADC0转换的结果
float get_photo_r(void); //获取光敏电阻的阻值
float get_var_r(void); //获取可调电阻的阻值
#endif
resister_adc.c
#include "resister_adc.h"
// 是与电阻相连的adc外设及其channel的初始化
void resister_adc_init(void){
gpio_config();
adc_config();
}
/* 初始化IO口为模拟输入模式 */
void gpio_config(){
rcu_periph_clock_enable(RCU_GPIOA); // 1.使能rcu时钟
gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_4 |GPIO_PIN_5); //2.初始化gpio输入模式
}
/* 初始化adc0 */
void adc_config(){
rcu_periph_clock_enable(RCU_ADC0); // 使能时钟
rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV8); // 配置ADC的时钟
/* 配置ADC0的参数 */
adc_mode_config(ADC_MODE_FREE); // 自由模式 各个ADC独立
adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE); //关闭连续模式
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); //对齐方式
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1); // 转换数量1 不同采集切换通道
adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE); // 触发方式,软件触发
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); // 使能外部触发
/* 使能ADC0 */
adc_enable(ADC0);
delay_1ms(2); //等待稳定
/* 自校准 */
adc_calibration_enable(ADC0);
}
// 读取ADC0转换的结果
uint16_t read_adc0_data(uint8_t adc_channel){
/*配置adc0的通道*/
adc_regular_channel_config(ADC0, 0, adc_channel, ADC_SAMPLETIME_1POINT5);
/*触发adc0的转换*/
adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
/*等待EOC置位,即ADC0转换完成*/
while(!adc_flag_get(ADC0, ADC_FLAG_EOC));
/*清零EOC*/
adc_flag_clear(ADC0, ADC_FLAG_EOC);
/*读常规通道数据寄存器值并返回*/
return adc_regular_data_read(ADC0);
}
/*获取光敏电阻的阻值,
* return:光敏电阻阻值,单位是千欧
*/
float get_photo_r(void){
uint16_t adc_value = 0;
uint8_t i;
for(i=0; i<8; i++){
adc_value += read_adc0_data(ADC_CHANNEL_5);
}
adc_value = adc_value / 8;
float v_photo_res = adc_value * 3.3f / 4096.0f; //得到模数转换的结果对应的电压值 基准电压3.3v 4096 = 2的12次方
float result = (v_photo_res * 10) / (3 - v_photo_res);
return result;
}
/*获取可调电阻的阻值,
* return:可调电阻阻值,单位是千欧
*/
float get_var_r(void){
uint16_t adc_value = 0;
uint8_t i;
for(i=0; i<8; i++){
adc_value += read_adc0_data(ADC_CHANNEL_4);
}
adc_value = adc_value / 8;
float v_var_res = adc_value * 3.3f / 4096.0f; //得到模数转换的结果对应的电压值
float result = (v_var_res * 10) / (5 - v_var_res);
return result;
}