![]() |
![]() |
#1 |
Moderator
Регистрация: 20.07.2014
Адрес: МСК
Сообщений: 991
Вес репутации: 1031 ![]() ![]() ![]() |
![]()
Мучая энкодер, понял, что вывод в Serial тормозит атмегу, что приводить к потере косяков энкодера.
Решил в прерываниях писать в FIFO, а в цикле выводить в Serial. За пару часов родилось и скомпилировалось это: КодКод:
#define set_bit(reg,value) reg |= (_BV(value)) #define unset_bit(reg,value) reg &= ~(_BV(value)) #define BUF_SIZE 256 //размер буфера обязательно равен степени двойки! #define BUF_MASK (BUF_SIZE-1) uint8_t idxIN, idxOUT; struct { uint8_t ReadPortD; //тут храним состояние порта D Пины с 0-7 на ардуино UNO unsigned long timer; }buff [BUF_SIZE] ; ISR(PCINT2_vect){ // сработало прерывание digitalWrite(13, HIGH); // включает светодиод unset_bit (PCICR,PCIE2); //отключаем прерывание до отработки прерывания, во избежании повторных срабатываний buff[idxIN++] = {PIND, millis()} ;//записываем состояние порта D idxIN &= BUF_MASK; set_bit (PCICR,PCIE2); //включаем прерывание. Вроде не забыл digitalWrite(13, LOW); // включает светодиод } void setup() { pinMode(5,INPUT_PULLUP); // Clock Подключаем к INT1, нельзя переназначать pinMode(6, INPUT_PULLUP); // второй вывод энкодера pinMode(7, INPUT_PULLUP); // кнопка энкодера pinMode(13, OUTPUT); // кнопка энкодера Serial.begin(9600); while (!Serial); set_bit (PCICR,PCIE2);//Включаем прерывание PCINT16-23 (PortD) PCIE2, регистр PCICR принимает значение 0b00000100; PCMSK2 |= (_BV(PCINT23)| _BV(PCINT22) | _BV(PCINT21)); //Указываем, что надо реагировать только на пины 5,7 // для порта D соответствуют pcint 16-23 Serial.println(PCMSK2,BIN); sei();//включаем прерывания Serial.println("ready"); } void loop() { if (idxIN != idxOUT) { // если сюда что-то записано, значит был поворот или нажатие кнопки, прерывания отключены. Надо бы не забыть их включить. Serial.print(idxIN); Serial.print(":"); Serial.print(idxOUT); Serial.print(":"); Serial.print(buff[idxOUT].timer); Serial.print(":"); Serial.println(buff[idxOUT++].ReadPortD,BIN); idxOUT &= BUF_MASK; } } [свернуть] Насколько он правильно работает - не знаю. Возможно в нем есть ошибки. Но в выводе есть странности: 11:4016:11100101 12:4016:10100101 13:4016:10100101 14:4016:10100101 15:4016:10100101 16:4016:11100101 В моем представлении в течении 4016 миллисекунды сначало произошло падение напряжения на 6 пине (с 11 на 12 срабатывание), потом 3 непонятных события (регистр PIND без изменений), и восстановление напряжения. А есть что-то быстрее чем millis()? Чтобы увидеть насколько разнесены по времени срабатывания. Последний раз редактировалось Tohin; 16.08.2018 в 21:11. |
![]() |
![]() |
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1) | |
|
|