说明:采用DMA方式读取8通道ADC以及1通道芯片内部温度,Chip_Temp最终为计算得出的温度值。注:温度精确度一般为±1℃,最大为±2℃。
代码详见如下:
/*ADC.C*/#include <stdio.h>
#include <math.h>
#include "stm32f0xx_exti.h"
#include "stm32f0xx_gpio.h"
#include "stm32f0xx_flash.h"
#include "stm32f0xx_rcc.h"
#include "stm32f0xx_usart.h"
#include "stm32f0xx_tim.h"
#include "stm32f0xx_rtc.h"
#include "stm32f0xx_dma.h"
#include "stm32f0xx_adc.h"
#include "platform_config.h"
#include "adc.h"#define ADC_BUF_LEN 10
#define Channel_Num 9 //增加内部温度
#define Sample_Num ((unsigned short)120)
#define ADC_DAT_LEN (Sample_Num*Channel_Num)#define ADC1_DR_ADDRESS (0x50000000+0x40)
extern struct SysInfo s;
unsigned short AdcDat[Sample_Num][Channel_Num]; //存储外部ADC通道数据
unsigned short Inject_Index;
#define VREF_TEMP_BUF_LEN 16
unsigned short VrefTempBuf[VREF_TEMP_BUF_LEN];
extern void UpdataAdcVal(unsigned char ch, unsigned short AdcVal);
extern void InsertDataToU16Buf(unsigned short Data, unsigned short *Buf, unsigned short Len);
/*
#define ADC_SampleTime_1Cycles5 ((uint8_t)0x00)
#define ADC_SampleTime_7Cycles5 ((uint8_t)0x01)
#define ADC_SampleTime_13Cycles5 ((uint8_t)0x02)
#define ADC_SampleTime_28Cycles5 ((uint8_t)0x03)
#define ADC_SampleTime_41Cycles5 ((uint8_t)0x04)
#define ADC_SampleTime_55Cycles5 ((uint8_t)0x05)
#define ADC_SampleTime_71Cycles5 ((uint8_t)0x06)
#define ADC_SampleTime_239Cycles5 ((uint8_t)0x07)信号为50hz交流信号,
8M/6分频=1.333M,
采用55.5采集周期,采样频率约等于24.024K,那么一个周期采样点=24.024K/50=480个点
*/unsigned short AverageU16(unsigned short *Buf, unsigned short Len){unsigned long temp;int i;for(i=0,temp=0; i<Len; i++){temp = temp + Buf[i];}return(temp/Len);
}
unsigned short MaxU16(unsigned short *Buf, unsigned short Len){unsigned long temp;int i;for(i=0,temp=0; i<Len; i++){if(temp < Buf[i]) temp = Buf[i];}return(temp);
}
void InitDma(void)
{ DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;DMA_InitStructure.DMA_MemoryBaseAddr = (unsigned long)&AdcDat;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_BufferSize = ADC_DAT_LEN;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_Cmd(DMA1_Channel1,ENABLE);ADC_DMACmd(ADC1, ENABLE);}
void DMA1_Channel1_IRQHandler(void){if(DMA_GetITStatus(DMA1_IT_TC1) != RESET) {DMA_ClearITPendingBit(DMA1_IT_TC1);StopAdc();}
}
void InitialAdc(void){ADC_InitTypeDef ADC_InitStructure;GPIO_InitTypeDef GPIO_InitStructure; InitDma(); //NVIC_InitTypeDef NVIC_InitStructure;/*设置ADC分频因子为4 ,ADC最大时间不能超过14M*/RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4); /* ADC1 Periph clock enable */RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);/* ADC1 DeInit */ ADC_DeInit(ADC1);/*初始化ADC结构体,此句必须加,不加的话多路ADC数据会交换*/ADC_StructInit(&ADC_InitStructure); /*配置ADC分辨率为12位*/ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;/*开启连续转换*/ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /*禁止触发检测,使用软件触发*/ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;/*ADC采集数据右对齐*/ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;/*向上扫描*/ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;/*ADC初始化*/ADC_Init(ADC1, &ADC_InitStructure); //配置IORCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3| GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOA,&GPIO_InitStructure); ADC_ChannelConfig(ADC1, ADC_Channel_0 | ADC_Channel_1| ADC_Channel_2| ADC_Channel_3| ADC_Channel_4| ADC_Channel_5| ADC_Channel_6| ADC_Channel_7| ADC_Channel_16, ADC_SampleTime_55_5Cycles); /* ADC 校准 */ADC_GetCalibrationFactor(ADC1);ADC_VrefintCmd(ENABLE);ADC_TempSensorCmd(ENABLE);//ADC_TempSensorVrefintCmd(); //开启内部温度传感器/* 循环模式下的 ADC DMA 请求 */ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);/* 使能 ADC_DMA */ADC_DMACmd(ADC1, ENABLE); /* 使能 ADC1 */ADC_Cmd(ADC1, ENABLE); /* 等待 ADCEN 标志 */while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));/* ADC1 常规软件启动转换 */ ADC_StartOfConversion(ADC1);}void StartAdc(void)
{ADC_StartOfConversion(ADC1);DMA_Cmd(DMA1_Channel1, ENABLE);
}void StopAdc(void)
{ADC_StopOfConversion(ADC1);DMA_Cmd(DMA1_Channel1, DISABLE);
}#if defined(SCU_ARM)
const unsigned char ADC_CHANNEL_MAP[8] = {0,1,2,3,4,5,6,7};
#elif defined(SCU_X86)
const unsigned char ADC_CHANNEL_MAP[8] = {0,1,2,3,4,5,6,7};
#endiffloat Chip_Temp;void ProcReadAdc(void){volatile int i,j;long v=0,v1=0;#if 0 //M0取消 Vint的处理方式//计算VREFINT,并校准, 得到的值用于模拟量校准for(j=0,v1=0; j<Sample_Num; j++){v1 = v1 + AdcDat[j][Channel_Num-1];}v = v1 / Sample_Num;InsertDataToU16Buf(v,VrefTempBuf, VREF_TEMP_BUF_LEN);s.u16_AdcVref_Now = AverageU16(VrefTempBuf, VREF_TEMP_BUF_LEN);///#endiffor(i=0; i<AI_NUM; i++){for(j=0,v=0; j<Sample_Num; j++){v = v + AdcDat[j][i];}v = v / Sample_Num;UpdataAdcVal(ADC_CHANNEL_MAP[i], v);//s.fCali_Vref[i] = (float)s.u16_AdcVref_Now/s.u16_ADC_Vref[i];//s.fCali_Vref[i] = 1.0;/}for(j=0,v=0; j<Sample_Num; j++){v = v + AdcDat[j][8];}v = v / Sample_Num;Chip_Temp = (float)(v) * ((float)3.3/4096);Chip_Temp = (1.43 -Chip_Temp)/0.0043 +25.0;StartAdc();
}
void ADC_IRQHandler(void){/* Clear ADC1 EOC pending interrupt bit */ADC_ClearITPendingBit(ADC1, ADC_IT_EOSMP);
}