模拟–数字转换器
共3个独立ADC(ADC1、ADC2、ADC3)
12位分辨率
每个独立ADC有18个通道,16个是外部通道
ADC的通道并没有固定的引脚,可以根据自己随意选用。
转换结束、注入转换结束和发生模拟看门狗事件时产生中断
ADCCLK最大是14MHz。
转换时间=采样时间+12.5个时钟周期。采样时间通过寄存器来配置
有俩种模式:
注入模式和规则模式(没搞懂)
(也不需要搞懂,因为开发板只放了一个ADC设备)
函数:
typedef struct
{
uint32_t ADC_Mode; //模式,一般使用ADC_Mode_Independent表示使用一个ADC
FunctionalState ADC_ScanConvMode; //扫描模式
FunctionalState ADC_ContinuousConvMode; //连续转换模式
uint32_t ADC_ExternalTrigConv; //外部触发选择模式
uint32_t ADC_DataAlign; //对齐方式
uint8_t ADC_NbrOfChannel; //转换的通道
}ADC_InitTypeDef;
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);//初始化ADC
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);//使能ADC
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//配置ADC为软件触发
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//配置ADC为外部触发
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);//ADC的规则通道配置
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);//ADC的DMA使能
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);//配置ADC的时钟
开发板中A/D输入电压调节电位器R37连接在M_PB0引脚,即GPIOB0.
查stm32f103rbt6参考手册,得知,PB0/ADC_IN8,即是第8通道。
且只有一个通道,因此也就不需要使用DMA。
步骤:
一、初始化
1.初始化GPIO
2.初始化ADC
3.配置ADC时钟,通道转换顺序和采样时间
4.使ADC完成后中断,配置中断,使能中断
5.使能ADC
6.校准ADC
7.软件触发ADC
二、中断服务函数或轮询函数
ADC设备:
就是一个滑动变阻器,一端3.3V电压,一段接地,M_PB0接到芯片上,读取电压转化的值。
adc.h
#ifndef _ADC_H
#define _ADC_H
#include "stm32f10x.h"
void ADC_NVIC(void);
void ADC1_Init(void);
float Read_ADC(void);
void delay(int x);
#endif
adc.c
#include "adc.h"
void ADC1_Init()
{
ADC_InitTypeDef ADC_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
//配置中断
ADC_NVIC();
//GPIO配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;//模拟输入
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
//ADC配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode = DISABLE;
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//不使用外部触发
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 1;
ADC_Init(ADC1,&ADC_InitStruct);
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_13Cycles5);
//ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
delay(10000000);
ADC1->CR2 |= 0x02;
}
void delay(int x)
{
while(x--)
;
}
void ADC_NVIC()
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStruct. NVIC_IRQChannel=ADC1_2_IRQn;
NVIC_InitStruct. NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStruct. NVIC_IRQChannelSubPriority =1;
NVIC_InitStruct. NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
float Read_ADC(void)
{
float ADC_VALUE;
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换完成
ADC_VALUE = ADC_GetConversionValue(ADC1)*3.30/0xfff;
return ADC_VALUE;
}
主函数
#include "stm32f10x.h"
#include "uart.h"
#include "adc.h"
extern __IO uint16_t value;
int main()
{
float fl_value;
usrt_init();
ADC1_Init();
while(1)
{
//使用中断
fl_value=(float)value/4096*3.3;
fl_value = ADC_GetConversionValue(ADC1)*3.30/0xfff;
//fl_value=Read_ADC();//使用轮询
printf("0x%x\n%f V\n",value,fl_value);
delay(10000000);
}
}
中断服务函数:
__IO uint16_t value;
void ADC1_2_IRQHandler(void)
{
if(ADC_GetITStatus(ADC1,ADC_IT_EOC)==SET)
{
value=ADC_GetConversionValue(ADC1);
}
ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);
}
使用通道传输数据:
(只需要在主函数调用初始化函数,然后读取value的值即可)
void DMA_ADC_Init(void)
{
DMA_InitTypeDef DMA_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
DMA_InitStruct.DMA_PeripheralBaseAddr =(uint32_t)&(ADC1->DR);
DMA_InitStruct.DMA_MemoryBaseAddr=(uint32_t)&value;
DMA_InitStruct.DMA_DIR =DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize=1;
DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc= DMA_MemoryInc_Disable;
DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_Mode= DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority=DMA_Priority_High;
DMA_InitStruct.DMA_M2M= DMA_M2M_Disable;
DMA_Init(DMA1_Channel1,&DMA_InitStruct);
DMA_Cmd(DMA1_Channel1,ENABLE);
ADC_DMACmd(ADC1,ENABLE);
}
来源:CSDN
作者:灵虚天
链接:https://blog.csdn.net/qq_42424228/article/details/104006612