BOOM
26.Октябрь.2024 12:18:16
1
Среда разработки: Atmel Studio 7
Симуляция в протеус 8. Ошибка звучит так:
PC=0x00F0. [AVR AD CONVERTER] Result is not written to the ADC register because it has been locked. [U1]
PC=0x00F2. [AVR AD CONVERTER] Result is not written to the ADC register because it has been locked. [U1]
PC=0x00F6. [AVR AD CONVERTER] Result is not written to the ADC register because it has been locked. [U1]
PC=0x00F0. [AVR AD CONVERTER] Result is not written to the ADC register because it has been locked. [U1]
PC=0x00F4. [AVR AD CONVERTER] Result is not written to the ADC register because it has been locked. [U1]
Минимальная схема и код повторяющий ошибку:
Код:
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile uint16_t analogData;
ISR (ADC_vect) {
analogData = (ADCH<<8) + ADCL;
}
int main(void) {
DDRB &= ~(1<<PORTB4); // PB4 на вход
// Настраиваем работу с ADC (АЦП)
ADMUX |= (1<<REFS0) | (1<<ADLAR) | (1<<MUX1); // опорное напряжение - Internal, левое ориентирование данных, выбран вход ADC2 (на него подается измеряемое напряжение)
ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIE) | (1<<ADPS2); // АЦП включен, запуск преобразования, режим автоизмерения, прерывание по окончанию преобразования, частота CLK/4
ADCSRB = 0x00; // режим автоизмерения: постоянно запущено
DIDR0 |= (1<<ADC2D); // запрещаем цифровой вход на ноге аналогового входа
sei(); //разрешаем глобально прерывания
while (1) {
}
}
Что я забыл или сделал не так?
ЗЫ: Даташит
А если код в самом протеусе набить ? Или там только asm под 13 …
BOOM
26.Октябрь.2024 12:41:40
3
Не знаю, никогда так не делал. Сейчас попробую посмотреть…
BOOM:
Что я забыл
ADCL must be read first, then ADCH
P.S. А можно просто
analogData = ADC;
BOOM
26.Октябрь.2024 13:00:50
6
Дим-мычъ:
ADCL must be read first
Спасибо, исправил. Но результат тот же.
#define F_CPU 1200000UL
//#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include <avr/sleep.h>
volatile uint16_t analogData;
ISR (ADC_vect) {
analogData = ADCL + (ADCH<<8);
}
int main(void) {
DDRB &= ~(1<<PORTB4); // PB4 на вход
// Настраиваем работу с ADC (АЦП)
ADMUX |= (1<<REFS0) | (1<<ADLAR) | (1<<MUX1); // опорное напряжение - Internal, левое ориентирование данных, выбран вход ADC2 (на него подается измеряемое напряжение)
ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIE) | (1<<ADPS2); // АЦП включен, запуск преобразования, режим автоизмерения, прерывание по окончанию преобразования, частота CLK/4
ADCSRB = 0x00; // режим автоизмерения: постоянно запущено
DIDR0 |= (1<<ADC2D); // запрещаем цифровой вход на ноге аналогового входа
sei(); //разрешаем глобально прерывания
while (1) {
}
}
Установил компилятор WinAVR и закинул код в сам протеус. Результат не изменен:
PC=0x0096. [AVR AD CONVERTER] Result is not written to the ADC register because it has been locked. [U1]
ua6em
26.Октябрь.2024 13:03:16
7
строку 17 закомментируй, коль намёков не понимаешь
пин на вход это ADMUX
Компилятор сначала в скобках сделает
byte lowb, highb;
lowb = ADCL;
highb = ADCH;
BOOM
26.Октябрь.2024 13:17:10
9
Да не думаю, что в этом дело.
Сделал вот так:
ISR (ADC_vect) {
uint8_t lowb, highb;
lowb = ADCL;
highb = ADCH;
analogData = (lowb + (highb<<8));
}
Ошибка осталась.
Result is not written to the ADC register because it has been locked
Какого фига он заблокирован? Кем он заблокирован? Как узнать? Я не понимать… ))
ua6em
26.Октябрь.2024 13:20:30
10
//highb = ADCH;
analogData =(ADCH<<8) | (lowb);
BOOM:
Сделал вот так:
Не знаю, вариант рабочий. Попробуй просто analogData = ADC;
У меня оба варианта работают
BOOM
26.Октябрь.2024 13:26:03
12
Да пробовал я, ничего не меняется)))
Да и как изменится, ошибка же не в чтении из регистров, а в записи в них )))
ua6em
26.Октябрь.2024 13:26:22
13
не, читать надо сначал L потом H, подозреваю, что надо вытащить процедуру чтения из прерывания
Так 14 стр. закоментил, как ua6em сказал?
BOOM
26.Октябрь.2024 13:29:38
15
Дим-мычъ:
14 стр. закоментил
На кой х$р?
Какая-то “ромашка” началась. Давайте перестанем тыкать в небо пальцем, я так и сам могу (но не хочу).
ua6em
26.Октябрь.2024 13:31:52
16
BOOM:
я так и сам могу
мы увидели, объясни нахрена ты цифровой пин на вход включаешь, а потом пытаешься это героически преодолеть, ADC2 (PB4) включил в ADMUXе
Сам так никогда не делал, но подкинул сейчас на ATtiny24 в Протеусе - не блокирует. Что-то ещё.
Кстати, исходный вариант
analogData = (ADCH<<8) + ADCL;
Как раз блокирует
BOOM
26.Октябрь.2024 13:44:54
19
В общем какая-то “байда” творится с ADCL.
Если его вообще не читать, то все работает нормально (правда разрядность уже не 10 бит, а всего 8).
Вот так работает, но надо до 10 бит добить.
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile uint16_t analogData;
ISR (ADC_vect) {
// uint8_t lowb, highb;
// highb = ADCH;
// lowb = ADCL;
// analogData = (lowb + (highb<<8));
analogData = ADCH;
}
int main(void) {
DDRB &= ~(1<<PORTB4); // PB4 на вход
// Настраиваем работу с ADC (АЦП)
ADMUX |= (1<<REFS0) | (1<<ADLAR) | (1<<MUX1); // опорное напряжение - Internal, левое ориентирование данных, выбран вход ADC2 (на него подается измеряемое напряжение)
ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1); // АЦП включен, запуск преобразования, режим автоизмерения, прерывание по окончанию преобразования, частота CLK/16
ADCSRB = 0x00; // режим автоизмерения: постоянно запущено
DIDR0 |= (1<<ADC2D); // запрещаем цифровой вход на входе ADC2 (PB4)
sei(); //разрешаем глобально прерывания
while (1) {
}
return 0;
}
ua6em
26.Октябрь.2024 13:44:57
20
а его код в протеус закинь
Я же говорю, тот что #1 - блокирует.
А мои варианты не блокирует.
Извиняюсь, отвечал ua6em
BOOM
26.Октябрь.2024 13:50:55
22
Какой именно?
У меня все что выше предлагалось блокирует. Не блокирует только если ADCL не читать вообще.