STM32F030通过DMA方式读取ADC及芯片内部温度程序
说明:采用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);
//配置IO
RCC_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};
#endif
float 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);
///
#endif
for(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);
}