1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/bg4uvr-ds3231

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
Клонировать/Скачать
main.c 9.8 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
bg4uvr Отправлено 5 лет назад 375fac1
/*
《STM8S105K4实验板+DS3231模块+HT1621模式 = 实时时钟实验》
程序较为完整地实现了时间显示、时间设置功能,并充分考虑了节电性能,
使之比较适合使用电池供电来长时间运行,具备一定的实用性。但程序仍然
是实验性的,因为使用了DS3231的SQW脚来输出1Hz信号唤醒MCU,所以程序
没用设计闹钟功能。
注:
1、除STM8官方库文件外,部分基础代码源于实验板例程;按键代码源于网
络;软件IIC驱动基于原子例程修改;DS3231代码、电源管理代码、全部主
程序逻辑为原创。
2、代码中有些源代码文件项目中并未使用,为方便以后使用并未中删除。
bg4uvr 最后版本完成于2020.3.5
*/
#include "stm8s.h"
#include "timer.h"
#include "ht1621.h"
#include "delay.h"
#include "myiic.h"
#include "ds3231.h"
#include "key.h"
#include "button.h"
#include "power.h"
bool last_halfsec; //半秒信号
uint8_t sysMode; //系统工作模式
uint8_t timeChanged; //设置时是否改变了时钟
uint8_t year,month,date,hour,min; //HEX格式时间(设置时间时使用)
uint8_t buf[4]; //显示缓存
ds3231_info ds3231; //DS3231结构体
Button_t Button1; //注册按键1
Button_t Button2; //注册按键2
//按键1单击
void Btn1_Dowm_CallBack(void *btn)
{
ModeTimeOutCnt=0; //模式超时计数器
switch(sysMode)
{
//普通模式,循环切换6种显示状态
case 0: //普通模式
case 1: //秒
case 2: //年
case 3: //月。日
case 4: //星期
sysMode++;
break;
case 5: //温度
sysMode=0;
break;
//设置模式
case 11: //设置年份的世纪位
if(year<100) year+=100;
else year-=100;
break;
case 12: //设置年份的10年位
if(year%100 < 90) year+=10;
else year-=90;
break;
case 13: //设置年份的个位
if(year%10 < 9) year++;
else year-=9;
break;
case 14: //设置月的十位
if(month<10) month=10;
else month=1;
break;
case 15: //设置月的个位
month++;
if(month>=13) month=10;
else if(month==10) month=1;
break;
case 16: //设置日的十位
date+=10;
if(date>max_date(year,month))
{
if(date/10!=0)
{
date=date/10*10;
if(date>max_date(year,month))
date=1;
}
else
date-=10;
}
break;
case 17: //设置日的个位
date++;
if(date%10==0)
{
date-=10;
if(date==0) date=1;
}
if(date>max_date(year,month))
{
date=date/10*10;
}
break;
case 18: //设置小时10位
hour+=10;
if(hour>23)
{
if(hour%10!=0) hour=20;
else hour=0;
}
timeChanged=1;
break;
case 19: //设置小时个位
hour++;
if(hour>23) hour=hour/10*10;
else if(hour%10==0) hour-=10;
timeChanged=1;
break;
case 20: //设置分钟10位
if(min<50) min+=10;
else min%=10;
timeChanged=1;
break;
case 21: //设置分钟个位
min++;
if(min>60) min/=10;
else if(min%10==0) min-=10;
timeChanged=1;
break;
//设置完毕,待启动模式
case 50:
ds3231.sec=0;
ds3231.min=hex2bcd(min);
ds3231.hour=hex2bcd(hour);
DS3231_Write(0,3,(uint8_t*)&ds3231); //写入时分秒数据
sysMode=0; //回到普通模式
break;
}
}
//按键2单击
void Btn2_Dowm_CallBack(void *btn)
{
ModeTimeOutCnt=0; //模式超时计数器
//普通显示模式,如果非主页面,切换回主页面
if(sysMode > 0 && sysMode < 10)
sysMode = 0;
//设置模式,变更为一下项设置
else if(sysMode >= 10 && sysMode <50)
{
if(++sysMode > 21) //设置模式供有21-11+1种,到第21种返回第11种
sysMode = 11;
}
}
//按键2长按
void Btn2_Long_CallBack(void *btn)
{
ModeTimeOutCnt=0; //模式超时计数器
//如果是普通模式,则进入设置模式
if(sysMode==0)
{
sysMode=10; //进入设置模式
timeChanged=0; //时钟已更改状态清零
//读取DS3231时间数据到缓存
DS3231_Read(0x00,7,(uint8_t*)&ds3231);
//把时间转换为hex数值,便于后续设置时计算
year=ds3231.month&0x80?bcd2hex(ds3231.year)+100:bcd2hex(ds3231.year);
month=bcd2hex(ds3231.month&0x1f);
date=bcd2hex(ds3231.date);
hour=bcd2hex(ds3231.hour);
min=bcd2hex(ds3231.min);
}
//如果是设置模式,则保存设置
else if(sysMode >=11 && sysMode < 50)
{
//把已设置的hex格式数据,转换为bcd格式
ds3231.date=hex2bcd(date);
ds3231.month=year/100?hex2bcd(month)|0x80:hex2bcd(month);
ds3231.year=hex2bcd(year%100);
//根据日期计算星期
ds3231.week=week(ds3231.year,ds3231.month,ds3231.date);
//保存年月日和星期(4个字节)
DS3231_Write(WEEK,4,(uint8_t*)&ds3231.week);
//如果更改为时间数据,进入等待启动状态
if(timeChanged) sysMode=50;
//否则直接返回普通模式
else sysMode=0;
}
}
//系统初始化
void Sys_init(void)
{
ht1621Init(); //初始化LCD
IIC_Init(); //初始化软件IIC
KEY_Init(); //按键初始化
DS3231_init(); //DS3231初始化
power_init(); //休眠模式初始化
//注册按键1
Button_Create("Button1",&Button1,Read_KEY1_Level,KEY_ON);
Button_Attach(&Button1,BUTTON_DOWM,Btn1_Dowm_CallBack); //单击
//注册按键2
Button_Create("Button2",&Button2,Read_KEY2_Level,KEY_ON);
Button_Attach(&Button2,BUTTON_DOWM,Btn2_Dowm_CallBack); //单击
Button_Attach(&Button2,BUTTON_LONG,Btn2_Long_CallBack); //长按
Timer4_Init(); //初始化定时器4
}
//主程序
int main(void)
{
Sys_init(); //初始化
sysMode=0; //系统模式初始化
while(1)
{
//检查是否是被按键唤醒
if(key_flag)
{
key_flag=FALSE; //清空按键标志
ModeTimeOutCnt=0; //清零超时计数器
TIM4_Cmd(ENABLE); //启动定时器4
}
//如果定时器4是开启状态并且已超时
if(TIM4->CR1&TIM4_CR1_CEN && ModeTimeOutCnt>500)
{
sysMode=0; //恢复普通模式
TIM4_Cmd(DISABLE); //关闭定时器4
}
//普通模式
if(sysMode == 0)
{
//只读取小时和分钟数据
DS3231_Read(MIN,2,(uint8_t*)&ds3231.min);
//显示小时和分钟
if(ds3231.hour>>4==0) //小时十位无效0消隐
buf[0]=halfsec?17:16;
else
buf[0]=halfsec?ds3231.hour>>4|0x80:ds3231.hour>>4;
buf[1]=ds3231.hour&0x0f;
buf[2]=ds3231.min>>4;
buf[3]=ds3231.min&0x0f;
dispAll((uint8_t*)buf);
//如果已超时,休眠
if(ModeTimeOutCnt>500) power_halt();
}
//其他模式
else
{
//每半秒才执行一次
while(last_halfsec==halfsec) wfi(); //如果未到半秒,MCU进入Wait模式,等待中断唤醒
last_halfsec=halfsec;
//读取全部7个字节的时间数据
if(sysMode<=10)
{
DS3231_Read(0,7,(uint8_t*)&ds3231);
}
//根据模式不同,显示相对应的数据
switch(sysMode)
{
//特殊显示模式
//显示秒数
case 1:
buf[0]=17; //显示冒号
buf[1]=16; //空白
buf[2]=ds3231.sec>>4; //秒十位
buf[3]=ds3231.sec&0x0f; //秒个位
break;
//显示年
case 2:
buf[0]=2;
buf[1]=ds3231.month&0x80?1:0; //月的最高位是世纪
buf[2]=ds3231.year>>4;
buf[3]=ds3231.year&0x0f;
break;
//显示月、日
case 3:
buf[0]=ds3231.month&0x10?1:16;
buf[1]=ds3231.month&0x0f;
buf[2]=ds3231.date>>4|0x80;
buf[3]=ds3231.date&0x0f;
break;
//显示星期
case 4:
buf[0] = 16;
buf[1] = 16;
buf[2] = ds3231.week;
buf[3] = 16;
break;
//显示温度
case 5:
DS3231_Read(TEMP_H,2,(uint8_t*)&ds3231.temp_h); //读取温度
buf[0] = ds3231.temp_h&0x80?18:16; //判断是否显示负号
buf[1] = (ds3231.temp_h&0x7f)/10;
buf[2] = (ds3231.temp_h&0x7f)%10;
buf[3] = ds3231.temp_l&0x80?5|0x80:0|0x80;
break;
//设置模式(以下模式,数据直接缓存中的,不从DS3231读取)
//显示 "-SET"
case 10:
buf[0] = 18;
buf[1] = 5;
buf[2] = 0x0e;
buf[3] = 7;
break;
//设置世纪位
case 11:
buf[0] = 2;
buf[1] = halfsec ? year/100 : 16;
buf[2] = year%100/10;
buf[3] = year%10;
break;
//设置十年位
case 12:
buf[0] = 2;
buf[1] = year/100?1:0;
buf[2] = halfsec ? year%100/10 : 16;
buf[3] = year%10;
break;
//设置年个位
case 13:
buf[0] = 2;
buf[1] = year/100?1:0;
buf[2] = year%100/10;
buf[3] = halfsec ? year%10 : 16;
break;
//设置月十位
case 14:
buf[0] = halfsec ? month/10 : 16;
buf[1] = month%10;
buf[2] = date/10|0x80;
buf[3] = date%10;
break;
//设置月个位
case 15:
buf[0] = month/10?1:16;
buf[1] = halfsec ? month%10:16;
buf[2] = date/10|0x80;
buf[3] = date%10;
break;
//设置日十位
case 16:
buf[0] = month/10?1:16;
buf[1] = month%10;
buf[2] = halfsec ? date/10|0x80 : 16|0x80;
buf[3] = date%10;
break;
//设置日个位
case 17:
buf[0] = month/10?1:16;
buf[1] = month%10;
buf[2] = date/10|0x80;
buf[3] = halfsec ? date%10 : 16;
break;
//设置小时十位
case 18:
buf[0] = halfsec ? hour/10|0x80 : 17;
buf[1] = hour%10;
buf[2] = min/10;
buf[3] = min%10;
break;
//设置小时个位
case 19:
buf[0] = hour/10|0x80;
buf[1] = halfsec ? hour%10 : 16;
buf[2] = min/10;
buf[3] = min%10;
break;
//设置分钟十位
case 20:
buf[0] = hour/10|0x80;
buf[1] = hour%10;
buf[2] = halfsec ? min/10 : 16;
buf[3] = min%10;
break;
//设置分钟个位
case 21:
buf[0] = hour/10|0x80;
buf[1] = hour%10;
buf[2] = min/10;
buf[3] = halfsec ?min%10 : 16;
break;
//待启动模式
//设置时钟后,时钟为停止状态,等待按KEY1键
case 50:
buf[0] = hour/10|0x80;
buf[1] = hour%10;
buf[2] = min/10;
buf[3] = min%10;
ModeTimeOutCnt=0; //模式超时计数器清零,永不超时
break;
}
dispAll((uint8_t*)buf); //刷新LCD
}
}
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/bg4uvr-ds3231.git
git@gitlife.ru:oschina-mirror/bg4uvr-ds3231.git
oschina-mirror
bg4uvr-ds3231
bg4uvr-ds3231
master