3D打印机温度读取
ADC3初始化
主控芯片为stm32f407ZG,对ADC3初始化,精度设定为12位
ADC3代码部分
void init_adc3() /ADC3初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); //使能
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE); //ADC3复位
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE);
/ADC通用寄存器CCR
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;//两个采样阶段延迟5个时钟
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//四分频ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟不能超过36Mhz
ADC_CommonInit(&ADC_CommonInitStructure);
/初始化ADC3参数
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfConversion = 1;//1¸
ADC_Init(ADC3, &ADC_InitStructure);
ADC_Cmd(ADC3, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//不带上下拉
#ifdef TEMP_0_PIN /定义TEMP_0_PIN 或删除
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_Init(GPIOF, &GPIO_InitStructure);
#endif
#ifdef TEMP_1_PIN
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOF, &GPIO_InitStructure);
#endif
#ifdef TEMP_2_PIN
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOF, &GPIO_InitStructure);
#endif
#ifdef TEMP_BED_PIN
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOF, &GPIO_InitStructure);
#endif
}
u16 get_adc(u8 ch)//ch为通道
{
ADC_RegularChannelConfig(ADC3, ch, 1, ADC_SampleTime_480Cycles );
ADC_SoftwareStartConv(ADC3);
while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC ));
return ADC_GetConversionValue(ADC3);
}
u16 get_adc_average(u8 ch,u8 times)ch为通道、Times为连续读取的次数
{
u32 temp_val=0;
u8 t;
get_adc(ch);首次读取ADC存在误差,跳过即可
for(t=0;t<times;t++)
{
temp_val+=get_adc(ch);
//delay_ms(5);省略后对精度影响不大
}
//printf("ch:%d,V:%d\n\r\n\r",ch,temp_val/times);
return temp_val/times;
}
计数转换
首先使用的是NTC 100K热敏电阻
型号:B2-100-3950±1%
于25摄氏度下测量,电阻为100K 误差为1%
于25或50摄氏度测量,温度系数为3950 误差为1%
由公式
即B=(ln(Rt1/Rt2))/(1/T1-1/T2)
而B=3950
令T2=25摄氏度=273.15+25华氏度=298.15K,则Rt2=100K欧
计数过程保留2位有效数字
3950*(1/T1-1/298.15)=lnR1-ln100K
ln100k=11.51
3950/298.15=13.25
化简T=3950/(lnR+1.74)
检验当R=100K欧时,得到温度T=24.963,误差0.037摄氏度
ADC为12位精度
电路图如下图所示
首先令热敏电阻为R1、电压为U1
串联的电阻为R2=4700欧
热敏电阻电压U1=get_adc()3.3/4096
由电流相等得U1/R1=(3.3-U1)/4700
化简得热敏电阻R1=(4700get_adc())/(4096-get_adc())
综上
获取温度代码为
float get_temp(u8 ch)
{
u16 volt;
float R,T;
volt=get_adc_average(ch,5);
R=(4700*volt)/(4096-volt);
T=(3950/(log(R)+1.74))-273.15;
printf("ch:%d,Temp:%f\n\r\n\r",ch,T);
return T;
}