STM32----------ADC和DMA(附:完整USART输出程序)

12位ADC是一种逐次逼近型模拟数字数字转换器。它有多达18个通道,可测量16个外部和2个内部信号源。
ADC的输入时钟不得超过14MHZ,它是由PCLK2经分频产生。
如果被ADC转换的模拟电压低于低阀值或高于高阀值,AWD模拟看门狗状态位被设置。

ADC通常要与DMA一起使用 这里只是简单的用库配置ADC 不断扫描来实现ADC的应用。

Injected Channels 为注入组,Regular Channel 为规则组(好比家里的10个温度传感器用来实时显示温度,此10个传感器放在规则组,另外2个室外传感器的偶尔看一下数据,这两个放在注入组),规则组相当于执行的程序,注入组相当于中断,注入组转换可以打断规则通道的转换,注入通道转换完成之后,规则通道继续转换



首先配置GPIO与ADC的时钟:

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 */
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值