ARM交通灯万年历
- 格式:doc
- 大小:806.50 KB
- 文档页数:15
单片机万年历毕业设计单片机万年历是一种集成了日历、时钟、闹钟等功能的电子设备,它可以显示日期、时间,并能够提醒用户重要的日程安排。
在现代社会,随着人们生活节奏的加快和工作压力的增大,一个可靠的万年历设备变得尤为重要。
本文将介绍关于单片机万年历的设计原理、功能以及实现方法。
首先,我们来了解一下单片机万年历的设计原理。
单片机万年历的核心是一块单片机芯片,它可以通过内部的时钟电路来计算日期和时间。
通过与外部的LCD液晶显示屏和按键电路的连接,单片机可以将计算得到的日期和时间显示在屏幕上,并接受用户的输入来设置闹钟等功能。
此外,单片机还可以通过与电源电路的连接来实现长时间的运行。
接下来,我们来讨论一下单片机万年历的功能。
除了基本的日期和时间显示功能外,单片机万年历还可以实现一些实用的功能。
比如,它可以设置多个闹钟,提醒用户重要的会议、约会等事项。
闹钟可以通过按键来设置,并且在到达设定时间时会发出声音或者振动来提醒用户。
此外,单片机万年历还可以实现倒计时功能,用户可以设置一个特定的时间,然后单片机会自动倒计时,并在倒计时结束时发出提醒。
这些功能的实现都依赖于单片机芯片的计算和控制能力。
然后,我们来探讨一下单片机万年历的实现方法。
在设计单片机万年历时,首先需要选择合适的单片机芯片,根据芯片的规格书来了解它的功能和接口。
然后,需要设计电路板,将单片机芯片、LCD液晶显示屏、按键电路和电源电路等元件连接起来。
在电路板设计完成后,需要进行焊接和调试工作,确保各个元件之间的连接正确无误。
最后,需要编写单片机的程序代码,实现各个功能的逻辑控制。
在编写代码时,需要根据芯片的指令集和编程规范来进行,以确保程序的正确性和稳定性。
最后,我们来总结一下单片机万年历的优点和应用前景。
单片机万年历具有体积小、功耗低、功能丰富等优点,适合用于个人和家庭使用。
它可以帮助人们合理安排时间,提醒重要的日程安排,提高生活和工作的效率。
此外,单片机万年历还可以应用于学校、办公室等场所,帮助人们更好地管理时间和任务。
ARM课程设计可调控万年历时钟1.初始化并运行RTC,然后读取时间值通过串口向上位机发送,并把秒的值输出到教学实验开发平台上的LED1~LED4进行显示。
2.分析。
万年历显示时间包括年、月、日、星期、时、分和秒,利用EasyARM.exe仿真软件把结果发送到上位机上显示。
通过按键进行上述的显示调节,其中月是1~12,日是1~31,星期是1~7,时是00~23,分是00~59,秒是00~59。
现在时间显示2012年6月11日星期一15:23:30。
3.4.程序#include "config.h"#include "stdio.h"#include "math.h"uint8 time[4];/*按键 GPIO口*/#define key1 1<<16#define key2 1<<17#define key3 1<<18#define key4 1<<19#define key5 1<<20#define key6 1<<21#define HC595_CS (1 << 29) // P0.29口为74HC595的片选typedef struct UartMode // 定义串口模式设置的数据结构{uint8 datab; // 字长度 5/6/7/8uint8 stopb; // 停止位 1/2uint8 parity; // 奇偶校验 0-无校验, 1-奇校验, 2-偶校验}UARTMODE;uint8 rcv_buf[6]; // UART0数据接收缓冲区volatile uint8 rcv_new; // 接收新数据标志void DelayNS (uint32 dly){uint32 m;for ( ; dly>0; dly--)for (m=0; m<5000; m++);}void MSPI_Init(void){//PINSEL0 = (PINSEL0 & 0xFFFF00FF) | 0x00005500; // 设置管脚连接SPI PINSEL0 = (PINSEL0 & (~(0xFF << 8))) | (0x55 << 8) ;SPCCR = 0x52; // 设置SPI时钟分频SPCR = (0 << 3) | // CPHA = 0, 数据在SCK 的第一个时钟沿采样(1 << 4) | // CPOL = 1, SCK 为低有效(1 << 5) | // MSTR = 1, SPI 处于主模式(0 << 6) | // LSBF = 0, SPI 数据传输MSB (位7)在先(0 << 7); // SPIE = 0, SPI 中断被禁止}uint8 MSPI_SendData(uint8 data){IOCLR = HC595_CS; // 片选74HC595SPI_SPDR = data;while( 0 == (SPI_SPSR & 0x80)); // 等待SPIF置位,即等待数据发送完毕IOSET = HC595_CS;return(SPI_SPDR);}/* 此表为LED0~F以及L、P的字模 */uint8 const DISP_TAB[19] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88, 0x83, 0xC6, 0xA1,0x86, 0x8E,};uint8 UART0_Init (uint32 baud, UARTMODE set){uint32 bak;/* 参数过滤*/if ((0 == baud) || (baud > 115200)) return (0);if ((set.datab < 5) || (set.datab > 8)) return (0);if ((0 == set.stopb) || (set.stopb > 2)) return (0);if (set.parity > 4) return (0);/* 设置串口波特率*/U0LCR = 0x80; // DLAB=1bak = (Fpclk >> 4) / baud;U0DLM = bak >> 8;U0DLL = bak & 0xff;/* 设置串口模式*/bak = set.datab - 5;if (2 == set.stopb) bak |= 0x04;if (0 != set.parity){set.parity = set.parity - 1;bak |= 0x08;}bak |= set.parity << 4;U0LCR = bak;return (1);}void SendByte (uint8 data){U0THR = data;while ((U0LSR & 0X20) == 0); // 等待数据发送}void PC_DispChar (uint8 no, uint8 chr){SendByte(0xff);SendByte(0x81);SendByte(no);SendByte(chr);SendByte(0x00);}uint8 const SHOWTABLE[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; void SendTimeRtc (void){uint32 datas;uint32 times;uint32 bak;times = CTIME0; // 读取完整的时钟寄存器datas = CTIME1;bak = (datas >> 16) & 0xfff; // 获取年PC_DispChar(0, SHOWTABLE[bak / 1000]);bak = bak % 1000;PC_DispChar(1, SHOWTABLE[bak / 100]);bak = bak % 100;PC_DispChar(2, SHOWTABLE[bak / 10]);PC_DispChar(3, SHOWTABLE[bak % 10]);bak = (datas >> 8) & 0x0f; // 获取月PC_DispChar(4, SHOWTABLE[bak / 10]);PC_DispChar(5, SHOWTABLE[bak % 10]);bak = datas & 0x1f; // 获取日PC_DispChar(6, SHOWTABLE[bak / 10]);PC_DispChar(7, SHOWTABLE[bak % 10]);bak = (times >> 24) & 0x07; // 获取星期PC_DispChar(8, SHOWTABLE[bak]);bak = (times >> 16) & 0x1f; // 获取小时PC_DispChar(9, SHOWTABLE[bak / 10]);PC_DispChar(10, SHOWTABLE[bak % 10]);bak = (times >> 8) & 0x3f; // 获取分钟PC_DispChar(11, SHOWTABLE[bak / 10]);PC_DispChar(12, SHOWTABLE[bak % 10]);bak = times & 0x3f; // 获取秒钟PC_DispChar(13, SHOWTABLE[bak / 10]);PC_DispChar(14, SHOWTABLE[bak % 10]);}void RTCInit (void){PREINT = Fpclk / 32768 - 1; // 设置基准时钟分频器PREFRAC = Fpclk - (Fpclk / 32768) * 32768;CCR = 0x00; // 禁止时间计数器YEAR = 2012; //设置时钟初值MONTH = 6;DOM = 11;DOW = 1;HOUR = 15;MIN = 23;SEC = 30;CIIR = 0x01; // 设置秒值的增量产生一次中断 ILR = 0x03; // 清除RTC增量和报警中断标志 CCR = 0x01; // 启动RTC}void __irq IRQ_UART0 (void){uint8 i;if ((U0IIR & 0x0F) == 0x04)rcv_new = 1; // 设置接收到新的数据标志for (i=0; i<14; i++){rcv_buf[i] = U0RBR; // 读取FIFO的数据,并清除中断}/*再次初始化时钟*/CCR = 0x00; // 禁止时间计数器YEAR=(rcv_buf[0]-0x30)*1000+(rcv_buf[1]-0x30)*100+(rcv_buf[2]-0x30)*10+(rcv_buf[3]-0x30);MONTH =(rcv_buf[4]-0x30)*10+(rcv_buf[5]-0x30);DOM =(rcv_buf[6]-0x30)*10+(rcv_buf[7]-0x30);DOW =(rcv_buf[8]-0x30);HOUR =(rcv_buf[9]-0x30)*10+(rcv_buf[1]-0x30);MIN =(rcv_buf[11]-0x30)*10+(rcv_buf[3]-0x30);SEC =(rcv_buf[13]-0x30)*10+(rcv_buf[5]-0x30);CIIR = 0x01; // 设置秒值的增量产生1次中断CCR = 0x01; // 启动RTCVICVectAddr = 0x00; // 中断处理结束}void SET_TIME (void){while ((IO0PIN & key1) == 0) // 等待发送信号{DelayNS(2);if ((IO0PIN & key1) == 0){YEAR=YEAR+1;time[0,1,2,3]=YEAR;loop1: while ((IO0PIN & key1) != 0);DelayNS(2);if ((IO0PIN & key1) == 0) goto loop1; // 等待按键恢复}}while ((IO0PIN & key2) == 0) // 等待发送信号{DelayNS(2);if ((IO0PIN & key2) == 0){if(MONTH>11)MONTH=1;else MONTH=MONTH+1;time[4,5]=MONTH;loop2: while ((IO0PIN & key2) != 0);DelayNS(1);if ((IO0PIN & key2) == 0) goto loop2; // 等待按键恢复 }}while ((IO0PIN & key3) == 0) // 等待发送信号 {DelayNS(2);if ((IO0PIN & key3) == 0){if(DOM>29)DOM=0;elseDOM=DOM+1;time[6,7]=DOM;loop3: while ((IO0PIN & key3) != 0);DelayNS(1);if ((IO0PIN & key3) == 0) goto loop3; // 等待按键恢复 }}while ((IO0PIN & key4) == 0) // 等待发送信号 {DelayNS(2);if ((IO0PIN & key4) == 0){if(DOW>5)DOW=0;elseDOW=DOW+1;time[8]=DOW;loop4: while ((IO0PIN & key4) != 0);DelayNS(2);if ((IO0PIN & key4) == 0) goto loop4; // 等待按键恢复 }}while ((IO0PIN & key5) == 0) // 等待发送信号 {DelayNS(2);if ((IO0PIN & key5) == 0){if(HOUR>22)HOUR=0;elseHOUR=HOUR+1;time[9,10]=HOUR;loop5: while ((IO0PIN & key5) != 0);DelayNS(2);if ((IO0PIN & key5) == 0) goto loop5; // 等待按键恢复 }}while ((IO0PIN & key6) == 0) // 等待发送信号{DelayNS(2);if ((IO0PIN & key6) == 0){if(MIN>58)MIN=0;elseMIN=MIN+1;time[11,12]=MIN;loop6: while ((IO0PIN & key6) != 0);DelayNS(2);if ((IO0PIN & key6) == 0) goto loop6; // 等待按键恢复 }}}int main (void){ uint8 i;UARTMODE uart0_set;PINSEL0 = 0x00000005; // 连接IO到串口UART0PINSEL1 = 0x00000000;PINSEL2 = PINSEL2 & (~0x08); // P1[25:16]连接GPIO//PINSEL1 = 0x00005500; // 设置SPI管脚连接//PINSEL2 = 0x00000000;IODIR = HC595_CS;uart0_set.datab = 8;uart0_set.stopb = 1;uart0_set.parity = 0;UART0_Init(115200, uart0_set);U0FCR = 0xc1; // 使能FIFO,并设置触发点为8字节U0IER = 0x01; // 允许RBR中断,即接收中断MSPI_Init();RTCInit();IRQEnable(); // 使能IRQ中断/* 使能UART0中断 */VICIntSelect = 0x00000000; // 设置所有的通道为IRQ中断VICVectCntl0 = 0x20 | 0x06; // UART0分配到IRQ slot0,即最高优先级VICVectAddr0 = (uint32)IRQ_UART0; // 设置UART0向量地址VICIntEnable = 1 << 0x06; // 使能UART0中断while (1){ while (0 == (ILR & 0x01)); // 等待RTC增量中断ILR = 0x01;for(i=1; i<8; i++){if(DOW==i)rcv_data = MSPI_SendData(DISP_TAB[i]); // 发送显示数据} // 清除中断标志SET_TIME();SendTimeRtc();}return (0);}。
基于单片机控制的电子万年历摘要本设计是一个带温度显示的万年历电路系统,该电路具有年、月、日、星期、时、分、秒、闹钟显示和调整功能,并且还包含显示温度功能。
其中显示部分采用LCD1602显示,时钟部分采用DS1302时钟芯片,温度部分采用DS18B20单线温度传感器。
软件方面我们采用C语言编程,利用Keil uVision3软件编写C语言程序并且生成HEX文件。
先将程序在Proteus 仿真,通过之后再烧录到单片机中。
该设计的优点是充分利用了LCD1602的显示功能完成了万年历应该具有的功能并且还扩展了温度;不足之处是收到LCD1602显示功能的限制没能显示农历日期。
电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。
该电路采用AT89S51单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
关键词:万年历;AT89C51;液晶显示(LCD1602);温度传感器(DS18B20);时钟芯片(DS1302);proteus仿真;目录摘要 (1)目录 (1)1引言: (2)2设计方案 (3)2.2模块选择 (4)2.3方案框图 (4)3 软件实现 (5)3.1流程图 (5)3.2程序编写 (6)3.3运行程序生成hex文件 (12)4 proteus仿真 (13)4.1软件简介 (13)4.2 Proteus电路仿真与调试 (14)5 PCB制版 (21)5.1 绘制电路原理图并仿真调试 (21)5.2加载网络表及元件封装 (21)5.3规划电路板并设置相关参数 (23)5.4元件布局及调整 (24)5.5布线并调整 (25)5.6输出及制作PCB (26)总结 (27)参考文献 (28)致谢 (29)1引言:随着微电子技术的高速发展,单片机在国民经济的个人领域得到了广泛的运用。
成绩评定表课程设计任务书目录1 系统设计 (1)1.1电子显示屏特性 (1)1.2 按键控制 (1)1.3LCD显示端 (1)1.4 万年历调控电路 (2)1.5 万年历的实现 (3)1.6 LCD调试电路图 (3)2 软件的具体功能和要求 (4)2.1 基本要求 (4)2.2软件设计平台的介绍及实现方法 (4)2.3 程序设计流程图 (4)3 设计总结 (6)3.1 proteus仿真电路图 (6)3.2 Keil 源代码 (7)3.3 性能分析 (23)[参考文献] (24)1 系统设计1.1电子显示屏特性1>LED由计算机专用设备、显示屏幕、视频输入端口和系统软件等组成。
2>计算机及专用设备直接决定了系统的功能,可根据用户对系统的不同要求选择不同的类型3>提供视频输入端口。
1.2 按键控制1>用于年月日的调控,复位。
2>用于时分秒的置换,清屏。
1.3 LCD显示端LCD显示端如图1所示。
图1 LCD显示端万年历调控电路如图2所示。
图2 万年历调控电路使用调试功能,经过反复的调试终于实现了计时功能,然后通过查询资料,实现了计时过程中时钟实时更新功能及实现LED灯跟节奏闪烁。
再经过程序的改进,实现了实时时钟和闹钟调整功能。
添加了LED灯指示调整时间点(秒、分、时、星期、日、月、年)功能。
1.6 LCD调试电路图调试电路图如图3所示。
图3 调试电路图2 软件的具体功能和要求2.1 基本要求本课题所设计的系统要求:(1)在理解基本实验代码的基础上,掌握万年历的工作原理,基于程序控制方式的驱动设计。
(2)在proteus中使用ARM7的LPC2106芯片并且结合Keil的源代码,实现万年历功能。
(3)编写基于万年历程序,实现代码编译。
2.2软件设计平台的介绍及实现方法本设计中采用可编程逻辑设计环境ARM7进行设计,Keil uVsion5采用C语言进行编程。
2.3 程序设计流程图万年历程序流程图如图4所示。
单片机万年历设计摘要:电子计时器在现代社会测量仪器越来越普及的时候,得到了广泛的应用。
这是一年来回报你自己。
DS1302的耐用性,相差不大。
数字显示在电子日历中,以及下一年、月、日、时,电路采用AT89S52微处理器设计,工作在低功耗、3V电压下,本项目基于51系列日历元件,可同时实现日期、小时、分钟、时间等,因为我们没有很好的基础知识和实践经验,我们完全准备好了创造整机的理论基础,拓展知识和软件设计,不可能精确地限制任何需要设备的工作,比如程序设计,算法如何执行等等,没有具体的依据,在编程过程中很难找到,写出来的任务也只有掌握了相应的知识才能完成。
日历设计过程与硬件和软件同步,硬件组件主要由AT89C52单片电路组成,LED显示电路和时键7 seg-mpx8-ca监视器,共有八个一般的正二极管,7seg-mpx4-ca带有四个一般性正二极管的监视器。
我使用三个74HC164驱动。
74HC164是一个带有8位边界开关的登记册,它仔细输入数据,然后并行发布数据。
软件包括,除其他外,日历,时间调整程序,日历,显示程序等,以方便设置时间和显示日历后,所有的wave调试程序完成后,由于教师和教师的共同努力,电子日历已经完成。
关键词:动态扫描,单片机时钟电钟,DS1302,DS18B20,一、设计要求与方案论证1.1 设计要求:(1)基本要求1.任务一年,一个月,一周,一小时,分钟,秒;2.日历具有按月控制键和显示功能3.函数校准年、月、日、周、小时、分、秒;( 2 )创新要求1.日历具有按阴历显示功能;② 具有检测室温的功能;1.2系统基本方案选择和论证1.2.1单片机芯片的选择方案和论证:--Flash-ROM采用89C51芯片作为硬件核心,同时采用4kb的ROM内部存储器,但由于缺乏ISPs网络软件,这种技术已经应用到目前的网络中,如果调试器是由于程序错误或附加程序功能引起的,则必须注销。
1.2.2模块论证:表1数字光栅用于显示。
任务要求:用ARM—M3芯片设计一个智能万年历,要求能够正确显示近100 年时间,星期几,时间格式为****年**月**日(星期**) **:**:**(时:分:秒),能够识别出闰年(计时范围能够从1970年1月1日到2100年左右)。
该程序设计工程里包含有main.c(相关配置、和终端联系,提醒输出初始时间、输出实时时间)/date.c(计算实时时间)/stm32f10x_it.c三个文件,各文件内容如下。
Main.c文件:#include "stm32f10x.h"#include "stdio.h"#include "date.h"__IO uint32_t TimeDisplay = 0;void RCC_Configuration(void);void NVIC_Configuration(void);void GPIO_Configuration(void);void USART_Configuration(void);int fputc(int ch, FILE *f);void RTC_Configuration(void);void Time_Regulate(struct rtc_time *tm);void Time_Adjust(void);void Time_Display(uint32_t TimeVar);void Time_Show(void);u8 USART_Scanf(u32 value);#define RTCClockSource_LSEu8 const *WEEK_STR[] = {"日", "一", "二", "三", "四", "五", "六"};struct rtc_time systmtime;int main(){RCC_Configuration();NVIC_Configuration();GPIO_Configuration();USART_Configuration();/*在启动时检查备份寄存器BKP_DR1,如果内容不是0xA5A5,则需重新配置时间并询问用户调整时间*/printf("\r\n\n RTC not yet configured....");RTC_Configuration();printf("\r\n RTC configured....");Time_Adjust();BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);}else{/*启动无需设置新时钟*//*检查是否掉电重启*/if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){printf("\r\n\n Power On Reset occurred....");}/*检查是否Reset复位*/else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){printf("\r\n\n External Reset occurred....");}printf("\r\n No need to configure RTC....");/*等待寄存器同步*/RTC_WaitForSynchro();/*允许RTC秒中断*/RTC_ITConfig(RTC_IT_SEC, ENABLE);/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();}#ifdef RTCClockOutput_EnableRCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); PWR_BackupAccessCmd(ENABLE);BKP_TamperPinCmd(DISABLE);BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);RCC_ClearFlag();Time_Show();}void RCC_Configuration(){SystemInit();RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);}void NVIC_Configuration(){NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}void GPIO_Configuration(){GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);}void USART_Configuration(){USART_InitTypeDef USART_InitStructure;USART_ART_WordLength = USART_WordLength_8b;USART_ART_StopBits = USART_StopBits_1;USART_ART_Parity = USART_Parity_No ;USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);}int fputc(int ch, FILE *f){/* 将Printf内容发往串口 */USART_SendData(USART1, (unsigned char) ch);while (!(USART1->SR & USART_FLAG_TXE));return (ch);}void RTC_Configuration(){/*允许PWR和BKP时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);/*允许访问BKP域*/PWR_BackupAccessCmd(ENABLE);/*复位备份域*/BKP_DeInit();#ifdef RTCClockSource_LSI/*允许LSI*/RCC_LSICmd(ENABLE);/*等待LSI准备好*/while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET){}/*选择LSI作为RTC时钟源*/RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);#elif defined RTCClockSource_LSE/*允许LSE*/RCC_LSEConfig(RCC_LSE_ON);/*等待LSE准备好*/while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET){}/*选择LSE作为RTC时钟源*/RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);#endif/* Enable RTC Clock */RCC_RTCCLKCmd(ENABLE);#ifdef RTCClockOutput_Enable/*禁止Tamper引脚*/BKP_TamperPinCmd(DISABLE);/*为了将RTCCLK/64在Tamper引脚输出,Tamper功能必须被禁止*//*允许RTC时钟在Tamper引脚上输出*/BKP_RTCCalibrationClockOutputCmd(ENABLE);#endif/*等待寄存器同步*/RTC_WaitForSynchro();/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();/*允许RTC秒中断*/RTC_ITConfig(RTC_IT_SEC, ENABLE);/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();#ifdef RTCClockSource_LSI/*设置分频系数*/RTC_SetPrescaler(31999); /*RTC周期=RTCCLK/RTC_PR=(32.000kHz/(31999+1))*/#elif defined RTCClockSource_LSERTC_SetPrescaler(32767); /*RTC周期=RTCCLK/RTC_PR=(32.768kHz/(31767+1))*/ #endif/*等待上次RTC寄存器写操作完成*/RTC_WaitForLastTask();}void Time_Regulate(struct rtc_time *tm){u32 Tmp_YY = 0xFF, Tmp_MM = 0xFF, Tmp_DD = 0xFF, Tmp_HH = 0xFF, Tmp_MI = 0xFF, Tmp_SS = 0xFF;printf("\r\n=========================Time Settings==================");printf("\r\n 请输入年份(Please Set Years): 20");while (Tmp_YY == 0xFF){Tmp_YY = USART_Scanf(99);}printf("\n\r 年份被设置为: 20%0.2d\n\r", Tmp_YY);tm->tm_year = Tmp_YY+2000;Tmp_MM = 0xFF;printf("\r\n 请输入月份(Please Set Months): ");while (Tmp_MM == 0xFF){Tmp_MM = USART_Scanf(12);}printf("\n\r 月份被设置为: %d\n\r", Tmp_MM);tm->tm_mon= Tmp_MM;Tmp_DD = 0xFF;printf("\r\n 请输入日期(Please Set Dates): ");while (Tmp_DD == 0xFF){Tmp_DD = USART_Scanf(31);}printf("\n\r 日期被设置为: %d\n\r", Tmp_DD);tm->tm_mday= Tmp_DD;Tmp_HH = 0xFF;printf("\r\n 请输入时钟(Please Set Hours): ");while (Tmp_HH == 0xFF){Tmp_HH = USART_Scanf(23);}printf("\n\r 时钟被设置为: %d\n\r", Tmp_HH );tm->tm_hour= Tmp_HH;Tmp_MI = 0xFF;printf("\r\n 请输入分钟(Please Set Minutes): ");while (Tmp_MI == 0xFF){Tmp_MI = USART_Scanf(59);}printf("\n\r 分钟被设置为: %d\n\r", Tmp_MI);tm->tm_min= Tmp_MI;Tmp_SS = 0xFF;printf("\r\n 请输入秒钟(Please Set Seconds): ");while (Tmp_SS == 0xFF){Tmp_SS = USART_Scanf(59);}printf("\n\r 秒钟被设置为: %d\n\r", Tmp_SS);tm->tm_sec= Tmp_SS;}void Time_Adjust()RTC_WaitForLastTask();Time_Regulate(&systmtime);GregorianDay(&systmtime);RTC_SetCounter(mktimev(&systmtime));RTC_WaitForLastTask();}void Time_Display(uint32_t TimeVar){to_tm(TimeVar, &systmtime);printf("\r 当前时间为: %d年 %d月 %d日 (星期%s) %0.2d:%0.2d:%0.2d", systmtime.tm_year, systmtime.tm_mon, systmtime.tm_mday, WEEK_STR[systmtime.tm_wday], systmtime.tm_hour,systmtime.tm_min, systmtime.tm_sec);}void Time_Show(){printf("\n\r");/* Infinite loop */while (1){/* 每过1s */if (TimeDisplay == 1){Time_Display(RTC_GetCounter());TimeDisplay = 0;}}}u8 USART_Scanf(u32 value){u32 index = 0;u32 tmp[2] = {0, 0};{while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET){}tmp[index++] = (USART_ReceiveData(USART1));if ((tmp[index - 1] < 0x30) || (tmp[index - 1] > 0x39)) /*数字0到9的ASCII 码为0x30至0x39*/{if((index == 2) && (tmp[index - 1] == '\r')){tmp[1] = tmp[0];tmp[0] = 0x30;}else{printf("\n\rPlease enter valid number between 0 and 9 -->: ");index--;}}}/* 计算输入字符的相应ASCII值*/index = (tmp[1] - 0x30) + ((tmp[0] - 0x30) * 10);/* Checks */if (index > value){printf("\n\rPlease enter valid number between 0 and %d", value);return 0xFF;}return index;}Date.c文件内容如下:#include "date.h"#define FEBRUARY 2#define STARTOFTIME 1970#define SECDAY 86400L#define SECYR (SECDAY * 365)#define leapyear(year) ((year) % 4 == 0)#define days_in_month(a) (month_days[(a) - 1])static int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };/*计算公历*/void GregorianDay(struct rtc_time * tm){int leapsToDate;int lastYear;int day;int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };lastYear=tm->tm_year-1;/*计算到计数的前一年之中一共经历了多少个闰年*/leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;/*如若计数的这一年为闰年,且计数的月份在2月之后,则日数加1,否则不加1*/ if((tm->tm_year%4==0) && ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && (tm->tm_mon>2)){day=1;}else{day=0;}day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; /*计算从计数元年元旦到计数日期一共有多少天*/tm->tm_wday=day%7;}u32 mktimev(struct rtc_time *tm){if (0 >= (int) (tm->tm_mon -= 2)){tm->tm_mon += 12;tm->tm_year -= 1;}return ((((u32) (tm->tm_year/4 - tm->tm_year/100 + tm->tm_year/400 + 367*tm->tm_mon/12 + tm->tm_mday)}void to_tm(u32 tim, struct rtc_time * tm){register u32 i;register long hms, day;day = tim / SECDAY;hms = tim % SECDAY;tm->tm_hour = hms / 3600;tm->tm_min = (hms % 3600) / 60;tm->tm_sec = (hms % 3600) % 60;/*算出当前年份,起始的计数年份为1970年*/for (i = STARTOFTIME; day >= days_in_year(i); i++) {day -= days_in_year(i);}tm->tm_year = i;/*计算当前的月份*/if (leapyear(tm->tm_year)){days_in_month(FEBRUARY) = 29;}for (i = 1; day >= days_in_month(i); i++){day -= days_in_month(i);}days_in_month(FEBRUARY) = 28;tm->tm_mon = i;/*计算当前日期*/tm->tm_mday = day + 1;GregorianDay(tm);}stm32f10x_it.c文件内容:#include "stm32f10x_it.h"extern uint32_t TimeDisplay;void NMI_Handler(void){}/*** @brief This function handles Hard Fault exception.* @param None* @retval : None*/void HardFault_Handler(void){/* Go to infinite loop when Hard Fault exception occurs */while (1){}}/*** @brief This function handles Memory Manage exception.* @param None* @retval : None*/void MemManage_Handler(void){/* Go to infinite loop when Memory Manage exception occurs */ while (1){}}/*** @brief This function handles Bus Fault exception.* @param None* @retval : None*/void BusFault_Handler(void){/* Go to infinite loop when Bus Fault exception occurs */while (1){}}* @brief This function handles Usage Fault exception.* @param None* @retval : None*/void UsageFault_Handler(void){/* Go to infinite loop when Usage Fault exception occurs */ while (1){}}/*** @brief This function handles SVCall exception.* @param None* @retval : None*/void SVC_Handler(void){}/*** @brief This function handles Debug Monitor exception.* @param None* @retval : None*/void DebugMon_Handler(void){}/*** @brief This function handles PendSVC exception.* @param None* @retval : None*/void PendSV_Handler(void){}/*** @brief This function handles SysTick Handler.* @param None* @retval : None*/}void RTC_IRQHandler(void){if (RTC_GetITStatus(RTC_IT_SEC) != RESET){/* Clear the RTC Second interrupt */RTC_ClearITPendingBit(RTC_IT_SEC);/* Enable time update */TimeDisplay = 1;/* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask();/* Reset RTC Counter when Time is 23:59:59 */if (RTC_GetCounter() == 0x00015180){RTC_SetCounter(0x0);/* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask();}}}。
单片机万年历是一种非常实用的电子设备,它可以准确地显示日期和时间,并且可以自动调整闰年和月份的天数。
在现代社会,随着人们生活水平的提高和科技的发展,电子设备在人们的日常生活中发挥着越来越重要的作用。
在这种背景下,单片机万年历应运而生,它不仅可以帮助人们准确地了解日期和时间,还可以提醒人们重要的日程安排。
单片机万年历的设计原理是通过单片机的控制,实现对时钟芯片的读取和控制,从而实现准确的时间显示。
同时,通过编程控制,还可以实现闰年和月份天数的自动调整功能。
为了实现更加精确的时间显示,可以通过连接网络进行时间同步,从而保证万年历的准确性。
单片机万年历的设计需要考虑多个方面,包括硬件设计和软件设计。
在硬件设计方面,需要选择适合的单片机和时钟芯片,同时还需要设计合适的电路板和显示屏,以及其他必要的外围电路。
在软件设计方面,需要编写相应的程序代码实现对时钟芯片的读取和控制,并实现闰年和月份天数的自动调整功能。
此外,还可以添加一些其他功能,如闹钟、倒计时等,以增加万年历的实用性和娱乐性。
在进行单片机万年历的毕业设计过程中,需要注意以下几个关键点。
首先,要确保硬件电路的正常工作,包括各个元件的连接和供电的稳定性。
其次,要确保编写的软件程序能够准确地读取和显示时间,并能够自动调整闰年和月份天数。
再次,要确保设计的功能实用性和稳定性,如闹钟功能的准点提醒、倒计时功能的精确计算等。
最后,还需要注意外观的美观性和易用性,以增加用户的满意度和使用体验。
综上所述,单片机万年历作为一种实用的电子设备,在现代社会中具有广泛的应用前景。
通过对硬件和软件的设计,可以实现准确的时间显示和自动调整功能,从而方便人们的日常生活和工作。
在进行单片机万年历的毕业设计过程中,需要注重电路的稳定性和软件的功能完善性,并通过实际测试和调试,不断优化设计,以实现更好的效果。
希望通过这篇文献,能够为单片机万年历的毕业设计提供一些参考和帮助。
龙岩学院
实验报告
班级07电本一班学号2007050326 姓名刘桂银同组人实验日期室温大气压成绩
(3)GPIO电路两种应用电路
1.无需上拉电阻的 GPIO
LPC2131 大多数GPIO都属于这种情况,这类GPIO的典型电路如下图所示,采用灌电流方式驱动需加一定阻值(如 470Ω)的限流电阻即可。
但也有例外,如下图所示,当P0 口连接GPIO且用于输入时,例如用于检测按键的时
GPIO输入时,内部无上拉电阻,所以需要加 10K左右的上拉电阻,把I/O 口拉到高电平。
在这种应用中,需要将(相应端口,这里为 P0.0)P0.0 设置为输入状态,然后读取
当按键 S0 按下时,P0.0 端口接地,将会读回 0,若松开按键 S0,P0.0 接高电
.需要上拉电阻的 GPIO
这里所说的上拉电阻是因为 I/O 口自身结构要求的上拉电阻。
LPC2131
口(P0.2-SCL、P0.3-SDA0;P0.11-SCL1、P0.14-SDA1)为开漏输出,
时,需要加 1K~10KΩ的上拉电阻。
用作 I C 总线时的典型电路如所示。
特性:
图一按键电路原理图
图二RTC功能结构图
)使用举例
先假设一个最简单的状况,pclk频率为65.537KHz。
那么:PREINT = int (pclk/32768) ((PREINT+1)×32768) = 1 使用此设定,每秒钟有32767次2个pclk周期计数,。