Обращаюсь к Вам с просьбой помощи, ибо сам я уже бьюсь над проблемой неделю и вывихнул себе весь мозг.
Итак, суть. Имеется отладочная плата STK600 + к ней микроконтроллер 2560.
Пишется элементарная программа (пробовал ее писать в AVR-studio 5.1, 6.0; CVavr; IAR; ImageCraft) везде работает практически одинаково, но везде не так, как мне хочется. Причем в Proteus моделируется точно так же, как на железе (поэтому грешу все-таки на свои кривые руки, а не на кристалл).
Суть программы: периодически запускается таймер. В обработке прерывания таймера запускается АЦП. По прерыванию АЦП запускается его обработчик, в котором реализуется следующий алгоритм: если переменная меньше определенного числа, то инкремент переменной. Если условие не выполняется, то в порт A (подключен шлейфом к светодиодам отладочной платы) отправляется значение 0xF0 (половина светодиодов платы должна зажечься). Итак, сама программа в упрощенном варианте(для AVR студио 5.1):
// Standard Input/Output functions
#include <stdio.h>
#include <avr\interrupt.h>
#define porog 0
#define ADC_VREF_TYPE 0x00
#define ER_F 0 // результат готов к обработке
#define UO_F 1 // передано по UART
// Declare your global variables here
unsigned int array_of_freq[1000]={0xAA};
volatile signed int adc_data;
volatile unsigned int period, freq=0, diff=0;
volatile signed int diskr=0, counter=0;
signed int preview_result=0;
// Timer 0 output compare A interrupt service routine
ISR(TIMER0_COMPA_vect)
{
asm("wdr");
ADCSRA |= (1<<ADSC);
}
// ADC interrupt service routine
ISR(ADC_vect)
{
// Read the AD conversion result
adc_data=ADCW;
adc_data -=512;
#if porog
if ((adc_data <= porog)&&(adc_data >= (-(porog)))) adc_data = 0;
#endif
GPIOR0 |= (1<<ER_F);
if (diskr<7813) diskr++;
else PORTA = ~0xf0;
}
int main(void)
{
// Инициализация (Вырезана, чтобы не мозолить глаза. см полную версию)
while (1)
{
}
}
Комментарии и куски неиспользуемого кода специально оставил как есть.
Маленькие пояснения. светодиоды по прошествии цикла инкремента переменной diskr не зажигаются. есть подозрения, что цикл инкремента выполняется всего 2 раза (вывод сделан на основании того факта, что если в начале переменной diskr присвоить значение 7812 (т.е. на 1 меньше критического), то светодиоды загораются). Изначально при просмотре дизассемблированного кода программы было обнаружено, что не был сгенерирован код сброса сторожевого таймера. Была введена команда отключения стор. таймера. Это не помогло. Повсеместная вставка команды сброса сторожевого таймера тоже не помогает. Отключение оптимизации и перебор разлиных настроек оптимизации также не помогает. Самое интересное, если вынести код инкремента переменной в основной цикл main, то все прекрасно работает. Опять повторюсь, смутило то, что Proteus полностью повторяет действия контроллера.
Помогите решить загадку! Я даже не прочь, если меня потыкают мордой в моё собственное дерьмо, только покажите, где ошибка?
Полный код программы (для вставки в студию и разбора):
- Вложения
-
- ADC.cpp
- (10.33 КБ) 406 скачиваний


