Светодиоды не работают, просто :)

Цель

Я пытаюсь изменить состояние контакта на PIC24FV16KA304 в зависимости от нажатия кнопки. Первоначально контакты устанавливаются как входы, при нажатии кнопки контакты меняются на выход с низким состоянием, еще одно нажатие кнопки сохранит контакты как выходы, но изменит состояние на высокое. Наконец, третье нажатие кнопки изменит контакты обратно на входы. Это зациклится навсегда. Цепь VDD - 3 В, а земля - ​​0 В.

Аппаратное обеспечение

http://i.imgur.com/017HpUM.jpg

Кнопка подключена к INT0 (вывод 43) этого PIC и VDD. При нажатии кнопки контакт 43 подтягивается к высокому уровню. Контакты, которыми управляют при нажатии кнопки, имеют номера контактов 42 (RB6) и 41 (RB5).

На каждом контакте есть 2 светодиода, всего 4 светодиода на обоих контактах. Каждый вывод используется в следующей структуре:

VDD -> Резистор -> КРАСНЫЙ СВЕТОДИОД 1-> RB6(SENS1) -> ЗЕЛЕНЫЙ СВЕТОДИОД 2-> Резистор -> Земля.

VDD -> Резистор -> КРАСНЫЙ СВЕТОДИОД 3-> RB5 (DEBUG_LED) -> ЗЕЛЕНЫЙ СВЕТОДИОД 4-> Резистор -> Земля.

Значения резисторов и пороги светодиодов были выбраны таким образом, что если контакт установлен как вход (высокий импеданс), ни один из светодиодов не горит. Если контакт является выходом на 3 В, зеленый светодиод будет включаться исключительно, если его 0 В - красный светодиод.

В качестве отладчика используется MPLAB ICD3.

Прошивка

Я написал следующую прошивку для этой цели:

//main.c

#include "main.h"

//configuration registers

_FDS( DSWDTEN_OFF & DSBOREN_ON )
_FICD( ICS_PGx1 )
_FPOR( BOREN_BOR0 & LVRCFG_ON & PWRTEN_ON & I2C1SEL_PRI & BORV_LPBOR & MCLRE_ON )
_FWDT( WDTPS_PS32768 & FWPSA_PR128 & FWDTEN_OFF &  WINDIS_OFF )
_FOSC( POSCMOD_NONE & OSCIOFNC_OFF & POSCFREQ_HS & SOSCSEL_SOSCLP & FCKSM_CSDCMD )
_FOSCSEL( FNOSC_FRC & SOSCSRC_ANA & LPRCSEL_HP & IESO_OFF)
_FGS(GWRP_OFF & GSS0_OFF )
_FBS(BWRP_OFF & BSS_OFF )

//variables
unsigned char index;
unsigned char continuity = 1; //will become more clear at problem.

//main
int main()
{
    INTCON2bits.INT0EP = 0; //Sets to trigger on rising edge
    IEC0 = IEC0 | 0x0001;   //turn on INT0 interrupt default priority 4
    IFS0bits.INT0IF = 0;    // Clearing interrupt flag


    while(1)                //inf loop
    {
        if((index == 0) && (continuity == 1))    
        {
            TRISBbits.TRISB6 = 1; //sets direction
            TRISBbits.TRISB5 = 1;
            continunity = 0;    
        }else if((index == 1) && (continuity == 1))
        {
            TRISBbits.TRISB6 = 0;
            TRISBbits.TRISB5 = 0;   
            PORTBbits.RB6 = 0;   //sets port value
            PORTBbits.RB5 = 0;
            continunity = 0;                
        }else if((index == 2) && (continuity == 1))
        {
            PORTBbits.RB6 = 1;
            PORTBbits.RB5 = 1;  
            continunity = 0;    
        }else if(index == 3)
        {
            index = 0;  
        }           
    }           
}

void __attribute__((interrupt, auto_psv)) _INT0Interrupt(void)
{
    //clear the interrupt flag  
    __delay_us(50);
    if(PORTBbits.RB7 == 1)
    {
        index++;
        continuity = 1;
    }   
    IFS0bits.INT0IF = 0;
} 

Проблемы

Есть несколько проблем, я постараюсь сохранить сплоченность.

  1. В большинстве случаев состояния меняются сами по себе. Это имеет (иногда) прямую связь с движениями моего тела. Я могу усилить эту ошибку, если буду держать телефон за металл во время зарядки и провожу рукой над доской. Он действует как ИДЕАЛЬНЫЙ детектор прокси. Почему эта плата работает как антенна?? Есть ли у вас какие-либо предложения по отладке, чтобы понять, что происходит? Если вам нужна дополнительная информация, дайте мне знать. РЕШЕНО

  2. Неправильные состояния светодиодов. Как видно из кода, никогда не может быть возможности включения 1 красного (RB6) и 1 зеленого (RB5) светодиода, однако при работе на полной скорости эта проблема возникает, хотя ожидается, что оба, например, будут зелеными (индекс = 2). Одно интересное наблюдение, касающееся этой проблемы, заключается в том, что я запустил код на полной скорости без переменной непрерывности, я разрешил ему постоянно входить в один и тот же блок IF, индекс 2, ожидается, что оба светодиода будут зелеными, но один из них красный. в действительности. Затем я останавливаю код и начинаю выполнять его отдельными шагами, и вдруг он начинает работать. РЕШЕНО

  3. Кнопка не работает. Когда я нажимаю кнопку, это не имеет никакого эффекта. Однако, если я подключаю осциллограф к переходному отверстию, которое соединяет его с PIC, он внезапно начинает работать правильно, и на осциллографе он ведет себя так, как должен. Если я уберу осциллограф, он снова перестанет работать. Я подумал, что, возможно, пробник влияет на некоторую емкость, поэтому я подключил самый маленький конденсатор, который у меня есть (10 мкФ), к точной промежуточной точке, и никаких изменений. Как еще щупы осциллографа влияют на плату? РЕШЕНО

  4. Если целостность кода удалена, контакт № 43 начинает колебаться в среднем с частотой 400 Гц. Когда это происходит, оба светодиода загораются одновременно. Это колебание не периодическое, оно очень случайное. Я не понимаю, как можно так повлиять на один контакт, если код не имеет такого состояния. Исчез

    Примечания

Я лично считаю, что аппаратное обеспечение было хорошо заземлено, и лично я не видел каких-либо явных аппаратных проблем.

Если вам, ребята, нужна дополнительная информация, дайте мне знать.

ПОМОЩЬ!

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

Кажется, что все вышеперечисленные симптомы вызваны одной и той же, возможно, аппаратной проблемой? Если вы, ребята, испытали что-то подобное, я с нетерпением жду этого!

Если вы загрузите свою схему на такой сервис, как imugr, и дадите нам ссылку в комментариях, кто-то с большей репутацией сможет добавить изображение в ваш пост.
Я также скоро добавлю голые костяные соединения.
Вы заполнили R30, он показан как DNP на картинке? Если нет, попробуйте кинуть туда 10к и посмотреть, что произойдет.

Ответы (2)

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

Спасибо. Это DNP, потому что я намеревался использовать внутренний подтягивающий резистор, но мое предположение о том, как он работает, было неверным. После включения внутреннего вытягивания он начал работать правильно. Теперь у меня есть интуиция в отношении того, насколько антенна может работать с одним переходным отверстием, как если бы она была на плавающем штырьке, и если я увижу что-то, реагирующее на меня в будущем, я думаю, что легко могу предположить плавающий штырь.
Также я добавил улучшенную процедуру устранения дребезга, и больше нет неучтенных изменений состояния.

Причина неправильных состояний светодиодов заключалась в том, что я не давал достаточно времени между командами смены порта.

При написании:

    PORTBbits.RB6 = 1;
    PORTBbits.RB5 = 1;  

На самом деле должно быть:

    PORTBbits.RB6 = 1;
    Nop(); //skip cycle
    PORTBbits.RB5 = 1;  

Единственный ключ к этому в таблице данных заключается в том, что для передачи данных из защелки порта в фактический порт требуется цикл.

Порт также можно просто обновить с помощью:

    PORTB = 0x60;

Для того же эффекта.

Это распространенная ошибка, вы пишете выходной порт, а не выходную защелку. Подробнее см. , например, stackoverflow.com/questions/2623428/… . Затем вы можете удалить NOP.