首先这是程序设计题
一下则是程序代码
#include "reg52.h"
#include "onewire.h"
#include "iic.h"
sfr P4=0xc0;
sbit R1=P3^0;
sbit R2=P3^1;
sbit R3=P3^2;
sbit R4=P3^3;
sbit C4=P3^4;
sbit C3=P3^5;
sbit C2=P4^2;
sbit C1=P4^4;
unsigned char SMG_stat=0; //0:温度显示 1:参数设置 2:DAC输出
bit K5_mode=0; //通过S5切换的模式1(0)和模式2(1)
unsigned char P_temper=25; //参数设置界面的参数
unsigned char code SMG_duanma[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};//数码管断码
unsigned char code SMG_dot[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//数码管断码(包含小数点的断码)
//寄存器选择
void selectHC573(unsigned char channel,unsigned char dat)
{
P2 = (P2 & 0x1f) | 0x00; //赋值之前,关闭所有锁存器,防止冲突
P0 = dat; //设置待赋值数据
switch(channel)
{
case 4:P2=(P2&0x1f)|0x80; break; //控制LED灯
case 5:P2=(P2&0x1f)|0xa0; break; //控制蜂鸣器继电器
case 6:P2=(P2&0x1f)|0xc0; break; //控制数码管显示位置
case 7:P2=(P2&0x1f)|0xe0; break; //控制数码管显示数字
case 0:P2=(P2&0x1f)|0x00; break; //不选择锁存器
}
P2 = (P2 & 0x1f) | 0x00; //赋值完成后,关闭所有锁存器
}
//延迟函数
void delay(unsigned int t)
{
while(t--);
}
//延迟函数
void delay_key(unsigned char t)
{
while(t--);
}
//========================温度读取========================================
unsigned int temper=0; //用于存储温度的参数
void DisSMG();
//读取温度的函数
void Read_temper()
{
unsigned char LSB,MSB; //定义两个变量
init_ds18b20(); //初始化DS18B20
Write_DS18B20(0xcc); //跳过rom指令
Write_DS18B20(0x44); //转换温度,启动DS18B20进行温度转换,结果保存在高速RAM中
DisSMG(); //动态刷新数码管
init_ds18b20(); //初始化DS18B20
Write_DS18B20(0xcc); //跳过ROM指令,忽略64位ROM地址,直接向DS18B20发起温度转换指令
Write_DS18B20(0xbe); //读数据指令,读取高速暂存存储器9个字节的内容
LSB=Read_DS18B20(); //读取温度低八位
MSB=Read_DS18B20(); //读取温度高八位
DisSMG(); //动态刷新数码管
temper=MSB; //先把高八位赋给temp
temper=(temper<<8)|LSB; //将temp左移八位,将低八位空出来后或上LSB组成16位温度数据
temper=temper*0.0625*100;//保留二位小数
}
//=======================================================================
//========================DAC==========================================
unsigned int DAC_dat = 0;
void Read_DAC_dat(unsigned char dat)
{
I2CStart(); //IIC总线起始信号
I2CSendByte(0x90); //PCF8951的写设备地址
I2CWaitAck(); //等待从机应答
I2CSendByte(0x43); //写入PCF8591的控制字节
I2CWaitAck(); //等待从机应答
I2CSendByte(dat);
I2CWaitAck(); //产生非应答信号
I2CStop(); //IIC总线停止信号
}
//=======================================================================
//=========================DAC输出模式=====================================
void DAC_mode()
{
if(K5_mode==0)
{
if(temper<P_temper*100)
{
Read_DAC_dat(0);
DAC_dat=0;
}
else
{
Read_DAC_dat(255);
DAC_dat=500;
}
}
if(K5_mode==1)
{
if(temper<=2000)
{
Read_DAC_dat(255/5);
DAC_dat=100;
}
else if(temper<=4000&&temper>=2000)
{
Read_DAC_dat((255/5)*0.15*((temper/100)-2));
DAC_dat=(0.15 * (temper/100) - 2) * 100;
}
else if(temper>=4000)
{
Read_DAC_dat(255/5*4);
DAC_dat=400;
}
}
}
//=======================================================================
//=========================数码管显示========================================
void DisSMG_bit(unsigned char dat,unsigned char pos)
{
selectHC573(6,0x01<<pos); //数码管位选
selectHC573(7,dat); //数码管内容
delay(500); //数码管动态显示需要的延迟函数
selectHC573(0,0xff);
}
void DisSMG_all(unsigned char dat)//在某些数码管动态后统一关闭数码管
{
selectHC573(6,0xff); //数码管位选
selectHC573(7,dat); //数码管内容
selectHC573(0,0xff);
}
void DisSMG()
{
if(SMG_stat==0)//温度显示
{
DisSMG_bit(0xc6,0);
DisSMG_bit(SMG_duanma[(temper/1000)%10],4);
DisSMG_bit(SMG_dot[(temper/100)%10],5);
DisSMG_bit(SMG_duanma[(temper/10)%10],6);
DisSMG_bit(SMG_duanma[temper%10],7);
}
else if(SMG_stat==1)//参数显示
{
DisSMG_bit(0x8c,0);
DisSMG_bit(SMG_duanma[(P_temper/10)%10],6);
DisSMG_bit(SMG_duanma[P_temper%10],7);
}
else if(SMG_stat==2)//DAC输出
{
DisSMG_bit(0x88,0);
DisSMG_bit(SMG_dot[(DAC_dat/100)%10],5);
DisSMG_bit(SMG_duanma[(DAC_dat/10)%10],6);
DisSMG_bit(SMG_duanma[DAC_dat%10],7);
}
DisSMG_all(0xff);
}
//=======================================================================
//==========================矩阵按键====================================
void scan_key()
{
R3=0;
R1=R2=R4=1;
C1=C2=C3=C4=1;
if(C1==0)//S5按键按下
{
delay_key(100);
if(C1==0)
{
while(C1==0)
{
DisSMG();
}
K5_mode=~K5_mode;
}
}
else if(C2==0)//S9按键按下
{
delay_key(100);
if(C2==0)
{
while(C2==0)
{
DisSMG();
}
if(SMG_stat==1)
{
P_temper++;
if(P_temper>=50)
{
P_temper=50;
}
}
}
}
R4=0;
R1=R2=R3=1;
C1=C2=C3=C4=1;
if(C1==0)//S4按键按下
{
delay_key(100);
if(C1==0)
{
while(C1==0)
{
DisSMG();
}
if(SMG_stat==0)
{
SMG_stat=1;
}
else if(SMG_stat==1)
{
SMG_stat=2;
}
else if(SMG_stat==2)
{
SMG_stat=0;
}
}
}
else if(C2==0)//S8按键按下
{
delay_key(100);
if(C2==0)
{
while(C2==0)
{
DisSMG();
}
if(SMG_stat==1)
{
P_temper--;
if(P_temper<=0)
{
P_temper=0;
}
}
}
}
}
//=======================================================================
//===========================LED显示=====================================
void LEDrunning()
{
if(K5_mode==0)
{
selectHC573(4,0xfe);//L1点亮
}
if(SMG_stat==0)
{
selectHC573(4,0xfd);//L2点亮
}
if(SMG_stat==1)
{
selectHC573(4,0xfb);//L3点亮
}
if(SMG_stat==2)
{
selectHC573(4,0xf7);//L4点亮
}
}
//=======================================================================
//系统初始化函数
void Init_system()
{
selectHC573(0, 0x00); //关闭所有锁存器
selectHC573(5, 0x00); //关闭蜂鸣器和继电器
selectHC573(4, 0xff); //关闭全部LED灯
}
//系统主函数
void main()
{
Init_system();
while(1)
{
Read_temper(); //读取温度
DisSMG(); //数码管显示
scan_key(); //按键扫描
DAC_mode(); //DAC模式控制
LEDrunning(); //LED灯
}
}
PS:本人第十届蓝桥杯单片机省赛第一,熟悉51单片机与STM32的操作与使用,如有关于单片机(51、STM32)的作业、课设、毕业设计皆可询问本人。