目录
一、前言
项目成品图片:
哔哩哔哩视频链接:
(资料分享见文末)
二、项目简介
1.功能详解
基于STM32的万年历,功能如下:
- 实时时钟显示
- 时间设置,断电保存
- 闹钟设置,蜂鸣器报警
- 温湿度采集与显示,异常报警
2.主要器件
- STM32F103C8T6最小系统板
- DHT11温湿度传感器
- OLED显示屏(7针SPI协议)
- DS1302时钟模块
- 蜂鸣器
- LED灯
三、原理图设计
四、PCB硬件设计
PCB图
五、程序设计
int main(void)
{
delay_init(); //延时函数 系统初始化
LED_GPIO_Config(); //初始化GPIO接口
KEY_Init(); //按键初始化
BEEP_Init(); //蜂鸣器初始化
GENERAL4_TIM_Init(); //10ms 通用定时器3初始化 10ms
NVIC_Configuration(); //中断优先级设置
ds1302_gpio_init();delay_ms(5); //初始化ds1302端口
ds1032_read_realTime(); //读取此时时刻
OLED_Init(); //初始化OLED
OLED_Clear(); //清屏
delay_ms(100);
DHT11_Init(); //传感器初始化
OLED_DrawBMP(0,0,128,8,BMP19); //欢迎使用开机页面
delay_ms(1000);
OLED_Clear(); //清屏
RealTime_Display_Init(); //上电初始化显示实时时间
while(1)
{
delay_ms(200); //添加延时,保证检测的稳定性
ds1032_read_realTime(); //读取此时时刻
RealTime_Display(); //实时时间日期实时刷新显示
if(DHT11_Data_Read_flag) //6秒读取一次温湿度数据
{
DHT11_Read_Data(&temperature, &humidity); //读取温湿度值
DHT11_Data_Read_flag=0; //复位读取DHT11数据标志
}
//************************闹钟报警程序段***********************************************//
if(Alarm_Clock&&!Alarm_Manual_Stop_flag)
{
if((TimeData.hour==Alarm_Hour)&&(TimeData.minute==Alarm_Minute))
{
Alarm_Clock_flag=1; //闹钟报警标志位
}
else
{
Alarm_Clock_flag=0; //闹钟报警标志位
}
}
else
{
Alarm_Clock_flag=0; //闹钟报警标志位
}
if(!KEY_DEC) //闹钟报警过程中停止按键 减少键
{
delay_ms(10);
if(KEY_DEC==0)
{
while(!KEY_DEC);
Alarm_Manual_Stop_flag=1;
}
}
if(TimeData.minute!=Alarm_Minute) //一旦设定值与当前时间不一致则手动终端报警复位
{
Alarm_Manual_Stop_flag=0;
}
//**************************按键修改时间和日期程序段***************************************//
if(!KEY_ADJ)
{
delay_ms(10);
if(KEY_ADJ==0)
{
while(!KEY_ADJ);
OLED_Clear(); //清屏
OLED_ShowChinese(0,0,21); //年
OLED_ShowChinese(68,0,22); //月
OLED_ShowChinese(0,3,23); //日
OLED_ShowChinese(68,3,24); //时
OLED_ShowChinese(0,6,25); //分
OLED_ShowChinese(68,6,26); //周
Show_Modify_Data(num); //显示默认的时间日期设定参数
while(1)
{
OLED_ShowNum(20,0,y,2,16);
OLED_ShowNum(88,0,m,2,16);
OLED_ShowNum(20,3,d,2,16);
OLED_ShowNum(88,3,h,2,16);
OLED_ShowNum(20,6,mi,2,16);
OLED_ShowNum(88,6,w,2,16);
if(!KEY_ALM)
{
delay_ms(10);
if(KEY_ALM==0)
{
while(!KEY_ALM);
num++;
if(num>5)
num= 0;
Show_Modify_Data(num);
}
}
if(!KEY_ADD )
{
delay_ms(10);
if(KEY_ADD ==0)
{
while(!KEY_ADD );
switch(num)
{
case 0 : y++; break;
case 1 : m++; break;
case 2 : d++; break;
case 3 : h++; break;
case 4 : mi++; break;
case 5 : w++; break;
}
if(y>59)
y = 59;
if(m>12)
m=12;
if(d>31)
d=31;
if(h>23)
h=23;
if(mi>59)
mi=59;
if(w>7)
w=7;
}
}
if(!KEY_DEC)
{
delay_ms(10);
if(KEY_DEC==0)
{
while(!KEY_DEC);
switch(num)
{
case 0 : y--; break;
case 1 : m--; break;
case 2 : d--; break;
case 3 : h--; break;
case 4 : mi--; break;
case 5 : w--; break;
}
if(y<=1)
y=1;
if(m<1)
m=1;
if(d<1)
d=1;
if(h<1)
h=1;
if(mi<1)
mi=1;
if(w<1)
w=1;
}
}
if(!KEY_ADJ)
{
delay_ms(10);
if(KEY_ADJ==0)
{
while(!KEY_ADJ);
switch(y)//设置年
{
case 0 : time_buf[1]=0x00;break;
case 1 : time_buf[1]=0x01;break;
case 2 : time_buf[1]=0x02;break;
case 3 : time_buf[1]=0x03;break;
case 4 : time_buf[1]=0x04;break;
case 5 : time_buf[1]=0x05;break;
case 6 : time_buf[1]=0x06;break;
case 7 : time_buf[1]=0x07;break;
case 8 : time_buf[1]=0x08;break;
case 9 : time_buf[1]=0x09;break;
case 10 : time_buf[1]=0x10;break;
case 11 : time_buf[1]=0x11;break;
case 12 : time_buf[1]=0x12;break;
case 13 : time_buf[1]=0x13;break;
case 14 : time_buf[1]=0x14;break;
case 15 : time_buf[1]=0x15;break;
case 16 : time_buf[1]=0x16;break;
case 17 : time_buf[1]=0x17;break;
case 18 : time_buf[1]=0x18;break;
case 19 : time_buf[1]=0x19;break;
case 20 : time_buf[1]=0x20;break;
case 21 : time_buf[1]=0x21;break;
case 22 : time_buf[1]=0x22;break;
case 23 : time_buf[1]=0x23;break;
case 24 : time_buf[1]=0x24;break;
case 25 : time_buf[1]=0x25;break;
case 26 : time_buf[1]=0x26;break;
case 27 : time_buf[1]=0x27;break;
case 28 : time_buf[1]=0x28;break;
case 29 : time_buf[1]=0x29;break;
case 30 : time_buf[1]=0x30;break;
case 31 : time_buf[1]=0x31;break;
case 32 : time_buf[1]=0x32;break;
case 33 : time_buf[1]=0x33;break;
case 34 : time_buf[1]=0x34;break;
case 35 : time_buf[1]=0x35;break;
case 36 : time_buf[1]=0x36;break;
case 37 : time_buf[1]=0x37;break;
case 38 : time_buf[1]=0x38;break;
case 39 : time_buf[1]=0x39;break;
case 40 : time_buf[1]=0x40;break;
case 41 : time_buf[1]=0x41;break;
case 42 : time_buf[1]=0x42;break;
case 43 : time_buf[1]=0x43;break;
case 44 : time_buf[1]=0x44;break;
case 45 : time_buf[1]=0x45;break;
case 46 : time_buf[1]=0x46;break;
case 47 : time_buf[1]=0x47;break;
case 48 : time_buf[1]=0x48;break;
case 49 : time_buf[1]=0x49;break;
case 50 : time_buf[1]=0x50;break;
case 51 : time_buf[1]=0x51;break;
case 52 : time_buf[1]=0x52;break;
case 53 : time_buf[1]=0x53;break;
case 54 : time_buf[1]=0x54;break;
case 55 : time_buf[1]=0x55;break;
case 56 : time_buf[1]=0x56;break;
case 57 : time_buf[1]=0x57;break;
case 58 : time_buf[1]=0x58;break;
case 59 : time_buf[1]=0x59;break;
default : time_buf[5]=0x01;
}
switch(m)//设置月
{
case 1 : time_buf[2]=0x01;break;
case 2 : time_buf[2]=0x02;break;
case 3 : time_buf[2]=0x03;break;
case 4 : time_buf[2]=0x04;break;
case 5 : time_buf[2]=0x05;break;
case 6 : time_buf[2]=0x06;break;
case 7 : time_buf[2]=0x07;break;
case 8 : time_buf[2]=0x08;break;
case 9 : time_buf[2]=0x09;break;
case 10 : time_buf[2]=0x10;break;
case 11 : time_buf[2]=0x11;break;
case 12 : time_buf[2]=0x12;break;
default : time_buf[2]=0x01;
}
switch(d)//设置日
{
case 1 : time_buf[3]=0x01;break;
case 2 : time_buf[3]=0x02;break;
case 3 : time_buf[3]=0x03;break;
case 4 : time_buf[3]=0x04;break;
case 5 : time_buf[3]=0x05;break;
case 6 : time_buf[3]=0x06;break;
case 7 : time_buf[3]=0x07;break;
case 8 : time_buf[3]=0x08;break;
case 9 : time_buf[3]=0x09;break;
case 10 : time_buf[3]=0x10;break;
case 11 : time_buf[3]=0x11;break;
case 12 : time_buf[3]=0x12;break;
case 13 : time_buf[3]=0x13;break;
case 14 : time_buf[3]=0x14;break;
case 15 : time_buf[3]=0x15;break;
case 16 : time_buf[3]=0x16;break;
case 17 : time_buf[3]=0x17;break;
case 18 : time_buf[3]=0x18;break;
case 19 : time_buf[3]=0x19;break;
case 20 : time_buf[3]=0x20;break;
case 21 : time_buf[3]=0x21;break;
case 22 : time_buf[3]=0x22;break;
case 23 : time_buf[3]=0x23;break;
case 24 : time_buf[3]=0x24;break;
case 25 : time_buf[3]=0x25;break;
case 26 : time_buf[3]=0x26;break;
case 27 : time_buf[3]=0x27;break;
case 28 : time_buf[3]=0x28;break;
case 29 : time_buf[3]=0x29;break;
case 30 : time_buf[3]=0x30;break;
case 31 : time_buf[3]=0x31;break;
default : time_buf[3]=0x01;
}
switch(h)//设置时
{
case 0 : time_buf[4]=0x00;break;
case 1 : time_buf[4]=0x01;break;
case 2 : time_buf[4]=0x02;break;
case 3 : time_buf[4]=0x03;break;
case 4 : time_buf[4]=0x04;break;
case 5 : time_buf[4]=0x05;break;
case 6 : time_buf[4]=0x06;break;
case 7 : time_buf[4]=0x07;break;
case 8 : time_buf[4]=0x08;break;
case 9 : time_buf[4]=0x09;break;
case 10 : time_buf[4]=0x10;break;
case 11 : time_buf[4]=0x11;break;
case 12 : time_buf[4]=0x12;break;
case 13 : time_buf[4]=0x13;break;
case 14 : time_buf[4]=0x14;break;
case 15 : time_buf[4]=0x15;break;
case 16 : time_buf[4]=0x16;break;
case 17 : time_buf[4]=0x17;break;
case 18 : time_buf[4]=0x18;break;
case 19 : time_buf[4]=0x19;break;
case 20 : time_buf[4]=0x20;break;
case 21 : time_buf[4]=0x21;break;
case 22 : time_buf[4]=0x22;break;
case 23 : time_buf[4]=0x23;break;
default : time_buf[4]=0x01;
}
switch(mi)//设置分
{
case 0 : time_buf[5]=0x00;break;
case 1 : time_buf[5]=0x01;break;
case 2 : time_buf[5]=0x02;break;
case 3 : time_buf[5]=0x03;break;
case 4 : time_buf[5]=0x04;break;
case 5 : time_buf[5]=0x05;break;
case 6 : time_buf[5]=0x06;break;
case 7 : time_buf[5]=0x07;break;
case 8 : time_buf[5]=0x08;break;
case 9 : time_buf[5]=0x09;break;
case 10 : time_buf[5]=0x10;break;
case 11 : time_buf[5]=0x11;break;
case 12 : time_buf[5]=0x12;break;
case 13 : time_buf[5]=0x13;break;
case 14 : time_buf[5]=0x14;break;
case 15 : time_buf[5]=0x15;break;
case 16 : time_buf[5]=0x16;break;
case 17 : time_buf[5]=0x17;break;
case 18 : time_buf[5]=0x18;break;
case 19 : time_buf[5]=0x19;break;
case 20 : time_buf[5]=0x20;break;
case 21 : time_buf[5]=0x21;break;
case 22 : time_buf[5]=0x22;break;
case 23 : time_buf[5]=0x23;break;
case 24 : time_buf[5]=0x24;break;
case 25 : time_buf[5]=0x25;break;
case 26 : time_buf[5]=0x26;break;
case 27 : time_buf[5]=0x27;break;
case 28 : time_buf[5]=0x28;break;
case 29 : time_buf[5]=0x29;break;
case 30 : time_buf[5]=0x30;break;
case 31 : time_buf[5]=0x31;break;
case 32 : time_buf[5]=0x32;break;
case 33 : time_buf[5]=0x33;break;
case 34 : time_buf[5]=0x34;break;
case 35 : time_buf[5]=0x35;break;
case 36 : time_buf[5]=0x36;break;
case 37 : time_buf[5]=0x37;break;
case 38 : time_buf[5]=0x38;break;
case 39 : time_buf[5]=0x39;break;
case 40 : time_buf[5]=0x40;break;
case 41 : time_buf[5]=0x41;break;
case 42 : time_buf[5]=0x42;break;
case 43 : time_buf[5]=0x43;break;
case 44 : time_buf[5]=0x44;break;
case 45 : time_buf[5]=0x45;break;
case 46 : time_buf[5]=0x46;break;
case 47 : time_buf[5]=0x47;break;
case 48 : time_buf[5]=0x48;break;
case 49 : time_buf[5]=0x49;break;
case 50 : time_buf[5]=0x50;break;
case 51 : time_buf[5]=0x51;break;
case 52 : time_buf[5]=0x52;break;
case 53 : time_buf[5]=0x53;break;
case 54 : time_buf[5]=0x54;break;
case 55 : time_buf[5]=0x55;break;
case 56 : time_buf[5]=0x56;break;
case 57 : time_buf[5]=0x57;break;
case 58 : time_buf[5]=0x58;break;
case 59 : time_buf[5]=0x59;break;
default : time_buf[5]=0x01;
}
switch(w)//设置星期
{
case 1 : time_buf[6]=0x01;break;
case 2 : time_buf[6]=0x02;break;
case 3 : time_buf[6]=0x03;break;
case 4 : time_buf[6]=0x04;break;
case 5 : time_buf[6]=0x05;break;
case 6 : time_buf[6]=0x06;break;
case 7 : time_buf[6]=0x07;break;
default : time_buf[6]=0x01;
}
ds1302_write_time(); //修改时间,写入
OLED_Clear(); //清屏
ds1032_read_realTime(); //读取此时时刻
Modify_RealTime_Display(); //修改后时间日期刷新一次显示
break;
}
}
}
}
}
//******************************修改闹钟时间和闹钟设定程序段*******************************//
if(!KEY_ALM)
{
delay_ms(10);
if(KEY_ALM==0)
{
while(!KEY_ALM);
OLED_Clear(); //清屏
OLED_ShowChinese(32,0,27); //闹钟设定
OLED_ShowChinese(48,0,28);
OLED_ShowChinese(64,0,29);
OLED_ShowChinese(80,0,30);
OLED_ShowChar(60,3,':',16);
Show_Modify_Alarm(num2); //显示修改闹钟信息
while(1)
{
OLED_ShowNum(44,3,Alarm_Hour,2,16);
OLED_ShowNum(68,3,Alarm_Minute,2,16);
if(Alarm_Clock) //闹钟开关显示
{
OLED_ShowChinese(104,3,31);
}
else
{
OLED_ShowChinese(104,3,32);
}
if(Alarm_Minute<10) //防止显示1位数,不整齐
{
OLED_ShowChar(68,3,'0',16); //0位补偿
}
if(!KEY_ADJ)
{
delay_ms(10);
if(KEY_ADJ==0)
{
while(!KEY_ADJ);
num2++;
if(num2>2)
num2= 0;
Show_Modify_Alarm(num2);
}
}
if(!KEY_ADD)
{
delay_ms(10);
if(KEY_ADD==0)
{
while(!KEY_ADD);
switch(num2)
{
case 0 : Alarm_Hour++; break;
case 1 : Alarm_Minute++; break;
case 2 : Alarm_Clock++; break;
}
if(Alarm_Hour>23)
Alarm_Hour= 23;
if(Alarm_Minute>59)
Alarm_Minute=59;
if(Alarm_Clock>=1)
Alarm_Clock=1;
}
}
if(!KEY_DEC)
{
delay_ms(10);
if(KEY_DEC==0)
{
while(!KEY_DEC);
switch(num2)
{
case 0 : Alarm_Hour--; break;
case 1 : Alarm_Minute--; break;
case 2 : Alarm_Clock--; break;
}
if(Alarm_Hour<=0)
Alarm_Hour=0;
if(Alarm_Minute<=0)
Alarm_Minute=0;
if(Alarm_Clock<=0)
Alarm_Clock=0;
}
}
if(!KEY_ALM)
{
delay_ms(10);
if(KEY_ALM==0)
{
while(!KEY_ALM);
OLED_Clear();
ds1032_read_realTime(); //读取此时时刻
Modify_RealTime_Display(); //修改后时间日期刷新一次显示
break;
}
}
}
}
}
//****************************主程序运行指示灯程序段**************************************//
if(Run_Indicate_num>=50) //闪烁则证明主程序在持续运行
{
RUN_Indicate_ENABLE; //指示灯亮
}
else
{
RUN_Indicate_UNABLE;//指示灯灭
}
}
}
六、实验效果
七、资料内容