基于51单片机的数字时钟(万年历)设计与实现
基于51单片机的数字时钟(万年历)设计与实现
摘要
随着科技的不断发展,数字时钟已成为人们日常生活中不可或缺的一部分。基于51单片机的数字时钟(万年历)设计,结合了传统时钟的功能与现代电子技术,具有高精度、低功耗、可靠性高等特点。本文首先介绍了数字时钟的研究背景与意义,然后阐述了系统设计的总体方案,包括硬件设计、软件设计以及系统调试。接着详细描述了各个模块的实现过程,并给出了相应的电路图和程序代码。最后对系统进行了性能测试与结果分析,总结了设计的优缺点,并提出了改进方向。
一、引言
时钟作为计时工具,自古以来就在人们的生活中扮演着重要角色。从日晷、沙漏到机械钟、电子钟,时钟的形态与技术不断发展。如今,基于单片机的数字时钟已成为主流,它具有显示直观、功能丰富、便于携带等优点。51单片机作为一款经典的微控制器,具有性价比高、编程简单、资源丰富等特点,在数字时钟的设计中得到了广泛应用。
二、系统设计方案
- 硬件设计
硬件设计是数字时钟设计的基础,它决定了系统的稳定性和可靠性。本设计采用51单片机作为核心控制器,通过扩展外部电路实现时钟功能。主要包括以下几个部分:
(1)主控芯片:选用STC89C52单片机,它是一款基于8051内核的高性能微控制器,具有低功耗、高速度、强抗干扰能力等特点。
(2)时钟模块:采用DS1302实时时钟芯片,它是一款高性能、低功耗、带RAM的实时时钟芯片,可以提供精确的秒、分、时、日、周、月、年等信息。
(3)显示模块:采用LCD1602液晶显示屏,它可以显示两行共16个字符,用于显示时间、日期等信息。
(4)按键模块:设计4个独立按键,分别用于调整时、分、秒和日期等信息。
(5)电源模块:采用5V直流电源供电,通过稳压电路为系统提供稳定的工作电压。
- 软件设计
软件设计是数字时钟设计的核心,它决定了系统的功能和性能。本设计采用C语言进行编程,通过模块化设计思想将程序分为若干个模块,便于调试和维护。主要包括以下几个部分:
(1)主程序:负责系统的初始化、各模块的调用以及主循环的执行。
(2)DS1302驱动程序:负责DS1302芯片的初始化、时间读取和设置等操作。
(3)LCD1602驱动程序:负责LCD1602显示屏的初始化、显示内容的更新等操作。
(4)按键处理程序:负责按键的扫描、去抖、识别以及相应功能的实现等操作。
(5)中断服务程序:负责处理定时器中断、外部中断等事件,实现时间的精确计时和按键的实时响应等功能。
- 系统调试
系统调试是数字时钟设计的最后一步,它决定了系统的可用性和可靠性。本设计采用分步调试法,先对各个模块进行单独调试,确保每个模块都能正常工作;然后再将整个系统联调起来,测试系统的整体性能和功能是否满足设计要求。
三、模块实现与测试
- 时钟模块实现与测试
时钟模块是本设计的核心部分之一,它负责提供精确的时间信息。本设计采用DS1302实时时钟芯片来实现时钟功能。首先通过单片机对DS1302进行初始化设置,包括设置时间格式、初始化时间等;然后通过单片机定时读取DS1302的时间信息,并更新到LCD1602显示屏上显示出来;最后通过按键模块实现对时间的调整功能。经过测试表明,时钟模块能够准确提供时间信息,并具有良好的稳定性和可靠性。
- 显示模块实现与测试
显示模块是本设计的另一个重要部分,它负责将时间信息以直观的方式显示出来。本设计采用LCD1602液晶显示屏来实现显示功能。首先通过单片机对LCD1602进行初始化设置;然后将从DS1302读取到的时间信息格式化后发送到LCD1602上显示出来;最后通过按键模块实现对显示内容的切换和调整功能。经过测试表明,显示模块能够清晰显示时间信息,并具有良好的可读性和可视性。
- 按键模块实现与测试
按键模块是本设计的输入部分之一,它负责接收用户的操作指令并传递给单片机处理。本设计采用4个独立按键来实现对时间和日期的调整功能。首先通过单片机对按键进行扫描和去抖处理;然后识别出被按下的按键并执行相应的功能;最后通过中断服务程序实现按键的实时响应功能。经过测试表明,按键模块能够准确识别用户的操作指令并做出正确响应。
四、性能测试与结果分析
为了验证本设计的性能和功能是否满足设计要求,进行了一系列性能测试和结果分析工作。主要包括以下几个方面:
-
时间精度测试:通过长时间运行观察系统时间是否与实际时间保持同步,并计算误差大小。测试结果表明,本设计的时间精度较高,误差在可接受范围内。
-
稳定性测试:通过连续运行观察系统是否出现死机、重启等异常情况,并统计故障率大小。测试结果表明,本设计的稳定性较好,故障率较低。
-
功耗测试:通过测量系统在待机状态和工作状态下的电流大小来评估功耗水平。测试结果表明,本设计的功耗较低,符合节能环保要求。
五、总结与展望
本文基于51单片机设计了一款数字时钟(万年历),详细介绍了系统设计的总体方案、模块实现与测试以及性能测试与结果分析等方面内容。通过实际测试表明,该设计具有较高的时间精度、稳定性和可靠性,能够满足人们日常生活中对计时工具的需求。然而,随着科技的不断发展进步和人们对生活质量要求的不断提高,未来数字时钟的设计还需要进一步完善和创新。例如可以增加更多实用功能(如闹钟提醒、温度显示等)、提高显示效果(如采用彩色显示屏或触摸屏等)、降低功耗水平(如采用低功耗芯片或优化电路设计等)等方面进行改进和优化。同时还需要关注新技术和新材料的应用发展趋势,以便及时将最新技术成果应用到数字时钟的设计中来提高其性能水平并满足人们日益增长的需求。
六、参考文献
[此处列出参考文献]
基于51单片机的数字时钟(万年历)设计涉及硬件电路搭建和软件编程。由于代码较长,这里提供一个简化的示例代码框架,用于指导你如何开始编写程序。请注意,这个示例代码并不是完整的实现,而是展示了如何初始化DS1302实时时钟芯片、如何在LCD1602上显示时间以及如何处理按键输入的基本结构。
#include <reg52.h> // 假设你已经定义了DS1302和LCD1602的接口和函数
// 这里只是给出函数原型,具体实现需要你根据硬件连接编写
void DS1302_Init(); // 初始化DS1302
void DS1302_GetTime(unsigned char *hour, unsigned char *minute, unsigned char *second); // 从DS1302获取时间
void LCD1602_Init(); // 初始化LCD1602
void LCD1602_ShowTime(unsigned char hour, unsigned char minute, unsigned char second); // 在LCD1602上显示时间 // 假设你已经定义了按键接口和函数
unsigned char Key_Scan(); // 扫描按键 void delay(unsigned int time); // 延时函数 void main() { unsigned char hour, minute, second; unsigned char key; DS1302_Init(); // 初始化DS1302时钟芯片 LCD1602_Init(); // 初始化LCD1602显示屏 while (1) { DS1302_GetTime(&hour, &minute, &second); // 从DS1302获取当前时间 LCD1602_ShowTime(hour, minute, second); // 在LCD1602上显示当前时间 key = Key_Scan(); // 扫描按键 if (key != 0) { // 根据按键调整时间,这里只是示例,具体实现需要你编写 // 比如:if (key == '1') { hour++; } 等等 } delay(1000); // 延时一段时间,这里假设是1秒 }
} // 以下是各个函数的简单实现框架,你需要根据具体的硬件连接来完善它们
void DS1302_Init() { // 初始化DS1302的代码,设置时钟频率、初始时间等
} void DS1302_GetTime(unsigned char *hour, unsigned char *minute, unsigned char *second) { // 从DS1302读取时间的代码,将读取到的时间赋值给hour, minute, second指针指向的变量
} void LCD1602_Init() { // 初始化LCD1602的代码,设置显示模式、清屏等
} void LCD1602_ShowTime(unsigned char hour, unsigned char minute, unsigned char second) { // 在LCD1602上显示时间的代码,将hour, minute, second格式化为字符串并显示到LCD上
} unsigned char Key_Scan() { // 扫描按键的代码,返回按下的按键值(如果有按键按下的话),否则返回0
} void delay(unsigned int time) { // 延时函数,根据给定的时间进行延时 unsigned int i, j; for (i = time; i > 0; i--) { for (j = 110; j > 0; j--); }
}
请注意,上面的代码只是一个框架,你需要根据你的硬件连接和具体需求来完善各个函数的具体实现。特别是DS1302_Init
、DS1302_GetTime
、LCD1602_Init
、LCD1602_ShowTime
和Key_Scan
这些函数,它们与硬件紧密相关,因此你需要查阅相关数据手册并编写对应的底层驱动代码。
此外,实际开发中还需要考虑时间的准确性、按键去抖、中断处理、低功耗设计等问题。这通常需要一定的电子和编程基础以及对51单片机和相关外设的深入了解。
当然,我可以提供一个更加详细的代码示例,但请注意,由于篇幅限制,这里仍然只能是一个简化的版本。此外,具体的硬件连接和配置可能因你的设计而异,因此你可能需要根据自己的硬件平台对代码进行调整。
以下是一个基于51单片机的数字时钟(万年历)的详细代码示例:
#include <reg52.h> // 假设DS1302的数据线连接到P2口,控制线连接到P3口
sbit DS1302_RST = P3^7; // DS1302复位线
sbit DS1302_IO = P3^6; // DS1302数据线
sbit DS1302_SCLK = P3^5; // DS1302时钟线 // 假设LCD1602的数据线连接到P0口,控制线连接到P3口
sbit LCD1602_RS = P3^4;
sbit LCD1602_RW = P3^3;
sbit LCD1602_EN = P3^2; // 定义按键接口,这里只是示例,具体连接可能不同
sbit KEY1 = P1^0; // 小时增加按键
sbit KEY2 = P1^1; // 小时减少按键
sbit KEY3 = P1^2; // 分钟增加按键
sbit KEY4 = P1^3; // 分钟减少按键 // DS1302命令定义
#define DS1302_SECONDS_REG 0x80
#define DS1302_MINUTES_REG 0x82
#define DS1302_HOURS_REG 0x84
// ... 其他寄存器定义(日期、星期、月、年等) // LCD1602函数声明
void LCD1602_Init();
void LCD1602_WriteCommand(unsigned char command);
void LCD1602_WriteData(unsigned char data);
void LCD1602_ShowString(unsigned char x, unsigned char y, char *str);
void LCD1602_ShowNumber(unsigned char x, unsigned char y, unsigned int num, unsigned char length); // DS1302函数声明
void DS1302_Init();
void DS1302_WriteByte(unsigned char address, unsigned char dat);
unsigned char DS1302_ReadByte(unsigned char address);
void DS1302_SetTime(unsigned char hour, unsigned char minute, unsigned char second);
void DS1302_GetTime(unsigned char *hour, unsigned char *minute, unsigned char *second); // 延时函数声明
void delay_ms(unsigned int ms); void main() { unsigned char hour = 12, minute = 0, second = 0; LCD1602_Init(); // 初始化LCD1602 DS1302_Init(); // 初始化DS1302 DS1302_SetTime(hour, minute, second); // 设置初始时间,这里可以根据需要调整 while (1) { DS1302_GetTime(&hour, &minute, &second); // 读取当前时间 // 显示时间到LCD1602上,格式为"HH:MM:SS" LCD1602_ShowNumber(0, 0, hour, 2); LCD1602_ShowString(2, 0, ":"); LCD1602_ShowNumber(3, 0, minute, 2); LCD1602_ShowString(5, 0, ":"); LCD1602_ShowNumber(6, 0, second, 2); // 检查按键并调整时间(这里只是简单的示例,没有防抖处理) if (KEY1 == 0) { delay_ms(20); if (KEY1 == 0) { hour++; if (hour == 24) hour = 0; while (!KEY1); } } if (KEY2 == 0) { delay_ms(20); if (KEY2 == 0) { hour--; if (hour == 255) hour = 23; while (!KEY2); } } if (KEY3 == 0) { delay_ms(20); if (KEY3 == 0) { minute++; if (minute == 60) minute = 0; while (!KEY3); } } if (KEY4 == 0) { delay_ms(20); if (KEY4 == 0) { minute--; if (minute == 255) minute = 59; while (!KEY4); } } delay_ms(500); // 延时一段时间,这里可以根据需要调整更新时间的频率 }
} // LCD1602函数实现部分(这里只给出部分函数的框架,具体实现需要完整编写)
void LCD1602_Init() { // 初始化LCD1602的代码(设置功能、显示模式、清屏等) // ...
} void LCD1602_WriteCommand(unsigned char command) { // 写命令到LCD1602的代码 // ...
} void LCD1602_WriteData(unsigned char data) { // 写数据到LCD1602的代码 // ...
} void LCD1602_ShowString(unsigned char x, unsigned char y, char *str) { // 在LCD1602上显示字符串的代码 // ...
} void LCD1602_ShowNumber(unsigned char x, unsigned char y, unsigned int num, unsigned char length) { // 在LCD1602上显示数字的代码(可能需要转换为字符串再显示) // ...
} // DS1302函数实现部分(同样只给出部分函数的框架)
void DS1302_Init() { // 初始化DS1302的代码(设置时钟、写入初始时间等) // ...
} void DS1302_WriteByte(unsigned char address, unsigned char dat) { // 向DS1302写入一个字节的代码(包括地址和数据) // ...
} unsigned char DS1302_ReadByte(unsigned char address) { // 从DS1302读取一个字节的代码(根据地址读取数据) // ... return 0; // 这里应该返回读取到的数据,0是占位符
} void DS1302_SetTime(unsigned char hour, unsigned char minute, unsigned char second) { // 设置DS1302时间的代码(转换为BCD格式并写入对应寄存器) // ...
} void DS1302_GetTime(unsigned char *hour, unsigned char *minute, unsigned char *second) { // 读取DS1302时间的代码(从对应寄存器读取并转换为BCD格式) // ... // 这里应该将从DS1302读取到的时间赋值给hour, minute, second指针指向的变量 // *hour = ...; // *minute = ...; // *second = ...;
} // 延时函数实现部分(简单的延时实现,可能需要根据具体的单片机频率进行调整)
void delay_ms(unsigned int ms) { unsigned int i, j; for (i = ms; i > 0; i--) { for (j = 120; j > 0; j--); // 这里的数字可能需要根据具体的单片机频率进行调整以达到准确的延时时间 }
}
请注意,上面的代码仍然是一个框架性质的示例,并没有包含所有函数的完整实现。特别是与DS1302和LCD1602通信的函数(如DS1302_WriteByte
、DS1302_ReadByte
、LCD1602_WriteCommand
、LCD1602_WriteData
等),你需要根据具体的硬件连接和数据手册来编写详细的位操作和时序控制代码。此外,按键处理部分也没有包含防抖逻辑,这在实际应用中通常是必需的。
相关文章:
基于51单片机的数字时钟(万年历)设计与实现
基于51单片机的数字时钟(万年历)设计与实现 摘要 随着科技的不断发展,数字时钟已成为人们日常生活中不可或缺的一部分。基于51单片机的数字时钟(万年历)设计,结合了传统时钟的功能与现代电子技术…...

2024年谷歌SEO的趋势预测及应对建议(川圣SEO)蜘蛛池
baidu搜索:如何联系八爪鱼SEO? baidu搜索:如何联系八爪鱼SEO? baidu搜索:如何联系八爪鱼SEO? 虽然说“SEO”已死这个口号已经喊了很多年了(最终也没死),但是在2023年很…...
Rust 生命周期符号使用的方法和规律
一、生命周期符号使用的规律 在 Rust 中,生命周期(lifetimes)是用于处理引用和所有权问题的关键概念。生命周期符号(通常表示为 a、b 等)用于指定引用的有效时间范围。这有助于编译器确保在引用被使用时,所…...
生成哈夫曼树(100%用例)C卷(JavaPythonC++Node.jsC语言)
给定长度为n的无序的数字数组,每个数字代表二叉树的叶子节点的权值,数字数组的值均大于等于1。请完成一个函数,根据输入的数字数组,生成哈夫曼树,并将哈夫曼树按照中序遍历输出。 为了保证输出的二又树中序遍历结果统一,增加以下限制:二叉树节点中,左节点权值小于等于右…...

el-form-item内的el-select如何自适应宽度
最近在使用element-ui做后台管理的时候,有个需求是在弹窗组件里面,添加一个el-select下拉框选项,但是给el-select设置的宽度无法自适应,原因很简单,我们不需要设置固定宽度,设置百分比就行了,让…...

什么洗地机值得推荐?旗舰洗地机希亦、追觅、西屋、海尔实际表现如何?
洗地机这个产品相信大家已经不陌生了,它集合吸尘器和电动扫地拖把的功能,轻轻推拉便可以解决地面上的赃物,且不用我们手动清洗滚刷,深得家务人的喜爱,可是,当我们真正要去选购的时候,还是很纠结…...
掘根宝典之C++隐式类型转化(整型提升,算术转换)
赋值中的隐式转换 话不多说,我们直接看例子 bool b42; //b为真 int ib; //i的值为1 i3.14; //i的值为3 double pi i; // pi的值为3.0 unsigned char c -1; // 假设char占8比特,c的值为255 s…...
group by order by having where union
力扣题目链接 having where 区别 having子句用于分组后筛选,where子句用于行条件筛选 having一般都是配合group by 和聚合函数一起出现如(count(),sum(),avg(),max(),min()) where条件子句中不能使用聚集函数,而having子句就可以。 having只能用在group…...

微信私信短剧机器人源码
本源码仅提供参考,有能力的继续开发 接口为api调用 云端同步 https://ys.110t.cn/api/ajax.php?actyingshilist 影视搜索 https://ys.110t.cn/api/ajax.php?actsearch&name剧名 每日更新 https://ys.110t.cn/api/ajax.php?actDaily 反馈接口 https://ys.11…...
java使用ws.schild.jave将视频转成mp4
<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://…...
python map函数
python map函数 文章目录 python map函数 在Python中, map()函数用于将一个函数应用于可迭代对象(如列表或元组)中的每个元素,并返回一个包含结果的新的可迭代对象。 map()函数的语法如下: map(function, iterable)其…...

基于SSM的党务政务服务热线平台(有报告)。Javaee项目。ssm项目。
演示视频: 基于SSM的党务政务服务热线平台(有报告)。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spri…...
Unity3D 动态生成场景管理节点详解
前言 Unity3D 提供了丰富的功能和工具,可以帮助开发者快速高效地创建各种类型的游戏。在游戏开发过程中,有时候我们需要动态生成场景管理节点来管理游戏场景中的各种元素,比如角色、道具、敌人等。本文将详细介绍如何在Unity3D中动态生成场景…...
js--构造函数
创建对象的方式: 1、利用对象字面量{}创建 const arr {name: tom,age: 18 } 2、利用js内置构造(Object,Array,String,Number)函数 var obj new Object() //创建一个空的对象 obj.uname tom obj.age 2…...

Tomcat目录结构
文章目录 binconfliblogswebapp bin 存放tomcat的可执行程序 从上图可以看出bin中的文件主要是两种文件,一种是.bat一种是.sh .bat:主要用于windows .sh:主要用于linux .bat文件是Windows操作系统中的批处理文件。它是一种简单的文本文件,其中包含了一…...

读西游记第一回:西游记世界格局
天地之数: 元:十二万九千六百岁(129600年) 1元12会:子、丑、寅、卯、巳、午、未、申、酉、戌、亥。每会18000年。与12地支对应。 亥会期:前5400年混沌期,后5400年,盘古开天辟地&am…...
【Unity知识点详解】Button点击事件拓展,单击、双击、长按实现
Button拓展 今天来聊一下关于Button的事件拓展,这里只是拿Button来举例,Unity中其他的UI组件如Toggle、Slider等都也适用。 我们知道在Button中我们可以通过onClick的方式来添加点击事件,但在游戏开发过程中我们往往对Button有着更多的功能需…...
了解财富的本质才能知道自己几斤几两
生活在现代都市中,经历了经济的潮起潮落。在一望无际的楼宇下,是每天匆忙工作的一个个鲜活个体。有的在为了生存而工作,有的在享受着惬意的时光,有人行色匆匆,目光所及之处,尽是可遇不可求的机会。成为中产…...

机器学习模型—K最近邻(KNN)
机器学习模型—K最近邻(KNN) K最近邻 (KNN) 算法是一种用于解决分类和回归问题的监督机器学习方法。Evelyn Fix 和 Joseph Hodges 于 1951 年开发了该算法,随后 Thomas Cover 对其进行了扩展。本文探讨了 KNN 算法的基本原理、工作原理和实现。 虽然 k近邻算法 (KNN) 可以用…...

BUUCTF-----[CISCN 2019 初赛]Love Math
<?php error_reporting(0); //听说你很喜欢数学,不知道你是否爱它胜过爱flag if(!isset($_GET[c])){show_source(__FILE__); }else{//例子 c20-1$content $_GET[c];if (strlen($content) > 80) {die("太长了不会算");}$blacklist [ , \t, \r, \n…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...
【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...

C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...