全部代码:主函数
#include <STC15F2K60S2.H>
#include "iic.h"
#include "onewire.h"
typedef struct
{
unsigned char b1:1;
unsigned char b2:1;
unsigned char b3:1;
unsigned char b4:1;
unsigned char b5:1;
unsigned char b6:1;
unsigned char b7:1;
unsigned char b8:1;
}bits;
typedef union
{
unsigned char Hex;
bits B;
}HexToBit;
HexToBit led_ctrl; // 控制led的字节
unsigned char code smg_duanma[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char smg[8];
unsigned char Tmax=30,Tmin=20;//退出参数界面后生效的参数。不用在数码管显示
unsigned char tTmax=30,tTmin=20;//在调整参数表界面使用
void vDevice_Process(unsigned char p2dat,unsigned char p0dat)
{
P0=p0dat;
P2 = (P2&0x1f)|p2dat;
P2 = (P2&0x1f)|0x00;
}
//定时器2
void Timer2Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x20; //设置定时初值
T2H = 0xD1; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
EA=1;
IE2 |= 0x04;
}
//读取温度
unsigned char temp;
void vRead_temp()
{
temp = rd_temperature();
}
//数码管操作函数
bit mode_smg=0;
bit mode_set=1;
unsigned int cnt_smg;
void vSMG_Process()
{
if(mode_smg==0)//显示温度
{
smg[0]=0xc6;
smg[1]=0xff;
smg[2]=0xff;
smg[3]=0xff;
smg[4]=0xff;
smg[5]=0xff;
smg[6]=smg_duanma[temp/10];
smg[7]=smg_duanma[temp%10];
}
if(mode_smg==1)//显示参数
{
if(mode_set==0)//设置上限
{
smg[0]=0x8c;
smg[1]=0xff;
smg[2]=0xff;
if(cnt_smg<500)
{
smg[3]=smg_duanma[tTmax/10];
smg[4]=smg_duanma[tTmax%10];
}
else if(cnt_smg<1000)
{
smg[3]=0xff;
smg[4]=0xff;
}
else
{
cnt_smg=0;
}
smg[5]=0xff;
smg[6]=smg_duanma[tTmin/10];
smg[7]=smg_duanma[tTmin%10];
}
if(mode_set==1)//设置下限
{
smg[0]=0x8c;
smg[1]=0xff;
smg[2]=0xff;
smg[3]=smg_duanma[tTmax/10];
smg[4]=smg_duanma[tTmax%10];
smg[5]=0xff;
if(cnt_smg<500)
{
smg[6]=smg_duanma[tTmin/10];
smg[7]=smg_duanma[tTmin%10];
}
else if(cnt_smg<1000)
{
smg[6]=0xff;
smg[7]=0xff;
}
else
{
cnt_smg=0;
}
}
}
}
//数码管显示
void vSMG_Show()
{
static unsigned char i;
vDevice_Process(0xc0,0x00);
vDevice_Process(0xe0,smg[i]);
vDevice_Process(0xc0,0x01<<i);
i=(i+1)%8;
}
//独立按键BTN
unsigned char Trg,Cont;
void Three_Keys()
{
unsigned char ReadData = P3^0xff;
Trg = ReadData&(ReadData^Cont);
Cont = ReadData;
}
//按键扫描
unsigned int cnt_key;
void vScan_Keys()
{
if(cnt_key>=10) //10ms扫描一次 消抖
{
cnt_key=0;
Three_Keys();
if(Trg&0x01)//S7
{
if(mode_smg==1)
{
if(mode_set==0)
{
if(tTmax>0)tTmax--;
}
else if(mode_set==1)
{
if(tTmin>0)tTmin--;
}
}
}
if(Trg&0x02)//S6
{
if(mode_smg==1)
{
if(mode_set==0)
{
if(tTmax<99)tTmax++;
}
else if(mode_set==1)
{
if(tTmin<99)tTmin++;
}
}
}
if(Trg&0x04)//S5
{
if(mode_smg==1)
{
mode_set=~mode_set;
}
}
if(Trg&0x08)//S4
{
mode_smg=!mode_smg;
if(mode_smg==1)
{
mode_set=1;//进入设置时选择下限参数设置
tTmax=Tmax;//将设置参数初始化为真实参数,避免显示上次保存的不合理参数
tTmin=Tmin;
}
if(mode_smg==0)
{
if(tTmax>=tTmin)
{
Tmax=tTmax;
Tmin=tTmin;
led_ctrl.B.b4=1;
}
else
{
led_ctrl.B.b4=0;
}
}
}
}
}
//DAC输出
void vDAC_out()
{
if(temp>Tmax)
{
DAC_out(204); //255/5*4 4V
led_ctrl.B.b1=0;//L1点亮
led_ctrl.B.b2=1;
led_ctrl.B.b3=1;
}
else if((temp<Tmax)&&(temp>Tmin))
{
DAC_out(153); //3V
led_ctrl.B.b1=1;//L2点亮
led_ctrl.B.b2=0;
led_ctrl.B.b3=1;
}
else if(temp<Tmin)
{
DAC_out(102); //2V
led_ctrl.B.b1=1;//L3点亮
led_ctrl.B.b2=1;
led_ctrl.B.b3=0;
}
}
//初始化系统
void System_init()
{
led_ctrl.Hex = 0xff;
vDevice_Process(0x80, led_ctrl.Hex);
vDevice_Process(0xa0, 0x00);
}
void main()
{
System_init();
Timer2Init();
while(1)
{
vRead_temp();
vSMG_Process();
vScan_Keys();
vDAC_out();
}
}
//定时器服务
void time2_service() interrupt 12
{
cnt_key++;
cnt_smg++;
vSMG_Show();
vDevice_Process(0x80, led_ctrl.Hex);
}
官方iic驱动函数
#include "reg52.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
//DAC输出
void DAC_out(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
官方单总线驱动函数
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t = t*12;
while(t--);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
//温度读取
unsigned char rd_temperature()
{
unsigned int temp;
unsigned char lsb,msb;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
lsb = Read_DS18B20();
msb = Read_DS18B20();
temp = ((msb<<8)|lsb)*0.0625;
return temp;
}