#include <STC15F2K60S2.H>
#include <intrins.h>
#include <stdio.h>
code unsigned char Seg_Table[27] =
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e, // +16.
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,//.
0xc1
};
sbit DQ = P1^4;
sbit scl = P2^0;
sbit sda = P2^1;
unsigned char uc_mod1,uc_10ms,uc_led = 0xff,uc_Y5C = 0x00;
unsigned int ui_tep,ui_v,ui_command = 0;
bit flag_18b20 = 0;
bit flag_L3;
bit flag_firstlock;
void smg_led();
bit lock;
#define DELAY_TIME 5
void UartInit(void) //9600bps@12.000MHz 波特率发生器
{
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器1时钟为Fosc/12,即12T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xE6; //设定定时初值
TH1 = 0xFF; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES = 1;
EA = 1;
}
void Timer0Init(void) //10毫秒@12.000MHz 计时时钟
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xF0; //设置定时初值
TH0 = 0xD8; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1;
ET0 = 1;
}
void timer0() interrupt 1 //计时闪烁
{
uc_10ms++;
if(uc_10ms == 10)
{
uc_10ms = 0;
flag_L3 = ~flag_L3;
}
}
void uart_receive() interrupt 4 //串口接收
{
while(RI == 0);
ui_command = SBUF;
RI = 0;
}
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 I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
void PCF8591_adc() //adc模块,并且对电位器采样
{
unsigned char uc_v;
float f_v;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
uc_v = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
f_v = uc_v / 255.0 * 5.0;
ui_v = f_v * 100;
}
void PCF8591_dac() //dac模块
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CSendByte(ui_v); //对采样值进行输出
I2CWaitAck();
I2CStop();
}
void Delay30ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 2;
j = 95;
k = 43;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay600us() //@12.000MHz
{
unsigned char i, j;
i = 7;
j = 254;
do
{
while (--j);
} while (--i);
}
void Delay700ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 32;
j = 236;
k = 16;
do
{
do
{
while (--k);
} 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 ds18b20()
{
float f_tep;
unsigned char low,high;
smg_led(); //保持亮度
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
smg_led();
if(flag_18b20 == 0) //首次进入标志,进行延时,避免默认值的出现
{
Delay700ms();
flag_18b20 = 1;
}
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low = Read_DS18B20();
high = Read_DS18B20();
smg_led();
ui_tep = (high << 8) | low;
if(ui_tep < 0xf800) //正负判断(实际我没有用到负的,也就略过了负数的输出
{
f_tep = ui_tep * 0.0625;
ui_tep = f_tep * 10;
}
else
{
ui_tep = ~ui_tep;
ui_tep += 1;
f_tep = ui_tep * 0.0625;
ui_tep = f_tep;
}
}
void HC138_choose(unsigned char k)
{
switch(k)
{
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 = Seg_Table[duan];
Delay600us();
P0 = 0xff;
}
void smg_led()
{
switch(uc_mod1) //两种显示模式切换
{
case 0:
{
smg_show(1,26);
smg_show(2,1);
smg_show(6,ui_tep / 100);
smg_show(7,ui_tep / 10 % 10 +16);
smg_show(8,ui_tep % 10);
break;
}
case 1:
{
smg_show(1,26);
smg_show(2,2);
smg_show(6,ui_v / 100 + 16);
smg_show(7,ui_v / 10 % 10);
smg_show(8,ui_v % 10);
break;
}
}
if(uc_mod1 == 0) //led模块
{
HC138_choose(4);
P0 = uc_led;
P00 = 0;
P01 = 1;
uc_led = P0;
}
else if(uc_mod1 == 1)
{
HC138_choose(4);
P0 = uc_led;
P00 = 1;
P01 = 0;
uc_led = P0;
}
if(lock == 1)
{
if(flag_firstlock == 0) //首次进入进行计时器清零,防止误差
{
flag_firstlock = 1;
uc_10ms = 0;
}
HC138_choose(4);
P0 = uc_led;
P02 = flag_L3;
uc_led = P0;
}
else
{
flag_firstlock = 0;
HC138_choose(4);
P0 = uc_led;
P02 = 1;
uc_led = P0;
}
}
void init()
{
HC138_choose(6);
P0 = 0x00;
HC138_choose(7);
P0 = 0xff;
HC138_choose(4);
P0 = 0xff;
HC138_choose(5);
P0 = 0x00;
}
void uart_send(unsigned m) //这段代码与putchar绑定,用来利用printf发送字符串
{
SBUF = m;
while(TI == 0);
TI = 0;
}
char putchar(unsigned char c) //注意,这次程序用到了uart的发送和接受
{ //发送我采用了stdio.h的头文件中的printf
uart_send(c); //如果不需要接收,那这段代码和上面的uart_send都不需要
return c; //因为要同时使用接收发送,则必须重新写一下putchar
}
void scan_key()
{
float f_tep,f_v;
P44 = 0;
P32 = 1;
P33 = 1;
P34 = 1;
P35 = 1;
P42 = 1;
if(lock == 1)
{
if(P32 == 0) //S5
{
while(P32 == 0)
{
ds18b20();
smg_led();
}
Delay30ms();
lock = 0;
ui_command = 0;
}
}
if(P33 == 0) //S4
{
while(P33 == 0)
{
ds18b20();
smg_led();
}
Delay30ms();
lock = 1;
ES = 0;
}
P35 = 1;
P33 = 0;
P30 = 1;
P31 = 1;
P32 = 1;
if(P35 == 0) //S12
{
ES = 0; //此时发送不能打开中断,因此在发送按钮提前关闭串口中断
while(P35 == 0) //我也不太理解为什么中断不能开启,我自认为是发送后TI置1进
{ //入中断但实际测试下来,就算串口中断函数不写,程序也会卡死
ds18b20(); //这里希望懂的大佬可以解释一下
smg_led();
}
if(uc_mod1 == 0)
{
f_tep = ui_tep / 10.0;
printf("TEMP:%.1f℃\r\n",f_tep); //利用了stdio.h中的printf进行字符串的发送
}
else if(uc_mod1 == 1)
{
f_v = ui_v / 100.0;
printf("Voltage:%.2fV\r\n",f_v);
}
Delay30ms();
ES = 1; //重新开启串口中断
}
}
void ADC_DAC() //调用一下dac,adc
{
PCF8591_adc();
PCF8591_dac();
}
void command_read() //接收串口指令判断
{
if(ui_command == 0x41)
{
uc_mod1 = 0;
}
else if(ui_command == 0x42)
{
uc_mod1 = 1;
}
}
void buzz_relay() //蜂鸣器继电器检测
{
if(ui_tep / 10 >= 28)
{
HC138_choose(5);
P0 = uc_Y5C;
P04 = 1;
uc_Y5C = P0;
}
else
{
HC138_choose(5);
P0 = uc_Y5C;
P04 = 0;
uc_Y5C = P0;
}
if(ui_v / 10 >= 36 )
{
HC138_choose(5);
P0 = uc_Y5C;
P06 = 1;
uc_Y5C = P0;
}
else
{
HC138_choose(5);
P0 = uc_Y5C;
P06 = 0;
uc_Y5C = P0;
}
}
void main()
{
init();
ds18b20();
UartInit();
Timer0Init();
while(1)
{
command_read();
scan_key();
ADC_DAC();
ds18b20();
smg_led();
buzz_relay();
}
}
以上,感谢阅读,如有错误恳请指正,另外串口部分等待大佬的解惑。