题目
题目也是很长的一坨。
但是外设只用到了ds18b20温度传感器,应该不会很难。
按键功能
S4简单的切换模式按键,s5切换触发模式,这两个都很常规,S8,S9不同界面不同参数的加减。
/*按键函数区域*/
void Key_Proc(){
if(Key_Slow) return;
Key_Slow = 1;
Key_Val = Key_Read();
Key_Down = Key_Val & (Key_Val ^ Key_Old);
Key_Up = ~Key_Val & (Key_Val ^ Key_Old);
Key_Old = Key_Val;
switch(Key_Down){
case 4://界面切换
if(++Seg_Mode == 3) Seg_Mode = 0;
break;
case 5://触发模式切换
Work_Mode ^= 1;
break;
case 8://减去
if(Seg_Mode == 1){//校准值界面校准值减一
adjust = adjust == -99?-99:adjust-1;
}
else if(Seg_Mode == 2){//参数界面参数减一
tempature = tempature == -99?-99:tempature-1;
}
break;
case 9:
if(Seg_Mode == 1){//校准值界面校准值加一
adjust = adjust == 99?99:adjust+1;
}
else if(Seg_Mode == 2){//参数界面参数加一
tempature = tempature == 99?99:tempature+1;
}
break;
}
}
显示界面
三种显示界面,标识符分别C,E,H。都是熄灭四位,这些共同的我们可以放在外面,
校准值的范围是-99~99,所以我们用int类型来作为校准值的变量,温度值依旧用float类型。
我们在对于校准值需要进行判断,这里按理来说,温度值是当前温度加上校准值,也有可能是负数,但是这里数码管的分配加上小数点后一位,并没有负号的空间,所以我们就根据题目的意思,正常显示温度即可。温度就不需要判断正负值了,判断一下高位熄灭就可以了。
而对于温度参数和温度校准值来说,就得判断正负和高位熄灭,两个显示模式代码一模一样就参数不一样罢了。
Seg_Buf[1] = 10;
Seg_Buf[2] = 10;
Seg_Buf[3] = 10;
Seg_Buf[4] = 10;
switch(Seg_Mode){
case 0://温度显示模式
Seg_Buf[0] = 11;//C
Seg_Buf[5] = (unsigned char)temp>=10?(unsigned char)temp/10:10;
Seg_Buf[6] = (unsigned char)(temp)%10;
Seg_Buf[7] = (unsigned int)(temp*10)%10;
Point[6] = 1;
break;
case 1://校准值界面
Point[6] = 0;
Seg_Buf[0] = 12;//E
if(adjust<0){//负数值
Seg_Buf[5] = adjust_negative>=10?14:10;//-
Seg_Buf[6] = adjust_negative>=10?adjust_negative/10:14;
Seg_Buf[7] = adjust_negative%10;
}
else{//正数
Seg_Buf[5] = 10;
Seg_Buf[6] = adjust>10?adjust/10:10;
Seg_Buf[7] = adjust%10;
}
break;
case 2:
Point[6] = 0;
Seg_Buf[0] = 13;//H
if(temp<0){
Seg_Buf[5] = temp_negative>=10?14:10;//-
Seg_Buf[6] = temp_negative>=10?temp_negative/10:10;
Seg_Buf[7] = temp_negative%10;
}
else{
Seg_Buf[5] = 10;
Seg_Buf[6] = tempature>=10?tempature/10:10;
Seg_Buf[7] = tempature%10;
}
break;
}
Led功能
L1~L5都是简单的界面功能点亮对应的灯,不多赘述。
L8就是在触发模式不同不一样的判断条件,定义一个标志位去判断即可。
if(Work_Mode == 0){//上限触发
if(temp>tempature) L8_flag = 1;
else L8_flag = 0;
}
else{//下限触发
if(temp<tempature) L8_flag = 1;
else L8_flag = 0;
}
/*Led函数区域*/
void Led_Proc(){
Led_Buf[0] = (Seg_Mode == 0);//温度界面点亮L1
Led_Buf[1] = (Seg_Mode == 1);
Led_Buf[2] = (Seg_Mode == 2);
Led_Buf[3] = (Work_Mode == 0);//上限触发点亮L4
Led_Buf[4] = (Work_Mode == 1);
Led_Buf[7] = L8_flag;
}
完整主函数
/*头文件区域*/
#include <STC15F2K60S2.H>
#include <Init.h>
#include <Seg.h>
#include <Led.h>
#include <Key.h>
#include <onewire.h>
#include <intrins.h>
/*变量参数区域*/
unsigned char Key_Slow,Seg_Slow;
unsigned char Seg_Pos;
unsigned char Key_Down,Key_Old,Key_Up,Key_Val;
//数据
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};
unsigned char Led_Buf[8] = {0,0,0,0,0,0,0,0};
unsigned char Point[8] = {0,0,0,0,0,0,0,0};
unsigned char Seg_Mode;//0温度界面,1校准值2参数
unsigned char Work_Mode;//0上触发1下触发
int adjust = 0;//校准值默认为0
unsigned char tempature = 26;//温度参数默认值26
float temp;//当前读取的温度
bit L8_flag;
/*按键函数区域*/
void Key_Proc(){
if(Key_Slow) return;
Key_Slow = 1;
Key_Val = Key_Read();
Key_Down = Key_Val & (Key_Val ^ Key_Old);
Key_Up = ~Key_Val & (Key_Val ^ Key_Old);
Key_Old = Key_Val;
switch(Key_Down){
case 4://界面切换
if(++Seg_Mode == 3) Seg_Mode = 0;
break;
case 5://触发模式切换
Work_Mode ^= 1;
break;
case 8://减去
if(Seg_Mode == 1){//校准值界面校准值减一
adjust = adjust == -99?-99:adjust-1;
}
else if(Seg_Mode == 2){//参数界面参数减一
tempature = tempature == -99?-99:tempature-1;
}
break;
case 9:
if(Seg_Mode == 1){//校准值界面校准值加一
adjust = adjust == 99?99:adjust+1;
}
else if(Seg_Mode == 2){//参数界面参数加一
tempature = tempature == 99?99:tempature+1;
}
break;
}
}
/*数码管函数区域*/
void Seg_Proc(){
unsigned int adjust_negative,temp_negative;
adjust_negative = -adjust;
temp_negative = -temp;
if(Seg_Slow) return;
Seg_Slow = 1;
temp = rd_tempature();
temp = temp + adjust;
if(Work_Mode == 0){//上限触发
if(temp>tempature) L8_flag = 1;
else L8_flag = 0;
}
else{//下限触发
if(temp<tempature) L8_flag = 1;
else L8_flag = 0;
}
Seg_Buf[1] = 10;
Seg_Buf[2] = 10;
Seg_Buf[3] = 10;
Seg_Buf[4] = 10;
switch(Seg_Mode){
case 0://温度显示模式
Seg_Buf[0] = 11;//C
Seg_Buf[5] = (unsigned char)temp>=10?(unsigned char)temp/10:10;
Seg_Buf[6] = (unsigned char)(temp)%10;
Seg_Buf[7] = (unsigned int)(temp*10)%10;
Point[6] = 1;
break;
case 1://校准值界面
Point[6] = 0;
Seg_Buf[0] = 12;//E
if(adjust<0){//负数值
Seg_Buf[5] = adjust_negative>=10?14:10;//-
Seg_Buf[6] = adjust_negative>=10?adjust_negative/10:14;
Seg_Buf[7] = adjust_negative%10;
}
else{//正数
Seg_Buf[5] = 10;
Seg_Buf[6] = adjust>10?adjust/10:10;
Seg_Buf[7] = adjust%10;
}
break;
case 2:
Point[6] = 0;
Seg_Buf[0] = 13;//H
if(temp<0){
Seg_Buf[5] = temp_negative>=10?14:10;//-
Seg_Buf[6] = temp_negative>=10?temp_negative/10:10;
Seg_Buf[7] = temp_negative%10;
}
else{
Seg_Buf[5] = 10;
Seg_Buf[6] = tempature>=10?tempature/10:10;
Seg_Buf[7] = tempature%10;
}
break;
}
}
/*Led函数区域*/
void Led_Proc(){
Led_Buf[0] = (Seg_Mode == 0);//温度界面点亮L1
Led_Buf[1] = (Seg_Mode == 1);
Led_Buf[2] = (Seg_Mode == 2);
Led_Buf[3] = (Work_Mode == 0);//上限触发点亮L4
Led_Buf[4] = (Work_Mode == 1);
Led_Buf[7] = L8_flag;
}
/*定时器0初始化区域*/
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 =1;
EA = 1;
}
/*定时器0中断服务函数*/
void Timer0_Service() interrupt 1
{
if(++Seg_Slow == 200) Seg_Slow = 0;
if(++Key_Slow == 50) Key_Slow = 0;
if(++Seg_Pos == 8) Seg_Pos = 0;
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Point[Seg_Pos]);
Led_Disp(Seg_Pos,Led_Buf[Seg_Pos]);
}
void Delay750ms(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/*主函数区域*/
void main(){
Timer0_Init();
Sys_Init();
rd_tempature();
Delay750ms();
while(1){
Key_Proc();
Seg_Proc();
Led_Proc();
}
}