基于STM32的PT100温度测量Word文档格式.docx
《基于STM32的PT100温度测量Word文档格式.docx》由会员分享,可在线阅读,更多相关《基于STM32的PT100温度测量Word文档格式.docx(19页珍藏版)》请在冰豆网上搜索。
常用的PT电阻接法有三线制和两线制,其中三线制接法的优点是将PT100的两侧相等的的导线长度分别加在两侧的桥臂上,使得导线电阻得以消除。
常用的采样电路有两种:
一为桥式测温电路,一为恒流源式测温电路。
本设计采用的是三线制桥式测温电路,电路如图所示
测温原理:
电路采用TL31和电位器VR1调节产生4.096V的参考电源;
采用R1、R2、VR2、RPT构成测量电桥(其中R1=R2,VR2为100Ω精密电阻),当RPT的电阻值和VR2的电阻值不相等时,电桥输出一个mV级的压差信号,这个压差信号经过运放LM3放大后输出期望大小的电压信号,该信号可直接连AD转换芯片。
差动放大电路中R3=R4、R5=R6、放大倍数=R5/R3,运放采用单一5V供电。
设计及调试注意点:
1.同幅度调整R1和R2的电阻值可以改变电桥输出的压差大小;
2.改变R5/R3的比值即可改变电压信号的放大倍数,以便满足设计者对温度范围的要求
4.VR2为电位器,调节电位器阻值大小可以改变温度的零点设定,测量电位器的阻值时须在没有接入电路时调节,这是因为接入电路后测量的电阻值发生了改变。
5.理论上,运放输出的电压为输入压差信号×
放大倍数,但实际在电路工作时测量输出电压与输入压差信号并非这样的关系,压差信号比理论值小很多,实际
输出信号为
VO=4.096*(RPT/(R1+RPT)-VR2/(R1+VR2))
式中电阻值以电路工作时量取的为准。
4.096为基于源电压。
6.电桥的正电源必须接稳定的参考基准,因为如果直接VCC的话,当网压波动造成VCC发生波动时,运放输出的信号也会发生改变,此时再到以VCC未发生波动时建立的温度-电阻表中去查表求值时就不正确了,这可以根据式进行计算得知。
3.31602LCD液晶屏
1602字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD。
引脚功能说明
1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如下表所示:
编号
符号
引脚说明
1
VSS
电源地
9
D2
数据
2
VDD
电源正极
10
D3
3
V0
对比调整电压
11
D4
4
RS
数据/命令选择
12
D5
5
R/W
读/写选择
13
D6
6
E
使能信号
14
D7
7
D0
15
BLA
背光源正极
8
D1
16
BLK
背光源负极
1602与STM32连接说明:
VSS接STM32上电源模块的地,VDD接5V正电源,V0接合适的对比电压
RS连接STM32F0板的PC0,R/W连接STM32F0板的PC2,E连接STM32F0板的PC3
D0~D7连接STM32F0板的PB0-PB7,BLA接5V正电源,BLK接地。
四、软件设计
4.1ADC程序
STM32F103RBT6内部有3个ADC,实际上我们只需要软件设置就可以正常工作,不过我们需要在外部连接其端口到被测电压上面。
本系统通过ADC1的通道0(PA0)来读取外部电压值。
测量电压不能超过3.3V。
程序步骤
1)启开启PA口和ADC1时钟,设置PA0为模拟输入。
2)复位ADC1,同时设置ADC1分频因子。
开启ADC1时钟之后,我们要复位ADC1,将ADC1的全部寄存器重设为缺省值之后我们就可以通过RCC_CFGR设置ADC1的分频因子。
分频因子要确保ADC1的时钟(ADCCLK)不要超过14Mhz。
这个我们设置分频因子位6,时钟为72/6=12MHz。
3)初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息。
设置单次转换模式、触发方式选择、数据对齐方式等都在这一步实现。
同时,我们还要设置ADC1规则序列的相关信息,我们这里只有一个通道,并且是单次转换的,所以设置规则序列中通道数为1。
5)使能ADC并校准。
在设置完了以上信息后,我们就使能AD转换器,执行复位校准和AD校准,注意这两步是必须的!
不校准将导致结果很不准确。
每次进行校准之后要等待校准结束。
这里是通过获取校准状态来判断是否校准是否结束。
6)读取ADC
在上面的校准完成之后,ADC就算准备好了。
接下来我们要做的就是设置规则序列1里面的通道,采样顺序,以及通道的采样周期,然后启动ADC转换。
在转换结束后,读取ADC转换结果值就是了。
7)多次读取ADC值,求平均
求平均使获得的ADC值稳定。
4.21602LCD显示程序
必要的声明定义等;
写入指令数据到LCD;
写入字符显示数据到LCD;
写字符串函数;
写数字函数;
GPIO配置;
LCD初始化设定;
4.3主程序
各子函数初始化
(SystemInit();
delay_init(72);
NVIC_Configuration();
uart_init(9600);
LED_Init();
LCD_Init();
Adc_Init();
)
while循环(获取ADC值,转换成电压值,写字符串,写数据值,LED闪烁)。
五、性能测试
硬件调试比较简单,主要是调试PT100温度传感器电路,首先检查电路的焊接是否正确,然后用万用表测试,首先检测PT100传感器的电阻值是否随温度变化,并测量其在0°
C和100°
C的电阻值;
然后在测量基准电压,将其调试到合适值(4.960V);
然后测量电桥输出的最大电压差Umax,并确定运算放大器的放大倍数(放大器的输出电压不能大于3.3V,倍数A=R5/R3=3.3/Umax,调试过程中可改变R5电阻值);
最后测量运算放大器实际的输出电压,与电桥输出电压,计算实际放大倍数与理论放大倍数比较;
调试完后可连接STM32进行软件编写。
软件调试可以先编写1602显示程序并进行硬件的正确性检验,然后分别进行ADC程序和主程序的编写和调试。
最后进行整体系统测试
六、课程设计心得
经过将近一段时间的设计、焊接、编程、调试,我们终于完成了温度测量的设计,基本能够达到设计要求,
此次的设计使我从中学到了一些很重要的东西,那就是如何从理论到实践的转化,怎样将我们所学到的知识运用到实践中去。
在大学课堂的学习只是给我们灌输专业知识,而我们应把所学的知识应用到我们现实的生活中去。
这次的设计不仅使我们将课堂上学到的理论知识与实际应用结合了起来,而且使我们对电子电路、电子元器件等方面的知识有了更进一步的认识,同时在软件编程、焊板调试、相关调试仪器的使用等方面得到较全面的锻炼和提高,为今后能够独立进行某些单片机应用系统的开发设计工作打下一定的基础。
此次单片机设计也为我们以后进行更复杂的单片机系统设计提供了宝贵的经验。
通过此次的综合设计,我们初步掌握了单片机系统设计的基本原理。
充分认识到理论学习与实践相结合的重要性,对于书本上的很多知识,不但要学会,更重要的是会运用到实践中去。
在以后的学习中,我们会更加注重实践方面的锻炼,多提高自己的动手实践能力。
参考文献
1、STM32F103RBT6数据开发手册;
2、ALIENTEKminiSTM32开发板资料
3、1602中文资料
4、戴蓉,刘波峰。
传感器原理与工程应用,电子工业出版社.2013.1
附录1:
系统实物图
附录2:
系统主要程序
一、ADC程序,文件名(adc.c)
#include"
adc.h"
delay.h"
voidAdc_Init(void)
{
ADC_InitTypeDefADC_InitStructure;
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1,ENABLE);
//使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
//72M/6=12,ADC最大时间不能超过14M
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
//PA0
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
//模拟输入引脚
GPIO_Init(GPIOA,&
GPIO_InitStructure);
ADC_DeInit(ADC1);
//将外设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=1;
//顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1,&
ADC_InitStructure);
//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1,ENABLE);
//使能指定的ADC1
ADC_ResetCalibration(ADC1);
//重置指定的ADC1的校准寄存器
while(ADC_GetResetCalibrationStatus(ADC1));
//获取ADC1重置校准寄存器的状态,设置状态则等待
ADC_StartCalibration(ADC1);
//开始指定ADC1的校准状态
while(ADC_GetCalibrationStatus(ADC1));
//获取指定ADC1的校准程序,设置状态则等待
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
//使能指定的ADC1的软件转换启动功能
}
//获得ADC值
//ch:
通道值0-3
u16Get_Adc(u8ch)
{
//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5);
//ADC1,,规则采样顺序值为1,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
//使能ADC的软件转换启动功能
while(!
ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
//等待转换结束
returnADC_GetConversionValue(ADC1);
//返回最近一次ADC1规则组的转换结果
}
//获取通道ch的转换值,取times次,然后平均
通道编号
//times:
获取次数
//返回值:
通道ch的times次转换结果平均值
u16Get_Adc_Average(u8ch,u8times)
u32temp_val=0;
u8t;
for(t=0;
t<
times;
t++)
{temp_val+=Get_Adc(ch);
delay_ms(5);
}
returntemp_val/times;
二、LCD程序,文件名(lcd.c)
lcd.h"
stdlib.h"
unsignedchardigit[]={"
0123456789"
};
voidLCD_Writecmd(ucharcmd)
{
LCD_RS=0;
delay_us
(1);
LCD_RW=0;
DATAOUT(cmd);
delay_us(300);
LCD_EN=1;
//必要的延时
LCD_EN=0;
//下降沿,LCD1602开始工作
voidLCD_Writedata(uchardat)
LCD_RS=1;
delay_us
(1);
DATAOUT(dat);
delay_us(300);
//很重要的延时,经调试,延时300us以上才可以
//下降沿,开始写入有效数据
voidLCD_DispString(charstr[])
uchari=0;
for(i=0;
str[i]!
='
\0'
;
i++)
LCD_Writedata(str[i]);
voidLCD_Dispnum(uint32_tnum)
{u16R1=5000;
u16R2=5000;
u16R3=300;
u16Vin=40960;
floatx,y,z,rx;
floatt,VB;
u16T,RX,i;
unsignedcharB1,B2,B3,B4,B5;
unsignedcharC1,C2,C3,C4,C5;
unsignedcharD1,D2,D3,D4,D5;
VB=(float)num/30;
x=(float)VB/(float)Vin;
//Rx=(R3*R2+R2*(R1+R3)VB/Vin)/(R1-(R1+R3)*VB/Vin)
y=R3*R2+(float)R2*(R1+R3)*x;
z=R1-(R1+R3)*x;
rx=y/z;
RX=rx*1000/10;
t=1.000/0.77*rx-300.000/0.77;
//(0C,300)(100,377)
T=t*1000/10;
B5=num/10000;
B4=num%10000/1000;
B3=num%1000/100;
B2=num%100/10;
B1=num%10;
C5=RX/10000;
C4=RX%10000/1000;
C3=RX%1000/100;
C2=RX%100/10;
C1=RX%10;
if(C5==0)
{C5=11;
if(C4==0){C4=11;
D5=T/10000;
D4=T%10000/1000;
D3=T%1000/100;
D2=T%100/10;
D1=T%10;
if(D5==0)
{D5=12;
if(D4==0){D4=12;
}
LCD_Writecmd(0x80+0x06);
LCD_Writedata(digit[B5]);
LCD_Writedata('
.'
);
LCD_Writedata(digit[B4]);
LCD_Writedata(digit[B3]);
LCD_Writedata(digit[B2]);
LCD_Writedata(digit[B1]);
LCD_Writecmd(0x80+0x41);
LCD_Writedata(digit[C5]);
LCD_Writedata(digit[C4]);
LCD_Writedata(digit[C3]);
LCD_Writedata(digit[C2]);
LCD_Writedata(digit[C1]);
LCD_Writecmd(0x80+0x48);
LCD_Writedata(digit[D5]);
LCD_Writedata(digit[D4]);
LCD_Writedata(digit[D3]);
LCD_Writedata(digit[D2]);
LCD_Writedata(digit[D1]);
i<
4;
i++)//每1s采集一次数据)
delay_ms(25);
voidGPIO_Configuration(void)
{GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
//JTAG-DP失能+SW-DP使能
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_Out_PP;
//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&
GPIO_Write(GPIOB,0XFFFF);
//PB口OD输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3;
GPIO_Init(GPIOC,&
GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_8|GPIO_Pin_3);
//如果每一位决定一个GPIO_Pin,则可以通过或的形式来初始化多个IO
voidLCD_Init(void)
{GPIO_Configuration();
delay_ms(200);
//延时200ms
LCD_EN=0;
LCD_Writecmd(0x38);
LCD_Writecmd(0x08);
LCD_Writecmd(0x06);
LCD_Writecmd(0x01);
LCD_Writecmd(0x0c);
三、主程序,文件名(main.c)
led.h"
#inclu