基于单片机的数字时钟设计与实现
作品名称
基于MSP430单片机的OLED显示数字时钟
作品功能
本作品实现了一个具有时间显示和整点报时功能的数字时钟。通过OLED屏幕显示当前时间,用户可以通过按键设置时间,并在整点时通过蜂鸣器播放音乐进行报时。
作品的硬件材料
- MSP430 单片机
- OLED 显示屏
- 蜂鸣器
- 按键(4个)
- 电阻和电容若干
- 面包板和连接线
电子元器件连接
以下是各电子元器件与MSP430单片机的连接方式:
OLED 显示屏
- VCC 接 3.3V
- GND 接 GND
- SCL 接 P2.0
- SDA 接 P2.2
按键
- KEY1 接 P1.2(共GND)
- KEY2 接 P1.3(共GND)
- KEY3 接 P1.4(共GND)
- KEY4 接 P1.5(共GND)
蜂鸣器
- VCC 接 3.3V
- GND 接 GND
- DAT 接 P4.3
部分程序功能简介
本程序主要包括初始化时钟、设置RTC、按键读取、显示更新和整点报时等功能。
初始化时钟
通过以下函数设置系统时钟为8MHz:
void initClock(void) {
UCSCTL3 = SELREF_2; // 设置DCO FLL参考为REFO
UCSCTL4 |= SELA_2; // 设置ACLK为REFO
UCSCTL0 = 0x0000; // 设置最低可能的DCOx, MODx
do {
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // 清除XT2,XT1,DCO故障标志
SFRIFG1 &= ~OFIFG; // 清除故障标志
} while (SFRIFG1 & OFIFG); // 检测振荡器故障标志
__bis_SR_register(SCG0); // 禁止FLL控制环路
UCSCTL1 = DCORSEL_5; // 设置DCO范围为16MHz操作
UCSCTL2 |= 249; // 设置DCO倍增器为8MHz
__bic_SR_register(SCG0); // 启用FLL控制环路
__delay_cycles(250000); // 延时以稳定DCO
}
设置RTC
通过以下函数设置RTC(实时时钟)模块:
void SetupRTC(void) {
RTCCTL01 = RTCHOLD + RTCMODE + RTCTEV_0; // 关闭RTC
RTCYEAR = 2024; // 设置年份
RTCMON = 5; // 设置月份
RTCDAY = 13; // 设置日期
RTCHOUR = 23; // 设置小时
RTCMIN = 12; // 设置分钟
RTCSEC = 12; // 设置秒数
RTCDOW = 1; // 设置星期
RTCCTL0 |= RTCRDYIE; // 使能RTC就绪中断
RTCCTL01 &= ~RTCHOLD; // 打开RTC
}
按键读取
通过以下函数读取按键状态:
unsigned char read_key(void) {
unsigned char key = 0;
if ((P1IN & BIT2) == 0) {
key = 1; // 按键1按下
} else if ((P1IN & BIT3) == 0) {
key = 2; // 按键2按下
} else if ((P1IN & BIT4) == 0) {
key = 3; // 按键3按下
} else if ((P1IN & BIT5) == 0) {
key = 4; // 按键4按下
}
return key;
}
显示更新
通过以下函数更新OLED显示内容:
void display_all(void) {
memset(buf, 0, sizeof(buf));
sprintf(buf, "%04d-%02d-%02d", nian, yue, ri); // 格式化日期
OLED_ShowString(16, 2, buf, 0); // 显示日期
memset(buf, 0, sizeof(buf));
sprintf(buf, "%02d:%02d:%02d", shi, fen, miao); // 格式化时间
OLED_ShowString(16, 4, buf, 0); // 显示时间
// 高亮显示根据mode的值选择的部分
if (mode == 1) {
sprintf(buf, "%04d", nian);
OLED_ShowString(16, 2, buf, 1);
} else if (mode == 2) {
sprintf(buf, "%02d", yue);
OLED_ShowString(16 + 5 * 8, 2, buf, 1);
} else if (mode == 3) {
sprintf(buf, "%02d", ri);
OLED_ShowString(16 + 8 * 8, 2, buf, 1);
} else if (mode == 4) {
sprintf(buf, "%02d", shi);
OLED_ShowString(16, 4, buf, 1);
} else if (mode == 5) {
sprintf(buf, "%02d", fen);
OLED_ShowString(16 + 3 * 8, 4, buf, 1);
} else if (mode == 6) {
sprintf(buf, "%02d", miao);
OLED_ShowString(16 + 6 * 8, 4, buf, 1);
}
}
整点报时
当达到整点时,通过蜂鸣器播放音乐:
if (integral_point == 1) { // 如果到达整点
integral_point = 0;
u = 0, t = 0;
while (music0[u] != 0xff) { // 播放音乐
TA0CCR0 = SYSCLK / music0[u] / 2;
TA0CTL = TASSEL_2 + MC_1 + TACLR + ID_3;
for (t = 0; t < music0_JP[u]; t++) {
delay1();
}
u++;
}
}
总结
通过本项目,熟悉了MSP430单片机的基础功能,如时钟设置、按键读取和OLED显示。同时,结合蜂鸣器实现了整点报时功能,为单片机应用提供了实用案例。这个数字时钟不仅展示了基本的电子设计和编程能力,还提供了可扩展的基础,适合进一步添加更多功能。
全部代码下载
咨询问询请访问:
https://docs.qq.com/sheet/DUEdqZ2lmbmR6UVdU?tab=BB08J2