zoukankan      html  css  js  c++  java
  • 基于MSP430F413水果电池供电的低功耗时钟

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

    最终效果

    水果电池时钟 水果电池时钟

    电路图:

    低功耗电路

    调试过程

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

    水果电池

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

    水果电池

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

    水果电池

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

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

    水果电池

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

    水果电池

    功耗分析

      这个低功耗的电路还有优化空间,单片机的不用的引脚可以再做优化,现有线路中有一般的液晶段引脚没有使用,却也提供的驱动波形,这里相对现有系统应当是浪费电流最大的一部分;另外一个优化空间是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)晚上,发觉液晶有些暗,水里面加了一些盐,显示效果更好一些,运行时间应该也会更久:

    水果电池

    水果电池

  • 相关阅读:
    Layui的省市区三级联动
    Uncaught SyntaxError: Unexpected token ','
    Cannot use 'in' operator to search for '23' in
    Linux 递归批量删除文件夹或文件的命令
    PHPstorm常用快捷键(Windows)
    Isset、empty、count、is_null的比较
    PHPstorm快捷键的学习
    Elasticsearch索引按月划分以及获取所有索引数据
    Elasticsearch入门
    java自学-流程控制语句
  • 原文地址:https://www.cnblogs.com/Engin/p/4853236.html
Copyright © 2011-2022 走看看