ADC的输入时钟不得超过14MHZ,它是由PCLK2经分频产生。
如果被ADC转换的模拟电压低于低阀值或高于高阀值,AWD模拟看门狗状态位被设置。
ADC通常要与DMA一起使用 这里只是简单的用库配置ADC 不断扫描来实现ADC的应用。
Injected Channels 为注入组,Regular Channel 为规则组(好比家里的10个温度传感器用来实时显示温度,此10个传感器放在规则组,另外2个室外传感器的偶尔看一下数据,这两个放在注入组),规则组相当于执行的程序,注入组相当于中断,注入组转换可以打断规则通道的转换,注入通道转换完成之后,规则通道继续转换
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AIN; // 模拟输入
GPIO_Init(GPIOB,&GPIO_InitStructure); // 默认速度为两兆
配置ADC的运行:
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式 ,ADC1和ADC2的关系
ADC_InitStructure.ADC_ScanConvMode =DISABLE; //连续多通道模式 开关,设置为ENABLE,通道数为1,则仍然还是单通道
ADC_InitStructure.ADC_ContinuousConvMode =ENABLE; //连续转换 还是单次转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换不受外界决定
ADC_InitStructure.ADC_DataAlign =ADC_DataAlign_Right; //右对齐
ADC_InitStructure.ADC_NbrOfChannel =1; //扫描通道数
ADC_Init(ADC1,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_9, 1,ADC_SampleTime_1Cycles5); //通道X,采样时间为1.5周期,1代表规则通道第1个这个1是啥意思我不太清楚只有是1的时候我的ADC才正常。
ADC_Cmd (ADC1,ENABLE); //使能或者失能指定的ADC
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能或者失能指定的ADC的软件转换启动功能
//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
//ADC1,ADC通道x,规则采样顺序值为y,采样时间为239.5周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 ); // 通道0 ,顺序为第 1 周期为239.5(采样周期越长越准确)
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_239Cycles5 );
注意:为了能够正确地配置每一个ADC通道,用户在调用ADC_Init()之后,必须调用ADC_ChannelConfig()来配置每个所使用通道的转换次序和采样时间。
然后就是不停的读;
u16 TestAdc(void)
{
u16 adc;
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET); //检查制定ADC标志位置1与否 ADC_FLAG_EOC 转换结束标志位
adc=ADC_GetConversionValue(ADC1);
return adc;//返回最近一次ADCx规则组的转换结果
}
完整程序:
#include "stm32f10x.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include "misc.h"
#include <stdarg.h> // 这个头文件用于后面USART的输出函数中有 不定参数 ...
#define ADC1_DR_Address ((u32)0x4001244C)
static unsigned long ticks;
unsigned char Clock1s;
vu16 ADC_ConvertedValue;
void RCC_Configuration(void);
void ADC_Configuration(void);
void Usart1_Init(void);
void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...);
int main(void)
{
RCC_Configuration();
Usart1_Init();
ADC_Configuration();
USART_OUT(USART1,"\r\n USART1 print AD_value -------------------------- \r\n");
while(1)
{
if (ticks++ >= 900000) { //每隔一段时间发送一次数据
ticks = 0;
Clock1s = 1;
}
if (Clock1s) {
Clock1s = 0;
USART_OUT(USART1,"The current AD value = %d \r\n", ADC_ConvertedValue);
}
}
}
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable DMA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable ADC1 and GPIOC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 1; //
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
ADC_DMACmd(ADC1, ENABLE); //使能 ADC DMA
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1); //<span style="color: rgb(102, 102, 102); font-family: 'Courier New'; line-height: 25.98958396911621px; text-indent: 28px;"><span style="font-size:12px;">执行复位校准</span></span>
while(ADC_GetResetCalibrationStatus(ADC1)); //等待校准结束
ADC_StartCalibration(ADC1); //执行ADC校准
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE); <span style="font-family: Arial, Helvetica, sans-serif;">}</span>
void RCC_Configuration(void){
SystemInit();
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
}
void Usart1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //USART1 TX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1 RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //开漏输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART1 */
USART_Init(USART1, &USART_InitStructure);
/* Enable the USART1 */
USART_Cmd(USART1, ENABLE);
}
char *itoa(int value, char *string, int radix)
{
int i, d;
int flag = 0;
char *ptr = string;
/* This implementation only works for decimal numbers. 非10进制的转换为0 */
if (radix != 10)
{
*ptr = 0;
return string;
}
if (!value)
{
*ptr++ = 0x30; // 0x30就是 字符 '0' 0x31 是 字符 ’1‘ (ASCII码)
*ptr = 0;
return string;
}
/* if this is a negative value insert the minus sign. */
if (value < 0)
{
*ptr++ = '-';
/* Make the value positive. */
value *= -1;
}
for (i = 10000; i > 0; i /= 10)
{
d = value / i;
if (d || flag)
{
*ptr++ = (char)(d + 0x30);
value -= (d * i);
flag = 1;
}
}
/* Null terminate the string. */
*ptr = 0;
return string;
} /* NCL_Itoa */