|
一、指导思想——又想马儿跑,又想马儿少吃草
低功耗设计的指导思想我认为这句话最贴切了。针对LPM系统无非是在不影响系统功能/性能(折中处理)的前提下更少的消耗整机能量。
如何消耗更少的整机能量呢,主要有两种途径:
1、器件/芯片本身功耗较低
相同执行时间周期基准下比较,比如MSP430FRxx和传统MSP430相同代码执行时的功耗消耗比较,这要归功于FRAM的低功耗特性。
这种方式有两种主要应对的策略:
- 1)相同功能器件/芯片选择功耗更低的,比如选择FR替代传统的MSP430/选择功耗更低的MEMS传感器件等
复制代码
2、只浪费必须的能量,空闲时让他睡觉
一般这需要针对整机的整体功能和性能来确认,拿我的设计来说,传感器数据采集可以周期性的进行,当然控制的实时性则关系到控制的性能。
这种方式需要对整机系统有很好的把握,建议在开发低功耗系统设计的时候,先把整机的功能做好,再去做功耗控制,当然在设计的时候外设驱动的设计/模块的设计等需要提前考虑低功耗的因素:
- 1)在整机功能完善的情况下,考虑低功耗设计思路会更加清晰
- 2)了解主控芯片的LPMx模式对应的外设特性/唤醒方式等,在对这些很熟悉的情况下才能更好的来考虑低功耗
复制代码
二、空气质量检测微信平台——实战低功耗设计
先分析一下整机的功能,这样便于后面来设计整机功耗。
1、支持按键P1.1切换工作模式
看一下软件复位函数
- <blockquote>#if SOFTWARE_RESET == BOR_RESET
复制代码
2、支持带时间戳的FRAM日志模式
- 1)时间戳需要RTC的支持,对于RTC可直接采用MSP430FR5xx自带的低功耗RTC实时时钟
复制代码 FRAM-LOG代码片段
- /*
- * 存储PM25数据到FRAM-LOG区域
- * 注意超过FRAM-LOG规定地址区域的处理
- */
- FRAM_PM25_log_ptr = (unsigned int*)(FRAM_PM25_LOG_START + *FRAM_index_ptr);
- *FRAM_PM25_log_ptr = (unsigned int)DSM501A_PM2P5_SENS;
-
- #if ENABLE_LOG_TIME_STAMP
- uint16_t ym,dh,ms;
- Calendar calendar;
- calendar = RTC_B_getCalendarTime(RTC_B_BASE);
-
- ym = ((uint16_t)((calendar.Year%100)&0x00FF)<<8) | calendar.Month;
- dh = ((uint16_t)(calendar.DayOfMonth&0x00FF)<<8) | calendar.Hours;
- ms = ((uint16_t)(calendar.Minutes&0x00FF)<<8) | calendar.Seconds;
-
- FRAM_PM25_stamp_ptr = (unsigned int*)(FRAM_PM25_STAMP_START + (*FRAM_index_ptr)*6 + 0);
- *FRAM_PM25_stamp_ptr = (unsigned int)ym;
-
- FRAM_PM25_stamp_ptr = (unsigned int*)(FRAM_PM25_STAMP_START + (*FRAM_index_ptr)*6 + 2);
- *FRAM_PM25_stamp_ptr = (unsigned int)dh;
-
- FRAM_PM25_stamp_ptr = (unsigned int*)(FRAM_PM25_STAMP_START + (*FRAM_index_ptr)*6 + 4);
- *FRAM_PM25_stamp_ptr = (unsigned int)ms;
- #endif
- *FRAM_index_ptr += 2;
- if ( (*FRAM_index_ptr)/2 > FRAM_PM25_LOG_TOTAL/2 ) {
- *FRAM_index_ptr = 0;
- *FRAM_fulld_ptr = 0xF11F;
- }
复制代码
3、支持温湿度传感器数据采集
- 1)温湿度传感器每隔60秒采集一次数据,平时处于LPMx模式
复制代码
4、支持PM2.5传感器数据采集
- 1)PM2.5传感器每隔60秒采集一次数据,平时处于LPMx模式
复制代码 捕获定时器中断代码
- #pragma vector = TIMER1_A1_VECTOR
- __interrupt void Timer1_A1_ISR(void)
- {
- switch ( __even_in_range(TA1IV, TA0IV_TAIFG) )
- {
- case TA1IV_TA1CCR1:
- break;
-
- case TA1IV_TA1CCR2:
- {
- /* 判断是否为下降沿捕获中断,切换到上升沿捕获中断,并清除CCR2 */
- if ( (TA1CCTL2&0xC000) == CM_2 ) {
- TA1CCTL2 = CM_1 | CCIS_0 | SCS | CAP | CCIE;
- TA1CCR2 = 0;
- TA1CTL |= TACLR;
- } else if ( (TA1CCTL2&0xC000) == CM_1 ) {
- TA1CCTL2 = CM_2 | CCIS_0 | SCS | CAP | CCIE;
- DSM501A_LOW_PULSE_TIME += (TA1CCR2/32);
- }
- } break;
-
- case TA1IV_TA1IFG:
- break;
-
- default:
- break;
- }
- }
复制代码
5、支持微信数据交互
- 1)微信数据交互支持设备---->微信 和 微信---->设备两种方式
复制代码- /**
- * brief sendSAE_GET_Head
- * note 发送GET头
- * param None
- * retval None
- */
- void sendSAE_GET_Head(uint8_t temp, uint8_t humi, uint8_t mode, uint16_t pm25)
- {
- char tempStr[10];
- char humiStr[10];
- char modeStr[10];
- char pm25Str[10];
-
- _DINT();
- memset(tempStr, 0x00, 10);
- memset(humiStr, 0x00, 10);
- memset(modeStr, 0x00, 10);
- memset(pm25Str, 0x00, 10);
-
- _itoa(temp, tempStr, 10);
- _itoa(humi, humiStr, 10);
- _itoa(mode, modeStr, 10);
- _itoa(pm25, pm25Str, 10);
-
- USCA1_strPrint((char*)GETHEAD[0]);
- USCA1_strPrint(tempStr);
-
- USCA1_strPrint((char*)GETHEAD[1]);
- USCA1_strPrint(humiStr);
-
- USCA1_strPrint((char*)GETHEAD[3]);
- USCA1_strPrint(pm25Str);
-
- USCA1_strPrint((char*)GETHEAD[4]);
- USCA1_strPrint((char*)GETHEAD[5]);
- USCA1_strPrint((char*)GETHEAD[6]);
- USCA1_strPrint((char*)GETHEAD[7]);
-
- _EINT();
- }
复制代码
6、支持FRAM-log日志打印
关于UART接收低功耗设计的思路可参考之前的帖子:
【TI首届低功耗设计大赛】为msp430fr5969移植命令行nanouif
- https://bbs.eeworld.com.cn/thread-447473-1-1.html
复制代码
仅仅举例FRAM时间戳日志代码
- /**
- * brief transmitFRAMData
- * note 传输FRAMlog数据
- * param None
- * retval None
- */
- void transmitFRAMData(void)
- {
- uint16_t i;
- uint8_t year,mon,day,hour,min,sec;
- char years[5],mons[5],days[5],hours[5],mins[5],secs[5];
-
- char PM25_Index[10];
- char PM25_Value[10];
-
- FRAM_index_ptr = (unsigned int*)FRAM_PM25_INDEX;
-
- if ((unsigned int)(*FRAM_fulld_ptr) == 0x0000) {
- _itoa( ((unsigned int)(*FRAM_index_ptr))/2, PM25_Index, 10);
- printf("FRAM log data index %s\r\n", PM25_Index);
-
- for (i=0; i<*FRAM_index_ptr; i+=2) {
- year = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+1)>>0)&0xFF;
- mon = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+0)>>0)&0xFF;
- day = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+3)>>0)&0xFF;
- hour = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+2)>>0)&0xFF;
- min = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+5)>>0)&0xFF;
- sec = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+4)>>0)&0xFF;
-
- _itoa( year, years, 10);
- _itoa( mon, mons, 10);
- _itoa( day, days, 10);
- _itoa( hour, hours, 10);
- _itoa( min, mins, 10);
- _itoa( sec, secs, 10);
- printf("Time stamp 20%02s-%02s-%02s %02s:%02s:%02s ", years, mons, days, hours, mins, secs);
-
- _itoa( *(unsigned int*)(FRAM_PM25_LOG_START+i), PM25_Value, 10 );
- printf("FRAM log data value %s\r\n", PM25_Value);
- __delay_cycles(100);
- }
- } else if ((unsigned int)(*FRAM_fulld_ptr) == 0xF11F) {
- _itoa( ((unsigned int)(*FRAM_index_ptr))/2, PM25_Index, 10);
- printf("FRAM log data index %s\r\n", PM25_Index);
-
- for (i=*FRAM_index_ptr; i<FRAM_PM25_LOG_TOTAL; i+=2) {
- year = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+1)>>0)&0xFF;
- mon = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+0)>>0)&0xFF;
- day = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+3)>>0)&0xFF;
- hour = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+2)>>0)&0xFF;
- min = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+5)>>0)&0xFF;
- sec = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+4)>>0)&0xFF;
-
- _itoa( year, years, 10);
- _itoa( mon, mons, 10);
- _itoa( day, days, 10);
- _itoa( hour, hours, 10);
- _itoa( min, mins, 10);
- _itoa( sec, secs, 10);
- printf("Time stamp 20%02s-%02s-%02s %02s:%02s:%02s ", years, mons, days, hours, mins, secs);
-
- _itoa( *(unsigned int*)(FRAM_PM25_LOG_START+i), PM25_Value, 10 );
- printf("FRAM log data value %s\r\n", PM25_Value);
- __delay_cycles(100);
- }
- for (i=0; i<*FRAM_index_ptr; i+=2) {
- year = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+1)>>0)&0xFF;
- mon = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+0)>>0)&0xFF;
- day = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+3)>>0)&0xFF;
- hour = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+2)>>0)&0xFF;
- min = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+5)>>0)&0xFF;
- sec = (*(uint8_t*)(FRAM_PM25_STAMP_START+6*i+4)>>0)&0xFF;
-
- _itoa( year, years, 10);
- _itoa( mon, mons, 10);
- _itoa( day, days, 10);
- _itoa( hour, hours, 10);
- _itoa( min, mins, 10);
- _itoa( sec, secs, 10);
- printf("Time stamp 20%02s-%02s-%02s %02s:%02s:%02s ", years, mons, days, hours, mins, secs);
-
- _itoa( *(unsigned int*)(FRAM_PM25_LOG_START+i), PM25_Value, 10 );
- printf("FRAM log data value %s\r\n", PM25_Value);
- __delay_cycles(100);
- }
- }
- }
复制代码
注册的AT指令,关于AT指令实现可参考之前的帖子
- /**
- * @brief uif_cmd_fram
- * @note FRAM命令
- * @param none
- * @retval none
- */
- void
- uif_cmd_fram (int argc, char **argv)
- {
- if (argc != 2) {
- printf("Error: Invalid argument list\r\n");
- printf("\r\n");
- return;
- }
-
- if ( ((argc-1) >= UIF_CMDTAB[1].min_args) && ((argc-1) <= UIF_CMDTAB[1].max_args) ) {
- if (argv[1] != NULL) {
-
- if (strcasecmp("pm2.5", argv[1]) == 0){
- transmitFRAMData();
- }else if (strcasecmp("cls", argv[1]) == 0){
- clearFRAMData();
- } else {
- printf(INVOPT, argv[1]);
- printf("\r\n");
- return;
- }
- }
-
- printf("+ok\r\n\r\n");
- return;
- } else {
- printf(INVARG, argv[0]);
- printf("\r\n");
- return;
- }
- }
复制代码
三、主要流程图——文字说不太清楚的逻辑
1、主流程
2、PORT1_ISR
3、TIMER0_A1_ISR
4、TIEMR1_A1_ISR
5、TIMER1_A2_ISR
6、USCI_A1_ISR
7、配置模式细节流程图全部忽略,画个图有点辛苦。。。
四、一些参考链接
【TI首届低功耗设计大赛】msp430fr5969_硬件准备好了
【TI首届低功耗设计大赛】msp430fr5969_漫谈铁电FRAM
【TI首届低功耗设计大赛】为msp430fr5969移植命令行nanouif
【TI首届低功耗设计大赛】为LaunchPad添加AT指令解析
【TI首届低功耗设计大赛】wifi通信测试
【TI首届低功耗设计大赛】PM2.5传感器驱动+测试
【TI首届低功耗设计大赛】空气质量检测_初步完成视频
【TI首届低功耗设计大赛】微信与FR5969交互
【TI首届低功耗设计大赛】小结一下,今天比较闲
|
|