ve_avr.h Портит код
- Войдите на сайт для отправки комментариев
Прошу прощения за возможно простецкие вопросы, но ответа в инете не нашел. Последний раз писал на ассемблере и под PIC16. Сейчас решил попробовать ардуино UNO. Написал небольшой скетч который измеряет напряжение, отдает его в порт, записывает в eeprom, читает входы, управляет выходами. Все работает. Но мне потребовался еще тактовый сигнал (t=50мкс, T=250мкс) для моего устройства. Входы/выходы ардуины все заняты, решил использовать А1, а сам сигнал генерировать в прерывании по достижению ТС1 числа A с применением библиотеки ve_avr.h . На этом все хорошее закончилось. Сигнал генерируется, но основная программа живет своей жизнью. Вопрос, что не так? Код уже изрядно перепахан, поэтому многое закоментированно. Изначально пробовал на функциях типа micros реализовать -не понравилось.
int k=4; int dk=0; int kreg; float sensorValue; byte voltage; // unsigned long ct; //currentTime int lt = 0; //loopTime // volatile bool tau = false; // #include <EEPROM.h> #include <ve_avr.h> // #define tau A1 void setup() { // initialize serial communication at 9600 bits per second: Serial.begin(9600); pinMode(2,INPUT); //UP_K pinMode(3,INPUT); //DOWN_K pinMode(4,INPUT); //K_REG pinMode(5,INPUT); //On pinMode(6,INPUT); //MEM_K pinMode(8,OUTPUT); //UP pinMode(9,OUTPUT); //DOWN pinMode(10,OUTPUT); //HC_ON pinMode(15,OUTPUT); //step digitalWrite(2,HIGH); digitalWrite(3,HIGH); digitalWrite(4,HIGH); digitalWrite(5,HIGH); digitalWrite(6,HIGH); digitalWrite(8,LOW); digitalWrite(9,LOW); digitalWrite(A1,LOW); // ct = micros(); // lt = ct; DEV_TIMER1.setClockSelect(TimerW::Prescaler_8); DEV_TIMER1.setWaveGenMode(TimerW::FastPWM_OCRA); DEV_TICTRL1.outCompIntEnableA(); DEV_TIMER1.setOutputCompareA(10); interrupts(); } // DEV_TIMER1 Output Compare A interrupt handler void loop() { // алгоритм генерации сигнала step //ct = micros(); //if (ct <= lt + 50) { // digitalWrite(A1,HIGH); //} //else { // digitalWrite(A1,LOW); //} //if (ct >= lt + 250) { // lt = ct; //} // конец алгоритма генерации step digitalWrite(10,LOW); kreg = digitalRead(4); if (kreg == LOW) { // read the input on analog pin 0: sensorValue = analogRead(A0); // Convert the analog reading voltage = sensorValue * (5.0 / 1023.0) * 240.0 / 4.0 ; // voltage = voltage * 240.0 / 4.0 ; // print out the value you read: Serial.println(voltage); int upk = digitalRead(2); if (upk == LOW) { digitalWrite(8,HIGH); digitalWrite(9,LOW); } int downk = digitalRead(3); if (downk == LOW) { digitalWrite(8,LOW); digitalWrite(9,HIGH); } if (downk == HIGH) { if (upk == HIGH) { digitalWrite(8,LOW); digitalWrite(9,LOW); } } int memk = digitalRead(6); if (memk == LOW) { if (dk == 0) { EEPROM.write(1,voltage); Serial.println("voltage memory:"); voltage = EEPROM.read(1); Serial.println(voltage); Serial.println("........................."); // float uf = voltage; dk=1; } } else { dk = 0; } } else { // ветка автоматического режима int thc = digitalRead(5); if (thc == LOW) { digitalWrite(10,HIGH); int uf = EEPROM.read(1); sensorValue = analogRead(A0); voltage = sensorValue * (5.0 / 1023.0) * 240.0 / 4.0 ; // voltage = voltage * 240.0 / 4.0 ; // print out the value you read: Serial.println(voltage); if (voltage <= uf - k) { digitalWrite(8,HIGH); digitalWrite(9,LOW); } if (voltage >= uf + k) { digitalWrite(8,LOW); digitalWrite(9,HIGH); } if (voltage > uf - k) { if (voltage < uf + k) { digitalWrite(8,LOW); digitalWrite(9,LOW); } } } else { digitalWrite(8,LOW); digitalWrite(9,LOW); digitalWrite(10,LOW); } } } ISR(TIMER1_COMPA_vect) { // DEV_TIMER1.setOutputCompareA(potValue); // This sets next interrupt timeout. // tau = ! tau; // if (lt == 0) { digitalWrite(A1,HIGH); } else { digitalWrite(A1,LOW); } lt ++; if ( lt >= 5) { lt = 0; } }
Не стоит вызывать функцию digitalWrite() из функции-обработчика прерывания ISR(TIMER1_COMPA_vect).
Дело в том, что компилятор avr-gcc использует соглашение о вызовах "вызывающий сохраняет регистры". Регистров в микроконтроллерах AVR8 - 32. При вызове функции из обработчика прерывания компилятор должен сохранить все регистры. То есть добавить в тело функции 32 команды PUSH и 32 команды POP.
Вариантов для того, чтобы установить значение на выводе микроконтроллера из функции-обработчика прерывания (для вывода A1 в данном случае), суть два:
1) Написать нечто не слишком читаемое
2) Использовать преимущества библиотеки VEduino (ve_avr.h)
Преимущество состоит в том, что код становится более читабельным, при том, что он будет скомпилирован в те же самые три команды ассемблера, что и в первом случае.