zoukankan      html  css  js  c++  java
  • MSP430 G2553 Launchpad实现电容测量

    一、基本原理

    对于Source-Free RC电路,其电容放电的特性可以描述为:

    其中V0是电容的初始电压,t是放电时间,R是串接的电阻阻值,C是电容值,v(t)是t时刻电容上的电压。因此,若已知V0、R、以及t1时刻的电压Vt1,便可求得C:

    二、如何控制和测量

    如上图所示,大致步骤为:1)由GPIO通过电阻R给电容C充电至Vcc;2)该GPIO输出0,电容C通过R进行放电,同时Timer开始计时、CA+开启;3)当电容电压放电至参考电压(此处是0.25Vcc)时,比较器CA+输出端出现电平变化;4)中断程序捕获这一变化,并利用Timer的capture mode获得该时刻的时间,最后通过以上方程计算电容值。

    上图中R推荐采用1%精度的电阻,以提高测试精度。

    三、状态转换图

    四、测试代码

    main.c程序:

      1 // C meter 2015.9.26
      2 //
      3 // P1.5(TA0.0) --[||||]----------- P1.4(CA3)
      4 //             R=10kOhm     |
      5 //                       -----
      6 //                   cap -----
      7 //                         |
      8 //                        GND
      9 //  http://zlbg.cnblogs.com
     10 /////////////////////////////////////////
     11 
     12 #include "io430.h"
     13 
     14 #define LED1 BIT0 // P1.0, red led
     15 #define LED2 BIT6 // P1.6, green led
     16 
     17 #define VMEAS BIT4 // P1.4(CA4) for voltage measurement of the cap
     18 #define VCTRL BIT5 // P1.5(TA0.0) for voltage control
     19 #define PUSH2 BIT3 // P1.3, button
     20 
     21 #define RXD BIT1 //P1.1
     22 #define TXD BIT2 //P1.2
     23 
     24 #define READY 0
     25 #define CHARGING 1
     26 #define DISCHARGING 2
     27 #define FINISH_DC 3
     28 
     29 #define R_SERIES 10000 //10kOhm
     30 #define LN4 1.3863
     31 
     32 //functions for C meter
     33 void P1Init(void);
     34 void TA0Init(void);
     35 void CAInit(void);
     36  
    37
    void setReadyStatus(void); 38 39 //functions for printf() 40 void sendByte(unsigned char); 41 void printf(char *, ...); 42 void initUART(void); 43 44 char state = READY; 45 unsigned char overflowsCharging = 0; 46 unsigned char overflowsDischarging = 0; 47 unsigned char i = 0; 48 float capacitance = 0; // unit: nF 49 50 void main(void) 51 { 52 // Stop watchdog timer to prevent time out reset 53 WDTCTL = WDTPW + WDTHOLD; 54 55 // DCO setup 56 BCSCTL1 = CALBC1_1MHZ; //running at 1Mhz 57 DCOCTL = CALDCO_1MHZ; 58 59 // P1 setup 60 P1Init(); 61 62 // Timer0 setup 63 TA0Init(); 64 65 // CA setup 66 CAInit(); 67 68 // UART setup 69 initUART(); 70 71 setReadyStatus(); 72 73 __enable_interrupt(); 74 75 // enter LP mode 76 LPM0; 77 78 } 79 80 81 void P1Init(void) 82 { 83 P1OUT = 0; 84 85 // set P1.3 (PUSH2) as input with pullup 86 P1OUT |= PUSH2; 87 P1REN |= PUSH2; 88 89 // set P1.0, P1.6, P1.5 as output 90 P1DIR |= LED1 + LED2 + VCTRL; 91 92 // enable P1.3 interrupt 93 P1IES |= PUSH2; // high -> low transition 94 P1IFG &= ~PUSH2; // clear the flag 95 P1IE |= PUSH2; 96 } 97 98 void TA0Init(void) 99 { 100 // use SMCLK (1MHz), no div, clear, halt 101 TA0CTL = TASSEL_2 + ID_0 + MC_0 + TACLR; 102 103 // TA0CCTL0: compare mode, enable interrupt 104 TA0CCTL0 = CCIE; 105 106 // TA0CCTL1: capture mode, no capture, CCI1B(CAOUT) input, syn capture 107 // interrupt enabled 108 TA0CCTL1 = CCIS_1 + SCS + CAP + CCIE; 109 } 110 111 void CAInit(void) 112 { 113 //0.25 Vcc ref on V+, halt 114 CACTL1 = CAREF_1 + CAIES; 115 // input CA4 (P1.4), remove the jumper) on V-, filter on 116 CACTL2 = P2CA3 + CAF; 117 } 118 119 void setReadyStatus(void) 120 { 121 state = READY; 122 // light led2 and turn off led1 to indicate ready 123 P1OUT &= ~LED1; 124 P1OUT |= LED2; 125 126 //stop and clear timer, stop T0_A1 capture & CA+ 127 TA0CTL = TASSEL_2 + ID_0 + MC_0 + TACLR; 128 TA0CCTL1 &= ~CM_3; 129 CACTL1 &= ~CAON; 130 131 overflowsCharging = 0; 132 } 133 134 void initUART(void) { 135 //config P1.1 RXD, P1.2 TXD 136 P1SEL |= TXD + RXD; 137 P1SEL2 |= TXD + RXD; 138 139 //reset UCA0, to be configured 140 UCA0CTL1 = UCSWRST; 141 //config 142 UCA0CTL1 |= UCSSEL_2; //SMCLK 143 UCA0BR0 = 104; 144 UCA0BR1 = 0;//1MHz baut rate = 9600 8-N-1 145 UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1 146 //make UCA0 out of reset 147 UCA0CTL1 &= ~UCSWRST; 148 } 149 150 151 void sendByte(unsigned char byte ) 152 { 153 while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? 154 UCA0TXBUF = byte; // TX -> RXed character 155 } 156 157 #pragma vector = PORT1_VECTOR 158 __interrupt void P1_ISR(void) 159 { 160 if((P1IFG & PUSH2) == PUSH2) 161 { 162 P1IFG &= ~PUSH2; //clear the flag 163 switch(state) 164 { 165 case READY: 166 state = CHARGING; 167 // light LED1 and turn off LED2, indicate a busy status 168 P1OUT |= LED1; 169 P1OUT &= ~LED2; 170 //start timer, continuous mode 171 TACTL |= MC_2; 172 //start charging 173 P1OUT |= VCTRL; 174 break; 175 default: 176 break; 177 } 178 179 } 180 else 181 { 182 P1IFG = 0; 183 } 184 } 185 186 #pragma vector = TIMER0_A0_VECTOR 187 __interrupt void CCR0_ISR(void) 188 { 189 switch(state) 190 { 191 case CHARGING: 192 if (++overflowsCharging == 50) // wait 6.5535*50 = 3.28s 193 { 194 state = DISCHARGING; 195 CACTL1 |= CAON; // turn on CA+ 196 TA0CCTL1 |= CM_1; // start TA1 capture on rising edge 197 P1OUT &= ~VCTRL; // start discharging 198 overflowsDischarging = 0; 199 } 200 break; 201 case DISCHARGING: 202 overflowsDischarging++; 203 default: 204 break; 205 206 } 207 208 } 209 210 #pragma vector = TIMER0_A1_VECTOR 211 __interrupt void CCR1_ISR(void) 212 { 213 TA0CTL &= ~MC_3; //stop timer 214 TA0CCTL1 &= ~CCIFG; // clear flag 215 switch(state) 216 { 217 case DISCHARGING: 218 state = FINISH_DC; 219 capacitance = (overflowsDischarging*65536 + TA0CCR1)*1000 / (R_SERIES*LN4); //nF 220 //send result to PC 221 printf("Capatitance: %n", (long unsigned)capacitance); 222 printf(" nF "); 223 224 setReadyStatus(); 225 break; 226 default: 227 break; 228 } 229 }

    printf.c程序:为将电容结果通过UART输出至PC显示,以下这段程序实现了printf()函数,代码来自于NJC's MSP430 LaunchPad Blog博客和oPossum的代码。

      1 /******************************************************************************
      2  *                          Reusable MSP430 printf()
      3  *
      4  * Description: This printf function was written by oPossum and originally
      5  *              posted on the 43oh.com forums. For more information on this
      6  *              code, please see the link below.
      7  *
      8  *              http://www.43oh.com/forum/viewtopic.php?f=10&t=1732
      9  *
     10  *              A big thanks to oPossum for sharing such great code!
     11  *
     12  * Author:  oPossum
     13  * Source:  http://www.43oh.com/forum/viewtopic.php?f=10&t=1732
     14  * Date:    10-17-11
     15  *
     16  * Note: This comment section was written by Nicholas J. Conn on 06-07-2012
     17  *       for use on NJC's MSP430 LaunchPad Blog.
     18  ******************************************************************************/
     19 
     20 #include "stdarg.h"
     21 
     22 void putc(unsigned);
     23 void puts(char *);
     24 
     25 static const unsigned long dv[] = {
     26 //  4294967296      // 32 bit unsigned max
     27         1000000000,// +0
     28         100000000, // +1
     29         10000000, // +2
     30         1000000, // +3
     31         100000, // +4
     32 //       65535      // 16 bit unsigned max
     33         10000, // +5
     34         1000, // +6
     35         100, // +7
     36         10, // +8
     37         1, // +9
     38         };
     39 
     40 static void xtoa(unsigned long x, const unsigned long *dp) {
     41     char c;
     42     unsigned long d;
     43     if (x) {
     44         while (x < *dp)
     45             ++dp;
     46         do {
     47             d = *dp++;
     48             c = '0';
     49             while (x >= d)
     50                 ++c, x -= d;
     51             putc(c);
     52         } while (!(d & 1));
     53     } else
     54         putc('0');
     55 }
     56 
     57 static void puth(unsigned n) {
     58     static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
     59             '9', 'A', 'B', 'C', 'D', 'E', 'F' };
     60     putc(hex[n & 15]);
     61 }
     62 
     63 void printf(char *format, ...)
     64 {
     65     char c;
     66     int i;
     67     long n;
     68 
     69     va_list a;
     70     va_start(a, format);
     71     while(c = *format++) {
     72         if(c == '%') {
     73             switch(c = *format++) {
     74                 case 's': // String
     75                     puts(va_arg(a, char*));
     76                     break;
     77                 case 'c':// Char
     78                     putc(va_arg(a, char));
     79                 break;
     80                 case 'i':// 16 bit Integer
     81                 case 'u':// 16 bit Unsigned
     82                     i = va_arg(a, int);
     83                     if(c == 'i' && i < 0) i = -i, putc('-');
     84                     xtoa((unsigned)i, dv + 5);
     85                 break;
     86                 case 'l':// 32 bit Long
     87                 case 'n':// 32 bit uNsigned loNg
     88                     n = va_arg(a, long);
     89                     if(c == 'l' && n < 0) n = -n, putc('-');
     90                     xtoa((unsigned long)n, dv);
     91                 break;
     92                 case 'x':// 16 bit heXadecimal
     93                     i = va_arg(a, int);
     94                     puth(i >> 12);
     95                     puth(i >> 8);
     96                     puth(i >> 4);
     97                     puth(i);
     98                 break;
     99                 case 0: return;
    100                 default: goto bad_fmt;
    101             }
    102         } else
    103             bad_fmt: putc(c);
    104     }
    105     va_end(a);
    106 }
    107 
    108 /******************************************************************************
    109  *                        MSP430G2553 printf() Tests
    110  *
    111  * Description: A modified version of the test code for testing oPossum's
    112  *              tiny printf() function. More information on the printf()
    113  *              function can be found at the following link.
    114  *
    115  *              http://www.43oh.com/forum/viewtopic.php?f=10&t=1732
    116  *
    117  *              This specific code tests the printf() function using
    118  *              the hardware UART on the MSP430G2553 with a baud rate
    119  *              of 9600. Once the character 't' is received, the test
    120  *              sequence is started.
    121  *
    122  *              This code was originally created for "NJC's MSP430
    123  *              LaunchPad Blog".
    124  *
    125  * Author:  Nicholas J. Conn - http://msp430launchpad.com
    126  * Email:   webmaster at msp430launchpad.com
    127  * Date:    06-07-12
    128  ******************************************************************************/
    129 
    130 void sendByte(unsigned char);
    131 
    132 /**
    133  * puts() is used by printf() to display or send a string.. This function
    134  *     determines where printf prints to. For this case it sends a string
    135  *     out over UART, another option could be to display the string on an
    136  *     LCD display.
    137  **/
    138 void puts(char *s) {
    139     char c;
    140 
    141     // Loops through each character in string 's'
    142     while (c = *s++) {
    143         sendByte(c);
    144     }
    145 }
    146 /**
    147  * puts() is used by printf() to display or send a character. This function
    148  *     determines where printf prints to. For this case it sends a character
    149  *     out over UART.
    150  **/
    151 void putc(unsigned b) {
    152     sendByte(b);
    153 }
    154 
    155 /**
    156  * Sends a single byte out through UART
    157  **/
    View Code

    五、测试结果

    串口工具推荐使用Realterm,选择MSP430 Launchpad对应的串口号,串口波特率设为9600、8-N-1。电路连接好后,按下S2键开始测量,测量完成后,在Realterm上可以显示测量结果。板上的红、绿LED灯显示了工作状态,绿灯表示空闲(测量结束),红灯表示正在测量。试测了一个标称47uF的电容,结果如下图所示。

  • 相关阅读:
    VS2013使用scanf、gets及字符串函数编译报错error C4996: 'scanf': This function or variable may be unsafe. 原因及解决方案
    关于vs2013与office系列软件一起安装出现bug的情况描述以及解决办法——打开vs2013鼠标不动/动不了
    武汉华师驾校学车笔记_纪实
    vs2013由修改模式改为输入模式。
    解析:求最大公约数的“辗转相除法原理”
    关于scanf与scanf_s的区别,以及用scanf编译出错并且提示找不到可执行文件.exe的解决办法。
    [C编译器]在VS中编译调试C程序
    使用vs编译程序选择新建”空项目“与”win32控制台应用程序“的区别。
    AngularJS+Ionic开发-1.搭建开发环境
    PetaPoco源代码学习--3.Sql类
  • 原文地址:https://www.cnblogs.com/zlbg/p/4841939.html
Copyright © 2011-2022 走看看