//温控PID程序
#include<reg51.h>
#include<intrins.h>
#include<math.h>
#include<string.h>
struct PID {
unsigned int SetPoint; // 设定目标 Desired Value
unsigned int Proportion; // 比例常数 Proportional Const
unsigned int Integral; // 积分常数 Integral Const
unsigned int Derivative; // 微分常数 Derivative Const
unsigned int LastError; // Error[-1]
unsigned int PrevError; // Error[-2]
unsigned int SumError; // Sums of Errors
};
struct PID spid; // PID Control Structure
unsigned int rout; // PID Response (Output)
unsigned int rin; // PID Feedback (Input)
sbit data1=P1^0;
sbit clk=P1^1;
sbit plus=P2^0;
sbit subs=P2^1;
sbit stop=P2^2;
sbit output=P3^4;
sbit DQ=P3^3;
unsigned char flag,flag_1=0;
unsigned char high_time,low_time,count=0;//占空比调节参数
unsigned char set_temper=35;
unsigned char temper;
unsigned char i;
unsigned char j=0;
unsigned int s;
/***********************************************************
延时子程序,延时时间以12M晶振为准,延时时间为30us×time
***********************************************************/
void delay(unsigned char time)
{
unsigned char m,n;
for(n=0;n<time;n++)
for(m=0;m<2;m++){}
}
/***********************************************************
写一位数据子程序
***********************************************************/
void write_bit(unsigned char bitval)
{
EA=0;
DQ=0; /*拉低DQ以开始一个写时序*/
if(bitval==1)
{
_nop_();
DQ=1; /*如要写1,则将总线置高*/
}
delay(5); /*延时90us供DA18B20采样*/
DQ=1; /*释放DQ总线*/
_nop_();
_nop_();
EA=1;
}
/***********************************************************
写一字节数据子程序
***********************************************************/
void write_byte(unsigned char val)
{
unsigned char i;
unsigned char temp;
EA=0;
TR0=0;
for(i=0;i<8;i++) /*写一字节数据,一次写一位*/
{
temp=val>>i; /*移位操作,将本次要写的位移到最低位*/
temp=temp&1;
write_bit(temp); /*向总线写该位*/
}
delay(7); /*延时120us后*/
// TR0=1;
EA=1;
}
/***********************************************************
读一位数据子程序
***********************************************************/
unsigned char read_bit()
{
unsigned char i,value_bit;
EA=0;
DQ=0; /*拉低DQ,开始读时序*/
_nop_();
_nop_();
DQ=1; /*释放总线*/
for(i=0;i<2;i++){}
value_bit=DQ;
EA=1;
return(value_bit);
}
/***********************************************************
读一字节数据子程序
***********************************************************/
unsigned char read_byte()
{
unsigned char i,value=0;
EA=0;
for(i=0;i<8;i++)
{
if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/
value|=0x01<<i;
delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/
}
EA=1;
return(value);
}
/***********************************************************
复位子程序
***********************************************************/
unsigned char reset()
{
unsigned char presence;
EA=0;
DQ=0; /*拉低DQ总线开始复位*/
delay(30); /*保持低电平480us*/
DQ=1; /*释放总线*/
delay(3);
presence=DQ; /*获取应答信号*/
delay(28); /*延时以完成整个时序*/
EA=1;
return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/
}
/***********************************************************
获取温度子程序
***********************************************************/
void get_temper()
{
unsigned char i,j;
do
{
i=reset(); /*复位*/
}while(i!=0); /*1为无反馈信号*/
i=0xcc; /*发送设备定位命令*/
write_byte(i);
i=0x44; /*发送开始转换命令*/
write_byte(i);
delay(180); /*延时*/
do
{
i=reset(); /*复位*/
}while(i!=0);
i=0xcc; /*设备定位*/
write_byte(i);
i=0xbe; /*读出缓冲区内容*/
write_byte(i);
j=read_byte();
i=read_byte();
i=(i<<4)&0x7f;
s=(unsigned int)(j&0x0f);
s=(s*100)/16;
j=j>>4;
temper=i|j; /*获取的温度放在temper中*/
}
/*====================================================================================================
Initialize PID Structure
=====================================================================================================*/
void PIDInit (struct PID *pp)
{
memset ( pp,0,sizeof(struct PID));
}
/*====================================================================================================
PID计算部分
=====================================================================================================*/
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
{
unsigned int dError,Error;
Error = pp->SetPoint - NextPoint; // 偏差
pp->SumError += Error; // 积分
dError = pp->LastError - pp->PrevError; // 当前微分
pp->PrevError = pp->LastError;
pp->LastError = Error;
return (pp->Proportion * Error // 比例项
+ pp->Integral * pp->SumEror // 积分项
+ pp->Derivative * dError); // 微分项
}
/***********************************************************
温度比较处理子程序
***********************************************************/
compare_temper()
{
unsigned char i;
if(set_temper>temper)
{
if(set_temper-temper>1)
{
high_time=100;
low_time=0;
}
else
{
for(i=0;i<10;i++)
{ get_temper();
rin = s; // Read Input
rout = PIDCalc ( &spid,rin ); // Perform PID Interation
}
if (high_time<=100)
high_time=(unsigned char)(rout/800);
else
high_time=100;
low_time= (100-high_time);
}
}
else if(set_temper<=temper)
{
if(temper-set_temper>0)
{
high_time=0;
low_time=100;
}
else
{
for(i=0;i<10;i++)
{ get_temper();
rin = s; // Read Input
rout = PIDCalc ( &spid,rin ); // Perform PID Interation
}
if (high_time<100)
high_time=(unsigned char)(rout/10000);
else
high_time=0;
low_time= (100-high_time);
}
}
// else
// {}
}
/*****************************************************
T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期
******************************************************/
void serve_T0() interrupt 1 using 1
{
if(++count<=(high_time))
output=1;
else if(count<=100)
{
output=0;
}
else
count=0;
TH0=0x2f;
TL0=0xe0;
}
/*****************************************************
串行口中断服务程序,用于上位机通讯
******************************************************/
void serve_sio() interrupt 4 using 2
{
/* EA=0;
RI=0;
i=SBUF;
if(i==2)
{
while(RI==0){}
RI=0;
set_temper=SBUF;
SBUF=0x02;
while(TI==0){}
TI=0;
}
else if(i==3)
{
TI=0;
SBUF=temper;
while(TI==0){}
TI=0;
}
EA=1; */
}
void disp_1(unsigned char disp_num1[6])
{
unsigned char n,a,m;
for(n=0;n<6;n++)
{
// k=disp_num1[n];
for(a=0;a<8;a++)
{
clk=0;
m=(disp_num1[n]&1);
disp_num1[n]=disp_num1[n]>>1;
if(m==1)
data1=1;
else
data1=0;
_nop_();
clk=1;
_nop_();
}
}
以前收藏的一个程序,与你分享一下,希望对你有用、
‘贰’ 用单片机做温控系统的程序谁懂
我去年做了一个差不多的,也是报警控制的,你借鉴一下吧:
软件设计:
有两个文件,DS18B20.c和DS18B20.h,将这两个文件添加到工程里即可。
DS18B20.c:
/******************************************************************
程序名称:DS18B20温度测量、报警系统
简要说明:DS18B20温度计,温度测量范围0~99.9摄氏度
可设置上限报警温度、下限报警温度
即高于上限值或者低于下限值时蜂鸣器报警
默认上限报警温度为32℃、默认下限报警温度为10℃
报警值可设置范围:最低上限报警值等于当前下限报警值
最高下限报警值等于当前上限报警值
将下限报警值调为0时为关闭下限报警功能
******************************************************************/
#include <AT89X52.h>
#include "DS18B20.h"
#define uint unsigned int
#define uchar unsigned char //宏定义
#define SET P3_1 //定义调整键
#define DEC P3_2 //定义减少键
#define ADD P3_3 //定义增加键
#define BEEP P3_7 //定义蜂鸣器
#define JDQ P3_5
bit shanshuo_st; //闪烁间隔标志
bit beep_st; //蜂鸣器间隔标志
sbit DIAN = P2^7; //小数点
uchar x=0; //计数器
signed char m; //温度值全局变量
uchar n; //温度值全局变量
uchar set_st=0; //状态标志
signed char shangxian=70; //上限报警温度,默认值为70
signed char xiaxian=0; //下限报警温度,默认值为0
uchar code LEDData[]=;
/*****延时子程序*****/
void Delay(uint num)
{
while( --num );
}
void shortdelay(void) //误差 0us
{
unsigned char a,b,c;
for(c=165;c>0;c--)
for(b=100;b>0;b--)
for(a=150;a>0;a--);
_nop_; //if Keil,require use intrins.h
_nop_; //if Keil,require use intrins.h
}
/*****初始化定时器0*****/
void InitTimer(void)
{
TMOD=0x1;
TH0=0x3c;
TL0=0xb0; //50ms(晶振12M)
}
/*****定时器0中断服务程序*****/
void timer0(void) interrupt 1
{
TH0=0x3c;
TL0=0xb0;
x++;
}
/*****外部中断0服务程序*****/
void int0(void) interrupt 0
{
EX0=0; //关外部中断0
if(DEC==0&&set_st==1)
{
shangxian--;
if(shangxian<xiaxian)shangxian=xiaxian;
}
else if(DEC==0&&set_st==2)
{
xiaxian--;
if(xiaxian<0)xiaxian=0;
}
}
/*****外部中断1服务程序*****/
void int1(void) interrupt 2
{
EX1=0; //关外部中断1
if(ADD==0&&set_st==1)
{
shangxian++;
if(shangxian>99)shangxian=99;
}
else if(ADD==0&&set_st==2)
{
xiaxian++;
if(xiaxian>shangxian)xiaxian=shangxian;
}
}
/*****读取温度*****/
void check_wen(void)
{
uint a,b,c;
c=ReadTemperature()-5; //获取温度值并减去DS18B20的温漂误差
a=c/100; //计算得到十位数字
b=c/10-a*10; //计算得到个位数字
m=c/10; //计算得到整数位
n=c-a*100-b*10; //计算得到小数位
if(m<0) //设置温度显示上限
if(m>99) //设置温度显示上限
}
/*****显示开机初始化等待画面*****/
Disp_init()
{
P2 = 0xbf; //显示-
P1 = 0xf7;
Delay(200);
P1 = 0xfb;
Delay(200);
P1 = 0xfd;
Delay(200);
P1 = 0xfe;
Delay(200);
P1 = 0xff; //关闭显示
}
/*****显示温度子程序*****/
Disp_Temperature() //显示温度
{
P2 =0xc6; //显示C
P1 = 0xf7;
Delay(300);
P2 =LEDData[n]; //显示个位
P1 = 0xfb;
Delay(300);
P2 =LEDData[m%10]; //显示十位
DIAN = 0; //显示小数点
P1 = 0xfd;
Delay(300);
P2 =LEDData[m/10]; //显示百位
P1 = 0xfe;
Delay(300);
P1 = 0xff; //关闭显示
}
/*****显示报警温度子程序*****/
Disp_alarm(uchar baojing)
{
P2 =0xc6; //显示C
P1 = 0xf7;
Delay(200);
P2 =LEDData[baojing%10]; //显示十位
P1 = 0xfb;
Delay(200);
P2 =LEDData[baojing/10]; //显示百位
P1 = 0xfd;
Delay(200);
if(set_st==1)P2 =0x89;
else if(set_st==2)P2 =0xc7; //上限H、下限L标示
P1 = 0xfe;
Delay(200);
P1 = 0xff; //关闭显示
}
/*****报警子程序*****/
void Alarm()
{
if(x>=10)
if((m>=shangxian&&beep_st==1)||(m<xiaxian&&beep_st==1))BEEP=0;
else BEEP=1;
if((m>=shangxian)||(m<xiaxian))
{shortdelay();
JDQ=0;}
else JDQ=1;
}
/*****主函数*****/
void main(void)
{
uint z;
InitTimer(); //初始化定时器
EA=1; //全局中断开关
TR0=1;
ET0=1; //开启定时器0
IT0=1;
IT1=1;
check_wen();
check_wen();
for(z=0;z<300;z++)
{
Disp_init();
}
while(1)
{
if(SET==0)
{
Delay(2000);
do{}while(SET==0);
set_st++;x=0;shanshuo_st=1;
if(set_st>2)set_st=0;
}
if(set_st==0)
{
EX0=0; //关闭外部中断0
EX1=0; //关闭外部中断1
check_wen();
Disp_Temperature();
Alarm(); //报警检测
}
else if(set_st==1)
{
BEEP=1; //关闭蜂鸣器
EX0=1; //开启外部中断0
EX1=1; //开启外部中断1
if(x>=10)
if(shanshuo_st)
}
else if(set_st==2)
{
BEEP=1; //关闭蜂鸣器
EX0=1; //开启外部中断0
EX1=1; //开启外部中断1
if(x>=10)
if(shanshuo_st)
}
}
}
/*****END*****/
DS18B20.h:
#include <AT89X52.h>
#define DQ P3_6 //定义DS18B20总线I/O
/*****延时子程序*****/
void Delay_DS18B20(int num)
{
while(num--) ;
}
/*****初始化DS18B20*****/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
Delay_DS18B20(8); //稍做延时
DQ = 0; //单片机将DQ拉低
Delay_DS18B20(80); //精确延时,大于480us
DQ = 1; //拉高总线
Delay_DS18B20(14);
x = DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
Delay_DS18B20(20);
}
/*****读一个字节*****/
unsigned char ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
Delay_DS18B20(4);
}
return(dat);
}
/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
Delay_DS18B20(5);
DQ = 1;
dat>>=1;
}
}
/*****读取温度*****/
unsigned int ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned int t=0;
float tt=0;
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0x44); //启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器
a=ReadOneChar(); //读低8位
b=ReadOneChar(); //读高8位
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t= tt*10+0.5; //放大10倍输出并四舍五入
return(t);
}
/*****END*****/
其中控制部分我用的是5V继电器,可以直接控制你的电机了。
两个电路图都差不多的,只不过我的多了几个调整按键,报警温度可以调的。我的这个程序你完全可以用到你的电路里德
‘叁’ 求一单片机温度控制程序
你说的不是很详细,没有硬件图,不好弄的
我大概说一下,你用了一个专用ADC芯片,这样一来,只要处理单片机与ADC芯片之间的通信就行了,你的控制比较简单,主要是读温度这一块.
而且这个ADC只是8位的,输出也是8bit的数据,所以只要读单片机的一个I/O口比如PD的8bit数据就OK了,很简单的.
最重要的就是要算出多少温度的时候对应的数值是多少,这要做一个查表.
‘肆’ 求一个51单片机 用DS18B20芯片实现 的温控程序
基于AT89S51单片机的数字温度测量及显示系统设计
程序
DI EQU P3.3
DO EQU P3.4
CLK EQU P3.5
CS EQU P3.6 ; LCD端口定义
D2RS EQU P2.7
D2RW EQU P2.6
D2E EQU P2.5
KEYPORT EQU P1 ; DS18B20端口定义
TEMPER_L EQU 36H
TEMPER_H EQU 35H
TEMPER_NUM EQU 38H
FLAG1 BIT 00H
DQ BIT P2.4
ORG 0000H
LJMP MAIN
ORG 0003H
JMP INT00
ORG 0038H
MAIN: MOV SP,#60H
SETB P2.0
SETB P2.1
SETB P2.2
SETB EA
SETB EX0
SETB P2.0
SEETB P2.1
SETB P2.2
MOV R0,#01H ;清屏并置地址计数器AC为0
LCALL DIS_CMD _WRT
MOV R0,#38H ;8位数据接口,双行显示,5*7点阵
LCALL DIS_CMD _WRT
CALL DIS_CUR_OFF
MOV 42H,#20
MOV 43H,#32
XIAN: LCALL GET_TEMPER
LCALL DISP
LCALL DELAY43MS
MOV A,TEMPER_NUM
SUBB A,42H
JC ZZZL
MOV A,TEMPER_NUM
SUBB A,43H
JNC ZZZ2
SETB P2.0
SETB P2.1
SETB P2.2
JMP XIAN
ZZZL: CLR P2.0
CLR P2.2
JMP XIAN
ZZZ2: CLR P2.0
CLR P2.1
JMP XIAN
INT0: ;扫描键盘程序
LCALL ASK
SAO: CLR 01H
LCALL KEY
JNB 01H,SAO
CJNE A,#10,PAN
LCALL ANSW
RETI
PAN: CJNE A,#12,SAO
RETI ;显示函数部分,可供调用
DIS_CUR_OFF: MOV R0,#0CH
LCALL DIS_CMD_WRT
RET
DIS_CUR_ON: MOV R0,#0EH
LCALL DIS_CMD_WRT
RET
CHK_BUSY_FLG: MOV P0,#0FFH
CLR D2RS
NOP
NOP
NOP
LCALL DISPLAY_RD
JB ACC.7,CHK_BUSY_FLG
RET
CLEAR_DIS: MOV R0,#01H
LCALL DIS_CMD_WRT
RET
DIS_CMD_WRT: LCALL CHK_BUSY_FLG
MOV P0,R0
CLR D2RS
NOP
NOP
NOP
LCALL DISPLAY_WRT
RET
DIS_DATA_WRT: LCALL CHK_BUSY_FLG
CJNE A,#10H,DIS_DAT_WRT1
MOV P0,#0C0H ;1100,00000行起始地址为40
CLR D2RS
NOP
NOP
NOP
LCALL DISPLAY_WRT
DIS_DAT_WRT1: MOV P0,R0
SETB D2RS
NOP
NOP
NOP
LCALL DISPLAY_WRT
RET
DISPLAY_WRT: CLR D2RW
NOP
NOP
NOP
SETB D2E
NOP
NOP
NOP
CLR D2E
NOP
NOP
NOP
RET
DISPLAY_RD: SETB D2RW
NOP
NOP
NOP
SETB D2E
NOP
NOP
NOP
MOV A,P0
NOP
NOP
NOP
CLR D2E
NOP
NOP
NOP
RET
DIS_DATA_RD: LCALL CHK_BUSY_FLG
MOV P0,#0FFH
SETB D2RS
LCALL DISPLAY_RD
RET ;键盘程序,出口:A为按键值 01H:0无键按下 1 有键按下
KEY: MOV KEYPORT,#0FH
MOV A,KEYPOR
CJNE A,#0FH,KEYDOWN
MOV A,#0FFH
RET
KEYDOWN: LCALL DELAY43MS
MOV KEYPORT,#0FH
MOV A,KEYPORT
CJNE A,#0FH,KEYDOWN_YES
MOV A,#0FFH
RET
KEYDOWN _YES: MOV B,A
MOV KEYPORT,#0F0H
MOV A,KEYPORT
ORL A,B
PUSH 30H
MOV 30H,A
MOV R3,#10H
MOV DPTR,#KEYVALUE
NEXT_KEY: MOV A,R3
MOVC A,@a+dptr
CJNE A,30h,NEXTKEYVALUE
DEC R3
POP 30H
WAITKEY_F: MOV KEYPORT,#0FH
MOV A,KEYPORT
CJNE A,#0FH, WAITKEY_F
MOV A,R3
SETB 01H
RET
NEXTKEYVALUE: DJNZ R3,NEXT_KEY
DEC R3
POP 30H
WAITKEY_FREE: MOV KEYPORT,#0FH
MOV A,KEYPORT
CJNE A,#0FH, WAITKEY_FREE
MOV A,R3
SETB 01H
RET
KEYVALUE: DB 0FFH,7EH,7DH,7BH,77H,0BEH,0BDH,0BBH,0B7H,0DEH,0DDH,0DBH,0D7H,0EEH,0EDH,0EBH,0E7H
DELAY43MS: PUSH A
MOV A,R3
PUSH A
MOV A,R2
PUSH A
MOV R3,#43
DELAY: MOV R2,#0FAH
LOOP: NOP ;内层循环为1MS
NOP
DJNZ R2,LOOP
DJNZ R3, DELAY
POP A
MOV R2,A
POP A
MOV R3,A
POP A
RET ;确认是否修改温度设定
ASK: MOV R0,#01H ;清屏并置地址计数器AC为0
LCALL DIS_CMD_WRT
MOV 40H,#0
ZDZ: MOV DPTR,#LINE
MOV A,40H
MOVC A,@A+DPTR
MOV R0,A
LCALL DIS_DATA_WRT
INC 40H
MOV A,40H
MOVC A,@A+DPTR
CJNE A,#00H,ZDZ
RET
LINE: DB " ARE YOU SURE
CHANGE T(Y/N)?",00H
ANSW: MOV R6,42H
MOV R7,43H
MOV R0,#01H
LCALL DIS_CMD_WRT
MOV R0,#44H
CALL DIS_DATA_WRT
MOV R0,#6FH
CALL DIS_DATA_WRT
MOV R0,#77H
CALL DIS_DATA_WRT
MOV R0,#6EH
CALL DIS_DATA_WRT
MOV R0,#3AH
CALL DIS_DATA_WRT
MOV 40H,#0
CLR 00H
JMP SAO1
GAI: MOV R0,#0FEH
CALL DIS_DATA_WRT
MOV R0,#55H
CALL DIS_DATA_WRT
MOV R0,#70H
CALL DIS_DATA_WRT
MOV R0,#3AH
CALL DIS_DATA_WRT
MOV 40H,#0
SAO1: CLR 01H
LCALL KEY
JNB 01H,SAO1
MOV R1,A
MOV B,#10
DIV AB
JZ NEXT2
MOV A,A1
CJNE A,#11,XU
JB 00H,DOWN
MOV 42H,40H
CPL 00H
JMP GAI
DOWN: MOV 43H,40H
RETI
XU: CJNE A,#12,SAO1
MOV 42H,R6
MOV 43H,R7
RETI
NEXT2: MOV A,R1
ADD A,#30H
MOV R0,A
LCALL DIS_DATA_WRT
MOV A,R1
XCH A,40H
MOV B,#10
MUL AB
NOP
CLR DQ
CLR C
WR1: CLR DQ
MOV R3,#6
DJNZ R3,$
RR R4,#2 R1,#36H ; 低位存入36H(TEMPER_L),高位存入35H(TEMPER_
NOP
NOP
SETB DQ
MOV R3,#7
DJNZ R3,$
MOV C,DQ
MOV R3,#23
DJNZ R3,$
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET ; 将从DS18B20中读出的温度数据进行转换
TEMPER_COV: MOV A,#0f0H
ANL A,TEMPER_L ; 舍去温度低位中小数点后的四位温度数值
SWAP A
MOV TEMPER_NUM,A
MOV A,TEMPER_L
JNB ACC.3,TEMPER_COV1 ; 四舍五入去温度值
INC TEMPER_NUM
TEMPER_COV1:MOV A,TEMPER_H
ANL A,#07H
SWAP A
ORL A,TEMPER_NUM
MOV TEMPER_NUM,A ; 保存变换后的温度数据
RET ;AD0832:
SETB DI
SETB DO
SETB CLK
CLR CS
NOP
SETB CS
CLR CLK
CLR CS
CALL DELAY1
SETB DI
SETB CLK
NOP
CLR CLK
SETB DI
SETB CLK
NOP
CLR CLK
CLR DI
SETB CLK
NOP
CLR CLK
NOP
SETB CLK
NOP
CLR CLK
NOP
SETB CLK
MOV C,DO
CLR CLK
RLC A;7
SETB CLK
MOV C,DO
CLR CLK
RLC A 6
SETB CLK
MOV C,DO
CLR CLK
RLC A ;5
SETB CLK
MOV C,DO
CLR CLK
RLC A ;4
SETB CLK
MOV C,DO
CLR CLK
RLC A ;3
SETB CLK
MOV C,DO
CLR CLK
RLC A ;2
SETB CLK
MOV C,DO
CLR CLK
RLC A ;1
SETB CLK
MOV C,DO
CLR CLK
RLC A ;0
SETB CLK
NOP
CLR CLK ;1
NOP
SETB CLK
NOP
CLR CLK ;2
NOP
SETB CLK
NOP
CLR CLK ;3
NOP
SETB CLK
NOP
CLK ;4
NOP
SETB CLK
NOP
CLR CLK ;5
NOP
SETB CLK
NOP
CLR CLK ;6
NOP
SETB CLK
NOP
CLR CLK ;7
NOP
SETB CLK
NOP
CLR CLK
NOP
SETB CLK
NOP
CLR CLK
NOP
CALL DELAY1
SETB CS
RET
DELAY1: MOV R7,#10
DELAY2: NOP
NOP
DJNZ R7,DELAY2
RET
‘伍’ 求单片机温控系统程序
在我的博客里有比较规范的DS18b20温度测量程序,你可看一下,也许有帮助。
对于你的具体要求,你要改写一下程序。
http://hi..com/xiaopc001/blog
‘陆’ 求数码管显示的温控电动机51单片机C程序
我去年做了一个差不多的,也是报警控制的,你借鉴一下吧:
软件设计:
有两个文件,DS18B20.c和DS18B20.h,将这两个文件添加到工程里即可。
DS18B20.c:
/******************************************************************
程序名称:DS18B20温度测量、报警系统
简要说明:DS18B20温度计,温度测量范围0~99.9摄氏度
可设置上限报警温度、下限报警温度
即高于上限值或者低于下限值时蜂鸣器报警
默认上限报警温度为32℃、默认下限报警温度为10℃
报警值可设置范围:最低上限报警值等于当前下限报警值
最高下限报警值等于当前上限报警值
将下限报警值调为0时为关闭下限报警功能
******************************************************************/
#include<AT89X52.h>
#include"DS18B20.h"
#defineuintunsignedint
#defineucharunsignedchar//宏定义
#defineSETP3_1//定义调整键
#defineDECP3_2//定义减少键
#defineADDP3_3//定义增加键
#defineBEEPP3_7//定义蜂鸣器
#defineJDQP3_5
bitshanshuo_st;//闪烁间隔标志
bitbeep_st;//蜂鸣器间隔标志
sbitDIAN=P2^7;//小数点
ucharx=0;//计数器
signedcharm;//温度值全局变量
ucharn;//温度值全局变量
ucharset_st=0;//状态标志
signedcharshangxian=70;//上限报警温度,默认值为70
signedcharxiaxian=0;//下限报警温度,默认值为0
ucharcodeLEDData[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff};
/*****延时子程序*****/
voidDelay(uintnum)
{
while(--num);
}
voidshortdelay(void)//误差0us
{
unsignedchara,b,c;
for(c=165;c>0;c--)
for(b=100;b>0;b--)
for(a=150;a>0;a--);
_nop_;//ifKeil,requireuseintrins.h
_nop_;//ifKeil,requireuseintrins.h
}
/*****初始化定时器0*****/
voidInitTimer(void)
{
TMOD=0x1;
TH0=0x3c;
TL0=0xb0;//50ms(晶振12M)
}
/*****定时器0中断服务程序*****/
voidtimer0(void)interrupt1
{
TH0=0x3c;
TL0=0xb0;
x++;
}
/*****外部中断0服务程序*****/
voidint0(void)interrupt0
{
EX0=0;//关外部中断0
if(DEC==0&&set_st==1)
{
shangxian--;
if(shangxian<xiaxian)shangxian=xiaxian;
}
elseif(DEC==0&&set_st==2)
{
xiaxian--;
if(xiaxian<0)xiaxian=0;
}
}
/*****外部中断1服务程序*****/
voidint1(void)interrupt2
{
EX1=0;//关外部中断1
if(ADD==0&&set_st==1)
{
shangxian++;
if(shangxian>99)shangxian=99;
}
elseif(ADD==0&&set_st==2)
{
xiaxian++;
if(xiaxian>shangxian)xiaxian=shangxian;
}
}
/*****读取温度*****/
voidcheck_wen(void)
{
uinta,b,c;
c=ReadTemperature()-5;//获取温度值并减去DS18B20的温漂误差
a=c/100;//计算得到十位数字
b=c/10-a*10;//计算得到个位数字
m=c/10;//计算得到整数位
n=c-a*100-b*10;//计算得到小数位
if(m<0){m=0;n=0;}//设置温度显示上限
if(m>99){m=99;n=9;}//设置温度显示上限
}
/*****显示开机初始化等待画面*****/
Disp_init()
{
P2=0xbf;//显示-
P1=0xf7;
Delay(200);
P1=0xfb;
Delay(200);
P1=0xfd;
Delay(200);
P1=0xfe;
Delay(200);
P1=0xff;//关闭显示
}
/*****显示温度子程序*****/
Disp_Temperature()//显示温度
{
P2=0xc6;//显示C
P1=0xf7;
Delay(300);
P2=LEDData[n];//显示个位
P1=0xfb;
Delay(300);
P2=LEDData[m%10];//显示十位
DIAN=0;//显示小数点
P1=0xfd;
Delay(300);
P2=LEDData[m/10];//显示百位
P1=0xfe;
Delay(300);
P1=0xff;//关闭显示
}
/*****显示报警温度子程序*****/
Disp_alarm(ucharbaojing)
{
P2=0xc6;//显示C
P1=0xf7;
Delay(200);
P2=LEDData[baojing%10];//显示十位
P1=0xfb;
Delay(200);
P2=LEDData[baojing/10];//显示百位
P1=0xfd;
Delay(200);
if(set_st==1)P2=0x89;
elseif(set_st==2)P2=0xc7;//上限H、下限L标示
P1=0xfe;
Delay(200);
P1=0xff;//关闭显示
}
/*****报警子程序*****/
voidAlarm()
{
if(x>=10){beep_st=~beep_st;x=0;}
if((m>=shangxian&&beep_st==1)||(m<xiaxian&&beep_st==1))BEEP=0;
elseBEEP=1;
if((m>=shangxian)||(m<xiaxian))
{shortdelay();
JDQ=0;}
elseJDQ=1;
}
/*****主函数*****/
voidmain(void)
{
uintz;
InitTimer();//初始化定时器
EA=1;//全局中断开关
TR0=1;
ET0=1;//开启定时器0
IT0=1;
IT1=1;
check_wen();
check_wen();
for(z=0;z<300;z++)
{
Disp_init();
}
while(1)
{
if(SET==0)
{
Delay(2000);
do{}while(SET==0);
set_st++;x=0;shanshuo_st=1;
if(set_st>2)set_st=0;
}
if(set_st==0)
{
EX0=0;//关闭外部中断0
EX1=0;//关闭外部中断1
check_wen();
Disp_Temperature();
Alarm();//报警检测
}
elseif(set_st==1)
{
BEEP=1;//关闭蜂鸣器
EX0=1;//开启外部中断0
EX1=1;//开启外部中断1
if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
if(shanshuo_st){Disp_alarm(shangxian);}
}
elseif(set_st==2)
{
BEEP=1;//关闭蜂鸣器
EX0=1;//开启外部中断0
EX1=1;//开启外部中断1
if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
if(shanshuo_st){Disp_alarm(xiaxian);}
}
}
}
/*****END*****/
DS18B20.h:
#include<AT89X52.h>
#defineDQP3_6//定义DS18B20总线I/O
/*****延时子程序*****/
voidDelay_DS18B20(intnum)
{
while(num--);
}
/*****初始化DS18B20*****/
voidInit_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ复位
Delay_DS18B20(8);//稍做延时
DQ=0;//单片机将DQ拉低
Delay_DS18B20(80);//精确延时,大于480us
DQ=1;//拉高总线
Delay_DS18B20(14);
x=DQ;//稍做延时后,如果x=0则初始化成功,x=1则初始化失败
Delay_DS18B20(20);
}
/*****读一个字节*****/
unsignedcharReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
Delay_DS18B20(4);
}
return(dat);
}
/*****写一个字节*****/
voidWriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
Delay_DS18B20(5);
DQ=1;
dat>>=1;
}
}
/*****读取温度*****/
unsignedintReadTemperature(void)
{
unsignedchara=0;
unsignedcharb=0;
unsignedintt=0;
floattt=0;
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0x44);//启动温度转换
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0xBE);//读取温度寄存器
a=ReadOneChar();//读低8位
b=ReadOneChar();//读高8位
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t=tt*10+0.5;//放大10倍输出并四舍五入
return(t);
}
/*****END*****/
其中控制部分我用的是5V继电器,可以直接控制你的电机了。
两个电路图都差不多的,只不过我的多了几个调整按键,报警温度可以调的。我的这个程序你完全可以用到你的电路里德
‘柒’ 求教:51单片机智能温控风扇程序编写
一路定时器扫描做数码管和按键,另外一路定时器做pwm调速。主程序循环里面去处理温度读取判断,按键处理等。只提供参考思路,这里是几乎不可能要到别人写好的程序的。
如果想要别人帮你写,要几百,某鱼和某宝上有很多,网络知道没有免费的程序员,你这个程序要花掉好几个小时,半天就花掉了,后续有bug你还要debug,你不会还得问,这种麻吃力不讨好的事情没人做的。。。
你要是来不及,花钱去某鱼和某宝代做是最好的选择。
‘捌’ AT89c2051单片机数字温度控制系统的程序
参考:
http://hi..com/do_sermon/item/78693092ff197abd83d29584
‘玖’ 请教关于单片机温控程序
我在10年做了一个差不多的,也是报警控制的,你借鉴一下吧:
软件设计:
有两个文件,DS18B20.c和DS18B20.h,将这两个文件添加到工程里即可。
DS18B20.c:
/******************************************************************
程序名称:DS18B20温度测量、报警系统
简要说明:DS18B20温度计,温度测量范围0~99.9摄氏度
可设置上限报警温度、下限报警温度
即高于上限值或者低于下限值时蜂鸣器报警
默认上限报警温度为32℃、默认下限报警温度为10℃
报警值可设置范围:最低上限报警值等于当前下限报警值
最高下限报警值等于当前上限报警值
将下限报警值调为0时为关闭下限报警功能
******************************************************************/
#include<AT89X52.h>
#include"DS18B20.h"
#defineuintunsignedint
#defineucharunsignedchar//宏定义
#defineSETP3_1//定义调整键
#defineDECP3_2//定义减少键
#defineADDP3_3//定义增加键
#defineBEEPP3_7//定义蜂鸣器
#defineJDQP3_5
bitshanshuo_st;//闪烁间隔标志
bitbeep_st;//蜂鸣器间隔标志
sbitDIAN=P2^7;//小数点
ucharx=0;//计数器
signedcharm;//温度值全局变量
ucharn;//温度值全局变量
ucharset_st=0;//状态标志
signedcharshangxian=70;//上限报警温度,默认值为70
signedcharxiaxian=0;//下限报警温度,默认值为0
ucharcodeLEDData[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff};
/*****延时子程序*****/
voidDelay(uintnum)
{
while(--num);
}
voidshortdelay()(void)//误差0us
{
unsignedchara,b,c;
for(c=165;c>0;c--)
for(b=100;b>0;b--)
for(a=150;a>0;a--);
_nop_;//ifKeil,requireuseintrins.h
_nop_;//ifKeil,requireuseintrins.h
}
/*****初始化定时器0*****/
voidInitTimer(void)
{
TMOD=0x1;
TH0=0x3c;
TL0=0xb0;//50ms(晶振12M)
}
/*****定时器0中断服务程序*****/
voidtimer0(void)interrupt1
{
TH0=0x3c;
TL0=0xb0;
x++;
}
/*****外部中断0服务程序*****/
voidint0(void)interrupt0
{
EX0=0;//关外部中断0
if(DEC==0&&set_st==1)
{
shangxian--;
if(shangxian<xiaxian)shangxian=xiaxian;
}
elseif(DEC==0&&set_st==2)
{
xiaxian--;
if(xiaxian<0)xiaxian=0;
}
}
/*****外部中断1服务程序*****/
voidint1(void)interrupt2
{
EX1=0;//关外部中断1
if(ADD==0&&set_st==1)
{
shangxian++;
if(shangxian>99)shangxian=99;
}
elseif(ADD==0&&set_st==2)
{
xiaxian++;
if(xiaxian>shangxian)xiaxian=shangxian;
}
}
/*****读取温度*****/
voidcheck_wen(void)
{
uinta,b,c;
c=ReadTemperature()-5;//获取温度值并减去DS18B20的温漂误差
a=c/100;//计算得到十位数字
b=c/10-a*10;//计算得到个位数字
m=c/10;//计算得到整数位
n=c-a*100-b*10;//计算得到小数位
if(m<0){m=0;n=0;}//设置温度显示上限
if(m>99){m=99;n=9;}//设置温度显示上限
}
/*****显示开机初始化等待画面*****/
Disp_init()
{
P2=0xbf;//显示-
P1=0xf7;
Delay(200);
P1=0xfb;
Delay(200);
P1=0xfd;
Delay(200);
P1=0xfe;
Delay(200);
P1=0xff;//关闭显示
}
/*****显示温度子程序*****/
Disp_Temperature()//显示温度
{
P2=0xc6;//显示C
P1=0xf7;
Delay(300);
P2=LEDData[n];//显示个位
P1=0xfb;
Delay(300);
P2=LEDData[m%10];//显示十位
DIAN=0;//显示小数点
P1=0xfd;
Delay(300);
P2=LEDData[m/10];//显示百位
P1=0xfe;
Delay(300);
P1=0xff;//关闭显示
}
/*****显示报警温度子程序*****/
Disp_alarm(ucharbaojing)
{
P2=0xc6;//显示C
P1=0xf7;
Delay(200);
P2=LEDData[baojing%10];//显示十位
P1=0xfb;
Delay(200);
P2=LEDData[baojing/10];//显示百位
P1=0xfd;
Delay(200);
if(set_st==1)P2=0x89;
elseif(set_st==2)P2=0xc7;//上限H、下限L标示
P1=0xfe;
Delay(200);
P1=0xff;//关闭显示
}
/*****报警子程序*****/
voidAlarm()
{
if(x>=10){beep_st=~beep_st;x=0;}
if((m>=shangxian&&beep_st==1)||(m<xiaxian&&beep_st==1))BEEP=0;
elseBEEP=1;
if((m>=shangxian)||(m<xiaxian))
{shortdelay()();
JDQ=0;}
elseJDQ=1;
}
/*****主函数*****/
voidmain(void)
{
uintz;
InitTimer();//初始化定时器
EA=1;//全局中断开关
TR0=1;
ET0=1;//开启定时器0
IT0=1;
IT1=1;
check_wen();
check_wen();
for(z=0;z<300;z++)
{
Disp_init();
}
while(1)
{
if(SET==0)
{
Delay(2000);
do{}while(SET==0);
set_st++;x=0;shanshuo_st=1;
if(set_st>2)set_st=0;
}
if(set_st==0)
{
EX0=0;//关闭外部中断0
EX1=0;//关闭外部中断1
check_wen();
Disp_Temperature();
Alarm();//报警检测
}
elseif(set_st==1)
{
BEEP=1;//关闭蜂鸣器
EX0=1;//开启外部中断0
EX1=1;//开启外部中断1
if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
if(shanshuo_st){Disp_alarm(shangxian);}
}
elseif(set_st==2)
{
BEEP=1;//关闭蜂鸣器
EX0=1;//开启外部中断0
EX1=1;//开启外部中断1
if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
if(shanshuo_st){Disp_alarm(xiaxian);}
}
}
}
/*****END*****/
DS18B20.h:
#include<AT89X52.h>
#defineDQP3_6//定义DS18B20总线I/O
/*****延时子程序*****/
voidDelay_DS18B20(intnum)
{
while(num--);
}
/*****初始化DS18B20*****/
voidInit_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ复位
Delay_DS18B20(8);//稍做延时
DQ=0;//单片机将DQ拉低
Delay_DS18B20(80);//精确延时,大于480us
DQ=1;//拉高总线
Delay_DS18B20(14);
x=DQ;//稍做延时后,如果x=0则初始化成功,x=1则初始化失败
Delay_DS18B20(20);
}
/*****读一个字节*****/
unsignedcharReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
Delay_DS18B20(4);
}
return(dat);
}
/*****写一个字节*****/
voidWriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
Delay_DS18B20(5);
DQ=1;
dat>>=1;
}
}
/*****读取温度*****/
unsignedintReadTemperature(void)
{
unsignedchara=0;
unsignedcharb=0;
unsignedintt=0;
floattt=0;
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0x44);//启动温度转换
Init_DS18B20();
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0xBE);//读取温度寄存器
a=ReadOneChar();//读低8位
b=ReadOneChar();//读高8位
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t=tt*10+0.5;//放大10倍输出并四舍五入
return(t);
}
/*****END*****/
其中控制部分我用的是5V继电器,可以直接控制你的电机了。
两个电路图都差不多的,只不过我的多了几个调整按键,报警温度可以调的。我的这个程序你完全可以用到你的电路里的