利用STM32F103RB进行AD采样,并且利用了DMA控制器,并且进行了软件滤波

void ADC1_init(void)
{
#if auto_samp==1
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;


TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1|RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
RCC_ADCCLKConfig(RCC_PCLK2_Div6);


//初始化 PA0口为模拟输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//初始化ADC
ADC_DeInit(ADC1);
     
 
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 2; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器


#else 
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
DMA_InitTypeDef DMA_InitStructure;

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1|RCC_APB2Periph_AFIO,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);


//初始化 PA0口为模拟输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//初始化ADC
ADC_DeInit(ADC1);
 
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //模数转换工作在扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 2; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_RegularChannelConfig(ADC1, ADC_Channel_0,1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_16,2, ADC_SampleTime_7Cycles5);


//DMA 初始化  在使用多通道采样时必须要使用DMA控制器
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 = 2; //缓存数据的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址寄存器地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;   //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;   //数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                     //工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道x拥有非常高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;     //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);


#endif
ADC_TempSensorVrefintCmd(ENABLE); //温度传感器使能
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 
ADC_ResetCalibration(ADC1); //重置指定的ADC1的校准寄存器
    while(ADC_GetResetCalibrationStatus(ADC1)); //获取ADC1重置校准寄存器的状态,设置状态则等待
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1)); //获取指定ADC1的校准程序,设置状态则等待




TIM_TimeBaseStructure.TIM_Period = 300; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到10为10Us
TIM_TimeBaseStructure.TIM_Prescaler =(72-1); //设置用来作为TIMx时钟频率除数的预分频值  1Mhz的计数频率  
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
TIM_ITConfig(  //使能或者失能指定的TIM中断
TIM2, //TIM2
TIM_IT_Update  |  //TIM 中断源
TIM_IT_Trigger,   //TIM 触发中断源 
ENABLE  //使能
);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器


TIM_Cmd(TIM2, ENABLE);  //使能TIMx外设   


}


u16 Td_Get_Adc(void)   
{
 
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道3,规则采样顺序值为1,采样时间为239.5周期      
 
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
void TIM2_IRQHandler(void)
{


vu16 samp_temp;
// vu16 temp[2];
u8 i;
u16 aa;
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
{

#if auto_samp==1 
//采集32个点函数   average_value()函数为对采集到的32个点排序然后求出温度和电压的大小
switch(samp_point_flag)
{
case 0:
ADC_RegularChannelConfig(ADC1, ADC_Channel_0,1, ADC_SampleTime_7Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )==0);
samp_temp=ADC_GetConversionValue(ADC1);
DC_samp[samp_point]=samp_temp;
IWDG_Feed();
break;
case 1:
ADC_RegularChannelConfig(ADC1, ADC_Channel_16,1, ADC_SampleTime_7Cycles5);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )==0);
samp_temp=ADC_GetConversionValue(ADC1);
TEM_samp[samp_point]=samp_temp;
IWDG_Feed();
break;
default: break;
}
AD_samp_point++;
samp_point= AD_samp_point&0x1f;
samp_point_flag=(AD_samp_point>>5)%2;
#else
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// while( DMA_GetFlagStatus(DMA1_FLAG_TC1)!=SET);
if(DMA_GetFlagStatus(DMA1_FLAG_TC1)==SET)
{
DMA_ClearFlag(DMA1_FLAG_TC1);
for(i=0;i<2;i++)
{
// num=DMA_GetCurrDataCounter(DMA1_Channel1);
aa= ADC_ConvertedValue[i] ;
temp[i]=aa;
delay_us(1);

}

}



// num=DMA_GetCurrDataCounter(DMA1_Channel1);
DC_sampone= temp[0];
TEM_sampone= temp[1];

#endif


// 每次进入中断自动扫描通道0和16
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
DMA_Cmd(DMA1_Channel1, DISABLE );
// ADC_Cmd(ADC1, DISABLE); //使能指定的ADC1
TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
// LED1=!LED1;
}
}    
void average_value(void) //把采样得到的电压信号和温度信号按照冒泡法从小到大排序
{
#if auto_samp==1
u8 i,j;
u16 temp;
// u32 sum;
u32 dsum;
u32 tsum;
u32 dc_average;
u32 tem_average;




temp=0;
for(i=0;i<31;i++)
{
for(j=i+1;j<32;j++)
{
if(DC_samp[i]>DC_samp[j])
{
temp=DC_samp[i];
DC_samp[i]=DC_samp[j];
DC_samp[j]=temp;
}
}
}
dsum=0;
for(i=1;i<31;i++)
{
dsum+= DC_samp[i];
}
dc_average= (dsum/30);
temp=0;
tsum=0;
    for(i=0;i<31;i++)
{
for(j=i+1;j<32;j++)
{
if(TEM_samp[i]>TEM_samp[j])
{
temp=TEM_samp[i];
TEM_samp[i]=TEM_samp[j];
TEM_samp[j]=temp;
}
}
}

for(i=1;i<31;i++)
{
tsum+= TEM_samp[i];
}
tem_average=(u16)tsum/30;


DC_volta= (float)dc_average*3.3/4096;
temperature=(float)tem_average*3.3/4096;
temperature=(float)((1.35- temperature)*1000/4.5)+25;
#else
DC_volta= (float)DC_sampone*3.3/4096;
temperature=(float)TEM_sampone*3.3/4096;
temperature=(float)((1.35- temperature)*1000/4.5)+25;
#endif
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值