下面是我自己写的题解,在我的板子上实现了所有功能,如果有问题可以留言,我会尽力帮忙。如果有错误或者更好的写法,恳请大佬指点。
#include <stc15f2k60s2.h>
#include <intrins.h>
sbit DQ = P1^4;
code unsigned char number[28] =
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,
0xbf,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10, // - 0.
0x8c
};//+17后为带.字
unsigned char ms10,uc_mod1,uc_recordtep = 25,uc_led = 0xff;
unsigned int ui_tep;
float f_v;
unsigned char uc_v;
void ds18b20();
sbit S4 = P4^4;
sbit S8 = P3^3;
sbit S9 = P3^2;
sbit S5 = P3^2;
sbit sda = P2^1;
sbit scl = P2^0;
void smg_led();
bit flag_tep,flag_mod2;
#define DELAY_TIME 5
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
void PCF8591()
{
if(flag_mod2 == 0) //判断模式1标志
{
if(ui_tep / 100 < uc_recordtep)
{
flag_tep = 1; //条件判断标志
}
else
{
flag_tep = 0;
}
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x40);
I2CWaitAck();
I2CSendByte(255 * flag_tep); //直接输出0V或者5V (8591范围在0 - 255 即255时输出5v 0时输出0v)
I2CWaitAck();
I2CStop();
}
else //进入模式2
{
if(ui_tep / 100 <= 20) //简单的计算 有很多种算法 不唯一
{
f_v = 1 / 5.0 * 255;
uc_v = f_v;
}
else if(ui_tep / 100 >= 40)
{
f_v = 4 / 5.0 * 255;
uc_v = f_v;
}
else
{
f_v = ui_tep;
f_v = (((f_v / 100.0) * 3) / 20.0 - 2) / 5.0 * 255;
uc_v = f_v; //取整后用于输出
}
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x40);
I2CWaitAck();
I2CSendByte(uc_v);
I2CWaitAck();
I2CStop();
}
}
void Delay30ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 2;
j = 67;
k = 183;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void scan_key()
{
P30 = 1; //注意,因为题目要求矩阵按键和独立按键混用,所以得排除干扰项
P31 = 1; //这边的赋值都是用于排除干扰项,具体可以看原理图思考下为什么这么写
P32 = 1;
P33 = 0;
S4 = 1;
if(S4 == 0)
{
while(S4 == 0)
{
smg_led();
}
Delay30ms();
uc_mod1++; //显示界面的切换
uc_mod1 %=3;
}
if(uc_mod1 == 1) //判断是否在参数设置界面
{
P44 = 1; //这里也是用于干扰项排除
S8 = 1;
S9 = 1;
P42 = 0;
if(S8 == 0)
{
while(S8 == 0)
{
smg_led();
}
Delay30ms();
uc_recordtep--;
}
if(S9 == 0)
{
while(S9 == 0)
{
smg_led();
}
Delay30ms();
uc_recordtep++;
}
}
if(uc_mod1 == 2) //判断是否在DAC界面
{
P42 = 1; //干扰项排除
P44 = 0;
S5 = 1;
if(S5 == 0)
{
while(S5 == 0)
{
smg_led();
}
Delay30ms();
flag_mod2 = ~flag_mod2;
}
}
}
void Delay600us() //@11.0592MHz
{
unsigned char i, j;
i = 7;
j = 113;
do
{
while (--j);
} while (--i);
}
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
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);
}
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;
}
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;
}
void HC138_choose(unsigned char m)
{
switch(m)
{
case 0 :
{
P2 = (P2 & 0x1f) | 0x00;
break;
}
case 4 :
{
P2 = (P2 & 0x1f) | 0x80;
break;
}
case 5 :
{
P2 = (P2 & 0x1f) | 0xa0;
break;
}
case 6 :
{
P2 = (P2 & 0x1f) | 0xc0;
break;
}
case 7 :
{
P2 = (P2 & 0x1f) | 0xe0;
break;
}
}
}
void smg_show(unsigned char wei,duan)
{
HC138_choose(6);
P0 = 0x01 << (wei - 1);
HC138_choose(7);
P0 = number[duan];
Delay600us();
P0 = 0xff;
}
void smg_led()
{
unsigned int v;
if(flag_mod2 == 0)
{
HC138_choose(4);
P0 = uc_led & 0xfe;
uc_led = P0;
}
else
{
HC138_choose(4);
P0 = (uc_led & 0xff) | 0x01;
uc_led = P0;
}
if(uc_mod1 == 0)
{
HC138_choose(4);
uc_led = (uc_led & 0xff) | 0x08; //关闭上一次点亮的灯(即关闭L4)
P0 = uc_led & 0xfd;
uc_led = P0;
}
else if(uc_mod1 == 1)
{
HC138_choose(4);
uc_led = (uc_led & 0xff) | 0x02; //同理关闭上个模式的灯
P0 = uc_led & 0xfb;
uc_led = P0;
}
else
{
HC138_choose(4);
uc_led = (uc_led & 0xff) | 0x04;
P0 = uc_led & 0xf7;
uc_led = P0;
}
if(uc_mod1 == 0) //温度显示界面
{
smg_show(1,12);
smg_show(5,ui_tep / 1000);
smg_show(6,ui_tep / 100 % 10 + 17);
smg_show(7,ui_tep / 10 % 10);
smg_show(8,ui_tep % 10);
}
else if(uc_mod1 == 1) //参数设置界面
{
smg_show(1,27);
smg_show(7,uc_recordtep / 10);
smg_show(8,uc_recordtep % 10);
}
else //DAC输出界面
{
if(flag_mod2 == 0) //模式判断
{
smg_show(1,10);
smg_show(6,5 * flag_tep + 17); // +17用于带. 例如5+17 = 22,在我的数组里为5.的段码位置
smg_show(7,0);
smg_show(8,0);
}
else
{
f_v = uc_v / 255.0 * 5; //这里f_v 只是借用上面的定义进行计算,不用考虑上下文联系
v = f_v * 100; //乘以100后进行小数运算,方便取整
smg_show(1,10);
smg_show(6,v / 100 + 17);
smg_show(7,v / 10 % 10);
smg_show(8,v % 10);
}
}
}
void ds18b20()
{
unsigned char low,high;
float f_tep;
smg_led();
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
smg_led();
f1:;
smg_led();
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
ui_tep = (high << 8) | low;
if(ui_tep < 0xf800)
{
f_tep = ui_tep * 0.0625;
ui_tep = f_tep * 100;
}
else
{
ui_tep = ~ui_tep;
ui_tep += 1;
f_tep = ui_tep * 0.0625;
ui_tep = f_tep * 100;
}
smg_led();
if(ui_tep == 8500)
{
goto f1; //排除初始值干扰 可以不加
}
}
void init()
{
HC138_choose(4);
P0 = 0xff;
HC138_choose(5);
P0 = 0x00;
HC138_choose(6);
P0 = 0x00;
HC138_choose(7);
P0 = 0xff;
}
void main()
{
init();
while(1)
{
ds18b20();
PCF8591();
scan_key();
smg_led();
}
}
以上,感谢大家的阅读