2011-12-28 33 views

Respuesta

4

http://github.com/dwelch67/msp430_samples

las muestras presentan períodos de medición de tiempo utilizando el temporizador, el temporizador de la muestra antes y después y restar la diferencia, que es su tiempo de ejecución.

EDIT:

este ejemplo se utilizan los temporizadores y divisores, en lugar de vigilar el rollo sobre el indicador de leer el registro del contador temporizador y suponiendo que usted está contando más que el número de temporizador de garrapatas, se resta uno del otro a obtener el tiempo Ajuste los divisores para evitar el vuelco y también intente la precisión que busca.

;This version is written for naken430asm. 
    ;http://www.mikekohn.net/micro/naken430asm_msp430_assembler.php 
    ;naken430asm -o filename.hex filename.s 
    ;mspdebug takes hex files as well as elfs. 

WDTCTL equ 0x0120 


CALBC1_1MHZ equ 0x10FF 
CALDCO_1MHZ equ 0x10FE 

DCOCTL equ 0x56 
BCSCTL1 equ 0x57 
BCSCTL2 equ 0x58 

TACTL equ 0x0160 
TAR  equ 0x0170 
TACCR0 equ 0x0172 
TACCTL0 equ 0x0162 

P1OUT equ 0x0021 
P1DIR equ 0x0022 


    org 0xFC00 

reset: 
    mov #0x0280,r1 

    mov #0x5A80,&WDTCTL ; 0x5A00|WDTHOLD 

    ; use calibrated clock 
    clr.b &DCOCTL 
    mov.b &CALBC1_1MHZ,&BCSCTL1 
    mov.b &CALDCO_1MHZ,&DCOCTL 

    ; make p1.0 and p1.6 outputs 
    bis.b #0x41,&P1DIR 
    bic.b #0x41,&P1OUT 
    bis.b #0x40,&P1OUT 

    ; 1MHz is 1000000 clocks per second 
    ; 1000000 = 0xF4240 
    ; The timers are 16 bit 
    ; Using a divide by 8 in BCSCTL2 gives 
    ; 125000 (0x1E848) clocks in a second 
    ; Using a divide by 8 in the timer gives 
    ; 15625 (0x3D09) timer ticks per second. 

    ; If both divisors are by 8, and we set 
    ; TACCR0 to 0x3D08 and set for count up mode 
    ; then, theory, we can measure seconds. 

    bis.b #0x06,&BCSCTL2 
    mov #0x02C4,&TACTL 
    mov #0x3D08,&TACCR0 
    mov #0x02D0,&TACTL 
    ;mov #0x02D0,&TACTL ; use this instead to blink faster 

loop: 
    xor.b #0x41,&P1OUT 
loop0: 
    bit.w #0x0001,&TACCTL0 
    jz loop0 
    bic.w #0x0001,&TACCTL0 

    jmp loop 


hang: 
    jmp hang 

    org 0xFFE0 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw hang 
    dw reset 

este ejemplo se utiliza el temporizador para medir un periodo de tiempo para transmitir caracteres serie (RS232), como se mencionó anteriormente ajustar los divisores para asegurar que usted no cuenta más de un ciclo del temporizador (el temporizador puede darse la vuelta, eso está bien 0xF000 a 0x3000 por ejemplo, no es un problema, 0xF000, alrededor de una vez a 0xF100 eso es un problema). Si es posible que se sobrepase ampliamente para que definitivamente no se mueva, la balanza retrocede los divisores hasta que obtenga la mejor precisión.

Sí, puede usar una interrupción para deshacerse de lo que está tratando de medir, pero no quiere hacerlo (a menos que la sobrecarga de la interrupción o el mecanismo que use para controlar la reiniciación del temporizador) (no necesita una interrupción para esto) es aceptable para su medida). backend msp430

#define WDTCTL  (*((volatile unsigned short *)0x0120)) 

#define CALBC1_1MHZ (*((volatile unsigned char *)0x10FF)) 
#define CALDCO_1MHZ (*((volatile unsigned char *)0x10FE)) 
#define CALBC1_8MHZ (*((volatile unsigned char *)0x10FD)) 
#define CALDCO_8MHZ (*((volatile unsigned char *)0x10FC)) 
#define CALBC1_12MHZ (*((volatile unsigned char *)0x10FB)) 
#define CALDCO_12MHZ (*((volatile unsigned char *)0x10FA)) 
#define CALBC1_16MHZ (*((volatile unsigned char *)0x10F9)) 
#define CALDCO_16MHZ (*((volatile unsigned char *)0x10F8)) 

#define DCOCTL (*((volatile unsigned char *)0x56)) 
#define BCSCTL1 (*((volatile unsigned char *)0x57)) 
#define BCSCTL2 (*((volatile unsigned char *)0x58)) 

#define TACTL (*((volatile unsigned short *)0x0160)) 
#define TAR  (*((volatile unsigned short *)0x0170)) 
#define TACCR0 (*((volatile unsigned short *)0x0172)) 
#define TACCTL0 (*((volatile unsigned short *)0x0162)) 


#define P1IN (*((volatile unsigned char *)0x0020)) 
#define P1OUT (*((volatile unsigned char *)0x0021)) 
#define P1DIR (*((volatile unsigned char *)0x0022)) 

// 16MHz clock 
// The timer is 16 bit 
// set to divide by 1 
// 16,000,000/155200 = 138.88889 
#define TACCR0_VALUE 138 

//------------------------------------------------------------------- 
void uart_putc (unsigned short c) 
{ 
    unsigned short sa; 
    unsigned short sb; 
    unsigned short then,now; 

    sa=c<<1; 
    sa|=1<<9; 
    sb=10; 
    then=TAR; 
    while(sb--) 
    { 
     if(sa&1) P1OUT|=1; else P1OUT&=(~1); 
     sa>>=1; 
     while(1) 
     { 
      now=TAR-then; 
      if(now>TACCR0_VALUE) break; 
     } 
     then+=TACCR0_VALUE; 
    } 
} 
//------------------------------------------------------------------- 
void hexstring (unsigned short d, unsigned short cr) 
{ 
    //unsigned short ra; 
    unsigned short rb; 
    unsigned short rc; 

    rb=16; 
    while(1) 
    { 
     rb-=4; 
     rc=(d>>rb)&0xF; 
     if(rc>9) rc+=0x37; else rc+=0x30; 
     uart_putc(rc); 
     if(rb==0) break; 
    } 
    if(cr) 
    { 
     uart_putc(0x0D); 
     uart_putc(0x0A); 
    } 
    else 
    { 
     uart_putc(0x20); 
    } 
} 
//------------------------------------------------------------------- 
void notmain (void) 
{ 
    unsigned short /*sa,*/sb; 
    //unsigned short start; 
    unsigned short then; //,now; 
    unsigned short bitin; 
    //unsigned short log[32]; 

    WDTCTL = 0x5A80; 

    // use calibrated clock 
    DCOCTL = 0x00; 
    BCSCTL1 = CALBC1_16MHZ; 
    DCOCTL = CALDCO_16MHZ; 

    // make p1.0 an output 
    P1DIR |= 0x01; 
    P1OUT |= 0x01; 

    P1DIR &= ~0x02; 


    BCSCTL2&=~0x06; 
    TACTL = 0x0204; 
    TACTL = 0x0220; 

    hexstring(0x1234,1); 
    hexstring(0x5678,1); 

    while(1) 
    { 
     //sa=0; 
     bitin=0; 
     while(1) if((P1IN&2)==0) break; 
     then=TAR; 
     while(1) 
     { 
      if((TAR-then)>=(TACCR0_VALUE>>1)) break; 
     } 
     if(P1IN&2) 
     { 
      bitin>>=1; 
      bitin|=1<<9; 
     } 
     else 
     { 
      bitin>>=1; 
     } 
     then+=(TACCR0_VALUE>>1); 
      for(sb=0;sb<9;sb++) 
     { 
      while(1) 
      { 
       if((TAR-then)>=TACCR0_VALUE) break; 
      } 
      if(P1IN&2) 
      { 
       bitin>>=1; 
       bitin|=1<<9; 
      } 
      else 
      { 
       bitin>>=1; 
      } 
      then+=TACCR0_VALUE; 
     } 
     hexstring(bitin,0); hexstring(bitin>>1,1); 
    } 
} 
//------------------------------------------------------------------- 
//------------------------------------------------------------------- 

de llvm es verdaderamente experimental, debe decir: roto, no te confiar en ella más que para jugar con él, el compilador gcc no es trivial, pero no excesivamente dolorosa, ya sea para construir. El ensamblador naken430asm es muy fácil de usar y el asm para este procesador es bastante simple, buena arquitectura ...

+0

Según las políticas estándar de StackOverflow, es preferible proporcionar una respuesta real, no solo un puntero a una respuesta (que puede moverse o desaparecer en el futuro). –

+0

al mismo tiempo, el desbordamiento de la pila pierde las mejoras realizadas en el enlace. Sin embargo, se agregó un código de muestra en la respuesta. –

+0

Es cierto, y estoy de acuerdo en que añadir el enlace también es útil. En cualquier caso, la explicación que agregaste con el código es mucho mejor de lo que pude encontrar en el enlace. Gustosamente votado. –

1

No hay una forma genérica de hacerlo, puede usar un recurso de temporizador de hardware disponible y configurarlo para Proporcione una base de tiempo apropiada. Yo sugeriría que para la ejecución del código de tiempo, un temporizador de milisegundos podría ser un curso; microsegundos podría ser más apropiado.

Un método más sencillo sin sobrecarga ni código adicional (o incluso hardware), y probablemente con una mayor precisión, sería ejecutar y perfilar el código en el simulador. Creo que Code Composer Studio incluye herramientas de creación de perfiles y simulación. Es probable que otras cadenas de herramientas también los incluyan. Si el código que se prueba tiene dependencias de temporización/latencia de hardware, este enfoque puede no ser adecuado.

Otro método simple consiste en alternar un GPIO disponible antes y después de la ejecución y supervisar el pin con un osciloscopio o temporizador/contador externo. Este enfoque incluirá latencias de hardware/jitter y también cualquier sobrecarga asociada con las interrupciones que puedan ocurrir durante la ejecución del código bajo prueba. También se puede implementar cuando no hay un recurso de temporizador de hardware disponible.

+0

Para "En milisegundos", esperaría que el tiempo del alcance de GPIO + fuera bastante bueno. – XTL

+0

@XTL: Punto justo dada la pregunta específica, pero para muchas aplicaciones "en tiempo real" los gastos generales pueden ser críticos. – Clifford

1

Algunos dispositivos MSP430 tienen un contador de ciclo incorporado, que está disponible cuando se utiliza un depurador. He descubierto que esto es extremadamente preciso al comparar secuencias de códigos.

No sé si su dispositivo tiene uno. De hecho, no he encontrado uno llamado MSP430f16, generalmente tienen tres o cuatro dígitos después de la "f".

0

Si está buscando algo rápido sin cambiar el software existente, pero no es súper preciso. Puede usar puntos de corte de registro antes y después del código que desea crear.

Si está utilizando IAR, esta opción está un poco oculta. Debe hacer clic con el botón derecho en la línea que desea agregar punto de interrupción y seleccionar punto de corte de registro.

Por supuesto, habrá un poco de retraso para activar el registro, este retraso debe ser constante.

Cuestiones relacionadas