自学开天斧第24课:
学习内容:小项目(2):计时器(EEPROM存储计数值)
学习简介:之前对STC8H8K64U的EEPROM的学习只是单纯地存入数据和读出数据,没有结合项目实战,理解不够深入,这次使用EEPROM的库函数制作一个断电存储计次数据的定时器 项目所含知识点:GPIO、定时器、中断、独立按键、OLED、EEPROM 项目内容:
①、按P3.5按键 开启/停止计时 ②、按P3.4按键 清零计时区域数据 ③、按P3.3按键 计次并将数据保存至EEPROM
④、按P3.2按键 查看计次值(读取EEPROM数据) ⑤、按P5.4按键 计时器数值、计次值清零,清空存储数据区域(擦除EEPROM第0扇区) 程序代码:(因代码量太大,这里只展示主函数,EEPROM相关函数来源于STC库函数)
#include <STC8H.H>
#include "EEPROM.h"
#include "Timer.h"
#include "Timer_Key.h"
#include "OLED.h"
#define Record_MAX 20 //存储计次最多数量
bit Timer1_ms_1;
bit Timer1_ms_2;
bit OLED_full_sign;
bit OLED_empty_sign;
unsigned char S_hour; //时
unsigned char S_min; //分
unsigned char S_sec; //秒
unsigned char S_cen; //百分之一秒
unsigned char OLED_past;
unsigned char OLED_know;
unsigned char EEPROM_unit_write;
unsigned char EEPROM_unit_read;
unsigned char Key_number;
unsigned int sign_more_delay;
unsigned int OLED_empty_count;
unsigned int OLED_full_count;
unsigned char Check_empty;
void main()
{
P_SW2 |= 0x80;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P34 = 1;P35 = 1;P32 = 1;P33 = 1;P54 = 1; //初始化开天斧板载独立按键
Timer0_Init();
Timer1_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
OLED_Clear();
TR0 = 0;
EA = 1;
OLED_ShowChinese(34,0,0,16); //计
OLED_ShowChinese(54,0,1,16); //时
OLED_ShowChinese(74,0,2,16); //器
OLED_ShowNum(7,3,0,2,16);
OLED_ShowChar(24,3,'h',16);
OLED_ShowNum(38,3,0,2,16);
OLED_ShowChar(55,3,'m',16);
OLED_ShowNum(69,3,0,2,16);
OLED_ShowChar(86,3,'s',16);
OLED_ShowNum(100,3,0,2,16);
OLED_ShowString(117,3,"c",16);
OLED_ShowChinese(0,6,6,16);
OLED_ShowChar(17,6,':',16);
OLED_ShowNum(24,6,0,2,16);
while(1)
{
Key_number = Key();
OLED_past = OLED_know;
OLED_know = S_cen;
if(OLED_past != OLED_know) //if计时变量改变刷新OLED
{
OLED_ShowNum(7,3,S_hour,2,16);
OLED_ShowNum(38,3,S_min,2,16);
OLED_ShowNum(69,3,S_sec,2,16);
OLED_ShowNum(100,3,S_cen,2,16);
}
if(Key_number == 1) //开启/关闭计时器
{
TR0 = ~TR0;
if(TR0 == 0)
{
sign_more_delay = 200;
}
else
{
sign_more_delay = 0;
}
}
if(Key_number == 2) //计时器清零
{
S_cen = 0;S_sec = 0;S_min = 0;S_hour = 0;
}
if(Key_number == 3) //计时器计次
{
OLED_ShowChinese(0,6,6,16);
OLED_ShowChar(17,6,':',16);
if(EEPROM_unit_write >= Record_MAX) //如果EEPROM_unit_write大于等于设定值,显示“满!”
{
OLED_ShowChinese(86,6,3,16);
OLED_ShowChinese(103,6,5,16);
OLED_full_sign = 1;
}
else
{
OLED_ShowNum(24,6,EEPROM_unit_write+1,2,16);
EEPROM_write_n(0x0000+1+EEPROM_unit_write*4,&S_hour,1);
EEPROM_write_n(0x0000+2+EEPROM_unit_write*4,&S_min,1);
EEPROM_write_n(0x0000+3+EEPROM_unit_write*4,&S_sec,1);
EEPROM_write_n(0x0000+4+EEPROM_unit_write*4,&S_cen,1);
EEPROM_unit_write++;
}
}
if(Key_number == 4) //计时器显示计次值
{
OLED_ShowChinese(0,6,7,16);
OLED_ShowChar(17,6,':',16);
EEPROM_read_n(0x0000+4+EEPROM_unit_read*4,&Check_empty,1);
if(Check_empty == 0xff ) //如果EEPROM下一字节是被擦除状态(0xff),显示“空!”
{
OLED_ShowChinese(86,6,4,16); //显示“空!”
OLED_ShowChinese(103,6,5,16);
OLED_empty_sign = 1;
}
else
{
EEPROM_read_n(0x0000+1+EEPROM_unit_read*4,&S_hour,1); //读取EEPROM数据
EEPROM_read_n(0x0000+2+EEPROM_unit_read*4,&S_min,1);
EEPROM_read_n(0x0000+3+EEPROM_unit_read*4,&S_sec,1);
EEPROM_read_n(0x0000+4+EEPROM_unit_read*4,&S_cen,1);
OLED_ShowNum(7,3,S_hour,2,16); //显示数据
OLED_ShowNum(38,3,S_min,2,16);
OLED_ShowNum(69,3,S_sec,2,16);
OLED_ShowNum(100,3,S_cen,2,16);
OLED_ShowNum(24,6,EEPROM_unit_read+1,2,16);
EEPROM_unit_read++;
}
}
if(Key_number == 5)
{
EEPROM_SectorErase(0x0000);
EEPROM_unit_read = 0;
EEPROM_unit_write = 0;
S_cen = 0;S_sec = 0;S_min = 0;S_hour = 0;
OLED_ShowNum(24,6,EEPROM_unit_write,2,16);
}
if(OLED_empty_sign == 1)
{
if(Timer1_ms_1 == 1)
{
Timer1_ms_1 = 0;
OLED_empty_count++;
if(OLED_empty_count >= 150+sign_more_delay)
{
OLED_empty_count = 0;
OLED_empty_sign = 0;
OLED_ShowString(86,6," ",16);
}
}
}
if(OLED_full_sign == 1)
{
if(Timer1_ms_2 == 1)
{
Timer1_ms_2 = 0;
OLED_full_count++;
if(OLED_full_count >= 150+sign_more_delay)
{
OLED_full_count = 0;
OLED_full_sign = 0;
OLED_ShowString(86,6," ",16);
}
}
}
}
}
void Timer0_Routine(void) interrupt 1
{
static unsigned char Timer0_cen; //定时器循环计时
Timer0_cen++;
if(Timer0_cen >= 10){Timer0_cen = 0;S_cen++;}
if(S_cen >= 100){S_cen = 0;S_sec++;}
if(S_sec >= 60){S_sec = 0;S_min++;}
if(S_min >= 60){S_min = 0;S_hour++;}
}
void Timer1_Routine(void) interrupt 3
{
static unsigned char T0_Key;
T0_Key++;
Timer1_ms_1 = 1;
Timer1_ms_2 = 1;
if(T0_Key>=20)
{
T0_Key = 0;
Timer_Key();
}
}
|