51单片机的多功能液晶显示日期、温度、闹钟制作

前言:

     本次多功能液晶,是在宋雪松编撰的《手把手教你学单片机》第19章的多功能电子时钟基础上改的。为了符合学校的期末考核要求,日期、温度、闹钟等均是显示在液晶上的。这个项目所有代码,我都会放在文章结尾。如有错误,欢迎在评论区指出来。感谢!

设计要求:

1)DS1302保持时间和日期

2)DS18B20采集温度

3)  蜂鸣器提示闹钟

4)可以修改日期、闹钟设置

主要代码展示:

   main.c

#define _MAIN_C
#include "config.h"
#include "Lcd1602.h"
#include "LedBuzzer.h"
#include "keyboard.h"
#include "DS1302.h"
#include "DS18B20.h"
#include "Time.h"
#include "main.h"

bit flag2s = 0; //2s 定时标志位
bit flag200ms = 0; //200ms 定时标志
bit staBuzzer = 0; //蜂鸣器状态控制位,1-鸣叫、0-关闭
uint8 T0RH = 0; //T0 重载值的高字节
uint8 T0RL = 0; //T0 重载值的低字节
enum eStaSystem staSystem = E_NORMAL; //系统运行状态

uint8 T2RH = 0;
uint8 T2RL = 0;


void main()
{
 EA = 1; //开总中断
 ConfigTimer0(1); //配置 T0 定时 1ms
 InitDS1302(); //初始化实时时钟模块
 InitLcd1602(); //初始化液晶模块
 Start18B20(); //启动首次温度转换
 
 while (!flag2s); //上电后延时 2 秒
 flag2s = 0;
	
 RefreshDate(1); //立即刷新日期显示
 RefreshTemp(1); //立即刷新温度显示
 RefreshAlarm();
 
 while (1) //进入主循环
 {
   KeyDriver(); //执行按键驱动
   if (flag200ms) //每隔 200ms 执行以下分支
  {
    flag200ms = 0;
    AlarmMonitor(); //监控闹钟
    if (staSystem == E_NORMAL) //正常运行时刷新日期显示
    {
      RefreshDate(1);
    }
 }
 if (flag2s) //每隔 2s 执行以下分支
 {
   flag2s = 0;
   if (staSystem == E_NORMAL) //正常运行时刷新温度显示
    {
        RefreshTemp(0);
    }
  }
 } 
}


/**************************温度部分代码*******************************************/
/* 整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */
unsigned char IntToString(unsigned char *str, int dat)
{
 signed char i = 0;
 unsigned char len = 0;
 unsigned char buf[5];
 
 if (dat < 0) //如果为负数,首先取绝对值,并在指针上添加负号
 {
 dat = -dat;
 *str++ = '-';
 len++;
 }
 do { //先转换为低位在前的十进制数组
 buf[i++] = dat % 10;
 dat /= 10;
 } while (dat > 0);
 len += i; //i 最后的值就是有效字符的个数
 while (i-- > 0) //将数组值转换为 ASCII 码反向拷贝到接收指针上
 {
 *str++ = buf[i] + '0';
  }
 *str = '\0'; //添加字符串结束符
 
 return len; //返回字符串长度
}

/* 温度刷新函数,读取当前温度并根据需要刷新液晶显示,
** ops-刷新选项:为 0 时只当温度变化才刷新,非 0 则立即刷新 */
void RefreshTemp(uint8 ops)
{
 int16 temp;
 int intT,decT;
 bit res;
 uint8 pdata str[8];
 uint8 len;
 static int16 backup = 0;
 
 res = Get18B20Temp(&temp); //获取当前温度值
 

 if(ops!=0) //按需要刷新液晶显示
 {
    if(res)
		{ 
			  intT = temp >> 4; 
				decT = temp & 0xF;
			  len = IntToString(str,intT);
		    str[len++] = '.';
        decT = (decT * 10) / 16;
		    str[len++] = decT + '0';
			
				while(len<6)
		  	{
				 str[len++] = ' ';
			  }
        str[len] = '\0';
			 LcdShowStr(11, 0, str); //显示到液晶上
			 LcdShowStr(15, 0, "C"); //显示到液晶上	
       backup = temp; //刷新上次温度值
		}
		else
		{
			  LcdShowStr(11, 0, "error");
		}

 }
   Start18B20(); //启动下一次转换
}

 



/* 配置并启动 T0,ms-T0 定时时间 */
void ConfigTimer0(uint16 ms)
{
 uint32 tmp;
 
 tmp = (SYS_MCLK*ms)/1000; //计算所需的计数值
 tmp = 65536 - tmp; //计算定时器重载值
 tmp = tmp + 33; //补偿中断响应延时造成的误差 
 T0RH = (uint8)(tmp>>8); //定时器重载值拆分为高低字节
 T0RL = (uint8)tmp;
 TMOD &= 0xF0; //清零 T0 的控制位
 TMOD |= 0x01; //配置 T0 为模式 1
 TH0 = T0RH; //加载 T0 重载值
 TL0 = T0RL;
 ET0 = 1; //使能 T0 中断
 TR0 = 1; //启动 T0
}
/* T0 中断服务函数,实现系统定时和按键扫描 */
void InterruptTimer0() interrupt 1
{
 static uint8 tmr2s = 0;
 static uint8 tmr200ms = 0;
 
 TH0 = T0RH; //重新加载重载值
 TL0 = T0RL;
 tmr200ms++; //定时 200ms
 if (tmr200ms >= 200)
 {
 tmr200ms = 0;
 flag200ms = 1;
 tmr2s++; //定时 2s
 if (tmr2s >= 10)
 {
 tmr2s = 0;
 flag2s = 1;
 }
 }
 KeyScan(); //执行按键扫描
}

void interrupttimer2() interrupt 5
{

	TH2 = T2RH;
	TL2 = T2RL;
	
}

这个温度模块有点没弄好,就直接放main.c里面了,如果看不过去,你们可以自己放其他.c文件里面。

不足:

     本次设计有两个不足的地方,代码没改好,如果不符合你们的要求,需要你们自己改啦。

     第一个就是闹钟,没有加入EEPROM模块保存闹钟设置,即使改变了闹钟设置,但给单片机重新上电后,都会变成6:30。

    第二个就是蜂鸣器设置,只要一重新设置了闹钟,那个时钟秒就会从原本的秒变成零,再开始向计数;蜂鸣器声音也超小声,滴滴的,不仔细听都听不见那种。

展示:

链接:https://pan.baidu.com/s/1yvydtKNk3WuDxZ9YWr3fvw 
提取码:axhs

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值