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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> АЦП и прерывания 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
gormih
сообщение Sep 22 2008, 11:41
Сообщение #2


nofb
***

Группа: Свой
Сообщений: 430
Регистрация: 18-05-06
Из: Москва, Зеленоград
Пользователь №: 17 218



Для инииализации АЦП небходимо обязательно инициализировать значения управляющих регистров adcsr и admux.

Компилятор языка си автоматически инициализирует прерывание, однако следует позаботится о том, чтобы время выполнение одного цикла прерывания не перекрывало время до возникновения следующего прерывания. Для этого опптимально было бы написать прерывание на ассемблере :-)


--------------------
Это не то что вы подумали ...

Go to the top of the page
 
+Quote Post
NikitoS-86
сообщение Sep 22 2008, 11:45
Сообщение #3


Участник
*

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



1) Так я помоему как раз в функции ADC_settings (); и инициализирую регистры...
2) Так ведь я как раз собираюсь сделать так, чтобы шло ожидание прерывания и после чего была обработка прерывания.... Кроме того, при входе в прерывание в SREG автоматом сбросится бит глобальных прерываний и ничего больше не вызовется до момента окончания прерывания....

вопрос пока остаётся=//

Сообщение отредактировал NikitoS-86 - Sep 22 2008, 11:47
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 22 2008, 12:18
Сообщение #4


Гуру
******

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



Давайте по-порядку.
1) Для начала очень даже неплохо. smile.gif
2) Использовать 1 вход АЦП и 3 выхода для демультиплексирования. Может сразу использовать 8 входов? Если ног не хватает микруху взять другую?
3) При вашей инициализации АЦП выдаст прерывание 1 раз. У вас установлен запуск прерывания. Для того чтобы АЦП опять замерило сигнал, надо опять сделать старт измерения (в прерывании после чтения предыдущего значения). ADATE указывает что надо непрерывно измерять сигнал. То есть не требуется перезапуска. Период измерения задаётся в других регистрах. Здесь надо учесть, что у вас не связаны измерение сигнала и смена канала. Следовательно в этом режиме вам придётся отбрасывать одно показание с момента переключения канала.
4) Вы можете перевести АЦП в "автоматический" режим (ADATE). Применить прерывание по таймеру. Настроить таймер так, чтобы Ттаймера > 3*Tацп. Прерывание от АЦП не обрабатывать, а значение читать в прерывании от таймера (после этого сменять канал).
5) Естественно целесообразно прямо из прерывания заполнять массив. Не требуется никаких макросов. Такой как вы указали я не знаю. Для этого Вам надо объявить массив глобальным. Тоесть он должен быть объявлен там где вы объявили help_reg. В этом случае, он будет виден и в прерывании ив голове.
Если вы хотите чтобы переменная была видна только в прерывании и в тоже время сохраняла своё значение м/у входами в прерывание (например текущий номер канала), то необходимо объявить её в прерывании с квалификатором static.



Вот мелкий пример. Правда компилятор другой, ну и вырвано из контекста по-живому, но в общем то представление сложить удастся.
Код
...
// Из main.h
#define KADMUX            (1<<ADLAR)                // работа от внешнего опорного источника с выравниванием "влево"
//#define KADMUX            0                        // работа от внешнего опорного источника 10 бит
#define KADCSRA            ((1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2))// ADC разрешено, стартовать преобразование, на частоте Fclk/128
//#define KADCSRB            ((1<<ADHSM)                // скоростной режим ADC разрешен
#define KADCSRB            0                        // скоростной режим ADC запрещён
#define VIRTCHAN        0x3                        // "Виртуальный" аварийный канал
...
// Инициализация
// Инициализация АЦП
  ADMUX = KADMUX;                                        // работа от внешнего опорного источника с выравниванием "влево"
  ADCSRA = KADCSRA;                                        // разрешить режим "одиночный" с частотой 125кГц
  ADCSRB = KADCSRB;                                        // запретить режим "high speed"
  DIDR0 = 0xf;                                            // закрыть 4 первых бита канала АЦП
...
// Прерывание
#pragma    vector=TIMER1_COMPA_vect
__interrupt    static void    pvPWWLvl1(void)
{
uint8_t    static    TekChan,InADCChan=1;                // Текущий канал, текущий измеряемый канал АЦП
uint8_t    static    ChngChan;                            // Смена канала АЦП
uint8_t    i;
...
ChngChan++;                                            // увеличить счётчик прерываний
if(ChngChan==5)                                        // На пятый цикл сменить канал и прочитать АЦП
{
   ChngChan=0;                                            // начать сначала
   InpAdc[InADCChan]=(InpAdc[InADCChan]+ADCH)>>1;        // Считать канал и усреднить
   InADCChan++;                                            // Сменить канал
   if(InADCChan==CAN_T_CHAN)
   {
     InADCChan=1;                                        // Переход по кольцу
     InpAdc[MAXADC-1]=InpAdc[VIRTCHAN];                    // Переприсвоить виртуальный канал
   }
   ADMUX=KADMUX | InADCChan;                            // Выбрать канал
   ADCSRA =KADCSRA;                                        // Начать отсчёт заново
}
}
...
Go to the top of the page
 
+Quote Post
NikitoS-86
сообщение Sep 22 2008, 12:43
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 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
Aleksandr Barano...
сообщение Sep 22 2008, 12:58
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118



Для манипуляции битами регистров в библиотеке avr-libc WinAVR есть модуль <avr/sfr_defs.h>.


--------------------
ASB
Go to the top of the page
 
+Quote Post
NikitoS-86
сообщение Sep 22 2008, 13:13
Сообщение #7


Участник
*

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



Цитата(Aleksandr Baranov @ Sep 22 2008, 16:58) *
Для манипуляции битами регистров в библиотеке avr-libc WinAVR есть модуль <avr/sfr_defs.h>.


А как она работает, если не секрет? Подключил, попробовал следующие варианты на примере 6го бита ADCSRA (ADSC - запуск АЦП):
ADCSRA.6 = 0x01;
ADCSRA.ADSC = 0x01;
ADSC = 0x01;
и ни один он не проглотил...

Спасибо.
Go to the top of the page
 
+Quote Post
Aleksandr Barano...
сообщение Sep 22 2008, 13:43
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118



Цитата(NikitoS-86 @ Sep 22 2008, 09:13) *
А как она работает, если не секрет? Подключил, попробовал следующие варианты на примере 6го бита ADCSRA (ADSC - запуск АЦП):
ADCSRA.6 = 0x01;
ADCSRA.ADSC = 0x01;
ADSC = 0x01;
и ни один он не проглотил...

Спасибо.


Там в доке все написано:

Bit manipulation
#define _BV(bit) (1 << (bit))
IO register bit manipulation
#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
#define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))
#define loop_until_bit_is_set(sfr, bit) do { } while (bit_is_clear(sfr, bit))
#define loop_until_bit_is_clear(sfr, bit) do { } while (bit_is_set(sfr, bit))

Значит, для проверки бита, надо написать нечто вроде:
Код
if(bit_is_set(PINB,3)){

}

По аналогии можно сделать:
Код
#define set_bit(sfr,bit)    (sfr |= _BV(bit))
#define clear_bit(sfr,bit)    (sfr &= ~(_BV(bit)))

У меня дока лежит тут:
file:///C:/WinAVR-20071221/doc/avr-libc/avr-libc-user-manual-1.6.1/index.html. У Вас, видимо, примерно в таком же месте.


--------------------
ASB
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 22 2008, 15:48
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 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
Guest_Цыкетчик_*
сообщение Sep 23 2008, 10:50
Сообщение #10





Guests






Надо не забыть ещё сделать задержку примерно на 1мС после включения модуля АЦП установкой бита ADEN. Хоть это и не написано в даташифтах, но длительность переходных процессов сосотавляет порядка 500мкС. Если делать АЦП до истечения этого временного интервала - показания сильно врут. Узнал это опытным путём


Цитата(SasaVitebsk @ Sep 22 2008, 19:48) *
Для этого в AVR Studio есть View/Disasmebler.

Который , кстати, глючит
Go to the top of the page
 
+Quote Post
NikitoS-86
сообщение Sep 23 2008, 12:25
Сообщение #11


Участник
*

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



Итак, во-первых, ОГРОМНОЕ спасибо всем откликнувшимся в данной теме=). Отдельное спасибо товарищам SasaVitebsk, Aleksandr Baranov и Цыкетчик за подробные ответы и сведения касающиеся практики!!! Я наконец разобрался!=)))

Как промежуточный конечный результат я сваял следующий код:

Цитата
#include <avr/io.h>
#include <avr/sfr_defs.h>
#include <avr/delay.h>

#define MYADMUX_U_T (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (1<<MUX2) | (1<<MUX1) | (1<<MUX0);
#define MYADMUX_I (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (1<<MUX2) | (1<<MUX1) | (0<<MUX0);

void port_B_settings (void);
void port_C_settings (void);
void measure_Ubat (int *, int *);
void measure_Tbat (int *, int *);
void measure_Icur (int *);

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

const int channel_number[8] =
{0b000, 0b001, 0b010, 0b011, 0b100, 0b101, 0b110, 0b111};

port_B_settings();

ADCSRA = 0x80;
_delay_ms(10);

measure_Ubat (&Ubat, &channel_number);

measure_Tbat (&Tbat, &channel_number);

measure_Icur (&Icur);
return;
}

void port_B_settings (void)
{
DDRB = 0x07;

return;
}

void measure_Ubat (int *Ubat, int *channel_number)
{
for (int i=0;i<4;i++)
{
ADMUX = MYADMUX_U_T;

PORTB = ((channel_number[i]>>2)<<PB2) | ((channel_number[i]>>1)<<PB1) | ((channel_number[i])<<PB0);
_delay_ms(10);

ADCSRA=ADCSRA | (1<<ADSC);

for (;;)
{
if (bit_is_set(ADCSRA,4))
break;
}

*(Ubat+i) = ADCH;
*(Ubat+i) = (*(Ubat+i)<<8) + ADCL;

ADCSRA = ADCSRA | (1<<ADIF);
}

return;
}

void measure_Tbat (int *Tbat, int *channel_number)
{
for (int i=0;i<4;i++)
{
ADMUX = MYADMUX_U_T;

PORTB = ((channel_number[i+4]>>2)<<PB2) | ((channel_number[i+4]>>1)<<PB1) | ((channel_number[i+4])<<PB0);
_delay_ms(10);

ADCSRA=ADCSRA | (1<<ADSC);

for (;;)
{
if (bit_is_set(ADCSRA,4))
break;
}

*(Tbat+i) = ADCH;
*(Tbat+i) = (*(Tbat+i)<<8) + ADCL;

ADCSRA = ADCSRA | (1<<ADIF);
}

return;
}

void measure_Icur (int *Icur)
{
ADMUX = MYADMUX_I

ADCSRA=ADCSRA | (1<<ADSC);

for (;;)
{
if (bit_is_set(ADCSRA,4))
break;
}

*Icur = ADCH;
*Icur = (*Icur<<8) + ADCL;

ADCSRA = ADCSRA | (1<<ADIF);

return;
}


Который вроде даже работает=)
У меня только вот что "вылезло":
1) В последнем ответе SasaVitebsk на мой пост есть фраза:
Цитата
В этом случае в п/п вам надо проверить флаг готовности АЦП и ждать его выставления и прочитать значение. Опять таки (см. выше) первое, после переключ. канала отбросить как не верное.

этот момент мне не очень понятен... Или таким образом реализуется "устаканивание" сигнала после смены канала? своего рода задержка между подачей сигнала на оцифровку и оцифровкой дабы получить более точное значение? Если так, то можно ли это реализовать функцией delay()?

2) На счёт встроенного дизасемблера и функции watch - спасибо, что подсказали... Удобно... НО почему она мне не позволяет наблюдать за метаморфозами моих переменных во время нахождения в вызываемых функциях? А я могу видеть состояние массивов только после возвращения из этих функций... Кроме того, переменную Icur она вообще наотрез отказывается отображать, всё время пишет либо "Location not valid" либо "Not in scope"... Таким образом я даже не вижу что с ней происходит... Может я как-то неправильно осуществляю вызов функций? Вроде бы всё что называется как по книжке... или может быть я где-то ошибся? Кстати при компиляции она мне пишет различного рода вонингсы как раз на моменты вызова функции... Они звучат следующим образом:
"../first.c:29: warning: passing argument 1 of 'measure_Ubat' from incompatible pointer type"
что я примерно перевожу как:
"впервый аргумент функции 'measure_Ubat' несовместим с сылочным типом..."
Я в чём-то заблуждаюсь при вызове функций?

Спасибо!

Чёрт, эта зараза не понимает рускую кодировку каментов из студии, пришлось все каменты удалить, ибо каракули отобразились при вставке...

Сообщение отредактировал NikitoS-86 - Sep 23 2008, 12:27
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Sep 23 2008, 12:35
Сообщение #12


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата
measure_Ubat (&Ubat , &channel_number);

По-моему, имя массива - это уже указатель, так что не нужно его разыменовывать


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
NikitoS-86
сообщение Sep 23 2008, 13:25
Сообщение #13


Участник
*

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



Да, так и есть по идее, и сначала я пользовал именно так, но он тоже писал:
../first.c:36: warning: passing argument 2 of 'measure_Ubat' from incompatible pointer type
т.е. и так и так, ворнинги...
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Sep 23 2008, 13:46
Сообщение #14


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(NikitoS-86 @ Sep 23 2008, 17:25) *
warning: passing argument 2 of 'measure_Ubat' from incompatible pointer type
т.е. и так и так, ворнинги...

1-й то аргумент в порядке.
а со вторым - может вот это...
Цитата
void measure_Ubat (int *, int * );
...
const int channel_number[8] =
{0b000, 0b001, 0b010, 0b011, 0b100, 0b101, 0b110, 0b111};


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 23 2008, 16:09
Сообщение #15


Гуру
******

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



Высскажу несколько соображений общего характера. В принципе они не принципиальны, и если они вас заденут, то просто проигнорируйте их. Во всяком случае не пытаюсь вас задеть либо обидеть, а хочу помочь осмыслить. Итак...

1) Вот такая конструкция мне не понравилась. "*(Ubat+i) = ADCH;"
Лучше перед циклом осуществить начальное присваивание, а в цикле применить конструкцию
"*Ubat++ = ADCH;". Ну и далее по тексту несколько аналогичных мест будет.
Поймите, у вас в руках не IBM370 и 2 десятка кластеров, а мааааленький камушек. И к ресурсам надо бережно относится. smile.gif
Посмотрите ради любопытства что ваш проект весит до модификации и после. Посмотрите как именно операторы превращаются в АСМ. Это очень полезно для дела. Да и интересно чёрт возьми. smile.gif

2) Или я чего-то просмотрел, или ваш main выполнится 1 раз и станет колом. Или каждый раз переинициализация, короче даже не знаю. Я так не делаю. Обычно в main идёт инициализация и главный цикл. Бесконечный.

3) по АЦП.
В общем то у вас всё правильно, только как бы вам сказать, так обычно стараются не делать. Стараются из камня выжать всё возможное и производительность важна. Как правило измерение АЦП - это не самоцель. По результату измерения что-то совершается.
Если исходить из этого, то цикл "Переключение канала-запуск измерения-ожидание завершения-чтение результата" не совсем удачен. Обычно делают цикл "чтение результата-переключение канала-запуск измерения-ожидание". Вы спросите - в чём разница - разница в том, что ожидание можно выкинуть. Точнее во время ожидания - можно заниматься другим делом, ну например фильтрацией результата и выводом его на ЖК дисплей.

4) Ответ на вопрос по АЦП.
Я писал про случай когда АЦП работает в автоматическом режиме. Тогда ваше переключение канала попадает на произвольное место цикла измерения АЦП, что, в свою очередь, делает неточным первый результат измерения после процесса переключения.
Go to the top of the page
 
+Quote Post

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

 


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


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