Страница 1 из 5
Помогите разобраться с программой
Добавлено: Пн май 26, 2008 11:00:36
Ежик в тумане
Помогите пожалуйста разобраться...
Есть устройство, у которого входной сигнал анализируется двумя каналами обработки. При совпадении сигналов каждого из каналов происходит включение выходных ключей. На каждый канал имеется мега 16 с программой. Требуется сделать так, что бы выходные ключи включались , когда на входе 2,9В. Сейчас включается при 1 В.
Калибровочные коэффициенты, как я поняла, записываются в епром, у меня в регистр данных епрома записывается число фф всегда...
Где и чего нужно поменять, подскажите плз, си практически не знаю... Ну или просто подскажите как разобраться в этом и понять как вообще работает эта программа. Буду рада любоу совету.
кусочек программы
// read cfg from eeprom
#define EEA_LEVEL 0
#define EEA_LEVELDELTA 1
#define EEA_STATUS 2
#define EEA_ERROR 3
void read_cfg()
{
eeprom_addr=0;
adc_addr=0;
run_mode=GET_MODE;
// read
//STATUS=eeprom_read_byte(EEA_STATUS);
STATUS=MODE_RUN;
level=eeprom_read_byte(EEA_LEVEL);
level_delta=eeprom_read_byte(EEA_LEVELDELTA);
}
Добавлено: Пн май 26, 2008 11:31:39
ARV
недостаточно данных!
1. проблема в чем: в сохранении/чтении в/из EEPROM или в обработке сигнало?
2. сигнал аналоговый? обработка через АЦП?
3. что за компилятор Си?
Добавлено: Пн май 26, 2008 11:53:50
Ежик в тумане
1. Проблема в непонимании как изменить калибровочные коэффициенты что бы работало от 2,9В а не от 1 В.
2. Сигнал аналоговый обрабатывается через ацп
3. AVR Studio
Добавлено: Пн май 26, 2008 12:15:03
ARV
аналогичная проблема в непонимании: что такое калибровочные коэффициенты? какие-то программные константы-переменные или что?
вот как надо работать с функцие
eeprom_read_byte:
Код: Выделить всё
EEMEM unsigned char my_var; // описание данных в EEPROM
unsigned char readed_var; // это перменная, куда мы будем считывать значение
readed_var = eeprom_read_byte((void *)&my_var); //собственно извлечение данных из EEPROM
P.S. если my_var проинициализировать, т.е. так:
то после компиляции создастся файл для прошивки в EEPROM, в котором
по адресу переменной
my_var будет задано ее начальное значение
123
Добавлено: Пн май 26, 2008 12:27:06
Ежик в тумане
Спасибо это я поняла... попробую дописать кусочек...
тогда вопрос а что может означать часть программы, которую в первом сообщении приложила
void read _cfg() и т.д. а конткретно строчки
level=eeprom_read_byte(EEA_LEVEL);
level_delta=eeprom_read_byte(EEA_LEVELDELTA);
я думала что здесь каким то образом задаются уровни...
Добавлено: Пн май 26, 2008 12:31:39
ARV
судя по константам EE_LEVEL и EE_LEVELDELTA в этом кусочке считываются 2 байта из EEPROM: один по адресу 0, другой по адроесу 1. что то за значения - это мне неизвестно. Но для того, чтобы оттуда считывалось не 0xFF, надо чтобы там было заранее что-то другое записано... например, программатором...
Добавлено: Пн июн 16, 2008 20:46:58
Ежик в тумане
Спасибо... худо бедно разобралась с числами в епроме и как выставить нужный уровень... теперь проблема в том, что сама программа немного некорректно написана. Я так поняла результат ацп сохраняется в массиве из 64 чисел, потом вычисляется среднее значение и сравнивается с числами в епром. Проблема в том, что нужно брать не среднее значение из этих 64 чисел, а брать максимальное и умножать на 2, а потом сравнивать с числами в епром.
1. Мне не понятно зачем нужен массив, может можно просто использовать одно число ацп, которое будет соответствовать нужному уровню?
2. Есть функция: непонятно что делает строчка val8=(uchar)(val>>8); и для чего нужны деррективы условной компиляции?
// analyze data
void analyze()
{ uchar i;
ushort val=0;
uchar val8;
//check agnd
//check uref
for(i=3;i<ADC_STOP_STEP>>8);
#ifdef DEBUG_AVG
send_data(val8);
#endif
if(val>(level-level_delta)) STATUS1_ON;
else STATUS1_OFF;
}
3. не понятно как работает конструкция:
switch(rx_buffer[0])
{ case 0 : send_data(FW_VERSION);break;//get FW version
case 1 : send_data(STATUS);break;//get status
case 2 :
case 3 : val=eeprom_read_byte(rx_buffer[2]);send_data(val);break;//get eeprom data
case 4 : ...............
Добавлено: Пн июн 16, 2008 21:30:24
ARV
1. вставки кода очень полезно оформлять именно как вставки кода

кнопочка такая есть - тогда оформление текста более приличным и читаемым получается.
2. массив и вычисление среднего - это в некотором роде фильтр (а может быть, оверсемплинг - повышение разрядности АЦП). Если скорость процесса позволяет - всегда лучше использовать среднее значнеие за несколько отсчетов АЦП - меньше шансов среагировать на случайную помеху. А иногда делают и более толковые фильтры...
3. директивы условной компиляции нужны, например, для отладки кода. приведу пример: если использовать функцию
_delay_ms(10) при отладке в
AVR Studio, то отладка займет дико много времени - 10 миллисекунд в симуляторе студии длятся больше минуты, а то и все 5 (от компа зависит)... но ведь в большинстве случаев для нахождения
логических ошибок длительность задаржек не играет роли - вот и можно при помощи директив условной компиляции сделать так, чтобы
для отладки все задержки были равны нулю...
4. благодаря тому, что в кусочках вашего кода некоторые символы заменились на смайлики - стало непонятно, что там было написано. если вы сделаете, как я советовал в п.1 - тогда, возможно, смогу ответить и на остальные вопросы.
Добавлено: Пн июн 16, 2008 22:25:16
Ежик в тумане
2. Есть функция: непонятно что делает выделенная строчка
Код: Выделить всё
// analyze data
void analyze()
{ uchar i;
ushort val=0;
uchar val8;
//check agnd
//check uref
for(i=3;i<ADC_STOP_STEP>>8);
--------val8=(uchar)(val>>8);---------- не понятно
#ifdef DEBUG_AVG
send_data(val8);
#endif
if(val>(level-level_delta)) STATUS1_ON;
else STATUS1_OFF;
}
Как работает конструкция:
Код: Выделить всё
switch(rx_buffer[0])
{ case 0 : send_data(FW_VERSION);break;//get FW version
case 1 : send_data(STATUS);break;//get status
case 2 :
case 3 : val=eeprom_read_byte(rx_buffer[2]);send_data(val);break;//get eeprom data
case 4 :
Спасибо огромное![/code]
Добавлено: Вт июн 17, 2008 06:37:59
ARV
1. назначение этой конструкции мне непонятно - по-моему, это какой-то кусок чего-то для отладки. думаю, оптимизатор этот кусок выкинет.
2. оператор switch(х) позволяет выполнить отдельные участки кода в хависимости от того, какое значение х: в вашем примере если rx_buffer[0] равно 0 - осуществится передача номера версии (я так понимаю имена констант), если равно 1 - вернется статус и т.д. Т.е. этот участок реализует варианты ответов на принятый запрос.
не забудьте, что оператор break заставляет прекратить выполнение всех далее следующих операторов до конца блока switch. если бы его не было, то после передачи версии сразу же пошла бы передача статуса и т.д.
Добавлено: Вт июн 17, 2008 07:08:39
Ежик в тумане
Спасибо огромное! Стало понятнее.
1. А что все таки на языке си означает эта строчка :
Код: Выделить всё
--------val8=(uchar)(val>>8);---------- не понятно
Это переменной val8 присваивается значение переменной val которую предварительно сдвигают на 8 разрядов? Зачем тогда в скобках писать еще uchar?
2. Теперь совсем непонятно как искать максимум из массива чисел... просто методом перебора? Важно ли знать по какому закону распределены числа в массиве и как это узнать?Может ли результат АЦП быть линейной функцией? Вопросы моет быть и глупые, но мне действительно пока это не понятно....
Добавлено: Вт июн 17, 2008 09:57:49
ARV
1. что присваивается - понятно. не понятен смысл предыдущего цикла и смысл этого присваивания, если следующая директива не сработает - результат
val8 никому более не нужен...
(uchar) означает явное приведение типов -
val8 у вас имеет тип
uchar (т.е. байт), а
val - тип
ushort (т.е. 2 байта). сдвиг на 8 разрядов приведет к тому, что старший байт окажется в младшем, который и присвоится переменной
val8
2. поиск максимума в уже готовом массиве - разумеется, только перебором.
3. нужно ли знать про закон распределения чисел в массиве - это вам виднее должно быть

для поиска максимального - в этом необходимости нет.
4. что вы имеете ввиду, говоря о результате АЦП, как линейной функции? само преобразование - да, линейно. а то, что получается в результате - есть повторение формы входного сигнала, т.е. может быть любой функцией

Добавлено: Вт июн 17, 2008 10:38:53
tych
ARV писал(а):оператор break заставляет прекратить выполнение всех далее следующих операторов до конца блока switch. если бы его не было, то после передачи версии сразу же пошла бы передача статуса и т.д.
Подробно про SWITCH на русском:
http://www.citforum.ru/programming/c/h14.shtml#145
Добавлено: Вт июн 17, 2008 13:13:28
Ежик в тумане
ARV писал(а):1. что присваивается - понятно. не понятен смысл предыдущего цикла и смысл этого присваивания, если следующая директива не сработает - результат val8 никому более не нужен...
А я вспомнила, там пол программы какие то непонятные мне функции. которые нужны для того, что бы плату с контроллером через какую то переходную плату можно было подключать к компутеру и с помощью какой то специальной программы смотреть ну например что выдает ацп... я до этого еще далека.
В целом считаю, что программа достаточно сложная и объемная, для меня это так. И начинать изучать си и авр нужно не с такого, но против начальства не попрешь...
Вам спасибо за помощь

Добавлено: Вт июн 17, 2008 15:09:45
tych
Ежик в тумане писал(а):начинать изучать си и авр нужно не с такого
Начать изучение Микроконтроллеров и Си можно с этого :
микроконтроллеры AVR и PIC начинающим - теория, примеры, программы, инструментарий.
Добавлено: Вт июн 17, 2008 16:22:54
Ежик в тумане
Буду очень признательна, если подскажите, на сколько будет работоспособна вот такая вот программа:
изначальный код такой (выше был приведен):
Код: Выделить всё
// analyze data
void analyze()
{ uchar i;
ushort val=0;
uchar val8;
//check agnd
//check uref
for(i=3;i<ADC_STOP_STEP>>8);
--------val8=(uchar)(val>>8);
#ifdef DEBUG_AVG
send_data(val8);
#endif
if(val>(level-level_delta)) STATUS1_ON;
else STATUS1_OFF;
}
теперь дописала кусочек, где ищем максимальное значение из массива:
Почему не вставить код целиком? При вставке кода часть функций куда то пропадают... или меняются на что то непонятное....
И еще вопрос требуется ли программно делать еще какой либо фильтр? Что это будет за фильтр, если на вход АЦП приходит сигнал положительная полуволна от синусоиды 50 Гц.
Добавлено: Вт июн 17, 2008 17:14:13
Ежик в тумане
Вставилось наконец то... Будет ли работать эта программа?
Добавлено: Вт июн 17, 2008 20:22:06
ARV
по-моему это кусочек полностью идентичен первоначальному

во всяком случае я не вижу поиска чего-либо в массиве

Добавлено: Вт июн 17, 2008 23:15:29
Ежик в тумане
Как ничего нового? Просто в первом сообщении я вставила исходный текст, а текст с исправлениями не вставился . Вставила его в следующем сообщении как рисунок.
попробую еще раз:

Добавлено: Ср июн 18, 2008 07:17:00
ARV
у меня по умолчанию картинки отключены

потому ничего и не увидел...
1. оформляйте код отступами - воспринимать логические блоки значительно проще будет
2. алгоритм поиска максимального мне как-то не глянулся... взгляните на такой вариант:
Код: Выделить всё
/* скрипт форума вырезает знак МЕНЬШЕ и все портит, на самом деле вместо MENEE просто введите знак МЕНЬШЕ */
int get_max(){ // функция возвращает максимальное число из внешнего массива int adc_buffer[BUF_SZ]
int i;
int result = adc_buffer[0]; // вначале первый считаем наибольшим
for(i=1; i MENEE BUF_SZ; i++) // перебираем остальные элементы
if(adc_buffer[i] > result) // и сравниваем их с максимальным
result = adc_buffer[i]; // если элемент больше - запоминаем его. как максимальное
return result; // возвращаем найденный максимум
}