Цель
Я пытаюсь изменить состояние контакта на PIC24FV16KA304 в зависимости от нажатия кнопки. Первоначально контакты устанавливаются как входы, при нажатии кнопки контакты меняются на выход с низким состоянием, еще одно нажатие кнопки сохранит контакты как выходы, но изменит состояние на высокое. Наконец, третье нажатие кнопки изменит контакты обратно на входы. Это зациклится навсегда. Цепь VDD - 3 В, а земля - 0 В.
Аппаратное обеспечение
Кнопка подключена к 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 красного (RB6) и 1 зеленого (RB5) светодиода, однако при работе на полной скорости эта проблема возникает, хотя ожидается, что оба, например, будут зелеными (индекс = 2). Одно интересное наблюдение, касающееся этой проблемы, заключается в том, что я запустил код на полной скорости без переменной непрерывности, я разрешил ему постоянно входить в один и тот же блок IF, индекс 2, ожидается, что оба светодиода будут зелеными, но один из них красный. в действительности. Затем я останавливаю код и начинаю выполнять его отдельными шагами, и вдруг он начинает работать. РЕШЕНО
Кнопка не работает. Когда я нажимаю кнопку, это не имеет никакого эффекта. Однако, если я подключаю осциллограф к переходному отверстию, которое соединяет его с PIC, он внезапно начинает работать правильно, и на осциллографе он ведет себя так, как должен. Если я уберу осциллограф, он снова перестанет работать. Я подумал, что, возможно, пробник влияет на некоторую емкость, поэтому я подключил самый маленький конденсатор, который у меня есть (10 мкФ), к точной промежуточной точке, и никаких изменений. Как еще щупы осциллографа влияют на плату? РЕШЕНО
Если целостность кода удалена, контакт № 43 начинает колебаться в среднем с частотой 400 Гц. Когда это происходит, оба светодиода загораются одновременно. Это колебание не периодическое, оно очень случайное. Я не понимаю, как можно так повлиять на один контакт, если код не имеет такого состояния. Исчез
Примечания
Я лично считаю, что аппаратное обеспечение было хорошо заземлено, и лично я не видел каких-либо явных аппаратных проблем.
Если вам, ребята, нужна дополнительная информация, дайте мне знать.
ПОМОЩЬ!
Любые решения или методы отладки, которые вы можете предложить, будут очень признательны, я начинаю терять волосы благодаря этой проблеме.
Кажется, что все вышеперечисленные симптомы вызваны одной и той же, возможно, аппаратной проблемой? Если вы, ребята, испытали что-то подобное, я с нетерпением жду этого!
Кажется, вам нужен подтягивающий резистор на INT0 (вы, кажется, не упоминаете, что он у вас есть), моя подсказка о том, что вам нужен подтягивающий резистор, - это ваша проблема номер один, когда ваше тело влияет на изменение состояния. Эта проблема возникает из-за того, что у вас есть вход с высоким импедансом (INT0) и он плавающий, нет никакой гарантии, что ваш INT0 имеет низкий уровень, потому что он остается плавающим, пока вы не нажмете кнопку и не удержите высокий уровень. Добавление подтягивающего резистора по умолчанию установит состояние INT0 на низкое, также помните, что ваш щуп выглядит как колпачок с параллельным резистором, поэтому каждый раз, когда вы прощупываете свою цепь, вы в основном устанавливаете подтягивающий резистор. Другая проблема, которую я вижу, заключается в том, что ваша кнопка не устраняет дребезг, добавление задержки в несколько миллисекунд не приведет к отмене ввода.
Причина неправильных состояний светодиодов заключалась в том, что я не давал достаточно времени между командами смены порта.
При написании:
PORTBbits.RB6 = 1;
PORTBbits.RB5 = 1;
На самом деле должно быть:
PORTBbits.RB6 = 1;
Nop(); //skip cycle
PORTBbits.RB5 = 1;
Единственный ключ к этому в таблице данных заключается в том, что для передачи данных из защелки порта в фактический порт требуется цикл.
Порт также можно просто обновить с помощью:
PORTB = 0x60;
Для того же эффекта.
Фотон
Вулкан
Вулкан
Вулкан
EE_PCB