//溫控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繼電器,可以直接控制你的電機了。
兩個電路圖都差不多的,只不過我的多了幾個調整按鍵,報警溫度可以調的。我的這個程序你完全可以用到你的電路里的