2016-02-15 1 views
0

J'essaye de communiquer un pic18f24k50 avec un arduino 101. J'utilise deux lignes pour établir une communication synchronisée. À chaque changement de bas en haut de la première ligne, j'ai lu la valeur de la deuxième ligne. Je n'ai aucun problème avec le code arduino, mon problème est que dans l'image, le changement d'Interrupt on se déclenche lors du second changement de bas en haut au lieu de se déclencher lors du premier changement. Cela n'arrive que la première fois que j'envoie des données, après cela, cela fonctionne parfaitement (il se déclenche dès le premier changement et je reçois l'octet correctement). Désolé pour mon anglais, je vais essayer de me expliquer mieux avec cette image:pic Interruption sur le changement ne déclenche pas la première fois

enter image description here

canal 1 est le signal d'horloge, channel2 est les données (Im envoie un octet pour le moment, avec des valeurs de bits 10101010). Le canal 4 est une sortie que je change chaque fois que je traite un peu. (comme vous pouvez le voir, il commence à la deuxième hausse du signal d'horloge au lieu du premier). Ceci est capturé sur le premier octet envoyé, les suivants fonctionnent bien.

je poste le code correspondant dans la photo ici:

C'est là que j'initialise choses:

TRISCbits.TRISC6 = 0; 
TRISCbits.TRISC1 = 1; 
TRISCbits.TRISC2 = 1; 
IOCC1 = 1; 
ANSELCbits.ANSC2=0; 
IOCC2 = 0; 
INTCONbits.IOCIE = 1; 
INTCONbits.IOCIF = 0; 

Et c'est le code d'interruption:

void interrupt SYS_InterruptHigh(void) 
{ 
    if (INTCONbits.IOCIE==1 && INTCONbits.IOCIF==1) 
    { 
      readByte(); 
    } 
} 

void readByte(void) 
{ 
while(contaBits<8) 
{ 
    INTCONbits.IOCIE = 0; 
    INTCONbits.IOCIF = 0; 

    while (PORTCbits.RC1 != HIGH) 
    { 
    }  

    if (PORTCbits.RC1 == HIGH) 
    { 

      LATCbits.LATC6 = !LATCbits.LATC6; 


     //LATCbits.LATC6 = ~LATCbits.LATC6; 
     switch (contaBits) 
     { 
      case 0: 
       if (PORTCbits.RC2 == HIGH) 
        varByte.b0 = 1; 
       else 
        varByte.b0 = 0; 
       break; 
      case 1: 
       if (PORTCbits.RC2 == HIGH) 
        varByte.b1 = 1; 
       else 
        varByte.b1 = 0; 
       break;  
      case 2: 
       if (PORTCbits.RC2 == HIGH) 
        varByte.b2 = 1; 
       else 
        varByte.b2 = 0; 
       break; 
      case 3: 
       if (PORTCbits.RC2 == HIGH) 
        varByte.b3 = 1; 
       else 
        varByte.b3 = 0; 
       break; 
      case 4: 
       if (PORTCbits.RC2 == HIGH) 
        varByte.b4 = 1; 
       else 
        varByte.b4 = 0; 
       break; 
      case 5: 
       if (PORTCbits.RC2 == HIGH) 
        varByte.b5 = 1; 
       else 
        varByte.b5 = 0; 
       break; 
      case 6: 
       if (PORTCbits.RC2 == HIGH) 
        varByte.b6 = 1; 
       else 
        varByte.b6 = 0; 
       break; 
      case 7: 
       if (PORTCbits.RC2 == HIGH) 
        varByte.b7 = 1; 
       else 
        varByte.b7 = 0; 
       break; 
     } 

     contaBits++; 
    } 

}//while(contaBits<8) 
INTCONbits.IOCIE = 1; 
contaBits=0; 
} 

LATCbits.LATC6 =! LATCbits.LATC6; < - c'est la ligne correspondant au canal 4.

RC1 est le canal 1 et RC2 est le canal 2

Ma question est ce que je fais mal, pourquoi le premier envoyé d'octets l'interruption doesn » t déclenche le premier changement de la ligne 1?

Merci.

+0

Où est ce "code d'interruption" placé? Il semble que ce soit dans votre boucle while, plutôt que dans un vecteur d'interruption. Votre commutateur de cas est une partie du code répétitif. En outre, cette question pourrait mieux sur EE.SE ou Arduino.SE. – Paul

+0

Vous pouvez également utiliser UART/série, ce qui est idéal pour la communication entre les microcontrôleurs. – Paul

+0

La photo traite un écran de leds, le rafraîchissant tout le temps. – takluiper

Répondre

0

Qu'essayez-vous d'accomplir?

Le protocole de communication que vous décrivez est communément appelé SPI (Serial Peripheral Interface). Vous devez utiliser l'implémentation matérielle disponible par PIC/Microchip, si possible, pour de meilleures performances.

Gardez votre code documenté/formaté/logique

J'ai remarqué votre code étant un peu bizarre. Le code bizarre donne des erreurs étranges.

Première: Vous utilisez des interruptions, vous avez ce code de blocage dans votre interruption. Ce qui n'est pas gentil du tout. Vos variables "contabits" et "varByte" viennent de nulle part, elles sont probablement globales. Ce qui pourrait ne pas être la meilleure pratique. Cependant, si vous utilisez des interruptions, et quand il peut être judicieux de transférer les variables à votre programme principal en utilisant un global. Le global doit être volatile.

Troisième: Ce commutateur est seulement 8x le même code, mais un peu différent.

Ajoutez également des commentaires à votre code.

Pour être honnête

Je ne suis pas votre erreur réelle repère, a été longtemps que je travaille avec PIC. Mais, vous devriez essayer le SPI matériel. Ci-dessous est ma tentative de logiciel SPI comme vous l'avez décrit, il pourrait être un peu plus logique, et supprime toute gêne des interruptions. Je recommande de remplacer le while(CLOCK_PIN_MACRO != 1){}; par for(unsigned int timeout = 64000; timeout > 0; timeout--){};. Afin que vous soyez sûr que votre programme ne se bloque pas en attendant un signal SPI qui ne viendra pas. (Faire le temps d'attente quelque chose qui correspond à vos besoins)

#define CLOCK_PIN_MACRO PORTCbits.RC1 
#define DATA_PIN_MACRO PORTCbits.RC2 

/* 
Test, without interrupts. 
I would strongly advise to use Hardware SPI or non-blocking code. 
*/ 

unsigned char readByte(void){ 
    unsigned char returnByte = 0; 
    for(int i = 0; i < 8; i++){    //Do this for bit 0 to 7, to get a complete byte. 
     while(CLOCK_PIN_MACRO != 1){};  //Wait until the Clock pin goes high. 
     if(DATA_PIN_MACRO == 1)    //Check the data pin. 
     returnByte = returnByte & (1 << i); //Shift the bit in our byte. (https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/bitshift.html) 
     while(CLOCK_PIN_MACRO == 1){};  //Wait untill the Clock pin goes low again. 
    } 
    return returnByte; 
} 

void setup(){ 
    TRISCbits.TRISC6 = 0; 
    TRISCbits.TRISC1 = 1; 
    TRISCbits.TRISC2 = 1; 
    //IOCC1 = 1; 
    ANSELCbits.ANSC2=0; 
    //IOCC2 = 0; 
    INTCONbits.IOCIE = 1; 
    INTCONbits.IOCIF = 0; 
} 

void run(){ 
    unsigned char theByte = readByte(); 
} 

main(){ 
    setup(); 
    while(1){ 
    run(); 
    } 
} 
+0

Merci pour votre publication. Le commutateur de cas est répétitif mais cela devrait fonctionner, votre solution est plus intelligente, d'accord, mais cela devrait fonctionner. – takluiper

0

Vous pouvez trouver ce qui suit de la fiche technique. Les broches sont comparées à l'ancienne valeur mémorisée lors de la dernière lecture de PORTB. Les sorties de "discordance" de RB7: RB4 sont combinées par OU pour générer le bit d'interruption de changement de port RB avec indicateur, RBIF (INTCON < 0>). Cela signifie que lorsque vous lisez les broches PORTB RB7: RB4, la valeur de chaque broche sera stockée dans un verrou interne. L'interruption sera générée seulement quand il y a un changement dans l'entrée de broche de la valeur précédemment verrouillée. Ensuite, quelle sera la valeur initiale par défaut dans la bascule? C'est-à-dire avant de lire quoi que ce soit de PORTB.

Quoi que ce soit. dans votre cas, la valeur de verrouillage par défaut est différente de l'état logique de votre signal d'entrée. Pendant la transition suivante du signal, la valeur de verrouillage et le niveau de signal deviennent identiques. Donc, aucune interruption n'est générée la première fois.

Ce que vous pouvez faire est de régler la valeur de verrouillage à l'état initial de votre signal. Cela peut être fait en lisant PORTB (devrait être fait avant d'activer l'intterrupt).

Le code ci-dessous est suffisant pour lire simplement le registre.

unsigned char ch; 
ch = PORTB; 

Espérons que cela aidera.