当前位置:   article > 正文

基于STM32的PT100测温系统仿真_stm32 pt100

stm32 pt100

准备

Proteus

Keil

Proteus原理图绘制

芯片:STM32F103R6

LCD:LM016L

运算放大器:LM358

PT100

运放电路
运放电路
系统电路
芯片设置
Keil设置

  芯片设置这里,选择你在keil里面编译的程序,注意在Keil里要勾选一下Create HEX File,频率那里要写50k,不然仿真的时候时间跳的很慢。

Keil程序编写

LCD部分的函数借鉴自LCD1602单片机(STC51/STM32)驱动程序详解,具体信息可移步至此观看。

LCD1602.h

  1. #ifndef __LCD1602_H
  2. #define __LCD1602_H
  3. /***************************根据自己的硬件引脚做修改*****************************/
  4. #define LCD_RS_Set() GPIO_SetBits( GPIOB, GPIO_Pin_12 )//1602的数据/指令选择控制线
  5. #define LCD_RS_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_12 )
  6. #define LCD_RW_Set() GPIO_SetBits( GPIOB, GPIO_Pin_13 )//1602的读写控制线
  7. #define LCD_RW_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_13 )
  8. #define LCD_EN_Set() GPIO_SetBits( GPIOB, GPIO_Pin_14 )//1602的使能控制线
  9. #define LCD_EN_Clr() GPIO_ResetBits( GPIOB, GPIO_Pin_14 )
  10. #define DATAOUT( x ) GPIO_Write( GPIOA, x ) //16028条数据控制线
  11. void GPIO_Configuration(void);
  12. void LCD1602_Init(void);
  13. void LCD1602_Wait_Ready(void);
  14. void LCD1602_Write_Cmd( u8 cmd );
  15. void LCD1602_Write_Dat( u8 data );
  16. void LCD1602_ClearScreen(void);
  17. void LCD1602_Set_Cursor( u8 x, u8 y );
  18. void LCD1602_Show_Str( u8 x, u8 y, u8 *str );
  19. #endif

LCD1602.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "LCD1602.h"
  4. /******************************************************************************
  5. * 函数名称:void GPIO_Configuration() *
  6. * 函数功能:LCD1602引脚初始化 *
  7. * 输入参数:无 *
  8. * 返回值 :无 *
  9. * 其他说明: *
  10. ******************************************************************************/
  11. /*******************根据自己的硬件引脚做修改*****************************************/
  12. void GPIO_Configuration(void)
  13. {
  14. GPIO_InitTypeDef GPIO_InitStructure;
  15. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE );
  16. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
  17. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//选择工作频率
  18. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置工作模式
  19. GPIO_Init( GPIOB, &GPIO_InitStructure );
  20. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |
  21. GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  22. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置工作模式
  23. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//选择工作频率
  24. GPIO_Init( GPIOA, &GPIO_InitStructure );
  25. }
  26. /******************************************************************************
  27. * 函数名称:void LCD1602_Init() *
  28. * 函数功能:LCD1602初始化 *
  29. * 输入参数:无 *
  30. * 返回值 :无 *
  31. * 其他说明: *
  32. ******************************************************************************/
  33. void LCD1602_Init(void)
  34. {
  35. GPIO_Configuration(); //初始化引脚
  36. LCD1602_Write_Cmd( 0x38 ); //显示模式设置
  37. Delay_ms( 5 );
  38. LCD1602_Write_Cmd( 0x0c ); //显示开及光标设置
  39. Delay_ms( 5 );
  40. LCD1602_Write_Cmd( 0x06 ); //显示光标移动位置
  41. Delay_ms( 5 );
  42. LCD1602_Write_Cmd( 0x01 ); //显示清屏
  43. Delay_ms( 5 );
  44. }
  45. /******************************************************************************
  46. * 函数名称:void LCD1602_Write_Cmd(u8 cmd) *
  47. * 函数功能:写命令函数 *
  48. * 输入参数: cmd 命令 *
  49. * 返回值 :无 *
  50. * 其他说明: *
  51. ******************************************************************************/
  52. void LCD1602_Write_Cmd( u8 cmd )
  53. {
  54. LCD_RS_Clr();
  55. LCD_RW_Clr();
  56. LCD_EN_Set();
  57. GPIO_Write( GPIOA, (GPIO_ReadOutputData( GPIOA ) & 0xff00) | cmd );//对电平的读取
  58. DATAOUT( cmd );
  59. Delay_ms( 5 );
  60. LCD_EN_Clr();
  61. }
  62. /******************************************************************************
  63. * 函数名称:void LCD1602_Write_Dat(u8 date) *
  64. * 函数功能:写数据函数 *
  65. * 输入参数: date 数据 *
  66. * 返回值 :无 *
  67. * 其他说明: *
  68. ******************************************************************************/
  69. void LCD1602_Write_Dat( u8 data )
  70. {
  71. LCD_RS_Set();
  72. LCD_RW_Clr();
  73. LCD_EN_Set();
  74. GPIO_Write( GPIOA, (GPIO_ReadOutputData( GPIOA ) & 0xff00) | data );//对电平的读取
  75. Delay_ms( 5 );
  76. LCD_EN_Clr();
  77. }
  78. /******************************************************************************
  79. * 函数名称:void LCD1602_ClearScreen() *
  80. * 函数功能:1602清屏函数 *
  81. * 输入参数:无 *
  82. * 返回值 :无 *
  83. * 其他说明: *
  84. ******************************************************************************/
  85. void LCD1602_ClearScreen(void)
  86. {
  87. LCD1602_Write_Cmd( 0x01 );
  88. }
  89. /******************************************************************************
  90. * 函数名称:void LCD1602_Set_Cursor(u8 x, u8 y) *
  91. * 函数功能:设置1602位置函数 *
  92. * 输入参数:x 横坐标 y 纵坐标 *
  93. * 返回值 :无 *
  94. * 其他说明: *
  95. ******************************************************************************/
  96. void LCD1602_Set_Cursor( u8 x, u8 y )
  97. {
  98. u8 addr;
  99. if ( y == 0 )
  100. addr = 0x00 + x;
  101. else
  102. addr = 0x40 + x;
  103. LCD1602_Write_Cmd( addr | 0x80 );
  104. }
  105. /******************************************************************************
  106. * 函数名称:void LCD1602_Show_Str( u8 x, u8 y, u8 *str ) *
  107. * 函数功能:指定位置显示字符串函数 *
  108. * 输入参数:x 横坐标 y 纵坐标 *str 字符串 *
  109. * 返回值 : 无 *
  110. * 其他说明: *
  111. ******************************************************************************/
  112. void LCD1602_Show_Str( u8 x, u8 y, u8 *str )
  113. {
  114. LCD1602_Set_Cursor( x, y );
  115. while ( *str != '\0' )
  116. {
  117. LCD1602_Write_Dat( *str++ );
  118. }
  119. }

AD处理模块搬运江科大自化协的教程,但是这里把校准函数屏蔽了,校准的第一个指令不返回RESET,一直没找到原因,屏蔽了好像也没什么影响

AD.h

  1. #ifndef __AD_H
  2. #define __AD_H
  3. void AD_Init(void);
  4. uint16_t AD_GetValue(void);
  5. #endif

AD.c

  1. #include "stm32f10x.h" // Device header
  2. void AD_Init(void)
  3. {
  4. RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  6. RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72MHz/6
  7. GPIO_InitTypeDef GPIO_InitStructure;
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  9. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
  11. GPIO_Init(GPIOB,&GPIO_InitStructure);
  12. ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_55Cycles5);
  13. ADC_InitTypeDef ADC_InitStructure;
  14. ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  15. ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  16. ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  17. ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  18. ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  19. ADC_InitStructure.ADC_NbrOfChannel = 1;
  20. ADC_Init(ADC1,&ADC_InitStructure);
  21. ADC_Cmd(ADC1,ENABLE);
  22. //ADC_ResetCalibration(ADC2);
  23. //while (ADC_GetResetCalibrationStatus(ADC2));
  24. //ADC_StartCalibration(ADC2);
  25. //while (ADC_GetCalibrationStatus(ADC2));
  26. }
  27. uint16_t AD_GetValue(void)
  28. {
  29. ADC_SoftwareStartConvCmd(ADC1,ENABLE);
  30. while (ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET);
  31. return ADC_GetConversionValue(ADC1);
  32. }

因为PT100电阻随温度并非线性变化,这里采用插值法计算温度,本芯片ADC转换精度12位,即ADC输入端口0-5V电压转换为0-4095(2^12),程序中给出温度与0-4095的对应关系,本例只模拟0-100℃。

Interpolation.h

  1. #ifndef INTERPOLATION__H
  2. #define INTERPOLATION__H
  3. float calculateTemperature(float measuredVoltage);
  4. #endif

Interpolation.c

  1. // 定义温度-电压查表
  2. const float temperatureTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  3. 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
  4. //const float voltageTable[] = {0.0656, 0.0686, 0.0717, 0.0751, 0.0788, 0.0828, 0.0871, 0.0918,
  5. // 0.0968, 0.1022, 0.1079, 0.1792, 0.2574, 0.3356, 0.4132, 0.4903,
  6. // 0.5668, 0.6427, 0.7181, 0.793};
  7. const float voltageTable[] = {54, 56, 59, 62, 65, 68, 71, 75, 79, 84, 88, 147, 211, 275, 338, 402, 464, 526, 588, 650};
  8. float calculateTemperature(float measuredVoltage)
  9. {
  10. int i;
  11. for (i = 0; i < sizeof(voltageTable)/sizeof(float); i++) {
  12. if (measuredVoltage <= voltageTable[i]) {
  13. break;
  14. }
  15. }
  16. if (i == 0) {
  17. return temperatureTable[0];
  18. } else if (i == sizeof(temperatureTable)/sizeof(float)) {
  19. return temperatureTable[sizeof(temperatureTable)/sizeof(float) - 1];
  20. } else {
  21. float voltage1 = voltageTable[i-1];
  22. float voltage2 = voltageTable[i];
  23. float temperature1 = temperatureTable[i-1];
  24. float temperature2 = temperatureTable[i];
  25. return temperature1 + (temperature2 - temperature1) * (measuredVoltage - voltage1) / (voltage2 - voltage1);
  26. }
  27. }

main.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "LCD1602.h"
  4. #include "AD.h"
  5. #include "stdio.h"
  6. #include "Interpolation.h"
  7. u8 str[] = "Temp test!";
  8. int main(void)
  9. {
  10. char buf[16];
  11. uint16_t ADValue = 0;
  12. //float voltage = 0;
  13. float Temp;
  14. LCD1602_Init();
  15. AD_Init();
  16. while(1)
  17. {
  18. LCD1602_Show_Str(0,0,str); //(列,行)
  19. ADValue = AD_GetValue();
  20. Temp = (int16_t) calculateTemperature((float)ADValue);
  21. //voltage = (float) ADValue* (5.0/4096);
  22. //Temp = (350.0 /(2049.0 - 54.0)) *(float) ADValue - 9.47;
  23. sprintf((char *)buf,(const char *)"Temp:%5.1f%cC",Temp,0xdf);
  24. //sprintf(buf,"ADValue: %u",ADValue);
  25. LCD1602_Show_Str(0,1,(u8 *)buf);
  26. }
  27. }

结语

本文是我在学习STM32阶段写的一个小Demo,,可能存在很多不完善的地方,欢迎各位交流指正!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/929045
推荐阅读
相关标签
  

闽ICP备14008679号