文章目录
- 功能
- 硬件连接
- 实物
- 程序
功能
- 功能
- 1 万年历显示
- 2 按键修改时间
- 3 按键修改闹钟
- 4 闹钟到达 蜂鸣器鸣叫10秒自动关闭 闹钟是音乐
- 5 温湿度显示
- 6 温度到达28度以上蜂鸣器鸣叫
采用单片机内部的RTC模块走时。
按键1 切换选择年月日时分秒,靠按键1退出时间不会保存
按键2 保存设置的万年历时间并退出
按键3 加1
按键4 减1
按键5 切换选择闹钟的时分秒
矩阵键盘的16个按键只用了5个。
温湿度依靠DHT11传感器。
闹钟到达后是鸣叫天空之城,最长10秒钟后自动关闭。
硬件连接
-
msp430f5529
-
矩阵键盘
-
oled 4针
-
蜂鸣器 无源 低电平触发
-
dht11温湿度传感器
-
OLED SCL–P3.0 SDA–P3.1 VCC–3.3V GND–GND
-
beep DAT–P2.4 VCC–3.3V GND–GND 无源 低电平触发
-
DHT11 DAT–P4.1 VCC–3.3 GND–GND
矩阵键盘
- 列0 P8.2
- 列1 P3.7
- 列2 P4.0
- 列3 P4.3
- 行0 P1.2
- 行1 P1.3
- 行2 P1.4
- 行3 P1.5
- 行作为上拉输入 列作为输出
实物
程序
全部程序:https://github.com/xddun/blog_code_search
部分程序如下
主程序:
这段程序是一个基于MSP430F5529微控制器的嵌入式系统应用程序。它使用了一些外部设备库(oled、delay、keyboard、rtc、dht11、beep_music)来实现以下功能:
万年历显示:在OLED屏幕上显示日期和时间。
按键修改时间:通过矩阵键盘输入,可以修改系统的当前时间。
按键修改闹钟:通过矩阵键盘输入,可以修改系统的闹钟时间。
闹钟到达:当系统的当前时间和闹钟时间匹配时,触发蜂鸣器鸣叫10秒钟,并自动关闭。闹钟的声音由音乐驱动。
温湿度显示:通过DHT11温湿度传感器获取环境的温度和湿度数据,并在OLED屏幕上显示。
温度到达28度以上蜂鸣器鸣叫:当温度超过28度时,触发蜂鸣器鸣叫。
整个程序的主要逻辑在main()函数中,初始化各个外部设备并进入一个无限循环。循环中不断读取按键、更新时间、读取温湿度数据,并根据条件触发蜂鸣器的开关和音乐播放。此外,还有一个定时器中断函数Timer_A(),用于控制蜂鸣器音乐的播放。
整个程序的功能是实现一个具有时间显示、闹钟设置、温湿度检测和报警的系统。
#include <msp430.h>
#include "oled.h"
#include "delay.h"
#include "keyboard.h"
#include "rtc.h"
#include "oled_disp.h"
#include "do_key.h"
#include "dht11.h"
#include "beep_music.h"
int main( void )
{
WDTCTL = WDTPW + WDTHOLD; /* Stop WDT */
init_clock_4mhz();
OLED_Init(); /* OLED初始化 */
KEY_Init();
SetupRTC();
P1DIR |= BIT0;
P4DIR |= BIT7;
/* 温度湿度 */
OLED_ShowCHinese( 16 * 0, 0, 0 );
OLED_ShowCHinese( 16 * 1, 0, 1 );
OLED_ShowCHinese( 16 * 4, 0, 2 );
OLED_ShowCHinese( 16 * 5, 0, 3 );
/* 闹钟 */
OLED_ShowCHinese( 16 * 0, 6, 4 );
OLED_ShowCHinese( 16 * 1, 6, 5 );
rtc_time_alarm.shi = 23;
rtc_time_alarm.fen = 12;
rtc_time_alarm.miao = 15;
_EINT();
while ( 1 )
{
delay_ms( 5 );
t++;
if ( t > 50 )
{
t = 0;
P4OUT ^= BIT7;
}
key = read_key_2( 0 );
if ( key )
{
user_pro_key( key );
disp_rtc();
oled_cnt = 0;
oled_disp[oled_cnt++] = key / 10 + '0';
oled_disp[oled_cnt++] = key % 10 + '0';
oled_disp[oled_cnt++] = 0;
OLED_ShowString( 16*6, 2, oled_disp, 0 );
}
/* 显示时间 */
if ( setting == 0 )
{
if ( sec != rtc_time.miao )
{
sec = rtc_time.miao;
disp_rtc();
/* 闹钟比对 */
if ( beep_open_state == 1 )
{
music_open_rtc_cnt++;
}
if ( (rtc_time_alarm.shi == rtc_time.shi)
&& (rtc_time_alarm.fen == rtc_time.fen)
&& (rtc_time_alarm.miao == rtc_time.miao) )
{
beep_open_state = 1; /* 0关闭蜂鸣器 1蜂鸣器音乐模式 2蜂鸣器pwm鸣叫模式 */
music_u = 0;
new_music = 0;
delay_music = 0;
music_open_rtc_cnt = 0;
}
}
}
/* 读取温湿度 */
dht11_read_cnt++;
if ( dht11_read_cnt > 400 ) /* 约2秒更新一次温湿度 */
{
dht11_read_cnt = 0;
/* 如果读取到了 并且校验成功 */
if ( receive_init() == 1 )
{
dht11_temp = temph;
dht11_humi = humdh;
if ( temph > 27 )
{
P1OUT |= BIT0; /* 点亮 */
if ( beep_open_state == 0 )
{
beep_open_state = 2; /* 0关闭蜂鸣器 1蜂鸣器音乐模式 2蜂鸣器pwm鸣叫模式 */
}
}else {
P1OUT &= ~BIT0; /* 熄灭 */
if ( beep_open_state == 2 )
{
beep_open_state = 0;
}
}
disp_rtc();
}
}
/* 蜂鸣器控制 */
if ( beep_open_state_previous != beep_open_state )
{
beep_open_state_previous = beep_open_state;
if ( beep_open_state == 0 ) /* 0关闭蜂鸣器 1蜂鸣器音乐模式 2蜂鸣器pwm鸣叫模式 */
{
close_beep();
}else if ( beep_open_state == 2 ) /* 0关闭蜂鸣器 1蜂鸣器音乐模式 2蜂鸣器pwm鸣叫模式 */
{
open_beep();
}else if ( beep_open_state == 1 ) /* 0关闭蜂鸣器 1蜂鸣器音乐模式 2蜂鸣器pwm鸣叫模式 */
{
open_beep_music();
}
}
}
}
/* Timer A0 interrupt service routine */
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A( void )
{
/* 100ms中断 */
if ( beep_open_state == 1 )
{
if ( music_open_rtc_cnt < 11 ) /* 音乐响10秒 */
{
if ( (delay_music < music0_JP[music_u]) && (new_music == 0) ) /* 计时没结束 且第一次赋值 */
{
if ( music0[music_u] != 0xff ) /* 只要不是最后一个音符 */
{
set_pwm_freq( music0[music_u] ); /* 设置pwm频率 */
}else {
new_music = 0;
delay_music = 0;
music_open_rtc_cnt = 0;
beep_open_state = 0;
close_beep();
}
new_music = 1;
}else if ( delay_music >= music0_JP[music_u] ) /* 计时结束 */
{
music_u += 1; /*下一个音符 fgvb5 */
new_music = 0; /* 重新计时 */
delay_music = 0; /* 重新计时 */
}
delay_music++;
}else {
new_music = 0;
delay_music = 0;
music_open_rtc_cnt = 0;
beep_open_state = 0;
close_beep();
}
}
}
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR( void )
{
switch ( __even_in_range( RTCIV, RTC_RT1PSIFG ) )
{
case RTC_NONE:
break;
case RTC_RTCRDYIFG:
{
if ( setting == 0 )
{
/* 读取时间 */
rtc_time.nian = RTCYEAR;
rtc_time.yue = RTCMON;
rtc_time.ri = RTCDAY;
rtc_time.shi = RTCHOUR;
rtc_time.fen = RTCMIN;
rtc_time.miao = RTCSEC;
rtc_time.zhou = RTCDOW;
}
/* 闪烁灯 */
P1OUT ^= BIT0;
}
break;
case RTC_RTCTEVIFG:
break;
case RTC_RTCAIFG:
break;
case RTC_RT0PSIFG:
break; /* 分频器 0 */
case RTC_RT1PSIFG:
break; /* 分频器 1 */
default:
break;
}
__no_operation();
}