http://blog.gkong.com/more.asp?name=lidongfa&id=74990
这是本人做的一个机箱温控的一段程序。是PLM51的代码,主频12MHz。
$db pw(94) rom(large) co ot(3) sb
MCS51OS: DO;
$nolist
$include(\PLM51\REG51.DCL)
$include(\PLM51\LIT.DCL)
$include(DS18B20.dcl)
$list
DCL System$Err LITERALLY '0';
DCL Hard$Err LITERALLY '1';
DCL Command$Err LITERALLY '2';
DCL Time$Err LITERALLY '3';
DCL Date$Err LITERALLY '4';
DCL TemperatureLimit LITERALLY '40';
/*=========================================================================*/
DCL Copyright(*) BYTE CON
(
'Copyright(c) 2003 by LiDongfa.All right reserved'
);
DCL Version BYTE CON(00H);
/*=========================================================================*/
/* */
/* System clock interrupt serve program. */
/* Use the 1# timer and 1# register. */
/* */
/*=========================================================================*/
DCL Timer0Cnt WORD CON(1000);
DCL Char$Img(31) BYTE CON
(
/* edga fbcp */
/* 0 */ 0010$0001B, /* 0 */
/* 1 */ 1111$1001B, /* 1 */
/* 2 */ 0000$1011B, /* 2 */
/* 3 */ 1000$1001B, /* 3 */
/* 4 */ 1101$0001B, /* 4 */
/* 5 */ 1000$0101B, /* 5 */
/* 6 */ 0000$0101B, /* 6 */
/* 7 */ 1110$1001B, /* 7 */
/* 8 */ 0000$0001B, /* 8 */
/* 9 */ 1000$0001B, /* 9 */
/* */ 1111$1111B /* 10 */
);
DCL Disp$Buf(2) BYTE;
DCL (Disp$Buf$Ptr) BYTE;
DCL LED1 LITERALLY 'P32';
DCL LED2 LITERALLY 'P33';
DCL TMDAT LITERALLY 'P35';
DCL FANOUT LITERALLY 'P37';
DCL FanOutTmp BIT;
DCL FirstRead BIT;
DCL FanOutDelay BYTE;
DCL Temperature WORD; /* 读取后温度值存于Temperature中 */
DCL Temp WORD;
DCL Second WORD;
DCL MSecond$Cnt WORD;
Display$Temp:PROCEDURE PUB;
Temp = Temperature / 16;
Disp$Buf(0) = Char$Img(Temp MOD 10);
Disp$Buf(1) = Char$Img((Temp / 10) MOD 10);
END Display$Temp;
System$Clock:PROCEDURE USING 1;
MSecond$Cnt = MSecond$Cnt + 1;
IF MSecond$Cnt MOD 4 = 0 THEN
DO;
LED1 = 1;
LED2 = 1;
P1 = Disp$Buf(Disp$Buf$Ptr);
IF Disp$Buf$Ptr = 0 THEN
LED1 = 0;
ELSE IF Disp$Buf$Ptr = 1 THEN
LED2 = 0;
Disp$Buf$Ptr = Disp$Buf$Ptr + 1;
IF Disp$Buf$Ptr >= 2 THEN
Disp$Buf$Ptr = 0;
END;
IF MSecond$Cnt < 1000 THEN
RETURN;
MSecond$Cnt = 0;
Second = Second + 1;
IF FanOutDelay > 0 THEN
FanOutDelay = FanOutDelay - 1;
END System$Clock;
/*=========================================================================*/
clk$Inter: PROCEDURE INTERRUPT 1 USING 1;
TR0 = 0;
TH0 = HIGH(-Timer0Cnt + 34);
TL0 = LOW(-Timer0Cnt + 34);
TR0 = 1;
CALL System$Clock;
END clk$Inter;
/* End of System clock interrupt serve program. */
/*=======================================================================*/
Sys$Reset:PROCEDURE;
DCL i BYTE;
DISABLE;
MSecond$Cnt = 0;
Second = 0;
TH0 = HIGH(-Timer0Cnt);
TL0 = LOW(-Timer0Cnt);
IP = 0000$0010B;
IE = 0000$0010B;
TMOD = 0001$0001B;
TCON = 0001$0000B;
PCON = 0;
P1 = 0FFH;
P3 = 0FFH;
Disp$Buf$Ptr = 0;
Disp$Buf(0) = Char$Img(10);
Disp$Buf(1) = Char$Img(10);
Temperature = 0;
FirstRead = 1;
FanOutDelay = 20;
ENABLE;
END Sys$Reset;
/* 延时部分 */
dmsec:PROCEDURE(tm) PUB;
DCL tm WORD;
DCL i BYTE;
DO WHILE (tm > 0);
i = 150;
DO WHILE (i > 0);
i = i - 1;
END;
tm = tm - 1;
END;
END dmsec;
/* 发送复位 */
tmreset:PROCEDURE PUB;
DCL i BYTE;
TMDAT = 0;
i = 150;
DO WHILE(i > 0);
i = i - 1; /* 延时 900 uS(11.0592Mhz时) */
END;
TMDAT = 1;
i = 5;
DO WHILE (i > 0);
i = i - 1;
END;
END tmreset;
/* 判断DS1820是否存在的子程序。最好不要用,因为当器件不存在时将会进入死循环 */
/* 等待存在脉冲 */
/* 判断器件是否存在 */
tmpre:PROCEDURE PUB;
DCL i BYTE;
DO WHILE (TMDAT);
END;
DO WHILE (NOT TMDAT);
END;
i = 7;
DO WHILE (i > 0);
i = i - 1;
END;
END tmpre;
/* 读一位 */
tmrbit:PROCEDURE BIT PUB;
DCL i BYTE;
DCL dat BIT;
TMDAT = 0;
i = i + 1;
i = i + 1;
TMDAT = 1;
i = 2;
DO WHILE (i > 0);
i = i - 1; /* 延时 */
END;
dat = TMDAT;
i = 10;
DO WHILE (i > 0);
i = i - 1; /* 延时 */
END;
RETURN (dat);
END tmrbit;
/* 读一个字节 */
tmrbyte:PROCEDURE BYTE PUB;
DCL (j,dat) BYTE;
DCL (i) BYTE;
dat = 0;
DO i = 1 TO 8;
j = EXPAND(tmrbit);
dat = SHL(j,7) OR SHR(dat,1);
END;
RETURN (dat);
END tmrbyte;
/* 写一个字节 */
tmwbyte:PROCEDURE(dat) PUB;
DCL dat BYTE;
DCL testb BIT;
DCL (i,j) BYTE;
DO j = 1 TO 8;
testb = BOOLEAN(dat AND 1);
dat = SHR(dat,1);
IF testb = 1 THEN
DO;
TMDAT = 0; /* 写1 */
i = i + 1;
i = i + 1;
TMDAT = 1;
i = 10;
DO WHILE (i > 0);
i = i - 1;
END;
END;
ELSE
DO;
TMDAT = 0; /* 写0 */
i = 10;
DO WHILE (i > 0);
i = i - 1;
END;
TMDAT = 1;
i = i + 1;
i = i + 1;
END;
END;
END tmwbyte;
/* 发送ds1820 开始转换 */
tmstart :PROCEDURE PUB;
CALL tmreset; /* 复位 */
/* CALL tmpre; */ /* 等待存在脉冲 */
CALL dmsec (1); /* 延时 */
CALL tmwbyte (0CCH); /* 跳过序列号命令 */
CALL tmwbyte (044H); /* 发转换命令 44H */
END tmstart;
/* 读取温度 */
tmrtemp :PROCEDURE PUB;
DCL (a,b) BYTE;
CALL tmreset; /* 复位 */
/* CALL tmpre; */ /* 等待存在脉冲 */
CALL dmsec (1); /* 延时 */
CALL tmwbyte (0CCH); /* 跳过序列号命令 */
CALL tmwbyte (0BEH); /* 发送读取命令 */
a = tmrbyte; /* 读取低位温度 */
b = tmrbyte; /* 读取高位温度 */
Temp = b * 256;
Temp = Temp + a;
IF FirstRead = 1 THEN
DO;
FirstRead = 0;
Temperature = Temp;
END;
ELSE
DO;
Temperature = (Temperature * 9 + Temp) / 10;
END;
END tmrtemp;
/* the program entry point */
DCL Cnt BYTE;
CALL Sys$Reset;
Cnt = 0;
MainLoop:
/* 这段是调试代码 */
/*
CALL dmsec (1000);
Disp$Buf(0) = Char$Img(Cnt);
Disp$Buf(1) = Char$Img(Cnt);
Cnt = Cnt + 1;
IF Cnt >= 10 THEN
DO;
Cnt = 0;
END;
IF FanOutTmp = 1 THEN
DO;
FanOutTmp = 0;
FANOUT = FanOutTmp;
END;
ELSE
DO;
FanOutTmp = 1;
FANOUT = FanOutTmp;
END;
*/
/* 启动ds18b20 */
DISABLE;
CALL tmstart;
ENABLE;
CALL dmsec (1200);
/* 读取温度,执行完毕温度将存于Temperature中 */
DISABLE;
CALL tmrtemp;
ENABLE;
Temp = Temperature / 16;
IF FanOutDelay = 0 THEN
DO;
IF Temp >= TemperatureLimit THEN
DO;
FanOutTmp = 0;
FANOUT = FanOutTmp;
FanOutDelay = 20;
END;
ELSE IF Temp < TemperatureLimit - 1 THEN
DO;
FanOutTmp = 1;
FANOUT = FanOutTmp;
FanOutDelay = 20;
END;
END;
CALL Display$Temp;
GOTO MainLoop;
END MCS51OS;
|