一,代码部分
1,ds18b20.c
#include "reg52.h"
#include "onewire.h"
void Convert_18b20()
{
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0x44);//开启温度转化
}
float Read_18b20()
{
int t;
float Temp;
unsigned char LSB,MSB;
init_ds18b20();//初始化
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
t=(MSB << 8) | LSB;
Temp=t/16.0;
return Temp;
}
void Init_18b20()
{
int T;
Convert_18b20();
do
{
T=Read_18b20();
}while(T>60);
}
2,onewire
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
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(50);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(50);
}
//从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(50);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
3,pcf8591.c
#include "reg52.h"
#include "iic.h"
//float Read_ADC()//RB2模拟量转数字量
//{
// unsigned char temp;
// float v;
// //伪写操作
// IIC_Start();
// IIC_SendByte(0x90);//设备地址,最后一位置0为可写入
// IIC_WaitAck();
// IIC_SendByte(0x43);//RB2连接在8591的通道3
// IIC_WaitAck();
//
// IIC_Start();
// IIC_SendByte(0x91);
// IIC_WaitAck();
// temp=IIC_RecByte();//0~255
// IIC_SendAck(1);
// IIC_Stop();
// v=temp*5/255.0;
// return v;
//}
void DAC(float temp)
{
unsigned char u;
u=temp*51;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_SendByte(u); //0~255
IIC_SendAck(1);
IIC_Stop();
}
3,smgshow.c
#include "reg52.h"
void Delay(int t)
{
while(t--);
}
void HC573(unsigned char channel, unsigned char dat)
{
P0=dat;
switch(channel)
{
case 4:
P2=(P2 & 0x1f) | 0x80;//选通Y4C,LED
break;
case 5:
P2=(P2 & 0x1f) | 0xa0;//选通Y5C,蜂鸣器,继电器
break;
case 6:
P2=(P2 & 0x1f) | 0xc0;//选通Y6C,数码管位选
break;
case 7:
P2=(P2 & 0x1f) | 0xe0;//选通Y7C,数码管段码
break;
}
P2=(P2 & 0x1f) | 0x00;
}
void Display_SMG(unsigned char pos,unsigned char val)
{
HC573(6,0x01<<pos);
HC573(7,val);
Delay(500);
// HC573(6,0x01<<pos);
HC573(7,0xff);//消隐
}
void Display_ALL(unsigned char dat)
{
HC573(6,0xff);
HC573(7,dat);
}
4,iic.c
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#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;
//}
5,main.c
#include "reg52.h"
#include "ds18b20.h"
#include "pcf8591.h"
#include "smgshow.h"
sbit R1=P3^2;
sbit R2=P3^3;
sbit C1=P4^4;
sbit C2=P4^2;
unsigned int T;//DS18B20温度
int T_stand=25;
float U_out;//输出的电压值
int U_smg;//用于显示输出电压
bit sta_DAC=0;
int T_temp=25;
void Read_T()//测量
{
Convert_18b20();
T=Read_18b20()*100;
}
void Out_DAC()
{
if(sta_DAC==0 && (T/100)<T_stand)//模式1
{
U_out=0;
DAC(U_out);
U_smg=U_out*100;
}
else
{
U_out=5;
DAC(U_out);
U_smg=U_out*100;
}
if(sta_DAC==1)//模式2
{
if((T/100)<20)
{
U_out=1;
DAC(U_out);
U_smg=U_out*100;
}
else if((T/100)>20 && (T/100)<40)
{
U_out=(T/100.0)*3/20.0;
DAC(U_out);
U_smg=U_out*100;
}
else
{
U_out=4;
DAC(U_out);
U_smg=U_out*100;
}
}
}
unsigned char sta_smg=0;
void SMGWork()
{
switch(sta_smg)
{
case 0:
Display_SMG(0,0xc6);
Display_SMG(4,SMGnotdotduanma[T/1000]);
Display_SMG(5,SMGdotduanma[T/100%10]);
Display_SMG(6,SMGnotdotduanma[T/10%10]);
Display_SMG(7,SMGnotdotduanma[T%10]);
break;
case 1:
Display_SMG(0,0x8c);
Display_SMG(6,SMGnotdotduanma[T_temp/10%10]);
Display_SMG(7,SMGnotdotduanma[T_temp%10]);
break;
case 2:
Display_SMG(0,0x88);
Display_SMG(5,SMGdotduanma[U_smg/100%10]);
Display_SMG(6,SMGnotdotduanma[U_smg/10%10]);
Display_SMG(7,SMGnotdotduanma[U_smg%10]);
break;
}
}
void Scan_KBD()//矩阵键盘扫描
{
//扫描S4
R2=0;
R1=C1=C2=1;
if(C1==0)
{
Delay(500);
if(C1==0)//实现显示状态切换
{
if(sta_smg==0)
{
sta_smg=1;
}
else if(sta_smg==1)
{
sta_smg=2;
T_stand=T_temp;
}
else
{
sta_smg=0;
}
while(C1==0)
{
SMGWork();
}
}
}
//扫描S8
R2=0;
R1=C1=C2=1;
if(C2==0)
{
Delay(500);
if(C2==0)
{
if(sta_smg==1)
{
T_temp=T_temp-1;
if(T_temp<0)
T_temp=99;
}
while(C2==0)
{
SMGWork();
}
}
}
//扫描S9
R1=0;
R2=C1=C2=1;
if(C2==0)
{
Delay(500);
if(C2==0)
{
if(sta_smg==1)
{
T_temp=T_temp+1;
if(T_temp>99)
{
T_temp=0;
}
}
while(C2==0)
{
SMGWork();
}
}
}
//扫描S5
R1=0;
R2=C1=C2=1;
if(C1==0)
{
Delay(500);
if(C1==0)
{
if(sta_DAC==0)
{
sta_DAC=1;
}
else
{
sta_DAC=0;
}
while(C1==0)
{
SMGWork();
}
}
}
}
unsigned char sta_LED=0xff;
void LED()
{
if(sta_DAC==0)
{
sta_LED &= ~0x01;
HC573(4,sta_LED);
}
else
{
sta_LED |= 0x01;
HC573(4,sta_LED);
}
if(sta_smg==0)
{
sta_LED &= ~0x02;
HC573(4,sta_LED);
}
else
{
sta_LED |= 0x02;
HC573(4,sta_LED);
}
if(sta_smg==1)
{
sta_LED &= ~0x04;
HC573(4,sta_LED);
}
else
{
sta_LED |= 0x04;
HC573(4,sta_LED);
}
if(sta_smg==2)
{
sta_LED &= ~0x08;
HC573(4,sta_LED);
}
else
{
sta_LED |= 0x08;
HC573(4,sta_LED);
}
}
void Inti_stsyem()
{
HC573(4,0xff);
HC573(5,0x00);
Display_ALL(0xff);
Init_18b20();
}
void main()
{
Inti_stsyem();
while(1)
{
Scan_KBD();
Out_DAC();
Read_T();
SMGWork();
LED();
}
}
除了温度跟电压的区间线性变化内容较新外,并没有其他难点,明天做一做第二场看会不会难一点。
二,总结
这题做了不到2个小时,很多功能都可以延用之前的。明天开始客观题。