大模板参考bilibili西风
/* 头文件声明区 */
#include <STC15F2K60S2.H>
#include <Sysinit.h> //外设初始化专属底层
#include <Seg.h> //数码管专属底层
#include <Key.h>
#include <Led.h>
#include <iic.h>
#include <intrins.h>
/* 变量声明区 */
unsigned char Key_Val,Key_Down,Key_Old;
unsigned char Key_Slow_Down;//键盘减速
unsigned char Seg_Slow_Down;//数码管减速
unsigned char Seg_Pos; //数码管动态扫描
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};
unsigned char Seg_Disp_Mode; //显示界面切换变量 0数据界面 1参数界面 2计数界面
float Voltage_Read; //电压采集
float Voltage_Set = 3.0; //设置电压
unsigned char Count;
unsigned char Count_Flag;
unsigned int Time;
unsigned char Led1_Open;
unsigned char Voltage_Save;
/* 信息处理区 */
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;
/* 数据读取区 */
Voltage_Read = AD_Read(0x43) / 51.0;
/* 数据处理区 */
switch(Seg_Disp_Mode)
{
case 0:
Seg_Buf[0] = 11;
Seg_Buf[5] = (unsigned char)Voltage_Read;
Seg_Buf[6] = (unsigned int)(Voltage_Read * 100) / 10 % 10;
Seg_Buf[7] = (unsigned int)(Voltage_Read * 100) % 10;
Seg_Point[5] = 1;
break;
case 1:
Seg_Buf[0] = 12;
Seg_Buf[5] = (unsigned char)Voltage_Set;
Seg_Buf[6] = (unsigned int)(Voltage_Set * 100) / 10 % 10;
Seg_Buf[7] = (unsigned int)(Voltage_Set * 100) % 10;
Seg_Point[5] = 1;
break;
case 2:
Seg_Buf[0] = 13;
Seg_Buf[6] = Count / 10;
Seg_Buf[5] = 10;
Seg_Buf[7] = Count % 10;
Seg_Point[5] = 0;
break;
}
}
/* 按键处理区 */
void Key_Proc()
{
if(Key_Slow_Down) return;
Key_Slow_Down = 1;
Key_Val = Key_Read();
Key_Down = Key_Val & (Key_Val ^ Key_Old);
Key_Old = Key_Val;
switch(Key_Down)
{
case 12:
if(++Seg_Disp_Mode == 3)
Seg_Disp_Mode = 0;
if(Seg_Disp_Mode == 2)
{
Voltage_Save = Voltage_Set * 10;
EEPROM_Write(&Voltage_Save,0,1);
}
break;
case 13:
if(Seg_Disp_Mode == 2)
Count = 0;
break;
case 16:
if(Seg_Disp_Mode == 1)
{
Voltage_Set = Voltage_Set + 0.5;
if(Voltage_Set > 5.0)
Voltage_Set = 0;
}
break;
case 17:
if(Seg_Disp_Mode == 1)
{
Voltage_Set = Voltage_Set - 0.5;
if(Voltage_Set < 0)
Voltage_Set = 5.0;
}
break;
}
}
/* 其他处理区 */
void Led_Proc()
{
switch(Count_Flag) //计数判定
{
case 0:
if(Voltage_Read > Voltage_Set)
Count_Flag = 1;
break;
case 1:
if(Voltage_Read < Voltage_Set)
{
Count++;
Count_Flag = 0;
}
break;
}
switch(Led1_Open) //LED0开关判定
{
case 0:
ucLed[0] = 0;
break;
case 1:
ucLed[0] = 1;
break;
}
switch(Count % 2) //LED1开关判定
{
case 0:
ucLed[1] = 0;
break;
case 1:
ucLed[1] = 1;
break;
}
}
/* 定时器0相关 */
void Timer0Init()
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0Server() interrupt 1
{
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;
if(++Seg_Slow_Down == 100) Seg_Slow_Down = 0;
if(++Seg_Pos == 8) Seg_Pos = 0;
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
if(Voltage_Read < Voltage_Set)
{
if(++Time > 5000)
{
Led1_Open = 1;
Time = 0;
}
}
else
{
Led1_Open = 0;
Time = 0;
}
}
/* 主函数 */
void main()
{
Sys_Init();
Timer0Init();
EEPROM_Read(&Voltage_Save,0,1);
AD_Read(0x43);
Voltage_Set = Voltage_Save / 10.0;
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
注意:
1. AD模块第一个读出来的是0x80,所以需要在初始化时读一次,避免LED逻辑出错。
2.用数码管显示float型时,可以这么做
第一位:(unsigned char)num
第二位:(unsigned int) (num * 100) / 10 % 10;
第三位:(unsigned int) (num * 100) % 10;