2016-05-18 2 views
0

Je suis à la recherche de conseils car je travaille sur un PIC18F452 sur Proteus.Enregistrement de la valeur PORTD dans un tableau sur pic18f452 (C)

Mon objectif est d'acquérir la valeur de PORTDbits.RD0 (définie en entrée) toutes les 100ms (à travers timer1) et de le stocker dans un tableau de 8 bits. Cette trame sera ensuite envoyée via SPI à l'esclave.

Pour le moment j'ai seulement implémenté ce que je considère être le remplissage de la matrice et le décalage de bits. Malheureusement, lorsque je lance la simulation, seul le bit du tableau contient à un certain point la valeur de PORTDbits.RD0.

Si quelqu'un a une idée qui pourrait aider, ce serait génial: D

Voici mon code

/* CONFIG *******************************************************************/ 
#pragma config PWRT = ON // Power-up Timer 
#pragma config OSC = HS // High-Speed Oscillator 
#pragma config LVP = OFF // Low-Voltage In-Circuit Serial Programming 
#pragma config DEBUG = ON // 

/* INCLUDES *****************************************************************/ 
#include "project_config.h" // All headers inclusion 

/* MACROS *******************************************************************/ 
#define nop() {_asm nop _endasm} 

/* DEFINES ******************************************************************/ 
#define SIZE 8 

/* FUNCTIONS PROTOTYPES *****************************************************/ 
void main(void); 

void isr_config(void); 
void io_config(void); 

void timer1_config(void); 
void timer1_isr(void); 

/* PROTOTYPES ***************************************************************/ 

/* VARIABLES DEFINITION *****************************************************/ 
unsigned int filling_cnt = 0; 

/* MAIN *********************************************************************/ 
void main(void) { 
    unsigned char array[SIZE]; 
    unsigned int index = 0; 
    int j; 

    /// Initialization 
    io_config(); 
    timer1_config(); 
    isr_config(); 

    /// Interruption 
    timer1_isr(); 

    /// Data acquisiton 
    while(1){ 
     array[index] = PORTDbits.RD0;   // Read RD0 and save in array   
     for(index = 0; index < SIZE; index++){ // Fill array 
      array[index] = array[index+1];  // shifting n_value to insert n+1_value 
      //printf("%s\n", array); 
     } //rof 

     filling_cnt++;       // Array counter for filling control 

     if(filling_cnt > SIZE){     // Reached the end of array ? 
      index = 0;       // Reset counter 
      printf("%s\n", array);    // Send data to terminal 
      for (j=0; j<SIZE; j++){ 
       array[j] = '\0';    // Empty array 
      } //rof 
     } //fi 
    } 
} 

/* FUNCTIONS ****************************************************************/ 
/// Configurations 
void timer1_config(void) { 
    T1CONbits.RD16 = 1; // Timer/Counter 8-bits/16-bits Control bit: 0=8-bits/1=16-bits 
    T1CONbits.T1CKPS1 = 1; // Prescaler 
    T1CONbits.T1CKPS0 = 1; // 1 = 0b00 
          // 2 = 0b01 
          // 4 = 0b10 
          // 8 = 0b11 
    T1CONbits.T1OSCEN = 1; // Timer1 Oscillator shut off 
    T1CONbits.TMR1CS = 0; // Timer1 Clock Source Select bit 
          // 0 = Internal Clock (Fosc/4) 
          // 1 = Transition on T1CKI pin 
    T1CONbits.TMR1ON = 1; // Timer1 On/Off Control bit 
          // 1 = Enables Timer1 
          // 0 = Stops Timer1 
    TMR1H=0x0B;   // Preset timer1 value for MSB register 
    TMR1L=0xDB;   // Preset timer1 value for LSB register 
          // to get a 100ms delay 
} 

void isr_config(void) { 
    PIE1bits.TMR1IE = 1; // Enable Timer1 interrupts 
    PIR1bits.TMR1IF = 0; // Clear Timer1 interrupt flag 
    IPR1bits.TMR1IP = 1; // Non high priority interrupt 

    RCONbits.IPEN = 1; // Interrupt High level 

    INTCONbits.PEIE = 1; // All peripherals interrutps verified 
    INTCONbits.GIE = 1; // All interrupts verified 
} 

void io_config(void) { 
    TRISB = 0x00;   // PORTB as output 
    TRISDbits.TRISD0 = 1; // COMP_OUT as input 
    TRISDbits.TRISD1 = 0; // DATA as output 
} 

/// Interruptions 
#pragma code highVector = 0x08 //lowVector = 0x18 
void InterruptHigh (void) { 
    _asm 
    goto timer1_isr 
    _endasm 
} 
#pragma code 

#pragma interrupt timer1_isr 
void timer1_isr(void) { 
    if (PIR1bits.TMR1IF == 1) { // check that timer1 overflow is reason for ISR. 
            // even though there is only one Interrupt source 
            // trigger enabled, it is good programming practice to 
            // test why we have arrived at the ISR. 
     PIR1bits.TMR1IF = 0; // Timer1 interrupt flag clear 

     TMR1H = 0x0B;  // Preset timer1 value for MSB register 
     TMR1L = 0xDC;  // Preset timer1 value for LSB register 
          // with a 20MHz xtal, Timer1 Prescalar set to /8 
          // decimal 3036 (0x0B 0xDC) is the counter start point 
          // which will result in Timer1 overflow 1 per 100ms 
          // 65536 - 3036 = 62500 cycles 
          // 10 interrupts per second 

     LATBbits.LATB4 = !LATBbits.LATB4; // invert the condition of LED to show program 
              // has entered the Interrupt routine 
     PORTDbits.RD1 = !PORTDbits.RD1; // invert the condition of DATA to show program 
              // has entered the Interrupt routine        
    } //fi 
} 

/* EOF main.c ***************************************************************/ 

Si quelque chose manque ou pas clair dans ce message, s'il vous plaît ne pas hésiter, ne me dites . Je ferai de mon mieux pour ajouter des détails ou pour repenser mon post afin de faciliter la compréhension. Merci à l'avance;)

+0

Quoi ?? Vous lisez le port: 'array [index] = PORTDbits.RD0;', et ils écrasent immédiatement la valeur que vous avez lue: 'array [index] = array [index + 1];'. Vous dites que ce code fonctionne réellement, un peu? –

+0

Aussi, 'unsigned char array [SIZE];' est un tableau 8 BYTE, pas 8 bits. Pouvez-vous être plus clair re. votre intention réelle? –

+0

Salut, Oui, je sais que c'est absolument stupide et illogique. Mais j'ai essayé dans l'autre sens: array [index + 1] = array [index] et ce n'était pas mieux ... EDIT: J'ai cherché de l'aide sur le bit shift et c'est ce que j'ai trouvé le faire manuellement – Daymov

Répondre

2
  1. Dans la fonction principale vous avez une boucle infinie, qui se déroule sans aucun délai entre deux acquisitions. Ce dont vous avez besoin est d'avoir un délai de 100ms entre les deux fois que vous lisez PORTD.

Ce que vous pouvez faire est d'introduire un drapeau global. Ceci est défini dans le sous-programme de minuterie, et est effacé dans le principal.

  1. Le code de remplissage des données dans le tableau est incorrect. Le code ci-dessous remplit le tableau à partir de l'emplacement arrray[0], array[1] au maximum dans l'ordre.

La minuterie doit être modifié comme celui-ci

void timer1_isr(void) { 
    if (PIR1bits.TMR1IF == 1) { 
     blTimeOverFlag = 1; 
     // Other code here 
    } 
} 

boucle de fonction principale est inférieure à

while(1){ 
    if (blTimeOverFlag == 1) 
    { 
    blTimeOverFlag = 0; 
    array[filling_cnt] = PORTDbits.RD0;   // Read RD0 and save in array   
    filling_cnt++;       // Array counter for filling control 

    if(filling_cnt >= SIZE){     // Reached the end of array ? 
     filling_cnt = 0; 
     printf("%s\n", array);    // Send data to terminal 
     for (j=0; j<SIZE; j++){ 
      array[j] = '\0';    // Empty array 
     } //rof 
    } //fi 
    } 
}   
+0

Merci! Avant que je ne puisse vous lire la réponse, j'avais réécrit le code pour remplir les données dans le tableau à un très proche de celui que vous suggérez (juste le nom des variables étaient différentes). En ce qui concerne le drapeau mondial, je suis désolé mais je ne comprends pas vraiment son but. Lors de la configuration de mon timer, j'ai réglé les registres, prescaler pour obtenir mon délai de 100ms.Ne fera-t-il pas une redondance si j'utilise le drapeau? – Daymov

+0

Le drapeau doit avoir un délai entre deux lectures de 'PORTDbits.RD0'. Dans votre code d'origine, après avoir terminé une itération de l'acquisition de données 'while (1)' boucle, il lit à nouveau les données immédiatement. La boucle while prendra dans l'ordre de microsecondes à exécuter. Les données suivantes sont lues après quelques microsecondes plutôt que 100ms comme souhaité. –

+0

OK. Merci beaucoup pour votre aide. – Daymov