转载

基于MSP430F413水果电池供电的低功耗时钟

我最早接触MSP430时候,看到书的第一页就是一张水果电池的图片,一直以来想做一个低功耗的可以水果电池供电的系统,毕业之后的下半年选择MSP430F413单片机来画了一个低功耗的板子,一直没有调试成功,液晶显示太暗几乎看不到,最近又拿出来调试,更换偏压电阻,最终更换液晶后才可以正常显示,先看下最终效果:

最终效果

基于MSP430F413水果电池供电的低功耗时钟 基于MSP430F413水果电池供电的低功耗时钟

电路图:

基于MSP430F413水果电池供电的低功耗时钟

调试过程

最初调试时,先准备好苹果一个,电池正负极(铜锌),程序是显示一个数字,效果如下:

基于MSP430F413水果电池供电的低功耗时钟

突发奇想,用自来水试了一下,效果也是杠杠的(程序中间修改过,这是显示较多的液晶段):

基于MSP430F413水果电池供电的低功耗时钟

时钟调试效果(这里电池没有接入电路,调试时所用,当时没有拿下来,用跳线帽接到水果供电的电路上):

基于MSP430F413水果电池供电的低功耗时钟

刚刚调试时,万用表测试水果电池电压接近0.9V,短路电流25-30uA,接上电路仅显示数字7的时候,电流12uA,4节水果电池电压从3.4降到2.6V;水(普通自来水,每个地方水中含有离子数量不一样,获得电压电流都有区别)每节电池0.8V,短路电流接近40uA。

程序换为时钟时,水果电池3.4V降到2.2V,大约维1个多小时,液晶完全没有显示,电极片换个位置重新插一下,时钟可以继续运行,测试电压和新做水果电池一样,苹果都要变干的时候,电压低一些,液晶明显变暗。

基于MSP430F413水果电池供电的低功耗时钟

后来,电路中提供液晶偏压电压的电阻有330K改为1M后,系统电流降到大约10uA,水果电池大约可以维持3-4小时,用水做的电池可以维持24小时以上

基于MSP430F413水果电池供电的低功耗时钟

功耗分析

这个低功耗的电路还有优化空间,单片机的不用的引脚可以再做优化,现有线路中有一般的液晶段引脚没有使用,却也提供的驱动波形,这里相对现有系统应当是浪费电流最大的一部分;另外一个优化空间是4个按键的上拉电阻太小,10K,3V的时候,按键按下瞬间,电流可以达到300uA,用水果电池的时候,按键功能不能使用,现在调试的时候,都是先拿CR2302供电,调节好时间后,再用水果(水)电池供电。进一步优化功耗后,电流应当可以降到5uA以下。

程序

按键程序继续使用之前程序库中的按键程序;

RTC计时使用TI的 RTC软件库

段码液晶的程序由程序库中的数码管程序移植而来:

 #include  <msp430x41x.h> #include  "segment_lcd_btl006.h" /*宏定义,数码管a-h各段对应的比特,更换硬件只用改动以下8行*/ #define a    0x01       //  AAAA #define b    0x02       // F B #define c    0x04       // F B #define d    0x80       //  GGGG #define e    0x40       // E C #define f    0x10       // E C #define g    0x20       //  DDDD  HH #define h    0x08  //小数点 /*用宏定义自动生成段码表,很好的写法,值得学习*/ /*更换硬件无需重写段码表*/ const char tab[] = {  a + b + c + d + e + f,      // Displays "0"  b + c,          // Displays "1"  a + b + d + e + g,       // Displays "2"  a + b + c + d + g,       // Displays "3"  b + c + f + g,        // Displays "4"  a + c + d + f +g,        // Displays "5"  a + c + d + e + f + g,      // Displays "6"  a + b + c,         // Displays "7"  a + b + c + d + e + f + g,     // Displays "8"  a + b + c + d + f + g,      // Displays "9"  a + b + c + e + f + g,      // Displays "A"  c + d + e + f + g,       // Displays "B"    a + d + e + f,        // Displays "C"  b + c + d + e + g,       // Displays "D"  a + d + e + f + g,       // Displays "E"  a + e + f + g,        // Displays "F"  a + c + d + e + f,       // Displays "G"  b + c + e + f + g,       // Displays "H"    e + f,          // Displays "I"  b + c + d + e,        // Displays "J"  b + d + e + f + g,       // Displays "K"  d + e + f,         // Displays "L"    a + c + e + g,        // Displays "M"   a + b + c + e + f,       // Displays "N"     c + e + g,         // Displays "n"  c + d + e + g,        // Displays "o"  a + b + c + d + e + f,      // Displays "O"  a + b + e + f + g,       // Displays "P"  a + b + c + f + g,       // Displays "Q"   e + g,          // Displays "r"  a + c + d + f +g,        // Displays "S"  d + e + f + g,        // Displays "t"  a + e + f ,        // Displays "T"   b + c + d + e + f,       // Displays "U"  c + d + e,         // Displays "v"   b + d + f + g,        // Displays "W"  b + c + d + f + g,       // Displays "Y"   a + b + d + e + g,       // Displays "Z"  g,           // Displays "-"  h,           // Displays "."    0            // Displays " " };  #undef a #undef b #undef c #undef d #undef e #undef f #undef g  void lcd_init() {  // Initialize LCD  LCDCTL = LCDP1+LCDP0+LCD4MUX+LCDON;    // 4-Mux LCD, segments S0-S23  BTCTL  = BTFRFQ1;       // Set freqLCD = ACLK/128  P5SEL  = 0xFC;       // Set Rxx and COM pins for LCD  // Clear LCD memory to clear display  for (int i=0; i<12; i++)  {   LCDMEM[i] = 0x00;  } } void lcd_clear() {   for (int i=0; i<12; i++)  {   LCDMEM[i] = 0x00;  } } //不影响小数点或者冒号 void lcd_display_char(char ch,char addr) {  addr = addr*2+2;  LCDMEM[addr] = ((tab[ch]&0x0f)<<4)|(LCDMEM[addr]&0x80);  LCDMEM[addr+1] = (tab[ch]&0xf0);//|(LCDMEM[addr+1]&0x80) } 

计时程序,每隔1s中断运行一次,计时则秒增1,设置则显示对应设置界面:

 #include  <msp430x41x.h>  #include  "RTC_Calendar.h"  #include  "RTC_TA.h"  #include "segment_lcd_btl006.h"  #include "time.h"  char state = 0;  //1-6:年月日 时分秒  void time_init()  {   lcd_init();   setDate(2015,9,13);   setTime( 0, 0, 0, 1);      // initialize time to 12:00:00 AM   TACCR0 = 32768-1;   TACTL = TASSEL_1+MC_1;     // ACLK, upmode   TACCTL0 |= CCIE;        // enable TA0CCRO interrupt  }  //两位时间显示,格式十六进制高地位 地址0低位,1高位  void time_display(char time,char addr)  {   addr = addr*2;   lcd_display_char(time>>4,addr+1);   lcd_display_char((time&0x0f),addr);    }  //4位时间显示,year,格式十六进制各个位   void year_display(int year)  {   lcd_display_char(year>>12,3);   lcd_display_char((year>>8)&0x0f,2);     lcd_display_char((year>>4)&0x0f,1);     lcd_display_char((year)&0x0f,0);    }  //计时标志,冒号闪烁  void tick()  {   LCDMEM[1]&=~0X80;   LCDMEM[2]^=0x80;   time_display(get24Hour(),1);   time_display(TI_minute,0);  }  void setting()  {   LCDMEM[1]=0X80;   switch(state)    {     case 1:      year_display(TI_year);      break;     case 2:      time_display(TI_month==9?TI_month+7:TI_month+1,1);      break;     case 3:      time_display(TI_day,0);      break;     case 4:      time_display(get24Hour(),1);      LCDMEM[2]|=0x80;      break;     case 5:      time_display(TI_minute,0);      LCDMEM[2]|=0x80;      break;     case 6:      time_display(TI_second,0);      LCDMEM[2]|=0x80;      break;     default:      state = 0;      break;    }  }  // Timer A0 interrupt service routine  #pragma vector=TIMERA0_VECTOR  __interrupt void Timer_A (void)  {   incrementSeconds();   if(state == 0)   {    tick();   }   else   {    setting();   }   __bic_SR_register_on_exit(LPM3_bits);  }  

主函数,根据按键更改操作状态,并且设置时间值:

 #include  <msp430x41x.h> #include  "RTC_Calendar.h" #include  "RTC_TA.h" #include  "segment_lcd_btl006.h" #include "time.h" #include "key.h" int main( void ) {   // Stop watchdog timer to prevent time out reset  WDTCTL = WDTPW + WDTHOLD;  FLL_CTL0 |= XCAP14PF;      // Configure load caps  time_init();  KeyInit();  __bis_SR_register(GIE);  while(1)  {   __bis_SR_register(LPM3_bits);     // enter LPM3, clock will be updated   char key = ReadKey();   if(key=='0'&&state==1)   {    setDate(2015,TI_month>9?TI_month-5:TI_month+1,(TI_day>>4)*10+(TI_day&0x0f));   }   if(key=='1')   {    if(++state == 7)    {     state = 0;    }     }   if(key=='2')   {    switch(state)    {     case 1:      incrementYears();      break;     case 2:      incrementMonths();      break;     case 3:      incrementDays();      break;     case 4:      incrementHours();      break;     case 5:      incrementMinutes();      break;     case 6:      incrementSeconds();      break;     default:      state = 0;      break;    }   }   if(state!=0)   {    lcd_clear();    setting();   }   else   {    tick();   }  }  return 0; } 

最新运行效果

上午刚刚拍的,昨天(2015-10-02)晚上,发觉液晶有些暗,水里面加了一些盐,显示效果更好一些,运行时间应该也会更久:

基于MSP430F413水果电池供电的低功耗时钟

基于MSP430F413水果电池供电的低功耗时钟

正文到此结束
Loading...