|
|
  |
флаги готовности данных, как красиво реализуются |
|
|
|
Nov 19 2014, 12:13
|
Местный
  
Группа: Участник
Сообщений: 408
Регистрация: 28-05-12
Пользователь №: 72 052

|
В моей программе я принимаю поток данных от АЦП и складываю в буфер длинной N, как только буфер заполняется, программа должна делать математическую обработку данных над числами в буфере и складывать результат в другой бефер, и так по кругу, заполняются два буфера по кругу и производятся вычисления. Вопрос: как наиболее красиво реализовать механизм "сигнализации" о том что буфер заполнен и пора производить вычисления? сейчас я использую глобальные переменные и конктрукции типа принимаем данные от АЦП: CODE Buf[i] = ADC_receive_data(); //принимаем данные if(i == N) { i = 0; j = READY; }
обработчик, опрашивающий переменную j и вызывающий соответствующую функцию: CODE while(1) { if( j == READY) { Data_processing(); } }
с ростом сложности программы, глобальных переменных становится больше и код трудно читаем. Когда нужно рассчитывать десяток параметров на разных временных интервалах встаёт вопрос об упрощении структуры и читаемости программного кода. Десяток опрашиваемых глобальных переменных - это не очень красиво. как сделать проще/удобнее/красивее ?
|
|
|
|
|
Nov 19 2014, 17:17
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Dubov @ Nov 19 2014, 12:13)  В моей программе я принимаю поток данных от АЦП и складываю в буфер длинной N, как только буфер заполняется, программа должна делать математическую обработку данных над числами в буфере и складывать результат в другой бефер, и так по кругу, заполняются два буфера по кругу и производятся вычисления. Вопрос: как наиболее красиво реализовать механизм "сигнализации" о том что буфер заполнен и пора производить вычисления?
с ростом сложности программы, глобальных переменных становится больше и код трудно читаем. Когда нужно рассчитывать десяток параметров на разных временных интервалах встаёт вопрос об упрощении структуры и читаемости программного кода. Десяток опрашиваемых глобальных переменных - это не очень красиво. как сделать проще/удобнее/красивее ? Как угодно  Слишком общий вопрос, ответить невозможно. "Скажите мне, как написать хорошую программу...." - вся рограмма однопоточная, все вызовы синхронные ? - программа настояще - многопоточная? - данные от АЦП принимаются в прерывании, обработка делается в главном цикле? - программные таймеры и флаговый автомат ? Можно вообще ничего явно не опрашивать, валить данные от АЦП в циклический буфер, обработчик данных из него будет выгребать. Вся функциональность сосредоточена в имплементации буфера. Каков вопрос, таков и ответ.
|
|
|
|
|
Nov 20 2014, 04:14
|
Частый гость
 
Группа: Участник
Сообщений: 91
Регистрация: 3-07-11
Пользователь №: 66 028

|
Как-то сталкивался я с такой проблемой, но так приоритет программы был на скорость, по этому использовал глобальные переменные. После этого нашёл статью "Применение SWITCH технологии при разработке прикладного программного обеспечения для микроконтроллеров" http://www.kit-e.ru/articles/circuit/2006_11_164.phpТам мне понравилась служба сообщений примерно выглядит это так Код #define ADC_COMPLEAT 1 unsigned char Messages[10]; //-------------------------------- Buf[i] = ADC_receive_data(); //принимаем данные if(i == N){ i = 0; SendMessage(ADC_COMPLEAT); } //-------------------------------- while(1) { if(GetMessage(ADC_COMPLEAT)){ Data_processing(); ResetMessage(ADC_COMPLEAT); } } //============================================= void ResetMessage(unsigned char Msg) { Messages[Msg] = 0; } } void SendMessage(unsigned char Msg) { Messages[Msg] = 1; } } unsigned char GetMessage(unsigned char Msg) { return Messages[Msg]; } Так же ещё можно отвести пару байт на битовые флаги и маской проверять на установления бита. Преимущество такого подхода можно одним условием проверить сразу несколько битовых флагов.
|
|
|
|
|
Nov 20 2014, 04:27
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
Согласен с CrimsonPig - слишком общий вопрос, но подкину пару примеров 1 Одна из организаций пинг-понг буфера, без флага Код int Voice_near[2*N]; // N - степень ДВОЙКИ!!! volatile unsigned int Voice_near_pos=0; ....... // прием символа, накопление - обычно в прерывании Voice_near[Voice_near_pos++] = ADC_receive_data(); Voice_near_pos &= (2*N-1); ................. while(1) { // обработка int j; cli(); // критическая секция j = Voice_near_pos; sei(); if(!(j & (N-1)) { Data_processing(&Voice_near[j ^ N]); } ..... } 2. Конечно не феншуйно, но можете несколько флагов объеденить в одну переменную и при работе пользоваться масками (0х01,0х02,0х04,0х08 и т.д.) 3. Если программа разрастается, то пора думать о ее правильной организации. Бейте на модули(отдельные файлы), отделите глобальные переменные от переменных, использующихся только в отдельном модуле. Называйте переменные осмысленно (а не i,j,k,p.....). Комментируйте назначение модулей, функций , да и вообще любых непонятные места в программе. И так далее, по этому поводу уже много чего написано и сказано 4. Да еще куча всего, например, можно ввести общую систему синхронизации процессов/потоков (события,сообщения,семафоры.....) 5...................
Сообщение отредактировал alexeyv - Nov 20 2014, 09:14
|
|
|
|
|
Nov 20 2014, 14:00
|
Местный
  
Группа: Свой
Сообщений: 271
Регистрация: 6-12-11
Из: Taganrog
Пользователь №: 68 701

|
Судя по первому сообщению, приём идёт в прерывании, ибо иначе можно было бы сразу и обработать. А обработка потом -- в одной, главной и единственной нити, ибо видим "while(1)". Я могу предложить "плюсОвую" "полуОСьно"-курчавую систему с сигнализацией в лишь одну глобальную переменную _is_, ну или даже живущую в стеке, которую и к С можно приспособить: - объявляется тип "буфера" с парой указателей на "ёмкость" для поочерёдного приёма (+связанный список буферов опционально), функция его инита, выделяющая эти буфера в куче (ну или присвоения статических памятей), функция регистрации буфера в "системе" -- привязка адреса сигнальной переменной в буфер, чтоб знал, куда "стучать"; - на старте все буфера инитятся, привязываются, начинается "while(1)"; - там при наступлении _is_ сначала она обнуляется, затем идёт перебор всех зарегистрированных буферов, и кто готов -- того обсчитываем. Ну или вообще без глобального _is_ можно -- в каждом буфере свой _is_, "while(1)" их все перенюхивает бесконечно и обрабатывает по мере достижения -- главное, что есть инкапсуляция всего необходимого по логике работы в полях одной структуры. И в обработчик прерывания её можно передать обычным void*, чтобы он добавил текущий байт к текущему буферу и выработал вдруг _is_. Не знаю, что кому приятней -- я бы и с десятком глобальных сигнализаторов не задымился, просто имена должны быть подлинней -- половина имени общая для смысла этой переменной, другая половина частная для её конкретности.
|
|
|
|
|
Dec 15 2014, 13:41
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
А я делаю по простому Код /*system Flags*/ #define FLAG0 BIT0 #define FLAG1 BIT1 #define FLAG2 BIT2 …………………………….. #define FLAG31 BIT31
uint32_t sysFlags; и потом проверить флаг Код if(sysFlags&FLAG1) установить флаг Код sysFlags |= FLAG1; сбросить флаг Код sysFlags &= ~FLAG1;
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|