Код инициализации:
Код
ADC_init();
// запускаем цикл измерений
FtransformFlush();
Channel_number = ParseBuf[0];
ADC_flush();
ADC_start();
// ожидаем завершения цикла измерений
ADC_wait();
// расчитываем модуль
//FtransformCalcModuls();
// подготавливаем пакет к отправки
unsigned char Data[8];
Data[0] = (unsigned char) Fsumm0;
Data[1] = (unsigned char) (Fsumm0 >> 8);
Data[2] = (unsigned char) (Fsumm0 >> 16);
Data[3] = (unsigned char) (Fsumm0 >> 24);
Data[4] = (unsigned char) Fsumm1;
Data[5] = (unsigned char) (Fsumm1 >> 8);
Data[6] = (unsigned char) (Fsumm1 >> 16);
Data[7] = (unsigned char) (Fsumm1 >> 24);
InsertPacket(0x02, Data, 8);
// запускаем цикл измерений
FtransformFlush();
Channel_number = ParseBuf[0];
ADC_flush();
ADC_start();
// ожидаем завершения цикла измерений
ADC_wait();
// расчитываем модуль
//FtransformCalcModuls();
// подготавливаем пакет к отправки
unsigned char Data[8];
Data[0] = (unsigned char) Fsumm0;
Data[1] = (unsigned char) (Fsumm0 >> 8);
Data[2] = (unsigned char) (Fsumm0 >> 16);
Data[3] = (unsigned char) (Fsumm0 >> 24);
Data[4] = (unsigned char) Fsumm1;
Data[5] = (unsigned char) (Fsumm1 >> 8);
Data[6] = (unsigned char) (Fsumm1 >> 16);
Data[7] = (unsigned char) (Fsumm1 >> 24);
InsertPacket(0x02, Data, 8);
В данном коде важно запомнить функцию ADC_wait(); Она выглядит так:
Код
void ADC_wait()
{
do {
} while(Flags != ADC_CONVERSION_COMPLETE);
}
{
do {
} while(Flags != ADC_CONVERSION_COMPLETE);
}
Данная функция ожидает завершения цикла измерений, здесь переменная Flags объявлена как volatile uint8_t Flags, ADC_CONVERSION_COMPLETE - константа равная 2, т.е. когда Flags будет равна 2 я выйду из бесконечного цикла и продолжу работу... Флаг устанавливается в прерывании, само прерывание:
Код
.global DMA_CH0_vect
DMA_CH0_vect:
cli
push r0; РЕГИСТР ПРОИЗВЕДЕНИЯ
push r1; РЕГИСТР ПРОИЗВЕДЕНИЯ
push r16; МНОЖИМОЕ
push r17; МНОЖИТЕЛЬ
push r4; СУММАТОР
push r5; СУММАТОР
push r6; СУММАТОР
push r18; РЕГИСТР ЗНАКА ПРОИЗВЕДЕНИЯ
push XL; УКАЗАТЕЛЬ СУММАТОРОВ
push XH; УКАЗАТЕЛЬ СУММАТОРОВ
push YL; УКАЗАТЕЛЬ СУММАТОРОВ
push YH; УКАЗАТЕЛЬ СУММАТОРОВ
push ZL; УКАЗАТЕЛЬ СТОЛБЦА ТАБЛИЦ
push ZH; УКАЗАТЕЛЬ ТАБЛИЦЫ
push r19
/// push - 1, summ == 14
[u][color="#FF0000"]lds r19, _SFR_IO_ADDR(PORTA_OUT)
sbr r19, 16
sts _SFR_IO_ADDR(PORTA_OUT), r19[/color][/u]
clr r18
// загружаем номер канала
lds ZH, Channel_number /// 1
inc ZH // инкрементируем так как таблицы начинаются с адресу 0х100 /// 1
inc ZH /// 1
// загружаем номер измерения
lds ZL, Point_number /// 1
/// 3
// загружаем Fsumm0
ldi XH, hi8(Fsumm0) /// 1
ldi XL, lo8(Fsumm0) /// 1
// загружаем Fsumm0
ldi YH, hi8(Fsumm0) /// 1
ldi YL, lo8(Fsumm0) /// 1
// загружаем коэффициент
lpm r17, Z /// 2
// загружаем точку
lds r16, Values /// 1
muls r16, r17 /// 2
// определение знака произведения
sbrc r1, 7 /// 2
// расширение знака на старший байт
ser r18 /// 1
// загрузка накопителя Fsumm0
ld r4, X+ /// 2
ld r5, X+ /// 2
ld r6, X /// 2
// накопление Fsumm0
add r4, r0 /// 1
adc r5, r1 /// 1
adc r6, r18 /// 1
// созранение Fsumm0
st Y+, r4 /// 2
st Y+, r5 /// 2
st Y, r6 /// 2
/// 27
clr r18
// загружаем номер канала
lds ZH, Channel_number /// 1
ldi XL, 3
add ZH, XL
/// 2
// загружаем Fsumm1
ldi XH, hi8(Fsumm1) /// 1
ldi XL, lo8(Fsumm1) /// 1
// загружаем Fsumm1
ldi YH, hi8(Fsumm1) /// 1
ldi YL, lo8(Fsumm1) /// 1
// загружаем коэффициент
lpm r17, Z /// 2
muls r16, r17 /// 2
// определение знака произведения
sbrc r1, 7 /// 2
// расширение знака на старший байт
ser r18 /// 1
// загрузка накопителя Fsumm1
ld r4, X+ /// 2
ld r5, X+ /// 2
ld r6, X /// 2
// накопление Fsumm1
add r4, r0 /// 1
adc r5, r1 /// 1
adc r6, r18 /// 1
// созранение Fsumm1
st Y+, r4 /// 2
st Y+, r5 /// 2
st Y, r6 /// 2
/// 26
// инкрементируем номер точки и сохраняем
inc ZL /// 1
sts Point_number, ZL /// 1
/// 2
// если последнее измерение
cpi ZL, 255 /// 1
brne DMA_CH0_vect_end /// 2
// stop ADC
ldi r18, 0
sts _SFR_IO_ADDR(ADCA_CTRLA), r18
// reload to Point_number default value (0)
sts Point_number, r18
// set ADC_CONVERSION_COMPLETE flag
ldi r18, 2
sts Flags, r18
///
DMA_CH0_vect_end:
/// 3
// DMA.CH0.CTRLB |= 48; // clear interrupt flags
lds r19, _SFR_IO_ADDR(DMA_CH0_CTRLB) /// 1
sbr r19, 0x30 /// 1
sts _SFR_IO_ADDR(DMA_CH0_CTRLB), r19 /// 1
/// 3
[u][color="#FF0000"]lds r19, _SFR_IO_ADDR(PORTA_OUT)
cbr r19, 16
sts _SFR_IO_ADDR(PORTA_OUT), r19[/color][/u]
pop r19
pop ZH
pop ZL
pop YH
pop YL
pop XH
pop XL
pop r18
pop r6
pop r5
pop r4
pop r17
pop r16
pop r1
pop r0
/// pop - 2, summ == 28
sei
reti /// 5
DMA_CH0_vect:
cli
push r0; РЕГИСТР ПРОИЗВЕДЕНИЯ
push r1; РЕГИСТР ПРОИЗВЕДЕНИЯ
push r16; МНОЖИМОЕ
push r17; МНОЖИТЕЛЬ
push r4; СУММАТОР
push r5; СУММАТОР
push r6; СУММАТОР
push r18; РЕГИСТР ЗНАКА ПРОИЗВЕДЕНИЯ
push XL; УКАЗАТЕЛЬ СУММАТОРОВ
push XH; УКАЗАТЕЛЬ СУММАТОРОВ
push YL; УКАЗАТЕЛЬ СУММАТОРОВ
push YH; УКАЗАТЕЛЬ СУММАТОРОВ
push ZL; УКАЗАТЕЛЬ СТОЛБЦА ТАБЛИЦ
push ZH; УКАЗАТЕЛЬ ТАБЛИЦЫ
push r19
/// push - 1, summ == 14
[u][color="#FF0000"]lds r19, _SFR_IO_ADDR(PORTA_OUT)
sbr r19, 16
sts _SFR_IO_ADDR(PORTA_OUT), r19[/color][/u]
clr r18
// загружаем номер канала
lds ZH, Channel_number /// 1
inc ZH // инкрементируем так как таблицы начинаются с адресу 0х100 /// 1
inc ZH /// 1
// загружаем номер измерения
lds ZL, Point_number /// 1
/// 3
// загружаем Fsumm0
ldi XH, hi8(Fsumm0) /// 1
ldi XL, lo8(Fsumm0) /// 1
// загружаем Fsumm0
ldi YH, hi8(Fsumm0) /// 1
ldi YL, lo8(Fsumm0) /// 1
// загружаем коэффициент
lpm r17, Z /// 2
// загружаем точку
lds r16, Values /// 1
muls r16, r17 /// 2
// определение знака произведения
sbrc r1, 7 /// 2
// расширение знака на старший байт
ser r18 /// 1
// загрузка накопителя Fsumm0
ld r4, X+ /// 2
ld r5, X+ /// 2
ld r6, X /// 2
// накопление Fsumm0
add r4, r0 /// 1
adc r5, r1 /// 1
adc r6, r18 /// 1
// созранение Fsumm0
st Y+, r4 /// 2
st Y+, r5 /// 2
st Y, r6 /// 2
/// 27
clr r18
// загружаем номер канала
lds ZH, Channel_number /// 1
ldi XL, 3
add ZH, XL
/// 2
// загружаем Fsumm1
ldi XH, hi8(Fsumm1) /// 1
ldi XL, lo8(Fsumm1) /// 1
// загружаем Fsumm1
ldi YH, hi8(Fsumm1) /// 1
ldi YL, lo8(Fsumm1) /// 1
// загружаем коэффициент
lpm r17, Z /// 2
muls r16, r17 /// 2
// определение знака произведения
sbrc r1, 7 /// 2
// расширение знака на старший байт
ser r18 /// 1
// загрузка накопителя Fsumm1
ld r4, X+ /// 2
ld r5, X+ /// 2
ld r6, X /// 2
// накопление Fsumm1
add r4, r0 /// 1
adc r5, r1 /// 1
adc r6, r18 /// 1
// созранение Fsumm1
st Y+, r4 /// 2
st Y+, r5 /// 2
st Y, r6 /// 2
/// 26
// инкрементируем номер точки и сохраняем
inc ZL /// 1
sts Point_number, ZL /// 1
/// 2
// если последнее измерение
cpi ZL, 255 /// 1
brne DMA_CH0_vect_end /// 2
// stop ADC
ldi r18, 0
sts _SFR_IO_ADDR(ADCA_CTRLA), r18
// reload to Point_number default value (0)
sts Point_number, r18
// set ADC_CONVERSION_COMPLETE flag
ldi r18, 2
sts Flags, r18
///
DMA_CH0_vect_end:
/// 3
// DMA.CH0.CTRLB |= 48; // clear interrupt flags
lds r19, _SFR_IO_ADDR(DMA_CH0_CTRLB) /// 1
sbr r19, 0x30 /// 1
sts _SFR_IO_ADDR(DMA_CH0_CTRLB), r19 /// 1
/// 3
[u][color="#FF0000"]lds r19, _SFR_IO_ADDR(PORTA_OUT)
cbr r19, 16
sts _SFR_IO_ADDR(PORTA_OUT), r19[/color][/u]
pop r19
pop ZH
pop ZL
pop YH
pop YL
pop XH
pop XL
pop r18
pop r6
pop r5
pop r4
pop r17
pop r16
pop r1
pop r0
/// pop - 2, summ == 28
sei
reti /// 5
В коде прерывания, приведенном выше, важны строчки, которые я выделил красным цветом и подчеркнул. Эти строчки просто дёргают пином, нужно чтоб на осциле посмотреть сколько времени занимает одно измерение и вычисление...
Проблема возникает именно когда пытаюсь дергать ногами. Если убрать строки где дёргаю ногами, то работает так как и задумывалось: цикл преобразования завершается, передаем то что насчитали на комп для дальнейшей обработки. Когда же есть данные строчки (дёрганье ногами), происходит следующее: делается 3 измерения (в прерывание попадаю 3 раза, у меня надо сделать 256 измерений) после вдуг, непонятно из за чего, попадаю на конец функции ADC_wait() и после начинаю пытаться передать на комп невернeю инфу...
Дебажил я JtagICE'ом в момент когда я нахожусь в конwе функции ADC_wait() переменная Flag равна 1 и я должен находиться в бесконечном цикле, но выхожу из него... Из за чего это происходит?
Сточки, в которых дергаю ногой, выделить красным цветом и подчеркнуть не вышло) Это строчки в коде прерывания которые расположены сразу после push'ов и до pop'ов)
Есть у меня одна идея: может компилятор выделяет определённое количество памяти под стек и происходит его переполнение? Если это так, то может ктонить подскажет где можно посмотреть размер стека и поменять его в AVR Studio 6, а то я чет не чего такого не нашёл в свойствах проекта?
Не идея точно не подходит) Ведь количество вызовов одно и тоже!
В общем проблему решил простым перемещением кусков кода, а именно в коде прерывания поменял местами код где сбрасываю флаг DMA и код где выставляю пин в 0, т.е. зделал так:
Код
...
...
...
lds r19, _SFR_IO_ADDR(PORTA_OUT)
cbr r19, 16
sts _SFR_IO_ADDR(PORTA_OUT), r19
// DMA.CH0.CTRLB |= 48; // clear interrupt flags
lds r19, _SFR_IO_ADDR(DMA_CH0_CTRLB) /// 1
sbr r19, 0x30 /// 1
sts _SFR_IO_ADDR(DMA_CH0_CTRLB), r19 /// 1
/// 3
pop r19
pop ZH
pop ZL
pop YH
pop YL
pop XH
pop XL
pop r18
pop r6
pop r5
pop r4
pop r17
pop r16
pop r1
pop r0
/// pop - 2, summ == 28
sei
reti /// 5
...
...
lds r19, _SFR_IO_ADDR(PORTA_OUT)
cbr r19, 16
sts _SFR_IO_ADDR(PORTA_OUT), r19
// DMA.CH0.CTRLB |= 48; // clear interrupt flags
lds r19, _SFR_IO_ADDR(DMA_CH0_CTRLB) /// 1
sbr r19, 0x30 /// 1
sts _SFR_IO_ADDR(DMA_CH0_CTRLB), r19 /// 1
/// 3
pop r19
pop ZH
pop ZL
pop YH
pop YL
pop XH
pop XL
pop r18
pop r6
pop r5
pop r4
pop r17
pop r16
pop r1
pop r0
/// pop - 2, summ == 28
sei
reti /// 5
Но причины я так и не понял!!!!!!!!!! Люди может ктонить встречался/знает причину? Откройте тайну!)