📄 18b20.c
字号:
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define DELAY_CLOSEDIS 5 //没按键,延时5秒关背光
#define DELAY_INPUT 5 //没按键,延时5秒返回显示温度
#define KEYCODE_UP 0x1 //加温度
#define KEYCODE_DOWN 0x2 //减温度
#define KEYCODE_FAN 0x4 //设置风速
#define KEYCODE_ONOFF 0x8 //开关风机
#define KEYCODE_TIME 0x6 //设置时间
#define KEYCODE_PWM 0xc //设置PWM
#define WAIT_cCurrTemp 0
#define MAX_TEMP 32
#define MIN_TEMP 15
sbit bDQ = P1^0; // DS1820数据线
sbit bLED_light = P1^1; // LED 背光驱动,低有效
sbit bKey1 = P1^2; // 键盘扫描线1,高有效
sbit bKey2 = P1^3; // 键盘扫描线2,高有效
sbit bKey3 = P1^4; // 键盘输入线1,低有效
sbit bKey4 = P1^5; // 键盘输入线2,低有效
sbit bFAN = P0^5; // 开风机PWM, 低有效
sbit bAC_Zero = P3^2; // 过零脉冲输入口
//uchar ucCount1; // 记录过零脉冲宽度
uchar ucCount; // 可控占空比0-95%宽度=10mS-ucCount1
uchar ucPWM; // 输出占空比
uchar bdata ucLED;
sbit bFAN_AUTO = ucLED^3;
sbit bFAN_LOW = ucLED^2;
sbit bFAN_MIN = ucLED^1;
sbit bFAN_HIGH = ucLED^0;
bit bPowerON = 0; // 开机状态=1
uchar ucTimer;
/**************** LED显示相关变量 ********************/
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, C, 度
const uchar code aucLEDNUMCODE[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x7,0x7F,0x6F,0x39,0x63};
const uchar code aucLEDcs[]={0x17,0x1b,0x1d,0x1e,0x0f}; /* LED位选 */
uchar ucScanIndex; /* 数码管位选控制 */
uchar ucLEDData[4]; /* 临时显示缓冲数组 */
uchar ucLEDFlash[5]; /* 显示缓冲数组 */
bit bNeg; /* 负号标志 */
uchar ucFlashType;
bit bFlash;
uchar ucCurrSec;
uchar ucSystemStatus;
uchar ucDelaySec; //切换延时秒数
uchar ucCloseDelaySec; //关背光延时秒数
uchar aucCurrTime[2];
uchar aucTmpValue[2];
uchar ucFanSpeed;
char cCurrTemp;
char cSetTemp;
/**********************************************************************/
uchar ucLongDelay; //长按键
uchar ucDelayKey;
uint nDelay100uS;
char cKEYCode;
bit bStill;
bit bUpdateDisOK;
/****************************** 函数声明 ******************************/
void DisplayValue(char *Value);
void SetFanStatus(void);
void DisposeKey(void);
void ScanLED(void);
uchar SCANKEY(void);
void DisplayTemp(char Temp);
void Key(uchar k);
void DisposeCurrTime(void);
void DisposeDelay(uchar LType);
void UpdateDis(uchar status);
/**********************************************************************/
bit Init_DS18B20(void)
{
bit sysOK = 0;
bDQ = 0; // 单片机将DQ拉低
nDelay100uS = 6;
while(nDelay100uS != 0); // 精确延时 大于 500us
bDQ = 1; // 拉高总线
nDelay100uS = 4;
while(bDQ && nDelay100uS); // 稍做延时后 如果bDQ=0则初始化成功 bDQ=1则初始化失败
if(nDelay100uS != 0)
{
nDelay100uS = 4;
while(~bDQ && nDelay100uS);
if(nDelay100uS != 0)
{
sysOK = 1; // 在延时时间内18B20有应答证明初始化成功
}
}
return(sysOK);
}
/**********************************************************************/
char ReadOneChar(void)
{
uchar i;
uchar j;
uchar dat = 0;
for (i=8; i>0; i--)
{
bDQ = 0; // 给脉冲信号
bDQ = 0;
dat >>= 1;
bDQ = 1; // 给脉冲信号
if(bDQ)
{
dat |= 0x80;
}
j = 8;
while(j--)
{
}
}
return(dat);
}
/**********************************************************************/
void WriteOneChar(uchar dat)
{
uchar i, j;
for (i = 8; i > 0; i--)
{
bDQ = 0;
bDQ = 0;
bDQ = dat & 0x01;
j = 8;
while(j--)
{
}
bDQ = 1;
dat >>= 1;
}
}
/**********************************************************************/
char ReadTemperature(void)
{
bit f;
union UniTEMP
{
uint T;
uchar T_byte[2];
}idata uT;
f=Init_DS18B20();
if(f != 0) // 18B20初始化成功?
{
ET0 = 0;
ET1 = 0;
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0xBE); // 读取温度寄存器等(共可读9个寄存器) 前两个就是温度
uT.T_byte[1] = ReadOneChar();
uT.T_byte[0] = ReadOneChar();
ET0 = 1;
ET1 = 1;
}
else
{
return(99);
}
f = Init_DS18B20();
if(f != 0)
{
ET0 = 0;
ET1 = 0;
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
nDelay100uS = 1100; // 等待AD转换结束9位AD约100mS
ET0 = 1;
ET1 = 1;
}
else
{
return(99);
}
bNeg = 0;
if((uT.T_byte[0] & 0x80) != 0)// 负数标志位为1?
{
uT.T = ~uT.T+1; // 转换成正数
bNeg = 1; // 负数标志置位
}
uT.T += 8; // 四舍五入
uT.T >>= 4; // 取整
return(uT.T_byte[1]);
}
/********************* 初始化变量 **********************/
void INITVar(void)
{
//自己添加
}
/****************************** 主函数 *********************************/
void main()
{
TMOD = 0x11;
TH0 = -30; // 定时器0
TL0 =39; // 定时中断
TR0 = 1;
ET0 = 1;
TH1 = -3; // 定时器1
TL1 = 0; // 定时中断
TR1 = 1;
ET1 = 1;
EA = 1;
Init_DS18B20();
if(Init_DS18B20())
{
bLED_light = 0; // 开机DS18B20正常就开背光
ucCloseDelaySec = 3; // 延时3秒关背光
}
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
nDelay100uS = 1100; // 等待AD转换结束9位AD约100mS
INITVar();
while(1)
{
if(nDelay100uS == 0)
{
cCurrTemp = ReadTemperature();
if(ucFlashType != FLASH_PWM)
{
SetFanStatus();
}
}
if(cKEYCode != 0)
{
DisposeKey(); //处理键盘数据
}
UpdateDis(ucSystemStatus);
if(ucDelaySec == 0)
{
DisposeDelay(ucSystemStatus);//处理延时
}
if(ucCloseDelaySec == 0)
{
bLED_light = 1; //关背光
}
DisposeCurrTime();
}
}
/***************** 定时器1中断:多任务分时处理 **************************/
void timer1() interrupt 3 //约840uS中断1次,11次约为10mS,即100Hz波的1个周期
{
TH1 = -3; //定时器1重装
//////////////////// 任务1:PWM输出 //////////////////////////////////
if(bAC_Zero == 0)
{
if(ucCount < 100)
ucCount += 5; // 定时器1中断记数有效控制宽度
}
else
{
ucCount = 0;
}
if(ucCount <= 100 - ucPWM)
{
bFAN = 1;
}
else
{
bFAN = 0;
}
///////////////////// 任务2:显示刷新 ////////////////////////
ScanLED();
///////////////////// 任务3:延时 ////////////////////////////
if(nDelay100uS)
{
nDelay100uS--;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -