《结题贴》
导引:本帖子下有 文献报告+视频展示+照片展示+主要程序设计 四个部分。
本设计 历经数月,从第一次接触msp430fr5969到现在基本能应用,收获很多。进步一点一滴,不管高端大气还是小儿科,对于自己来说这都是是一个成长的过程。
论坛管理员姐姐,多次提醒我 更新设计进度,在这里也表示感谢。从各位高手分享的帖子中受益匪浅,感谢大家一路陪伴。
附件1:设计报告
TI首届低功耗设计大赛项目报告
项目名称:
基于MSP430FR5969的太阳能电子时钟的设计
项目定位:一款智能综合清洁能源的电子显示装置解决方案,本设计以电子时钟为例。廉价、光伏示范性工程。
项目发展远景规划:我们大家都知道车站、学校、政府、医院、机场等场合都需要时钟以及显示屏。结合MSP430FR5969的特性,我开发的这款电子时钟,可以应用于以上场合。
尤其是作为学生参考时钟使用非常合适。一般学生上课都是白天,需要时钟参考。可以将这种电子时钟,应用在大学宿舍的出门处、教学楼的进口出,以及操场等地方。利用太阳能无污染以及MSP430FR5969低功耗和自带时钟模块的优势,可以为学生提供良好的时钟参考。
实现的功能:
1.在三种能源中进行自动切换,实现时钟的正常显示,这种切换无时间间隔,实现节能和稳定的统一。
2.利用开发板上的S1,S2实现对时钟的校准和设定时间。
3.使用12864液晶作为模拟显示屏进行显示,串口操作,节省MCU的I/O口。
4.低功耗转换。
创新点:
1.能源方面创新:在三种能源中进行自动切换,实现时钟的正常显示,这种切换无时间间隔,实现节能和稳定的统一。
这三种能源分别是太阳能、电网的电能、板载大电容。
2.策略方面创新:以往大家总是把蓄电池作为太阳能的储能器,本设计将大电容作为储能器,结合电网作为后备电源。实现了无缝切换。
3.显示方面创新:用时间来控制时钟显示,省去了光敏电阻等光照探测元件,节省单片机的AD资源,利用电网作为后备来保障时钟的正常运行,进而达到我们想要的时间段,时钟正常的显示。
4.其他创新之处:
1)程序写作中,一般来说我们所能用到的年份不会超过2200年,所以在年份的设定中,我们可以让年份不超过2200年,将其改变设定在1900到2200年之间。甚至可以根据需要设定在1900-2100年之间,来节省调节周期。
2)在时间调整子程序中,我发现每次从新写好时间,写入寄存器,会自动触发一个时钟中断,因此在调整之中,只需写入,不需要显示子程序。当运行官方给的写入子程序时,可直接进入中断,显示时钟。这样可大大减少代码的写作。
使用过程中遇到的问题及解决的过程:
1.软件环境搭建。
问题:不会熟练使用CCS和IAR;
解决方法:学习EEWORLD网上MSP430FR5969课程;
2.I/O口问题。
问题:开始无法使用I/O口;
解决方法:必须先使能I/O口;
3.时钟调节的问题。
BCD码和十六进制之间的转换问题。
解决方法:可以直接调用官方给出的例程,进行转换。
4.显示乱码问题。
解决方法:参照官方例程,去掉不相关的子函数,改用CASE语句来实现状态转换,和中断处理。
5.时钟电源调整不能做到无时差。
解决方法:增加电网,稳定后备电源,增强系统的稳定性,实现无时差供能切换。
注:原理图、BOM、软硬件设计思路、照片(见附件)
附件2:设计主要程序代码
- #include "driverlib.h" //TI自带的相关库
- #include "LCD12864P.h"//12864的串行写入相关驱动函数
- volatile Calendar newTime;
- /**************************
- 延时子程序 for 按键扫描
- ***************************/
- void delay(int t)
- {
-
- while(t--);
- }
- /**************************
- 主函数
- ***************************/
- void main()
- {
- uint display=0;
- WDTCTL = WDTPW + WDTHOLD;
- Calendar currentTime;
- //Set P1.0,P4.6 to output direction
- //P4.6 为显示器电源的控制端口,
- //在设定的时间 关闭显示
- GPIO_setAsOutputPin(
- GPIO_PORT_P1,
- GPIO_PIN0
- );
- GPIO_setAsOutputPin(
- GPIO_PORT_P4,
- GPIO_PIN6
- );
- //Set P1.1andP4.5to input direction withPullUpresistor
- GPIO_setAsInputPinWithPullUpresistor(GPIO_PORT_P1,
- GPIO_PIN1);
- GPIO_setAsInputPinWithPullUpresistor(GPIO_PORT_P4,
- GPIO_PIN5);
- /*
- * Select Port J
- * Set Pin 4, 5 to input Primary Module Function, LFXT.
- */
- GPIO_setAsPeripheralModuleFunctionInputPin(
- GPIO_PORT_PJ,
- GPIO_PIN4 + GPIO_PIN5,
- GPIO_PRIMARY_MODULE_FUNCTION
- );
- PMM_unlockLPM5(PMM_BASE);
- //Initialize LFXT1
- CS_LFXTStart( CS_BASE,
- CS_LFXT_DRIVE3
- );
- //Setup Current Time for Calendar
- currentTime.Seconds = 0x00;
- currentTime.Minutes = 0x38;
- currentTime.Hours = 0x12;
- currentTime.DayOfWeek = 0x01;
- currentTime.DayOfMonth = 0x22;
- currentTime.Month = 0x12;
- currentTime.Year = 0x2014;
- //Initialize Calendar Mode of RTC
- /*
- * Base Address of the RTC_B
- * Pass in current time, intialized above
- * Use BCD as Calendar Register Format
- */
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- //Setup Calendar Alarm for 5:00pm on the 5th day of the week.
- //Note: Does not specify day of the week.
- RTC_B_setCalendarAlarm(RTC_B_BASE,
- 0x00,
- 0x17,
- RTC_B_ALARMCONDITION_OFF,
- 0x05);
-
- //Specify an interrupt to assert every minute
- RTC_B_setCalendarEvent(RTC_B_BASE,
- RTC_B_CALENDAREVENT_MINUTECHANGE);
-
- RTC_B_clearInterrupt(RTC_B_BASE,
- RTC_B_CLOCK_READ_READY_INTERRUPT +
- RTC_B_TIME_EVENT_INTERRUPT +
- RTC_B_CLOCK_ALARM_INTERRUPT
- );
- //Enable interrupt for RTC Ready Status, which asserts when the RTC
- //Calendar registers are ready to read.
- //Also, enable interrupts for the Calendar alarm and Calendar event.
- RTC_B_enableInterrupt(RTC_B_BASE,
- RTC_B_CLOCK_READ_READY_INTERRUPT +
- RTC_B_TIME_EVENT_INTERRUPT +
- RTC_B_CLOCK_ALARM_INTERRUPT
- );
-
- //Start RTC Clock
- RTC_B_startClock(RTC_B_BASE);
-
- //Enter LPM3 mode with interrupts enabled
- // __bis_SR_register(LPM0_bits + GIE);
- __bis_SR_register(GIE);
- __no_operation();
-
- Ini_Lcd();//12864 初始化 串口写入,等待写入指示
-
- while(1)
- {
- if (!GPIO_getInputPinValue( GPIO_PORT_P1, GPIO_PIN1))
- {
- delay(30000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P1, GPIO_PIN1))
- {
-
- GPIO_setOutputHighOnPin(GPIO_PORT_P1,GPIO_PIN0);
- display+=1;
- if(display==9)display=0;//0 显示,1调秒。2调分。。7、8调年,
- lcd_pos(1,7);
- Disp_SZ(display); //可增加调整界面
- lcd_pos(2,6);
- switch(display)
- {
- case 1: Disp_HZ("调秒",2);break;
- case 2: Disp_HZ("调分",2);break;
- case 3: Disp_HZ("调时",2);break;
- case 4: Disp_HZ("调周",2);break;
- case 5: Disp_HZ("调月",2);break;
- case 6: Disp_HZ("调月",2);break;
- case 7: Disp_HZ("调年",2);break;
- case 8: Disp_HZ("调年",2);break;
- case 0: Disp_HZ("显示",2);break;
- default: break;
- }
-
- }
- }
- else
-
- {
- //if P1.4 set, set P1.0
- GPIO_setOutputLowOnPin( GPIO_PORT_P1,GPIO_PIN0);
- }
-
-
- switch(display)//调整时间程序
- {
- case 0:break;
- case 1:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- { delay(20000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- {
- currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
- currentTime.Seconds+=1;
- if(currentTime.Seconds>=0x59)currentTime.Seconds=0;
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
- //currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
- }
- }
- break;
- case 2:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- { delay(20000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- {
- currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃
- currentTime.Minutes+=1;
- if(currentTime.Minutes>=0x59)currentTime.Minutes=0;
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
-
- }
- }break;
- case 3:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- { delay(20000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- {
- currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
- currentTime.Hours+=1;
- if(currentTime.Hours>=0x24)currentTime.Hours=0;
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
-
- }
- }
- break;
- case 4:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- { delay(20000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- {
- currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
- currentTime.DayOfWeek+=1;
- if(currentTime.DayOfWeek>=0x07)currentTime.DayOfWeek=0;
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
-
- }
- }
- break;
- case 5:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- { delay(20000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- {
- currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
- currentTime.DayOfMonth+=1;
- if(currentTime.DayOfMonth>=0x32)currentTime.DayOfMonth=0;
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
-
- }
- }break;
- case 6:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- { delay(20000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- {
- currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
- currentTime.Month+=1;
- if(currentTime.Month>=0x13)currentTime.Month=0;
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
-
- }
- }break;
- case 7:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- { delay(20000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- {
- currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
- currentTime.Year+=1;
- if((currentTime.Year&0x00ff)>=0xA0)currentTime.Year&=0xff00;
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
- }
- }break;
- case 8:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- { delay(20000);
- if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
- {
- currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
- currentTime.Year+=0x100;
- if((currentTime.Year>>8)>=0x40) currentTime.Year&=0x00ff;
- RTC_B_calendarInit(RTC_B_BASE,
- currentTime,
- RTC_B_FORMAT_BCD);
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
-
- }
- }break;
- default: break;
-
- }
-
- }
-
- }
- #pragma vector=RTC_VECTOR
- __interrupt void RTC_B_ISR(void) //时钟中断
- {
- switch (__even_in_range(RTCIV, 16)) {
- case 0: break; //No interrupts
- case 2: //RTCRDYIFG
- //Toggle P1.0 every second
-
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
-
- //RTC_B_convertBinaryToBCD(RTC_B_BASE,
- // newTime.Seconds);
- lcd_pos(1,1);
- Disp_HZ("太阳能时钟",5);
- lcd_pos(2,2);
- Disp_SZ((newTime.Year>>8)/16);
- Disp_SZ((newTime.Year>>8)%16);
- Disp_SZ((newTime.Year&0x00ff)/16);
- Disp_SZ((newTime.Year&0x00ff)%16);
- Disp_HZ("年",1);//数字代表字的个数
-
- lcd_pos(3,0);
- Disp_SZ(newTime.Month/16);
- Disp_SZ(newTime.Month%16);
- Disp_HZ("月",1);
- Disp_SZ(newTime.DayOfMonth/16);
- Disp_SZ(newTime.DayOfMonth%16);
- Disp_HZ("日",1);
-
- Disp_HZ("周",1);
- switch(newTime.DayOfWeek%16)//显示周几
- {
- case 1: Disp_HZ("一",1);break;
- case 2: Disp_HZ("二",1);break;
- case 3: Disp_HZ("三",1);break;
- case 4: Disp_HZ("四",1);break;
- case 5: Disp_HZ("五",1);break;
- case 6: Disp_HZ("六",1);break;
- case 0: Disp_HZ("日",1);break;
- default: break;
- }
- lcd_pos(4,1);
- Disp_SZ(newTime.Hours/16);
- Disp_SZ(newTime.Hours%16);
- Disp_HZ("时",1);
- Disp_SZ(newTime.Minutes/16);
- Disp_SZ(newTime.Minutes%16);
- Disp_HZ("分",1);
- Disp_SZ(newTime.Seconds/16);
- Disp_SZ(newTime.Seconds%16);
- Disp_HZ("秒",1);
- if(newTime.Hours>=0x08&&newTime.Hours<0x18)//每天早上 8点 启动显示
- GPIO_setOutputHighOnPin(GPIO_PORT_P4,GPIO_PIN6);
- else //每下午6点 关闭显示
- GPIO_setOutputLowOnPin(GPIO_PORT_P4,GPIO_PIN6);
-
-
- break;
- case 4: //RTCEVIFG
- //Interrupts every minute
-
-
- __no_operation();
-
- //Read out New Time a Minute Later BREAKPOINT HERE
- newTime = RTC_B_getCalendarTime(RTC_B_BASE);
- break;
- case 6: //RTCAIFG
- //Interrupts 5:00pm on 5th day of week
- //也可以在这里设置相关时间节点
- __no_operation();
- break;
- case 8: break; //RT0PSIFG
- case 10: break; //RT1PSIFG
- case 12: break; //Reserved
- case 14: break; //Reserved
- case 16: break; //Reserved
- default: break;
- }
- }
附件3 : 各个部分演示视频
视频1:时钟功能演示(注:请将视频格式 设置为超清 即可看清楚 显示器上的内容,如果标清的 话 看不清12864的内容)
视频2:能量转换演示
视频3:系统联调演示
本帖最后由 传媒学子 于 2015-1-2 15:54 编辑