2016-02-15 2 views
0

Я пытаюсь познакомиться с pic18f24k50 с arduino 101. Я использую две строки, чтобы установить синхронизированную связь. При каждом изменении от низкого к высокому в первой строке я читаю значение со второй строки. У меня нет проблем с кодом arduino, моя проблема в том, что на рис., Прерывание по смене триггеров на втором изменяет с низкого на высокий, а не на запуск при первом изменении. Это происходит только в первый раз, когда я отправляю данные, после чего он работает отлично (он запускается при первом изменении, и я получаю байт правильно). Извините за мой английский, я попытаюсь объяснить себя лучше с этим изображением:pic Прерывание при изменении не запускается в первый раз

enter image description here

Канал 1 является сигналом синхронизации, channel2 это данные (Im посылая один байт на данный момент, с битовыми значениями 10101010). Канал 4 - это выход, который я меняю каждый раз, когда обрабатываю бит. (как вы можете видеть, он начинается со второго повышения тактового сигнала вместо первого). Это фиксируется в первом отправленном байте, а остальные работают нормально.

я отправляю соответствующий код в картинке здесь:

Это где я инициализировать вещи:

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

И это на код прерывания:

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; < - это линия, соответствующая каналу 4.

RC1 является канал 1 и RC2 является канал 2

Мой вопрос: что я делаю не так, почему на первый послал байт прерывания Безразлично» t триггеров при первом изменении строки 1?

спасибо.

+0

Где находится этот «код прерывания»? Кажется, что он находится в вашем цикле while, а не в векторе прерывания. Переключатель вашего случая - это одна из основных частей повторяющегося кода. Кроме того, этот вопрос может поместиться лучше на EE.SE или Arduino.SE. – Paul

+0

Вы также можете использовать UART/serial, что отлично подходит для связи между микроконтроллерами. – Paul

+0

Pic обрабатывает экран светодиодов, обновляя его все время. У меня нет доступных портов UART :(, поэтому я попытался реализовать свой собственный «протокол», потому что информация, которую я должен отправить, довольно проста. – takluiper

ответ

0

Что вы пытаетесь достичь?

Протокол связи, который вы описываете, обычно называется SPI (Serial Peripheral Interface). Вы должны использовать аппаратную реализацию, доступную PIC/Microchip, если это возможно, для лучшей производительности.

свой код документирован/отформатированных/логика

Я заметил код, будучи немного, странно. Странный код дает странные ошибки.

Первый: Вы используете прерывания, у вас есть этот блокирующий код в вашем прерывании. Что совсем не приятно.

Второе: Ваши переменные «contabits» и «varByte» выходят из ниоткуда, возможно, они глобальны. Это может быть не самая лучшая практика. Хотя, если вы используете прерывания и когда имеет смысл переносить переменные в вашу основную программу, используя глобальный. Глобальный должен быть volatile.

В-третьих: В этом случае переключатель всего 8 раз аналогичный код, но немного отличается.

Также добавьте комментарии к своему коду.

Чтобы быть честным

я не заметил фактическую ошибку, было долгое время, так как я работал с ПОС. Но вы должны попробовать аппаратное SPI.

Ниже приведена моя попытка программного обеспечения SPI, как вы описали, оно может быть немного более логичным и вызывать любое раздражение прерываний.

Я бы рекомендовал заменить while(CLOCK_PIN_MACRO != 1){}; на for(unsigned int timeout = 64000; timeout > 0; timeout--){};. Чтобы вы могли быть уверены, что ваша программа не будет висеть, ожидая сигнала SPI, который не появится. (Сделайте тайм-аут чем-то подходящим для ваших нужд)

#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

Спасибо за сообщение. Переключатель case повторяется, но он должен работать, ваше решение умнее, хорошо, но оно должно работать. – takluiper

0

Вы можете найти следующее из таблицы.

Булавки сравниваются со старым значением, зафиксированным при последнем чтении PORTB. Выходы «несоответствия» RB7: RB4 объединены вместе для генерации прерывания изменения порта RB с битом флага, RBIF (INTCON < 0>).

Это означает, что когда вы читаете контакты PORTB RB7: RB4, значение каждого булавки будет храниться во внутренней защелке. Прерывание будет генерироваться только в случае изменения входного сигнала штыря от ранее зафиксированного значения.

Тогда, каково будет начальное значение по умолчанию в защелке? Т.е. перед тем, как мы прочитаем что-нибудь из PORTB.

Что бы это ни было. в вашем случае значение защелки по умолчанию отличается от логического состояния вашего входного сигнала. Во время следующего перехода сигнала значение защелки и уровень сигнала становятся одинаковыми. Таким образом, intterrupt не генерируется в первый раз.

Что вы можете сделать, это установить значение фиксации в исходное состояние вашего сигнала. Это можно сделать, прочитав PORTB (должно быть сделано до включения intterrupt).

Этот код достаточно, чтобы просто прочитать регистр.

unsigned char ch; 
ch = PORTB; 

Надеюсь, это поможет.

Смежные вопросы