开源一个双路热电偶测温系统(基于MAX6675)
本帖最后由 一路向北lm 于 2018-10-27 12:46 编辑基于单片机 的双路热电偶测量系统
1. 识别热电偶是否在线。
2. 精度为0.5度。
3. 液晶实时显示。
4. 可玩性很高。
5. 练手也不错。
6. 实用性也挺强。
http://v.youku.com/v_show/id_XMzg5MDAxMDQ2OA==.html?spm=a2h3j.8428770.3416059.1
代码:
max6675 驱动
#include "max6675.h"
sbitSO= P1^0; //P3.6口与SO相连
sbitSCK = P1^2; //P3.4口与SCK相连
sbitCS= P1^1; //P3.5口与CS相连
sbitSO1= P1^5; //P3.6口与SO相连
sbitSCK1 = P1^3; //P3.4口与SCK相连
sbitCS1= P1^4; //P3.5口与CS相连
//读取MAX6675内存器
unsigned int MAX6675_ReadReg(void)
{
unsigned char i;
unsigned int dat;
i = 0;
dat = 0;
CS= 0;
SCK = 0;
for(i=0; i<16; i++) //get D15-D0 from 6675
{
SCK = 1;
dat = dat<<1;
if( SO==1 )
dat = dat|0x01;
SCK = 0;
}
CS = 1;
return dat;
}
unsigned int MAX6675_ReadReg1(void)
{
unsigned char i;
unsigned int dat;
i = 0;
dat = 0;
CS1= 0;
SCK1 = 0;
for(i=0; i<16; i++) //get D15-D0 from 6675
{
SCK1 = 1;
dat = dat<<1;
if( SO1==1 )
dat = dat|0x01;
SCK1 = 0;
}
CS1 = 1;
return dat;
}
#ifndef __MAX6675_H_
#define__MAX6675_H_
#include "reg52.h"
#include "intrins.h"
unsigned int MAX6675_ReadReg(void);
unsigned int MAX6675_ReadReg1(void);
#endif
LCD 驱动
#include "lcd.h"
/*******************************************************************************
* 函 数 名 : Lcd1602_Delay1ms
* 函数功能 : 延时函数,延时1ms
* 输 入 : c
* 输 出 : 无
* 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c) //误差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*******************************************************************************
* 函 数 名 : LcdWriteCom
* 函数功能 : 向LCD写入一个字节的命令
* 输 入 : com
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 0; //选择写入命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = com << 4; //发送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdWriteData
* 函数功能 : 向LCD写入一个字节的数据
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择输入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择写入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //写入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdInit()
* 函数功能 : 初始化LCD屏
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38);//开显示
LcdWriteCom(0x0c);//开显示不显示光标
LcdWriteCom(0x06);//写一个指针加1
LcdWriteCom(0x01);//清屏
LcdWriteCom(0x80);//设置数据指针起点
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //将8位总线转为4位总线
LcdWriteCom(0x28); //在四位线下的初始化
LcdWriteCom(0x0c);//开显示不显示光标
LcdWriteCom(0x06);//写一个指针加1
LcdWriteCom(0x01);//清屏
LcdWriteCom(0x80);//设置数据指针起点
}
#endif
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include<reg52.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_RS=P2^0;
sbit LCD1602_RW=P2^1;
sbit LCD1602_E=P2^2;
/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c); //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/
void LcdWriteData(uchar dat);
/*LCD1602初始化子程序*/
void LcdInit();
#endif
主函数
#include "reg52.h"
#include "lcd.h"
#include "max6675.h"
uint temp,temp1;
bit temp_flag,flag,flag1;
sbit SO=P1^0;
void main()
{
LcdInit(); //LCD1602初始化
TMOD|=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
TR0=1;
EA=1;
//LCD1602液晶初始化
while(1)
{
if(temp_flag==1)
{
temp_flag=0;
temp=MAX6675_ReadReg();
temp = temp<<1;
temp = temp>>4;
temp = temp*2.5;
temp1=MAX6675_ReadReg1();
temp1= temp1<<1;
temp1= temp1>>4;
temp1= temp1*2.5;
if((temp==10237))
{
temp=0; flag=1;
}
else
{
flag=0;
}
if((temp1==10237))
{
temp1=0; flag1=1;
}
else
{
flag1=0;
}
}
LcdWriteCom(0x80);
LcdWriteData('C');
LcdWriteCom(0x81);
LcdWriteData('H');
LcdWriteCom(0x82);
LcdWriteData('1');
LcdWriteCom(0x83);
LcdWriteData(':');
LcdWriteCom(0x85);
LcdWriteData(temp1/10000+0x30);
LcdWriteCom(0x86);
LcdWriteData(temp1%10000/1000+0x30);
LcdWriteCom(0x87);
LcdWriteData(temp1%1000/100+0x30);
LcdWriteCom(0x88);
LcdWriteData(temp1%100/10+0x30);
LcdWriteCom(0x89);
LcdWriteData('.');
LcdWriteCom(0x80+10);
LcdWriteData(temp1%10+0x30);
LcdWriteCom(0x80+10+1);
LcdWriteData('C');
if(flag1==1) // 掉线
{
LcdWriteCom(0x80+10+3);
LcdWriteData('O');
LcdWriteCom(0x80+10+4);
LcdWriteData('F');
LcdWriteCom(0x80+10+5);
LcdWriteData('F');
}
if(flag1==0) //在线
{
LcdWriteCom(0x80+10+3);
LcdWriteData(' ');
LcdWriteCom(0x80+10+4);
LcdWriteData('O');
LcdWriteCom(0x80+10+5);
LcdWriteData('N');
}
LcdWriteCom(0x80+0x40);
LcdWriteData('C');
LcdWriteCom(0x80+0x40+1);
LcdWriteData('H');
LcdWriteCom(0x80+0x40+2);
LcdWriteData('2');
LcdWriteCom(0x80+0x40+3);
LcdWriteData(':');
LcdWriteCom(0x80+0x40+5);
LcdWriteData(temp/10000+0x30);
LcdWriteCom(0x80+0x40+6);
LcdWriteData(temp%10000/1000+0x30);
LcdWriteCom(0x80+0x40+7);
LcdWriteData(temp%1000/100+0x30);
LcdWriteCom(0x80+0x40+8);
LcdWriteData(temp%100/10+0x30);
LcdWriteCom(0x80+0x40+9);
LcdWriteData('.');
LcdWriteCom(0x80+0x40+10);
LcdWriteData(temp%10+0x30);
LcdWriteCom(0x80+0x40+11);
LcdWriteData('C');
if(flag==1) // 掉线
{
LcdWriteCom(0x80+0x40+13);
LcdWriteData('O');
LcdWriteCom(0x80+0x40+14);
LcdWriteData('F');
LcdWriteCom(0x80+0x40+15);
LcdWriteData('F');
}
if(flag==0) //在线
{
LcdWriteCom(0x80+0x40+13);
LcdWriteData(' ');
LcdWriteCom(0x80+0x40+14);
LcdWriteData('O');
LcdWriteCom(0x80+0x40+15);
LcdWriteData('N');
}
}
}
void time() interrupt 1
{
uint count1,count2,t;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count1++;count2++;
if(count1==20)
{
count1=0;
temp_flag=1;
}
}
感谢分享! 牛X啊 caijie001 发表于 2018-10-29 14:09
牛X啊
小玩意,我啥牛X的{:biggrin:} 电路呢? 6688hyc 发表于 2018-10-30 11:42
电路呢?
电路就不用画了吧,51最小系统引脚已经定义好了,没难度 你用了两个6675,可以用一个6675,用低阻模拟开关来选择热电偶,又省掉一个6675钱又节省mcu引脚。 用2个MAX6675的,可以保证市场上找不到类似的批量的产品的,实用性肯定不高的。
性价比低的,实用性肯定差了呀。 gx_huang 发表于 2018-12-8 16:18
用2个MAX6675的,可以保证市场上找不到类似的批量的产品的,实用性肯定不高的。
性价比低的,实用性肯定差 ...
是的,这个不能跟专业产品比 一路向北lm 发表于 2018-12-10 12:54
是的,这个不能跟专业产品比
如果你能用TM7711之类的ADC芯片,自己搭电路,自己做冷端补偿,自己做线性修正,
这比用MAX6675的方案便宜多了,分辨率也可以更好,也让你知道K型热电偶的特性了。
我甚至不用ADC芯片,只用运放放大,然后LM393之类的比较器,也可以采集热电偶的温度。 gx_huang 发表于 2018-12-10 13:40
如果你能用TM7711之类的ADC芯片,自己搭电路,自己做冷端补偿,自己做线性修正,
这比用MAX6675的方案便 ...
这个更强了,真没有深入研究过 再有新方案的话,推荐这个max31855 max6675停产!
【MAX31855关键特性】
冷端补偿
14位、0.25°C分辨率
转换器的温度分辨率为0.25°C,
温度读数为-270°C 至+1800°C,
对于K型热电偶,在-200°C至+700°C温度范围内,保持±2°C精度。
提供K、J、N、T和E型热电偶器件版本
简单的SPI兼容接口(只读)
检测热电偶对GND或VCC短路
检测热电偶开路
应用
电器设备
汽车
HVAC
工业
maximQ820270087 发表于 2020-6-9 12:17
再有新方案的话,推荐这个max31855 max6675停产!
【MAX31855关键特性】
冷端补偿
max31855多少钱 10块左右具体要看哪个版本的热电偶了 一路向北lm 发表于 2018-10-27 12:44
主函数
void time() interrupt 1
{
uint count1,count2,t;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count1++;count2++;
if(count1==20)
{
count1=0;
temp_flag=1;
}
}
这个count1能够等于20绝对是个奇迹,应该改为静态或全局变量
页:
[1]