[原创] 【TI首届低功耗设计大赛】太阳能电子时钟结题贴

传媒学子   2015-1-2 14:32 楼主
《结题贴》
导引本帖子下有 文献报告+视频展示+照片展示+主要程序设计 四个部分。 本设计 历经数月,从第一次接触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:设计主要程序代码
  1. #include "driverlib.h" //TI自带的相关库
  2. #include "LCD12864P.h"//12864的串行写入相关驱动函数
  3. volatile Calendar newTime;
  4. /**************************
  5. 延时子程序 for 按键扫描
  6. ***************************/
  7. void delay(int t)
  8. {
  9. while(t--);
  10. }
  11. /**************************
  12. 主函数
  13. ***************************/
  14. void main()
  15. {
  16. uint display=0;
  17. WDTCTL = WDTPW + WDTHOLD;
  18. Calendar currentTime;
  19. //Set P1.0,P4.6 to output direction
  20. //P4.6 为显示器电源的控制端口,
  21. //在设定的时间 关闭显示
  22. GPIO_setAsOutputPin(
  23. GPIO_PORT_P1,
  24. GPIO_PIN0
  25. );
  26. GPIO_setAsOutputPin(
  27. GPIO_PORT_P4,
  28. GPIO_PIN6
  29. );
  30. //Set P1.1andP4.5to input direction withPullUpresistor
  31. GPIO_setAsInputPinWithPullUpresistor(GPIO_PORT_P1,
  32. GPIO_PIN1);
  33. GPIO_setAsInputPinWithPullUpresistor(GPIO_PORT_P4,
  34. GPIO_PIN5);
  35. /*
  36. * Select Port J
  37. * Set Pin 4, 5 to input Primary Module Function, LFXT.
  38. */
  39. GPIO_setAsPeripheralModuleFunctionInputPin(
  40. GPIO_PORT_PJ,
  41. GPIO_PIN4 + GPIO_PIN5,
  42. GPIO_PRIMARY_MODULE_FUNCTION
  43. );
  44. PMM_unlockLPM5(PMM_BASE);
  45. //Initialize LFXT1
  46. CS_LFXTStart( CS_BASE,
  47. CS_LFXT_DRIVE3
  48. );
  49. //Setup Current Time for Calendar
  50. currentTime.Seconds = 0x00;
  51. currentTime.Minutes = 0x38;
  52. currentTime.Hours = 0x12;
  53. currentTime.DayOfWeek = 0x01;
  54. currentTime.DayOfMonth = 0x22;
  55. currentTime.Month = 0x12;
  56. currentTime.Year = 0x2014;
  57. //Initialize Calendar Mode of RTC
  58. /*
  59. * Base Address of the RTC_B
  60. * Pass in current time, intialized above
  61. * Use BCD as Calendar Register Format
  62. */
  63. RTC_B_calendarInit(RTC_B_BASE,
  64. currentTime,
  65. RTC_B_FORMAT_BCD);
  66. //Setup Calendar Alarm for 5:00pm on the 5th day of the week.
  67. //Note: Does not specify day of the week.
  68. RTC_B_setCalendarAlarm(RTC_B_BASE,
  69. 0x00,
  70. 0x17,
  71. RTC_B_ALARMCONDITION_OFF,
  72. 0x05);
  73. //Specify an interrupt to assert every minute
  74. RTC_B_setCalendarEvent(RTC_B_BASE,
  75. RTC_B_CALENDAREVENT_MINUTECHANGE);
  76. RTC_B_clearInterrupt(RTC_B_BASE,
  77. RTC_B_CLOCK_READ_READY_INTERRUPT +
  78. RTC_B_TIME_EVENT_INTERRUPT +
  79. RTC_B_CLOCK_ALARM_INTERRUPT
  80. );
  81. //Enable interrupt for RTC Ready Status, which asserts when the RTC
  82. //Calendar registers are ready to read.
  83. //Also, enable interrupts for the Calendar alarm and Calendar event.
  84. RTC_B_enableInterrupt(RTC_B_BASE,
  85. RTC_B_CLOCK_READ_READY_INTERRUPT +
  86. RTC_B_TIME_EVENT_INTERRUPT +
  87. RTC_B_CLOCK_ALARM_INTERRUPT
  88. );
  89. //Start RTC Clock
  90. RTC_B_startClock(RTC_B_BASE);
  91. //Enter LPM3 mode with interrupts enabled
  92. // __bis_SR_register(LPM0_bits + GIE);
  93. __bis_SR_register(GIE);
  94. __no_operation();
  95. Ini_Lcd();//12864 初始化 串口写入,等待写入指示
  96. while(1)
  97. {
  98. if (!GPIO_getInputPinValue( GPIO_PORT_P1, GPIO_PIN1))
  99. {
  100. delay(30000);
  101. if (!GPIO_getInputPinValue( GPIO_PORT_P1, GPIO_PIN1))
  102. {
  103. GPIO_setOutputHighOnPin(GPIO_PORT_P1,GPIO_PIN0);
  104. display+=1;
  105. if(display==9)display=0;//0 显示,1调秒。2调分。。7、8调年,
  106. lcd_pos(1,7);
  107. Disp_SZ(display); //可增加调整界面
  108. lcd_pos(2,6);
  109. switch(display)
  110. {
  111. case 1: Disp_HZ("调秒",2);break;
  112. case 2: Disp_HZ("调分",2);break;
  113. case 3: Disp_HZ("调时",2);break;
  114. case 4: Disp_HZ("调周",2);break;
  115. case 5: Disp_HZ("调月",2);break;
  116. case 6: Disp_HZ("调月",2);break;
  117. case 7: Disp_HZ("调年",2);break;
  118. case 8: Disp_HZ("调年",2);break;
  119. case 0: Disp_HZ("显示",2);break;
  120. default: break;
  121. }
  122. }
  123. }
  124. else
  125. {
  126. //if P1.4 set, set P1.0
  127. GPIO_setOutputLowOnPin( GPIO_PORT_P1,GPIO_PIN0);
  128. }
  129. switch(display)//调整时间程序
  130. {
  131. case 0:break;
  132. case 1:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  133. { delay(20000);
  134. if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  135. {
  136. currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
  137. currentTime.Seconds+=1;
  138. if(currentTime.Seconds>=0x59)currentTime.Seconds=0;
  139. RTC_B_calendarInit(RTC_B_BASE,
  140. currentTime,
  141. RTC_B_FORMAT_BCD);
  142. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  143. //currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
  144. }
  145. }
  146. break;
  147. case 2:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  148. { delay(20000);
  149. if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  150. {
  151. currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃
  152. currentTime.Minutes+=1;
  153. if(currentTime.Minutes>=0x59)currentTime.Minutes=0;
  154. RTC_B_calendarInit(RTC_B_BASE,
  155. currentTime,
  156. RTC_B_FORMAT_BCD);
  157. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  158. }
  159. }break;
  160. case 3:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  161. { delay(20000);
  162. if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  163. {
  164. currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
  165. currentTime.Hours+=1;
  166. if(currentTime.Hours>=0x24)currentTime.Hours=0;
  167. RTC_B_calendarInit(RTC_B_BASE,
  168. currentTime,
  169. RTC_B_FORMAT_BCD);
  170. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  171. }
  172. }
  173. break;
  174. case 4:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  175. { delay(20000);
  176. if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  177. {
  178. currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
  179. currentTime.DayOfWeek+=1;
  180. if(currentTime.DayOfWeek>=0x07)currentTime.DayOfWeek=0;
  181. RTC_B_calendarInit(RTC_B_BASE,
  182. currentTime,
  183. RTC_B_FORMAT_BCD);
  184. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  185. }
  186. }
  187. break;
  188. case 5:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  189. { delay(20000);
  190. if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  191. {
  192. currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
  193. currentTime.DayOfMonth+=1;
  194. if(currentTime.DayOfMonth>=0x32)currentTime.DayOfMonth=0;
  195. RTC_B_calendarInit(RTC_B_BASE,
  196. currentTime,
  197. RTC_B_FORMAT_BCD);
  198. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  199. }
  200. }break;
  201. case 6:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  202. { delay(20000);
  203. if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  204. {
  205. currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
  206. currentTime.Month+=1;
  207. if(currentTime.Month>=0x13)currentTime.Month=0;
  208. RTC_B_calendarInit(RTC_B_BASE,
  209. currentTime,
  210. RTC_B_FORMAT_BCD);
  211. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  212. }
  213. }break;
  214. case 7:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  215. { delay(20000);
  216. if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  217. {
  218. currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
  219. currentTime.Year+=1;
  220. if((currentTime.Year&0x00ff)>=0xA0)currentTime.Year&=0xff00;
  221. RTC_B_calendarInit(RTC_B_BASE,
  222. currentTime,
  223. RTC_B_FORMAT_BCD);
  224. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  225. }
  226. }break;
  227. case 8:if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  228. { delay(20000);
  229. if (!GPIO_getInputPinValue( GPIO_PORT_P4, GPIO_PIN5))
  230. {
  231. currentTime=newTime;//加上这句话,时钟就在走的地方开始调,不会出现跳跃。
  232. currentTime.Year+=0x100;
  233. if((currentTime.Year>>8)>=0x40) currentTime.Year&=0x00ff;
  234. RTC_B_calendarInit(RTC_B_BASE,
  235. currentTime,
  236. RTC_B_FORMAT_BCD);
  237. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  238. }
  239. }break;
  240. default: break;
  241. }
  242. }
  243. }
  244. #pragma vector=RTC_VECTOR
  245. __interrupt void RTC_B_ISR(void) //时钟中断
  246. {
  247. switch (__even_in_range(RTCIV, 16)) {
  248. case 0: break; //No interrupts
  249. case 2: //RTCRDYIFG
  250. //Toggle P1.0 every second
  251. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  252. //RTC_B_convertBinaryToBCD(RTC_B_BASE,
  253. // newTime.Seconds);
  254. lcd_pos(1,1);
  255. Disp_HZ("太阳能时钟",5);
  256. lcd_pos(2,2);
  257. Disp_SZ((newTime.Year>>8)/16);
  258. Disp_SZ((newTime.Year>>8)%16);
  259. Disp_SZ((newTime.Year&0x00ff)/16);
  260. Disp_SZ((newTime.Year&0x00ff)%16);
  261. Disp_HZ("年",1);//数字代表字的个数
  262. lcd_pos(3,0);
  263. Disp_SZ(newTime.Month/16);
  264. Disp_SZ(newTime.Month%16);
  265. Disp_HZ("月",1);
  266. Disp_SZ(newTime.DayOfMonth/16);
  267. Disp_SZ(newTime.DayOfMonth%16);
  268. Disp_HZ("日",1);
  269. Disp_HZ("周",1);
  270. switch(newTime.DayOfWeek%16)//显示周几
  271. {
  272. case 1: Disp_HZ("一",1);break;
  273. case 2: Disp_HZ("二",1);break;
  274. case 3: Disp_HZ("三",1);break;
  275. case 4: Disp_HZ("四",1);break;
  276. case 5: Disp_HZ("五",1);break;
  277. case 6: Disp_HZ("六",1);break;
  278. case 0: Disp_HZ("日",1);break;
  279. default: break;
  280. }
  281. lcd_pos(4,1);
  282. Disp_SZ(newTime.Hours/16);
  283. Disp_SZ(newTime.Hours%16);
  284. Disp_HZ("时",1);
  285. Disp_SZ(newTime.Minutes/16);
  286. Disp_SZ(newTime.Minutes%16);
  287. Disp_HZ("分",1);
  288. Disp_SZ(newTime.Seconds/16);
  289. Disp_SZ(newTime.Seconds%16);
  290. Disp_HZ("秒",1);
  291. if(newTime.Hours>=0x08&&newTime.Hours<0x18)//每天早上 8点 启动显示
  292. GPIO_setOutputHighOnPin(GPIO_PORT_P4,GPIO_PIN6);
  293. else //每下午6点 关闭显示
  294. GPIO_setOutputLowOnPin(GPIO_PORT_P4,GPIO_PIN6);
  295. break;
  296. case 4: //RTCEVIFG
  297. //Interrupts every minute
  298. __no_operation();
  299. //Read out New Time a Minute Later BREAKPOINT HERE
  300. newTime = RTC_B_getCalendarTime(RTC_B_BASE);
  301. break;
  302. case 6: //RTCAIFG
  303. //Interrupts 5:00pm on 5th day of week
  304. //也可以在这里设置相关时间节点
  305. __no_operation();
  306. break;
  307. case 8: break; //RT0PSIFG
  308. case 10: break; //RT1PSIFG
  309. case 12: break; //Reserved
  310. case 14: break; //Reserved
  311. case 16: break; //Reserved
  312. default: break;
  313. }
  314. }
附件3 : 各个部分演示视频 视频1:时钟功能演示(注:请将视频格式 设置为超清 即可看清楚 显示器上的内容,如果标清的 话 看不清12864的内容) 视频2:能量转换演示 视频3:系统联调演示 本帖最后由 传媒学子 于 2015-1-2 15:54 编辑
  • 系统全家福

回复评论 (14)

大神莫拍板。。
点赞  2015-1-2 14:49
还有真人声音的,支持一下
点赞  2015-1-3 12:01
好帖好帖
点赞  2015-1-3 12:44
我觉得,楼主这个有一个小bug,那就是调节的时候时钟是会动的,这个不太好
点赞  2015-1-3 12:50
引用: 随风暗影 发表于 2015-1-3 12:50
我觉得,楼主这个有一个小bug,那就是调节的时候时钟是会动的,这个不太好
我故意让它动的。。。你设想啊当你调好秒后,再去调时的时候,如果秒不走,是不是意味着你的秒不对了。。我这样设计,可以随时调整当前位而不用担心秒位。当然也会存在进位的问题,但比起秒不动来说,还可以容忍的。
点赞  2015-1-3 13:46
谢谢鼓励
点赞  2015-1-3 13:47
引用: IC爬虫 发表于 2015-1-3 12:01
还有真人声音的,支持一下
大神来捧场了,多谢多谢
点赞  2015-1-3 13:47
太阳能电池 好大 好大
虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2015-1-3 13:55
引用: littleshrimp 发表于 2015-1-3 13:55
太阳能电池 好大 好大
手上没小的,10W的。。
点赞  2015-1-3 14:02
这个电池板,真够大的
能充电不?
So TM what......?
点赞  2015-1-3 15:07
引用: ljj3166 发表于 2015-1-3 15:07
这个电池板,真够大的
能充电不?
必须能,中午还能给你手机充电呢。有7W左右的有效输出功率
点赞  2015-1-3 15:21
引用: 传媒学子 发表于 2015-1-3 15:21
必须能,中午还能给你手机充电呢。有7W左右的有效输出功率
试着自己做了个锂电池充电板,结果没成功,搁浅了。楼主的充电板抛出来大家学习一下呀
So TM what......?
点赞  2015-1-3 15:24
引用: ljj3166 发表于 2015-1-3 15:24
试着自己做了个锂电池充电板,结果没成功,搁浅了。楼主的充电板抛出来大家学习一下呀
额。文档里面有原理图的,但是我这是对着太阳能电池板的,其最大输出电流也就不大,所以不用加什么保护电路,只需一个DC——DC转换即可。。楼主是不是想的麻烦了
点赞  2015-1-4 15:25
引用: 传媒学子 发表于 2015-1-4 15:25
额。文档里面有原理图的,但是我这是对着太阳能电池板的,其最大输出电流也就不大,所以不用加什么保护电路,只需一个DC——DC转换即可。。楼主是不是想的麻烦了



感觉太阳能应该属于功率连续但是比较微弱一类的能量,ti、凌力尔特都有类似微能量搜集的IC,最近很想折腾一下
So TM what......?
点赞  2015-1-4 18:54
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复