реклама на сайте
подробности

 
 
> АЦП и прерывания ATmega48, помогите начинающему...
NikitoS-86
сообщение Sep 22 2008, 10:29
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380



Добрый день. Я занялся изучением AVR, использую AVRStudio в связке с WinAVR.
И у меня появились затруднения определённого плана. Я имею представление о том, что есть прерывание, что есть стек, указатель команд и вообще имею хорошее знание касательно теории... Но дошло дело до практики... И попытался я написать простейший код... Итак ситуация: в качестве входа АЦП использоваться ADC7, надо будет на 3 выхода (PB0..2) выдавать адрес на мультиплексер, который будет переключать свои входы, на входв АДС7 будет как раз приходить сигнал с демультеплексора, АЦП должен оцифровать и записать эти данные в массив...
Вот примерный код:

Цитата
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

void port_B_settings (void);
void ADC_settings (void);
void port_C_settings (void);


int help_reg=0;

ISR (ADC_vect)
{
help_reg = 1;
}

void main (void)
{
int Ubat[4];
int Tbat[4];
int Icur;

port_B_settings();
ADC_settings();


for (int i=0;i<3;i++)
{
ADCSRA = 0xC8;
sei();

while (!help_reg)
{}

Ubat[i] = help_reg;
}
}

void port_B_settings (void)
{
DDRB = 0x07; //PB0..1 - outputs
}

void ADC_settings (void)
{
ADMUX = 0x07; //ADC7
ADCSRA = 0x88; //ADEN=1 | ADIE = 1
}



В нём правда ещё не выдаётся адрес никуда и т.д. Не суть... А суть в том, что у меня по-левому работает прерывание.
Я хочу, чтобы после начала прерывания шло ожидание прерывания, после чего его обработка и после чего запись..., а у меня выходит всякая ересь и в симуляторе вконце концов вообще после первого "прохода" получается бесконечный цикл....=/
Что я делаю неправильно?
Вопрос касательно языка С - можно ли обрабатывать прерывание не по этому макросу, а что называется ручками... Просто я не знаю как мне в такой обработчик прерывания отправить например указатель на мой массив, чтобы прям в обработчике осуществлять запись в массив, а не вводить для этого пресловутый help_reg=/

И ещё вопрос: я перед запуском АЦП настраиваю только его вход в ADMUX, а надо ли настраивать ещё первые байты, которые отвечают за настройку напряжения если не ошибаюсь... Вообще если можно, то посвятите немного о том, как настраивать и запускать АЦП, поскольку из даташита к сожалению не всё понял на английском, например мне не понятно немного что такое некий "непрерывный режим работы" АЦП, который настраивается через запись бита ADATA в регистре ADCSRA...

Ах да, последнее: речь идёт о ATmega48

Заранее огромное спасибо ответившим, просто уже 2 дня мучаюсь с этим АЦП=/

Сообщение отредактировал NikitoS-86 - Sep 22 2008, 10:31
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
NikitoS-86
сообщение Sep 22 2008, 12:43
Сообщение #2


Участник
*

Группа: Новичок
Сообщений: 28
Регистрация: 22-09-08
Пользователь №: 40 380



1) К сожалению выбрать другую микруху - уже нельзя, схему делал не я, и у меня на руках уже готовая схема, плата будет в скором времени изготовлена - уже не пойдёт=/
2) Да, согласен, в этом месте я ступил....
3) Как можно всётаки обойтись без макросов на С? МОжно ли сделать так, чтобы вызов прерывания был похож на вызов функции? Потому что даже если я сделаю массивы гнлобальными, то мне как-то надо ведь им сообщать какое по счёту это прерывание? Можно конечно завести ещё вдобавок глобальную переменную-счётчки... Но я если честно вообще не очень жалую глобальные переменные именно потому, что доступ к ним - откуда хочешь...
Если не сложно можно получить пример простейший как вообще выполнять обработчик что называется по-простому....
4) Переделал немножко код, и теперь он выглядит вот так вот... и вроде даже что-то делает:

Цитата
int help_reg;

SIGNAL (SIG_ADC)
{
help_reg = 1;
}

void main (void)
{
int Ubat[4];
int Tbat[4];
int Icur;

cli();

port_B_settings();
ADC_settings();


for (int i=0;i<3;i++)
{
ADCSRA = 0xC8;
sei();

for (;;)
{
if (ADCSRA == 0x98)
break;
}

Ubat[i] = help_reg;
help_reg=0;
}
}

void port_B_settings (void)
{
DDRB = 0x07; //PB0..1 - outputs
}

void ADC_settings (void)
{
ADMUX = 0x07; //ADC7
ADCSRA = 0x88; //ADEN=1 | ADIE = 1
}


У меня только возник ещё вопросы: поскольку мы пишем на С, а не на ассемблере, то при прогоне программы дебагер проскакивает те месте, где я работаю со своими переменными! Совершенно очевидно, что когда я пишу intX = ...; на ассемблере это может занять больше строчек... Но всётаки можно как-нибудь заставить его показывать что вообще происходит с моими переменными? Как мне например после прохода программы определить что он поместил в мой массив? как это увидеть?

И ещё один вопрос: как средствами языка мне получить доступ к отдельным битам регистров? Как видно в исправленном варианте я просто ставлю условие того, что изменится значение всего регистра! А как мне проверить изменение только одного бита в этом регистре?

Всем большое спасибо!

Пока писал ответ Вы добавили код=) Но тем лучше... МОжно только поподробнее по поводу синтаксиса прерывания...
#pragma..........
как работает?

И ещё одно... В примере в самом начале есть строчка:
#define KADMUX (1<<ADLAR) // работа от внешнего опорного источника с выравниванием "влево"

Разве ADLAR имеет какое-то отношение к тому, какой источник используется? Помоему он отвечает только за то, в каком виде представлять результат=/ Или это как раз из-за того, что вырвано из контекста?
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 22 2008, 15:48
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(NikitoS-86 @ Sep 22 2008, 15:43) *
3) Как можно всётаки обойтись без макросов на С? МОжно ли сделать так, чтобы вызов прерывания был похож на вызов функции? Потому что даже если я сделаю массивы гнлобальными, то мне как-то надо ведь им сообщать какое по счёту это прерывание? Можно конечно завести ещё вдобавок глобальную переменную-счётчки... Но я если честно вообще не очень жалую глобальные переменные именно потому, что доступ к ним - откуда хочешь...
Если не сложно можно получить пример простейший как вообще выполнять обработчик что называется по-простому....

1) А... Вот вы о чём. smile.gif
То есть вы вообще хотите обойтись без прерываний, на сколько я понял.
Да - можно. И, по-моему это понятно из моего текста.
У меня ведь прерывание по таймеру, а я там читаю АЦП. А вы можете вызывать чтение АЦП непосредственно в main. Либо прямо в теле, либо с помощью п/п.
В этом случае в п/п вам надо проверить флаг готовности АЦП и ждать его выставления и прочитать значение. Опять таки (см. выше) первое, после переключ. канала отбросить как не верное.
2) Доступ к глобальным переменным можно ограничить тем же static. В этом случае обращение к ним будет возможно только из данного файла. Посмотрите также мой текст внимательно. Так номер канала у меня размещён в озу (не портится от вызова к вызову) и в тоже время обращение к этой переменной возможно только из прерывания. Всё это, я предвидя ваши вопросы уже писал - почитайте внимательно.
Цитата
4) Переделал немножко код, и теперь он выглядит вот так вот... и вроде даже что-то делает:
У меня только возник ещё вопросы: поскольку мы пишем на С, а не на ассемблере, то при прогоне программы дебагер проскакивает те месте, где я работаю со своими переменными! Совершенно очевидно, что когда я пишу intX = ...; на ассемблере это может занять больше строчек... Но всётаки можно как-нибудь заставить его показывать что вообще происходит с моими переменными? Как мне например после прохода программы определить что он поместил в мой массив? как это увидеть?

1) Вы можете расскрыть этот оператор при необходимости. Для этого в AVR Studio есть View/Disasmebler. И ... идите по асмовому тексту
2) Для просмотра содержимого переменных (в том числе массивов, структур и даже указателей) есть View/Watch. Кстати если на переменной щёлкнуть правой кн. мыши, то сразу можно добавить в окно отладки. И ... пожалуйста - смотри - меняй. В любом виде.
Цитата
Пока писал ответ Вы добавили код=) Но тем лучше... МОжно только поподробнее по поводу синтаксиса прерывания...
#pragma..........
как работает?

Я работаю под IAR. Там это фактически указание компилятору по какому вектору расположить данное прерывание ну и тому подобное (например закончить RETI вместо RET)
Цитата
И ещё одно... В примере в самом начале есть строчка:
#define KADMUX (1<<ADLAR) // работа от внешнего опорного источника с выравниванием "влево"

Разве ADLAR имеет какое-то отношение к тому, какой источник используется? Помоему он отвечает только за то, в каком виде представлять результат=/ Или это как раз из-за того, что вырвано из контекста?

Просто в данном регистре также кодируется источник ОН. Если соотв. бит=0 (как у меня) так - внутр. опора. Я это написал в коментариях, чтобы видеть. Возможно правильнее было бы написать
#define KADMUX (1<<ADLAR) |(0<<REFS0)|(0<<REFS1) // работа от внешнего опорного источника с

Всё в ваших руках. Я коментирую для себя. Сам пишу - сам читаю. smile.gif Поэтому местами упрощаю.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- NikitoS-86   АЦП и прерывания ATmega48, помогите начинающему...   Sep 22 2008, 10:29
- - gormih   Для инииализации АЦП небходимо обязательно инициал...   Sep 22 2008, 11:41
- - NikitoS-86   1) Так я помоему как раз в функции ADC_settings ()...   Sep 22 2008, 11:45
- - SasaVitebsk   Давайте по-порядку. 1) Для начала очень даже непло...   Sep 22 2008, 12:18
||- - Цыкетчик   Надо не забыть ещё сделать задержку примерно на 1м...   Sep 23 2008, 10:50
|- - Сергей Борщ   Цитата(NikitoS-86 @ Sep 22 2008, 15...   Sep 23 2008, 18:23
- - Aleksandr Baranov   Для манипуляции битами регистров в библиотеке avr-...   Sep 22 2008, 12:58
|- - NikitoS-86   Цитата(Aleksandr Baranov @ Sep 22 2008, 16...   Sep 22 2008, 13:13
|- - Aleksandr Baranov   Цитата(NikitoS-86 @ Sep 22 2008, 09...   Sep 22 2008, 13:43
- - NikitoS-86   Итак, во-первых, ОГРОМНОЕ спасибо всем откликнувши...   Sep 23 2008, 12:25
- - MrYuran   Цитатаmeasure_Ubat (&Ubat , &channel_numbe...   Sep 23 2008, 12:35
- - NikitoS-86   Да, так и есть по идее, и сначала я пользовал имен...   Sep 23 2008, 13:25
|- - MrYuran   Цитата(NikitoS-86 @ Sep 23 2008, 17...   Sep 23 2008, 13:46
- - SasaVitebsk   Высскажу несколько соображений общего характера. В...   Sep 23 2008, 16:09
- - NikitoS-86   Цитата(SasaVitebsk @ Sep 23 2008, 20:09) ...   Sep 23 2008, 19:25


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th July 2025 - 23:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01372 секунд с 7
ELECTRONIX ©2004-2016