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

来源:互联网 发布:android编程权威指南3 编辑:程序博客网 时间:2024/05/17 19:23
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 DMAADC_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 0
原创粉丝点击