赞
踩
蓝桥杯单片机设计与开发_基础模块_DS18B20__小猪沉塘的博客-CSDN博客,承接上文,本文将继续介绍剩余蓝桥杯涉及模块(DS1302、PCF8591、AT24C02、PWM、串口通信、NE555以及超声波测距),为大家做出详细编程指导。
笔者将基于蓝桥杯官方给的赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包)进行编程,为大家讲解编程调用各语句的含义,帮助大家编写温度传感器的程序,也便于大家记忆。
首先,创建工程和导入.c文件笔者已在文章(蓝桥杯单片机设计与开发_标准模板)中向大家详细介绍了,这里就不再赘述。
读者可下载赛点资源包(蓝桥杯单片机设计与开发_赛点资源数据包),解压后可得到以下图片所示文件。
我们双击打开文件“3-底层驱动代码参考”文件,将得到以下 .c
和 .h
文件。接下来将 ds1302.c
和 ds1302.h
文件拷贝到工程所在文件夹中,并在编译器中将这两个文件导入,便可以开始编写程序了。
![[Pasted image 20231013184631.png]]
首先,在编写驱动函数之前,我们需要在底层驱动代码ds1302.c
文件中编写 时间读写函数。我们可以打开赛点资源数据包中的文件“5-竞赛板芯片资料”。
打开“DS1302”芯片手册。笔者将借助芯片手册中的资料编写温度读取函数并为大家讲解。
![[Pasted image 20231013185402.png]]
时间写函数:编写时间写函数,即设置时间模块的初始时间函数。我们只需要通过调用底层驱动函数中的 ds1302 写入字节函数。
// 时间写函数
void DS1302_write(unsigned char *time_tab)
{
Write_Ds1302_Byte(0x8e,0x00); // 写开始初始化函数
Write_Ds1302_Byte(0x84,((time_tab[0]/10)<<4)+time_tab[0]%10); // 时(十进制->十六进制)
Write_Ds1302_Byte(0x82,((time_tab[1]/10)<<4)+time_tab[1]%10); // 分(十进制->十六进制)
Write_Ds1302_Byte(0x80,((time_tab[2]/10)<<4)+time_tab[2]%10); // 秒(十进制->十六进制)
Write_Ds1302_Byte(0x8e,0x80); // 写结束初始化函数
}
其中,在编写时间写函数指令可通过查阅芯片资料手册,不需要死记硬背。
时间读函数:编写时间读函数,即从时间模块中得到当前时间。我们只需要通过调用底层驱动函数中的ds1302读取字节函数。
// 时间读函数
unsigned char hour,minute,second; // 设置全局变量
void DS1302_read()
{
hour = Read_Ds1302_Byte(0x85); // 读取 - 时(从指定地址读取)
minute = Read_Ds1302_Byte(0x83); // 读取 - 分(从指定地址读取)
second = Read_Ds1302_Byte(0x81); // 读取 - 秒(从指定地址读取)
}
同样可以查阅上述芯片资料手册,不需要死记硬背,此处将不再赘述。
![[Pasted image 20231013190436.png]]
在编写完时间读写函数后务必要在 ds1302.h
文件中声明函数,才可在主函数中调用。
#ifndef __DS1302_H
#define __DS1302_H
void DS1302_write(unsigned char *time_tab);
void DS1302_read();
extern unsigned char hour,minute,second; // 全局变量存储 时、分、秒
#endif
在主函数中调用时间模块底层函数,首先需要在主函数开头包含驱动 ds1302 头文件。
#include "STC15F2K60S2.h" //头文件
#include "ds1302.h" //包含DS18B20驱动头文件
除此之外,笔者将个位数后的小数点显示出来,采取的方法是在定义 tab 数组时,在后面再定义十个小数点点亮的数,即通过将 0~9 对应的高八位减去 8,即可点亮小数点 dp 位。再在数码管显示的缓冲区上加上 11,即可显示带小数点的数字(与上文一致,下文将不再继续赘述)。
u8 code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //定义数组存放数码管数字状态
// 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 灭 , 0. , 1. , 2. , 3. , 4. , 5. , 6. , 7. , 8. , 9.
main主函数
主程序调用比较简单,下文中实现了 初始化 ds1302 时钟模块,并通过矩阵按键修改当前的时间值,并在数码管中实时显示时间。由于考虑初学者基础较为薄弱,因此将完整的 main.cpp 代码贴出来,包含中断函数、矩阵键盘、数码管显示等,并且在关键处进行了注释,希望对大家有所帮助。
// 包含头文件 #include "STC15F2K60S2.h" #include "ds1302.h" // 数据类型定义 #define u8 unsigned char #define u16 unsigned int // 8位数码管状态 u8 dspbuf[8] = {10,10,10,10,10,10,10,10}; u8 code tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x89,0xc1,0xbf}; // 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 灭 , 0. , 1. , 2. , 3. , 4. , 5. , 6. , 7. , 8. , 9. , H , U , - ; u8 time_tab[3] = {23,59,50}; // 初始化时间数组 u8 dspcom = 0; bit clock_flag = 0,key_flag = 0; // 标注位 // 中断函数 void Timer0Init(void) //2毫秒@12.000MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0x40; //设置定时初值 TH0 = 0xA2; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; //开定时中断 EA= 1; //开总中断 } // 573锁存器封装成函数 void door(u8 choose,u8 input) { P2 = (P2 & 0x1f) | choose; P0 = input; P2 &= 0x1f; } // 关数码管 void clo_num() { dspbuf[0] = 10; dspbuf[1] = 10; dspbuf[2] = 10; dspbuf[3] = 10; dspbuf[4] = 10; dspbuf[5] = 10; dspbuf[6] = 10; dspbuf[7] = 10; } // 初始化,关灯、蜂鸣器、数码管 void all_init() { door(0x80,0xff); door(0xa0,0xaf); clo_num(); } // 数码管显示函数 void display() { door(0xe0,0xff); //消隐 door(0xc0,0x01<<dspcom); door(0xe0,tab[dspbuf[dspcom++]]); if(dspcom >= 8) //or dspcom &= 0x07; dspcom = 0; } // 矩阵键盘,接KBD u8 keypress = 0,keyvalue = 0xff,keyread = 0; u8 Read_key(void) { u8 key_m,cal; P3 = 0xf0;P42=1;P44=1; P36=P42;P37=P44; //变量替换 key_m = (P3 & 0xf0); if(key_m != 0xf0) keypress++; else keypress = 0; if(keypress == 3) { keypress = 0; keyread = 1; switch(key_m) { case 0x70:cal = 0;break; case 0xb0:cal = 1;break; case 0xd0:cal = 2;break; case 0xe0:cal = 3;break; } P3 = 0x0f;P42=0;P44=0; P36=P42;P37=P44; //变量替换 key_m = (P3 & 0x0f); switch(key_m) { case 0x0e:keyvalue = (4*cal+7);break; case 0x0d:keyvalue = (4*cal+6);break; case 0x0b:keyvalue = (4*cal+5);break; case 0x07:keyvalue = (4*cal+4);break; } } P3 = 0x0f;P42=0;P44=0; P36=P42;P37=P44; //变量替换 key_m = (P3&0x0f); if((keyread == 1) && (key_m == 0x0f)) //松手检测 { keyread = 0; return keyvalue; } return 0xff; } //````````````````````````````````主函数```````````````````````````````````` void main() { u8 key_re,clock_w; // 初始化 all_init(); // 中断初始化 Timer0Init(); // DS1302初始化 DS1302_write(time_tab); while(1) { if(key_flag) { key_flag = 0; key_re = Read_key(); if(key_re != 0xff) { switch(key_re) { // 按键调整 时 case 13:time_tab[0]++; if(time_tab[0] == 24) time_tab[0] = 0; DS1302_write(time_tab);break; case 12:time_tab[0]--; if(time_tab[0] <= 0) time_tab[0] = 23; DS1302_write(time_tab);break; default:break; } } } // 实时更新当前时间并存入 time_tab ,用于按键调整时间时修改 if((clock_flag) && (clock_w)) { clock_flag = 0; DS1302_read(); dspbuf[0] = hour/16; dspbuf[1] = hour%16; dspbuf[2] = 23; dspbuf[3] = minute/16; dspbuf[4] = minute%16; dspbuf[5] = 23; dspbuf[6] = second/16; dspbuf[7] = second%16; time_tab[0] = hour/16*10+hour%16; time_tab[1] = minute/16*10+minute%16; time_tab[2] = second/16*10+second%16; } } } // 中断服务函数 void timer0() interrupt 1 { static u8 t_20ms = 0,t_50ms = 0; //MAX = 500 ms //不需要重载装载值 display(); //数码管显示函数放里面 t_20ms++; t_50ms++; if(t_20ms >= 10) //每20ms扫描一次按键 { t_20ms = 0; key_flag = 1; } if(t_50ms >= 25) { t_50ms = 0; clock_flag = 1; } }
至此,本次 DS1302 时钟程序已编写完毕。
在结尾处向各位读者致歉,已经有两年多没有进行更新,最近又重新拾起CSDN,笔者会抽出时间,在保证质量的前提下把蓝桥杯系列博文更新完毕!希望对大家有所帮助,欢迎读者在评论区交流。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。