今天将完成其他部分驱动的调试。
Ds1302.c
#include “Head.h”
U8 code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};//阅读地址 秒 分 时 日 月 年
U8 code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};//写入地址即初始化日期地址顺序同上
U8 TIME[7] = {0, 0, 0x00, 0x01, 0x01, 0x01, 0x20};//秒分时日月年

void Ds1302Write(U8 addr, U8 dat)//写函数
{
U8 n;
RST = 0;
Delay_Us(1);
SCLK = 0;
Delay_Us(1);
RST = 1;
Delay_Us(1);
for (n=0; n<8; n++)
{
DSIO = addr & 0x01;
addr >>= 1;
SCLK = 1;
Delay_Us(1);
SCLK = 0;
Delay_Us(1);
}
for (n=0; n<8; n++)
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;
Delay_Us(1);
SCLK = 0;
Delay_Us(1);
}
RST = 0;
Delay_Us(1);
}
void Ds1302Init()//初始化配置函数
{
U8 n;
Ds1302Write(0x8E,0X00);
for (n=0; n<7; n++)
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80);
}
U8 Ds1302Read(U8 addr)//读函数
{
U8 n,dat,dat1;
RST = 0;
Delay_Us(1);
SCLK = 0;
Delay_Us(1);
RST = 1;
Delay_Us(1);
for(n=0; n<8; n++)
{
DSIO = addr & 0x01;
addr >>= 1;
SCLK = 1;
Delay_Us(1);
SCLK = 0;
Delay_Us(1);
}
Delay_Us(1);
for(n=0; n<8; n++)
{
dat1 = DSIO;
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
Delay_Us(1);
SCLK = 0;
Delay_Us(1);
}
RST = 0;
Delay_Us(1);
SCLK = 1;
Delay_Us(1);
DSIO = 0;
Delay_Us(1);
DSIO = 1;
Delay_Us(1);
return dat;
}
void Ds1302ReadTime()//读时间函数
{
U8 n;
for (n=0; n<7; n++)
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
Ds1302.h
#ifndef _DS1302_H
#define _DS1302_H
#include “Define_Data.h”
sbit DSIO=P2^0;
sbit RST=P2^1;
sbit SCLK=P2^2;
extern U8 TIME[7];
void Ds1302Write(U8 addr, U8 dat);
void Ds1302Init();
U8 Ds1302Read(U8 addr);
void Ds1302ReadTime();
#endif

修改main.c函数如下:
#include “Head.h”
main()
{
InitUart();
InitADC();
Ds1302Init();
while(1)
{
Ds1302ReadTime();
Delay_Ms(1000);
SendData(TIME[0]);
}
}
主函数含义是:每间隔1s钟,读取DS1302时间寄存器,及只打印读取的秒数据。秒数据将会60秒进一分钟。
串口打印结果如下图所示:

通过打印结果看到,秒时间打印正确。再通过打印函数把年月日时分秒都打印出来。
#include “Head.h”
main()
{ U8 i;
InitUart();
InitADC();
Ds1302Init();
while(1)
{
Ds1302ReadTime();
Delay_Ms(1000);
for(i=7;i>0;i–)
SendData(TIME[i-1]);
}
}

打印的数据和初始设置的年月日时分一致,说明读写函数正确。模块硬件工作正常。
下面开始调试,数码管显示。
测试数码管的驱动函数:
74Hc164.c
#include “Head.h”
U8 code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
U8 code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
void Send_74Hc164(U8 dat,U8 w)//dat 显示的数据,w 0-7显示的位数
{
U8 num,c;
num=tab[dat];
for(c=0;c<8;c++)
{
CP=0;
DAT=num&0x80;
CP=1;
num<<=1;
}
num=wei[w];
for(c=0;c<8;c++)
{
CP=0;
DAT=num&0x80;
CP=1;
num<<=1;
}
}
void Test_Dis()
{
U8 i;
for(i=0;i<8;i++)
{
Send_74Hc164(i,i);
Delay_Ms(1000);
}
}
74Hc164.h
#ifndef _74HC164_H
#define _74HC164_H
sbit DAT=P2^3;
sbit CP=P2^2;
void Send_74Hc164(U8 dat,U8 w);
void Test_Dis();
#endif
撰写main.c
#include “Head.h”
main()
{ U8 i;
InitUart();
InitADC();
Ds1302Init();
while(1)
{
Test_Dis();
}
}
根据main函数中 Test_Dis()函数的意思,实现的效果是第0位显示 数字0 ,第1位显示数字1 ,逐位类推。
实验的效果

实现了设计的意图。所以任何一位显示任何一个数字的函数是成功的。为后面的综合调用打好基础。
上一讲验证了AD按键函数的输出数值,下面对按键函数进一步包装,
1、按一次 只能打印一个数值,即只能识别一次。
2、不按不能打印任何值。
对个别AD函数进行了修改。增加了稳定性。
AdKey.c
#include “Head.h”
U8 KeyNum=0;
U8 Adc_V;

void Adc_Value_Deal(U8 n,U8 ch)//n 累计n次 求平均值。ch -ADC转换通道。
{
U8 i;
U16 temp=0;
for(i=0;i<n;i++)
{
temp=temp+GetADCResult(ch);
Delay_Ms(10);
}
Adc_V=temp/n;
temp=0;
}
/----------------------------
Get ADC result
----------------------------
/
U8 GetADCResult(U8 ch)
{
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
nop(); //Must wait before inquiry
nop();
nop();
nop();
while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
ADC_CONTR &= ~ADC_FLAG; //Close ADC

return ADC_RES;                 //Return ADC result

}
void InitADC()
{
P1ASF = 0xff; //Open 8 channels ADC function
ADC_RES = 0; //Clear previous result
ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
Delay_Ms(2); //ADC power-on and delay
}
void Key_Scan(U8 n,U8 ch)//sw5 -0x57; sw4-0x29; sw3-0x15; sw2-7; sw1-0; n取采集次数 ch ad转换通道
{
Adc_Value_Deal(n,ch);
if(Adc_V>0x60)
{
KeyNum=0;
}
if(Adc_V>0x50 && Adc_V<0x5b) //按键 sw5
{Delay_Ms(50);
Adc_Value_Deal(n,ch);
if(Adc_V>0x50 && Adc_V<0x5b)
{
while(1)//按键松手检测
{
Adc_Value_Deal(n,ch);
if(Adc_V>0xf0) break;
}
KeyNum=5;
SendData(KeyNum);
}
}
if(Adc_V>0x24 && Adc_V<0x2f) //按键 sw4
{ Delay_Ms(50);
Adc_Value_Deal(n,ch);
//SendData(Adc_V);
if(Adc_V>0x24 && Adc_V<0x2f)
{
while(1)
{
Adc_Value_Deal(n,ch);
if(Adc_V>0xf0) break;
}
KeyNum=4;
SendData(KeyNum);
}
}
if(Adc_V>0x10 && Adc_V<0x19) //按键 sw3 -15
{Delay_Ms(50);
Adc_Value_Deal(n,ch);
if(Adc_V>0x10 && Adc_V<0x19)
{
while(1)
{
Adc_Value_Deal(n,ch);
if(Adc_V>0xf0) break;
}
KeyNum=3;
SendData(KeyNum);
}
}
if(Adc_V>0x4 && Adc_V<0x0b) //按键 sw2-7
{Delay_Ms(50);
Adc_Value_Deal(n,ch);
if(Adc_V>0x4 && Adc_V<0x15)
{
while(1)
{
Adc_Value_Deal(n,ch);
if(Adc_V>0xf0) break;
}
KeyNum=2;
SendData(KeyNum);
}
}
if(Adc_V<=1) //按键 sw1-0
{Delay_Ms(50);
Adc_Value_Deal(n,ch);
if(Adc_V<=1)
{
while(1)
{
Adc_Value_Deal(n,ch);
if(Adc_V>0xf0) break;
}
KeyNum=1;
SendData(KeyNum);
}
}
}
AdKey.h
#ifndef _ADKEY_H
#define _ADKEY_H
#include “Define_Data.h”
sfr ADC_LOW2 = 0xBE; //ADC low 2-bit result register

/Define ADC operation const for ADC_CONTR/
/ADC_POWER: ADC 电源控制位。
0:关闭ADC 电源;1:打开A/D 转换器电源.建议进入空闲模式前,将ADC 电源关闭,ADC_POWER =0.
启动AD 转换前一定要确认AD 电源已打开,AD 转换结束后关闭AD 电源可降低功耗,也可不关闭。
初次打开内部A/D 转换模拟电源,需适当延时,等内部模拟电源稳定后,再启动A/D 转换
建议启动A/D 转换后,在A/D 转换结束之前,不改变任何I/O 口的状态,有利于高精度A/D 转换
/
#define ADC_POWER 0x80 //ADC power control bit
/* ADC_FLAG: 模数转换器转换结束标志位,当A/D 转换完成后,ADC_FLAG = 1,要由软件清0。
不管是A/D 转换完成后由该位申请产生中断,还是由软件查询该标志位A/D 转换是否结束,
当A/D 转换完成后,ADC_FLAG = 1,一定要软件清0。*/
#define ADC_FLAG 0x10 //ADC complete flag
/ADC_START: 模数转换器(ADC)转换启动控制位,设置为“1”时,开始转换,转换结束后为0。/
#define ADC_START 0x08 //ADC start control bit
/SPEED1,SPEED0:模数转换器转换速度控制位
S P E E D 1 S P E E D 0 A / D 转换所需时间
1 1 9 0 个时钟周期转换一次, C P U 工作频率2 1 M H z 时, A / D 转换速度约3 0 0 K H z
1 0 1 8 0 个时钟周期转换一次
0 1 3 6 0 个时钟周期转换一次
0 0 5 4 0 个时钟周期转换一次
/
#define ADC_SPEEDLL 0x00 //420 clocks
#define ADC_SPEEDL 0x20 //280 clocks
#define ADC_SPEEDH 0x40 //140 clocks
#define ADC_SPEEDHH 0x60 //70 clocks

extern U8 KeyNum;
extern U8 Adc_V;

void Adc_Value_Deal(U8 n,U8 ch);
void InitADC();
U8 GetADCResult(U8 ch);
void Key_Scan(U8 n,U8 ch);
#endif

主函数做了一些修改:
#include “Head.h”
main()
{ U8 i;
InitUart();
InitADC();
Ds1302Init();
while(1)
{
Key_Scan(2,0);
}
}

最终测试结果是按键非常稳定,不会出现误判的。验证了按键驱动的稳定性。实现了一次按键只操作一次的构想。

至此,通过三天的调试,按键、DS1302、数码管显示、串口等驱动调试完成。为后续的逻辑操作打好一个坚实的基础。

单片机项目式教学训练-基于DS1302电子钟设计与应用(第3天)相关推荐

  1. 项目式教学:为学生创造沉浸式学习体验

    近日,笔者认真阅读了< 项目式教学:为学生创造沉浸式学习体验 >一书(中国人民大学出版社),对教师如何开展项目式教学有了清晰的认识.在阅读期刊网上下载的相关文章时,笔者留意到,我国的不少研 ...

  2. python在教育领域的应用课题_项目式教学在高中信息技术教学中的应用探索——以Python基本程序结构教学为例...

    项目式教学在高中信息技术教学中的应用探索--以 Python基本程序结构教学为例 宋芹芹 济南西城实验中学 摘要:教学改革思想理念的深入发展,要求教师在课堂教学中不断尝试新鲜模式.在高中信息技术课堂教 ...

  3. scratch少儿编程实例教程(模拟动画片项目式教学)——幻影龙动画编程

    作为中小学普及的课程,scratch不同于传统的字符代码,图形编程不存在英文门槛,孩子通过拖拽积木就可以直观了解到代码背后的运转原理,在不知不觉中掌握编程算法.通过学员喜爱的动画等模拟动画片项目式教学 ...

  4. 【单片机项目实训】基于nRF905的多点温度无线采集系统

    将单片机项目实训--基于nRF905的多点温度无线采集系统分享出来,如有不足,敬请指出. [实验图片] [实验视频] 基于nRF905的多点温度无线采集系统设计 目录 目录 一.设计要求 二.方案设计 ...

  5. 初中计算机实践研究计划,项目式教学法在初中信息技术课堂教学中的研究与实践...

    褚震雨 摘 要:项目式教学法是一种新型教学方法,就是指在老师的指导下,将一个相对独立的项目交由学生自己处理,学生自己负责收集信息.设计方案.项目的实施及最终评价,学生通过对该项目的研究学习,了解并把握 ...

  6. 计算机网络教学的交互性,基于VR技术实现“计算机网络”课程的交互体验式教学...

    张良 李娜 曾志峰 夏平 摘 要:"计算机网络"是一门理论与实践相结合的课程,但是由于实验设备不足,传统的教学方法无法在现有的条件下完成大规模网络工程的实训操作.文章介绍了基于VR ...

  7. 计算机基础项目任务教学重构,面向计算思维培养的中职课程项目式重构研究

    摘要: 21世纪以来,随着信息技术的飞速发展,有专家指出,计算思维应该是继实验思维和理论思维之后人们应该具备的第三种思维;我国2017年发布的高中信息技术课程标准中明确提出了计算思维的概念,并将其作为 ...

  8. python解题教学设计的理解_面向计算思维培养的初中 Python 项目式学习教学设计流程构建...

    2006 年, 美国卡内基梅隆大学的周以真教授提出了计算思维的概念.计算思维是利用计算机科学的基本理念解决问题.设计系统和理解人类行为的一种方法,并指出计算思维的本质是抽象(Abstraction)和 ...

  9. 项目介绍——对话式教学系统

    对话式教学系统 背景 该项目为团队合作开发完成的课程项目,是一个基于微信小程序的教学内容管理平台.教师在网页端编辑并发布课程内容,学生通过微信小程序进行对话式学习.对话式学习,就是学生在微信小程序端一 ...

最新文章

  1. 如何彻底解决pip install慢的问题
  2. 你知道面试必问的AOP吗(1),2021吊打面试官系列
  3. 微软的公开的DLL库
  4. 《C champion》C语言发展
  5. Tensorflow 指令加速
  6. Robot Framework自动化测试(五)--- 开发系统关键字
  7. 数据库的主键和外键总结
  8. 接口测试面试题及参考答案(汇总),真香
  9. 卷积码编码器matlab,卷积码的编解码matlab仿真.doc
  10. “90后”男子酒后乱性强奸醉酒女获刑3年
  11. 自从会了爬虫妈妈再也不担心我不会植物分类啦
  12. buuctf:Ping Ping Ping(命令执行)
  13. 解决在SQLYog中执行SQL语句会提示错误的信息,但数据能查出来
  14. 【论文阅读笔记】Incremental Network Quantizatio:Towards Lossless CNNs with Low-Precision Weights
  15. 《数理天地》期刊简介及投稿邮箱
  16. 计算机应用基础实训指导教程 王,计算机应用基础案例教程及实训指导-第2章___Windows操...
  17. python实现计时器(装饰器)
  18. 【转】NLP的巨人肩膀(上)
  19. AMD虚拟机服务器,实现VM在AMD和Intel间实时迁移
  20. 【linux】 apache多后缀文件解析漏洞复现

热门文章

  1. Xmind中文版本质研究
  2. java mysql dbutils_Java数据库--DBUtils
  3. 3dsmax学习心得
  4. Latex插入GIF动态图片
  5. 诺学网c++视频教程在线观看+打包下载
  6. svn 冲突解决办法
  7. 制定steam教育理念明文
  8. HttpClient 教程 :HttpClient执行Http的方法。
  9. linux里pwd命令怎么用,linux系统PWD命令的使用
  10. 如何使用Finder的文具垫功能在Mac上创建文件模板