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)
Преимущество состоит в том, что код становится более читабельным, при том, что он будет скомпилирован в те же самые три команды ассемблера, что и в первом случае.