STM32采集4-20mA传感器及解决ADC DMA问题

STM32只能采集0-3.3V的数据,如果需要采集0-5V和4-20mA的数据需要在电路中进行相关设计:

0-5V采集电路

4-20mA采集电路

本文主要讲述4-20mA采集电路采集

电路输入4-20mA,作用在120欧姆电路(后面面是电压跟随电路,并联),对应输入电压0.48~2.4V

STM32103ZET6为例,内部ADC采集12bit,0-3.3V对应采集到12bit的0-4095数值,则采集的电流对应大约为0.48/3.3*4059~2.4/3.3*4095–>595~2978数值

假如我们是采集的0-6Mpa的压力,那么简单的换算为:

(采集的数值-595)*6000000/(2978-595)=采集的压力(pa)

代码如下:代码需要将GPIO和ADC和DMA根据自己的电路接口简单配置即可

ADC.c代码,两个函数分别是ADC+DMA初始化代码和ADC采集一次代码
#include "stm32f10x.h"                  // Device header
#include "Serial1.h"
extern uint16_t AD_Value[4];//压力变送器Kpa4095*6000//温度℃4095*200
extern uint16_t AD_ValueTrasition[4][20];
void AD_Init(void){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);//ADCCLK=APB2/8=14MHz
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

	GPIO_InitTypeDef GPIO_InitStructureADC;
	GPIO_InitStructureADC.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitStructureADC.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_3|GPIO_Pin_4;
	GPIO_InitStructureADC.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStructureADC);

	ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_13Cycles5);//采集总转换时间=采样时间+12.5ADC周期=13.5+12.5=26个周期
	ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_13Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_13,3,ADC_SampleTime_13Cycles5);//一个ADC周期14MHz=1/14 us每周期=26/14 us≈1.9us
	ADC_RegularChannelConfig(ADC1,ADC_Channel_14,4,ADC_SampleTime_13Cycles5);//1.9*4=7.6us
	
	
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//连续转换开启/单次转换;
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//数据右对齐
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//是否使用硬件触发;目前该程序使用软件触发
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//独立模式,ADC1单独使用,不和ADC2等一起使用
	ADC_InitStructure.ADC_NbrOfChannel=4;//非扫描模式下该参数无效,用于重装载扫描序列数
	ADC_InitStructure.ADC_ScanConvMode=ENABLE;//扫描模式(多通道)/非扫描模式(单通道),指扫描序列
	ADC_Init(ADC1,&ADC_InitStructure);
	
//如果需要配置看门狗,有几个参数需要配置阈值和监测通道。
//如果需要配置中断,则需要在中断输出控制中用ITConfig函数开启对应的中断输出,然后配置NVIC的优先级
	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_BufferSize=4;//缓冲区大小,传输计数器次数,0-65535,2个ADC通道所以传输2次
	DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//传输方向;外设站点作为源
	DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//是否使用软件触发(软件触发和计数器自动重装循环模式不能同时使用,会不能停止)
	
	DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)AD_Value;//存储器站点的起始地址,stm32中地址都是32bit,AD_Value是我们存储转移的地址 
	DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//存储器站点的数据宽度
	DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器站点是否自增,数组地址会自增
	
	DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)&ADC1->DR;//外设站点的起始地址,一般使用SARM的话是系统分配,使用变量名获取地址
	DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//外设站点的数据宽度,Byte-8bit-uint8_t、HalfWord-16bit-uint16_t、Word-32bit-uint32_t;(ADC外设是12bit数据,具体的DMA数据转移对齐,可以看DMA数据宽度对齐方式大小端表格)
	DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设站点是否自增,ADC开启DMA后数据直接转移到DMA,所以不自增
	
	DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//传输模式,是否使用自动重装,自动重装和软件触发不能同时使用(不可控),Normal正常模式,Circular循环模式
	
	DMA_InitStructure.DMA_Priority=DMA_Priority_High;//优先级
	DMA_Init(DMA1_Channel1,&DMA_InitStructure);//DMA1,使用软件触发时通道可以任意选择,硬件要根据手册中实际电路选择;目前使用ADC1-13、14触发DMA
//开启,如果使用的硬件触发,要在对应外设调用XXX_DMACmd(),开启触发信号输出,如果使用DMA中断,则使用DMA_ITConfit(),然后在NVIC配置响应的中断通道,然后写中断函数
	DMA_Cmd(DMA1_Channel1,ENABLE);
//开启ADC到DMA触发输出
	ADC_DMACmd(ADC1,ENABLE);
//开启ADC。可以软件触发也可以硬件触发。
	ADC_Cmd(ADC1,ENABLE);
//进行ADC校准
	ADC_ResetCalibration(ADC1);//ADC1复位校准
	while(ADC_GetResetCalibrationStatus(ADC1)){//获取复位校准状态;等待复位校准完成
		;
	}
	ADC_StartCalibration(ADC1);//开始校准
	while(ADC_GetCalibrationStatus(ADC1)){//获取开始校准状态;等待校准完成
		;
	}
}

void AD_Once(void){
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//软件开始ADC转换
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC==RESET)){;}
	ADC_SoftwareStartConvCmd(ADC1,DISABLE);//软件停止ADC转换
}
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "ADC.h"
#include "MySPI1.h"
#include "Serial1.h"
//需要将该文件中的USE_STDPERIPH_DRIVER定义在define的设置里  这样才能使用外设库
//若是导入了头文件需要设置头文件包含路径
extern uint16_t MAX31855KASA_In_Temp,MAX31855KASA_Out_Temp;
extern uint16_t AD_Value[4];
extern uint16_t AD_ValueTrasition[4][20];
uint8_t SendData[30];
int main(void){
	Serial_Init();
	MySPI_Init();
	AD_Init();
	while(1){

		Delay_ms(1);
		AD_Transition();
		Serial_printf("%s","压力Kp为:");
		Serial_printf("%d",AD_Value[2]);
		Serial_printf("%s","\r\n");
		Serial_printf("%s","温度为:");
		Serial_printf("%d",AD_Value[3]);
		Serial_printf("%s","\r\n");
		Delay_ms(500);
	}
}

作者:aloneboyooo

物联沃分享整理
物联沃-IOTWORD物联网 » STM32采集4-20mA传感器及解决ADC DMA问题

发表评论