// Данный пример написан только для портов RB, при использовании другого порта // указывайте свои TRIS и LAT // Пример вызова функции: CallibrateButton(0, &button_open_time); // Здесь button_open_time - глобальная переменная, адрес которой передаётся в функцию void CallibrateButton(unsigned char button_id, unsigned int open_button_time) { // Так как в моём случае я использую порт B, нужно убедиться, что перед началом опроса он работает как Digital Out // Состояние порта B в PIC18F2580 зависит также от регистра ADCON1 ADCON1 |= 0b00001000; // Калибровка проводится для оценки времени заряда сенсора без прикосновения TRISB &= ~(1 << button_id); // Порт на выход LATB &= ~(1 << button_id); // В порт ноль __delay_us(200); // Ждём пока сенсор разрядится TMR0H = 0; TMR0L = 0; GIE = 0; TMR0ON = 1; // Обнуление таймера, запрет прерываний и запуск таймера TRISB |= (1 << button_id); // Переводим порт в высокоимпедансное состояние while ( (PORTB&(1 << button_id)) == 0 ); // ждём пока порт не покжает единицу TMR0ON = 0; GIE = 1; // Выключаем таймер и разрешаем прерывания open_button_time = TMR0 + 5; // Сохраняем значение таймера, с запасом для исключения ложных нажатий // Вместо "5" тут можно использовать переменную и ею подстраивать чувствительность // В моём случае я просто использовал 16-bit таймер и глобальную переменную типа int, // Но вообще-то должно хватать и 8-bit таймера TRISB &= ~(1 << button_id); // Порт на выход LATB &= ~(1 << button_id); } // В порт ноль unsigned char CheckButton(unsigned char button_id, unsigned int open_button_time) { // Собственно опрос кнопки. Функция возвращает состояние кнопки unsigned int button_time = 0; ADCON1 |= 0b00001000; TRISB &= ~(1 << button_id); // Порт на выход LATB &= ~(1 << button_id); // В порт ноль __delay_us(200); // Ждём пока сенсор разрядится TMR0H = 0; TMR0L = 0; GIE = 0; TMR0ON = 1; // Обнуление таймера, запрет прерываний и запуск таймера TRISB |= (1 << button_id); // Переводим порт в высокоимпедансное состояние while ( (PORTB&(1 << button_id)) == 0 ); // ждём пока порт не покжает единицу TMR0ON = 0; GIE = 1; // Выключаем таймер и разрешаем прерывания button_time = TMR0; // Сохраняем значение таймера TRISB &= ~(1 << button_id); // Порт на выход LATB &= ~(1 << button_id); // В порт ноль if ( button_time > open_button_time) { return 1; } else { return 0; }; } // Если заряжался дольше открытого - значит есть касание