找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5408|回复: 7
收起左侧

单片机NTC温敏电阻的模拟温度传感器 仿真+PCB+源程序

  [复制链接]
ID:324435 发表于 2020-2-28 17:49 | 显示全部楼层 |阅读模式

1、功能:实现温度的测量,温度达到或超过设定温度时,蜂鸣器发出报警声 。2、性能指标:温度范围:-40℃~300℃,分辨率 0.1℃,温度误差≤±2℃,转换时间:100ms
     在上电之后,STC89C52 单片机进行相关的初始化,并启动 ADC,初始化完毕之后,进入 while 循环并不断通过串行口的移位寄存器功能扫描数码管,实时显示所控温度值和当前温度值,当达到所控温度时,蜂鸣器发出报警。
温度测量:当启动 ADC 之后,每间隔 100ms 进行一次测量,ADC 测量完毕之后产生一个下降沿触发,单片机的外部中断口检测到外部中断后立即通过一根时钟线和一根数据线完成 ADC 数据的读取,并计算出温敏电阻的压降和电流,根据欧姆定律再计算出温敏电阻的阻值,再通过该温敏电阻的温度计算公式计算出当前的温度,并更新温度值,更新报警标志。
键盘检测:按键的功能是增减所控温度,键盘检测由或非门和外部中断组成,当按下按键时产生一个下降沿,触发外部中断进入键盘处理函数,根据所按下的
键位来确定温度的增减,与此同时启动定时器,检测按键是否处于长按状态,如果是则每隔一定时间增减一定的温度值。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)

PCB

PCB


单片机程序:
  1. #include <REG52.H>
  2. #include <INTRINS.H>
  3. #include <MATH.H>

  4. typedef unsigned int u16;
  5. typedef unsigned char u8;
  6. typedef char int8;

  7. #define ENABLE 1
  8. #define DISABLE 0

  9. //-------------pin-define---------------

  10. sbit STORE = P2 ^ 0;
  11. sbit OE = P2 ^ 1;
  12. sbit MR = P2 ^ 2;

  13. sbit TRIG_DB = P3 ^ 3;
  14. sbit PD_SCK = P3 ^ 4;
  15. sbit ADC_CTRL = P3 ^ 5;
  16. sbit DAT = P1 ^ 3;

  17. sbit BUZZER = P2 ^ 4;

  18. #define KEYBOARD P1

  19. //-------------------------------------

  20. #define ALARM_INIT_VALUE 25.0f

  21. #define TABLE_SIZE 17
  22. #define SYMBOL_NEGATIVE 16

  23. #define POINT_MASK 0x7F //&

  24. u8 segTable[TABLE_SIZE] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, 0xbf};

  25. u8 dispVal[8];
  26. u8 t0_loopCount;

  27. float alarmVal, currentVal;

  28. //-------------------------

  29. #define Delay10Us()                              \
  30.     _nop_(), _nop_(), _nop_(), _nop_(), _nop_(); \
  31.     _nop_(), _nop_(), _nop_(), _nop_(), _nop_();

  32. #define Delay50Us() \
  33.     Delay10Us();    \
  34.     Delay10Us();    \
  35.     Delay10Us();    \
  36.     Delay10Us();    \
  37.     Delay10Us()

  38. #define UpdateAlarmVal() UpdateValue(alarmVal, 0)
  39. #define UpdateCurrentVal() UpdateValue(currentVal, 4)
  40. #define SetOverflow() \
  41.     dispVal[4] = dispVal[5] = dispVal[6] = dispVal[7] = segTable[SYMBOL_NEGATIVE]

  42. //---------------------

  43. #define BUZZER_CMD(val) BUZZER = (val)

  44. #define SEG_INIT() \
  45.     SCON = 0x00;   \
  46.     OE = 1

  47. #define SEG_UPDATE(ledx, val) \
  48.     OE = 1;                   \
  49.     P0 = (val);               \
  50.     SBUF = 0x80U >> (ledx);   \
  51.     while (TI == 0)           \
  52.         ;                     \
  53.     TI = 0;                   \
  54.     STORE = 0;                \
  55.     STORE = 1;                \
  56.     OE = 0

  57. #define KEYBOARD_INIT() \
  58.     KEYBOARD = 0x00;    \
  59.     IT0 = 1;            \
  60.     EX0 = 1
  61. #define KEY_ADD() alarmVal = alarmVal < 300.0f ? (alarmVal + 0.5f) : alarmVal
  62. #define KEY_DEC() alarmVal = alarmVal > -40.0f ? (alarmVal - 0.5f) : alarmVal

  63. #define ADC_INIT()     \
  64.     currentVal = 0.0f; \
  65.     ADC_CTRL = 1;      \
  66.     TRIG_DB = 1;       \
  67.     DAT = 1;           \
  68.     PD_SCK = 0;        \
  69.     IT1 = 1
  70. #define ADC_IT_CMD(val) EX1 = (val)
  71. #define ADC_START() ADC_CTRL = 0

  72. #define T0_LOOP_MAX 6
  73. #define T0_INIT() \
  74.     TMOD = 0x01;  \
  75.     TH0 = 0x3C;   \
  76.     TL0 = 0xB0;   \
  77.     ET0 = 1;      \
  78.     t0_loopCount = 0

  79. #define T0_CMD(val) TR0 = (val)

  80. //----------------------

  81. void DisplayAll(void);
  82. void UpdateValue(float v, u8 offset) reentrant;
  83. float ADC_Measure(void);
  84. void Delay(u16 x);
  85. void HandleKey(void) reentrant;

  86. //----------------------

  87. void main()
  88. {
  89.     alarmVal = ALARM_INIT_VALUE; //报警值初始化

  90.     BUZZER_CMD(DISABLE); // 关闭蜂鸣器

  91.     SEG_INIT(); // 初始化串口
  92.     T0_INIT();  // 初始化定时器T0, 50ms

  93.     KEYBOARD_INIT();  // 初始化键盘,外部中断0,下降沿触发
  94.     UpdateAlarmVal(); // 温度报警值初始化
  95.     SetOverflow();    // 当前温度值初始化为 “----”

  96.     ADC_INIT();         // 初始化ADC的控制引脚
  97.     ADC_IT_CMD(ENABLE); // 使能ADC的触发中断(外部中断1)

  98.     EA = 1; // 开总中断

  99.     Delay(100);

  100.     ADC_START(); // 启动ADC

  101.     while (1)
  102.     {
  103.         EA = 0;
  104.         DisplayAll(); // 显示所有数码管
  105.         EA = 1;
  106.         Delay(4);
  107.     }
  108. }

  109. void HandleKey(void) reentrant
  110. {
  111.     switch (KEYBOARD & 0x03)
  112.     {
  113.     case 0x01:
  114.         KEY_ADD();
  115.         UpdateAlarmVal();
  116.         T0_CMD(ENABLE);
  117.         break;
  118.     case 0x02:
  119.         KEY_DEC();
  120.         UpdateAlarmVal();
  121.         T0_CMD(ENABLE);
  122.         break;
  123.     default:
  124.         T0_CMD(DISABLE);
  125.         break;
  126.     }
  127. }

  128. void Delay(u16 x)
  129. {
  130.     u16 i;
  131.     while (x--)
  132.         for (i = 0; i < 62; i++)
  133.             ;
  134. }

  135. void DisplayAll()
  136. {
  137.     u8 i;
  138.     for (i = 0; i < 8; i++)
  139.     {
  140.         SEG_UPDATE(i, dispVal[i]);
  141.         Delay(4);
  142.     }
  143. }

  144. void UpdateValue(float v, u8 offset) reentrant
  145. {
  146.     u16 val = (v > 0.0f ? v : -v) * 10;

  147.     if (v > 0.0f)
  148.     {
  149.         dispVal[0 + offset] = segTable[val / 1000];
  150.         dispVal[1 + offset] = segTable[(val % 1000) / 100];
  151.         dispVal[2 + offset] = segTable[(val % 100) / 10] & POINT_MASK;
  152.         dispVal[3 + offset] = segTable[val % 10];
  153.     }
  154.     else
  155.     {
  156.         dispVal[0 + offset] = segTable[SYMBOL_NEGATIVE];
  157.         dispVal[1 + offset] = segTable[val / 100];
  158.         dispVal[2 + offset] = segTable[(val % 100) / 10] & POINT_MASK;
  159.         dispVal[3 + offset] = segTable[val % 10];
  160.     }
  161. }
复制代码
后续见附件

全部资料51hei下载地址:
DPJ_KS.rar (567.34 KB, 下载次数: 187)

评分

参与人数 2黑币 +55 收起 理由
ed34 + 5 赞一个!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:59830 发表于 2020-4-13 00:42 | 显示全部楼层
点赞!这个是负温度系数的,没有看到正温度系数.
回复

使用道具 举报

ID:65956 发表于 2020-4-13 09:00 | 显示全部楼层
个人认为用不着这么麻烦吧,单片机用自带ADC功能的就可以省掉外挂ADC,控制也可以直接用单片机的两个外部中断口来操作也可以得到即时响应;由于电路原理看得不是很清,所以只是提个小意见
回复

使用道具 举报

ID:668601 发表于 2020-4-13 11:32 | 显示全部楼层
谢谢楼主的分享
回复

使用道具 举报

ID:324435 发表于 2020-4-24 17:48 | 显示全部楼层
aking991 发表于 2020-4-13 09:00
个人认为用不着这么麻烦吧,单片机用自带ADC功能的就可以省掉外挂ADC,控制也可以直接用单片机的两个外部中 ...

为了完成师傅要求改的
回复

使用道具 举报

ID:120677 发表于 2020-12-30 16:41 | 显示全部楼层
来见一见 代码写得工整
回复

使用道具 举报

ID:941205 发表于 2022-9-8 18:15 | 显示全部楼层
下来学习下NTC的用法。
回复

使用道具 举报

ID:941205 发表于 2022-9-8 18:26 | 显示全部楼层
有点货不对版,仿真用不了,原理图不全。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表