Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: MSP430 - снова вопросы от чайника
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Страницы: 1, 2, 3, 4, 5, 6
rezident
Цитата(Daria @ Aug 31 2008, 00:33) *
Да знаю я, знаю, что долго сидеть в прерывании нехорошо, не ругайтесь так... biggrin.gif Но тут какая проблема была - если вычисления делать просто в цикле for(;;), то за время, пока эти вычисления делаются, уже успевает прийти несколько прерываний, и данные обновляются прямо по ходу вычислений.
Есть два способа решения этой проблемы. Либо на время вычислений в основном цикле запрещать прерывания от АЦП (либо останавливать его) - все равно АЦП не работает, когда вы считаете в прерывании. Либо использовать два циклических буфера. В то время пока вы обсчитываете результаты одного буфера, в другой буфер (по прерываниям АЦП) идет запись новых результатов изменений. В основном цикле вы только устанавливаете номер буфера и флаг сигнализирующий обработчику прерывания АЦП о смене номера буфера. В прерывании АЦП сначала анализируется состояние флага и при необходимости изменяется указатель на буфер, а запись новых значений происходит уже в другой буфер.
Цитата(Daria @ Aug 31 2008, 00:33) *
И происходит такая вещь - если плавно поворачивать плату, то оцифрованый уровень меняется далеко не плавно, жутко скачет во время поворота и долго "успокаивается", если вращать быстро, то будет долгий переходной процесс - т.е. улетает сначала намного выше реального уровня, затем медленно возвращается. Вот, по-женски так объясняю, самой смешно biggrin.gif я думаю, это происходит оттого, что допустим координата Х уже просчиталась, а У еще нет, пришло прерывание, данные обновились, У считается, и уже характеризует новое положение, а Х - еще старое, поэтому при вращении возникают большие ошибки.
Значит у вас где-то ошибка в алгоритме. нужно синхронизировать обновления значений переменных координат так, чтобы не было разбега, как он у вас описан.
Цитата(Daria @ Aug 31 2008, 00:33) *
Кстати, на ваш вопрос - да, усредняю скользящим, среднее арифметическое - это глупо даже для меня biggrin.gif Каждый раз дожидаться, пока наберется 30 отсчетов... Я жду, пока они наберутся только в самом начале работы, а потом каждое новое число записывается 30-м элементом массива, и массив усредняется и сдвигается.
Ну да, зато теперь тратится куча времени... 05.gif
А вам приниципально усреднять уже готовые значения координат или можно усреднять непосредственно отсчеты АЦП? Ведь просуммировать целые числа получается гораздо быстрее, чем получить сумму "плавучих" чисел? К тому же при целочисленных вычислениях не накапливается ошибка округления. Поэтому алгоритм скользящего вычисления среднего можно значительно ускорить. Для этого нужно лишь хранить отдельно текущее значение суммы элементов буфера. При поступлении нового значения в буфер достаточно вычесть из этой суммы значение самого древнего элемента буфера, прибавить значение нового элемента буфера и вуаля! - вы получаете готовую сумму. Итого одно сложение и одно вычитание, вместо суммирования всего буфера. Для "плавучки" такой способ не годиться, т.к. довольно быстро набегает ошибка вычисления суммы. К тому же зачем вы каждый раз при записи нового значения в буфер сдвигаете все элементы в буфере? Это же лишнее время и совершенно ненужное действие. Сдвигайте не сам буфер, а лишь индекс-указатель на текущий элемент буфера. Получается то же самый неоднократно упомянутый циклический буфер.
Код
#define MAXNUMFLTRBUF  30

unsigned int funcSMA(unsigned int val)
{ static unsigned int fltrBuf[MAXNUMFLTRBUF];
  static unsigned int idx;
  static unsigned long sumBuf;
  sumBuf-=fltrBuf[idx];     //вычитаем из суммы значение самого старого элемента
  sumBuf+=val;              //прибавляем к сумме значение нового элемента
  fltrBuf[idx]=val;         //записываем в буфер значение нового элемента
  if (idx<(MAXNUMFLTRBUF-1))//сдвигаем индекс
    idx++;
  else
    idx=0;
  return(sumBuf/MAXNUMFLTRBUF);//высисляем среднее значение
}

При желании можно добавить команды управления фильтром. Например, команду очистки буфера или инициализация его определенным значением. Для того, чтобы увеличить начальную крутизну его переходной характеристики.
Код
#define MAXNUMFLTRBUF  30

unsigned int funcSMA(unsigned int cmd, unsigned int val)
{ static unsigned int fltrBuf[MAXNUMFLTRBUF];
  static unsigned int idx;
  static unsigned long sumBuf;
  if (cmd==0)                 //это случано не команда инициализации фильтра?
  { sumBuf-=fltrBuf[idx];     //нет, вычитаем старое значение
    sumBuf+=val;              //прибавляем к сумме значение нового элемента
    fltrBuf[idx]=val;         //записываем в буфер значение нового элемента
    if (idx<(MAXNUMFLTRBUF-1))//сдвигаем индекс
      idx++;
    else
      idx=0;
    return(sumBuf/MAXNUMFLTRBUF);//вычисляем среднее значение
  }
  else                        //да, инициализируем буфер фильтра новым значением
  { sumBuf=val*MAXNUMFLTRBUF;
    idx=MAXNUMFLTRBUF-1;
    while (idx!=0)
      fltrBuf[idx--]=val;
    return(val);
  }
}

Учитывая, что входные значения 12-и разрядные и сумма заведомо не превышает разрядности типа long, то при целочисленном вычислении среднего можно повысить точность, если перед делением сдвигать сумму до заполнения разрядности типа, а потом сдвигать обратно.
Код
return(((sumBuf<<8UL)/MAXNUMFLTRBUF)>>8UL);
Daria
Цитата(rezident @ Aug 31 2008, 01:04) *
Есть два способа решения этой проблемы. Либо на время вычислений в основном цикле запрещать прерывания от АЦП (либо останавливать его) - все равно АЦП не работает, когда вы считаете в прерывании.

А разве не тож на тож получится? 07.gif Та же самая потеря времени... Единственное, что таймер не будет пробрасывать свои прерывания и будет четко вести счетчик прерываний... но лишние 10-20мс до начала короткого импульса - вроде не проблема...
Цитата(rezident @ Aug 31 2008, 01:04) *
Либо использовать два циклических буфера. В то время пока вы обсчитываете результаты одного буфера, в другой буфер (по прерываниям АЦП) идет запись новых результатов изменений. В основном цикле вы только устанавливаете номер буфера и флаг сигнализирующий обработчику прерывания АЦП о смене номера буфера. В прерывании АЦП сначала анализируется состояние флага и при необходимости изменяется указатель на буфер, а запись новых значений происходит уже в другой буфер.

Ух. Жестко! Ладно, спасибо, попробую.
Цитата(rezident @ Aug 31 2008, 01:04) *
Значит у вас где-то ошибка в алгоритме. нужно синхронизировать обновления значений переменных координат так, чтобы не было разбега, как он у вас описан.

Нужно. Вопрос - как biggrin.gif
Цитата(rezident @ Aug 31 2008, 01:04) *
А вам приниципально усреднять уже готовые значения координат или можно усреднять непосредственно отсчеты АЦП?

Э-э... а я вроде именно отсчеты АЦП и усредняю... 05.gif так мне казалось... biggrin.gif
Цитата(rezident @ Aug 31 2008, 01:04) *
Для этого нужно лишь хранить отдельно текущее значение суммы элементов буфера. При поступлении нового значения в буфер достаточно вычесть из этой суммы значение самого древнего элемента буфера, прибавить значение нового элемента буфера и вуаля! - вы получаете готовую сумму.

Точно! Спасибо большое! Действительно, куча лишних действий получалась!
Только немного не ясно, почему строка
sumBuf-=fltrBuf[idx];- это вычитание самого старого элемента 05.gif Вы записываете новый элемент fltrBuf[idx]=val; и сдвигаете счетчик - idx++. Значит, при поступлении следующего элемента fltrBuf[idx] будет хранить значение предыдущего, а не самого старого... Поясните, пожалуйста.
Цитата(rezident @ Aug 31 2008, 01:04) *
Учитывая, что входные значения 12-и разрядные и сумма заведомо не превышает разрядности типа long, то при целочисленном вычислении среднего можно повысить точность, если перед делением сдвигать сумму до заполнения разрядности типа, а потом сдвигать обратно.
Код
return(((sumBuf<<8UL)/MAXNUMFLTRBUF)>>8UL);

А почему это повышает точность?
как всегда спасибо за комментарии! smile.gif
rezident
Цитата(Daria @ Aug 31 2008, 22:48) *
Нужно. Вопрос - как biggrin.gif
Как обычно. С помощью буферов. Две переменные которые будут обновляться одновременно и считывание значений из которых не будет прерываться вычислениями.
Цитата(Daria @ Aug 31 2008, 22:48) *
Э-э... а я вроде именно отсчеты АЦП и усредняю... 05.gif так мне казалось... biggrin.gif
Опс! Это я ошибся sad.gif Извиняюсь! Почему-то отложилось в памяти, что у вас там фильтрация плавающих числе идет, а страницу с вашим кодом еще раз посмотреть поленился. twak.gif
Цитата(Daria @ Aug 31 2008, 22:48) *
Только немного не ясно, почему строка
sumBuf-=fltrBuf[idx];- это вычитание самого старого элемента 05.gif Вы записываете новый элемент fltrBuf[idx]=val; и сдвигаете счетчик - idx++. Значит, при поступлении следующего элемента fltrBuf[idx] будет хранить значение предыдущего, а не самого старого... Поясните, пожалуйста.
В полностью заполненном циклическом буфере фильтра индекс указывает на тот элемент, куда нужно записать новое значение, которое замещает самое старое значение. Следовательно индекс указывает на самое старое значение.
Пример. Буфер из трех элементов. Поток состоит из последовательности натуральных чисел.
Код
         | значения
значение | элементов
индекса  |  буфера
---------------------------
  0       -, -, -    - буфер пуст
  1       1, -, -    - 1 элемент, единственный и самый старый, индекс указывает на следующий, но буфер ЕЩЕ НЕ ЗАПОЛНЕН
  2       1, 2, -    - 2 элемента, самый старый 1-й, буфер ЕЩЕ НЕ ЗАПОЛНЕН, индекс указывает на следующий
  0       1, 2, 3    - 3 элемента, буфер заполнен!!!, индекс указывает на следующий (1-й элемент), который является самым старым
  1       4, 2, 3    - 3 элемента, буфер заполнен, индекс указывает на следующий (2-й элемент). который является самым старым
  2       4, 5, 3    - 3 элемента, буфер заполнен, индекс указывает на следующий (3-й элемент). который является самым старым
  0       4, 5, 6    - ну и т.д.
  1       7, 5, 6

Цитата(Daria @ Aug 31 2008, 22:48) *
А почему это повышает точность?
Это особенности целочисленной математики. Хотя пожалуй в данном конкретном случае (единственная операция в выражении) это рояли не играет. Я просто перестраховался. Отставить сдвиги! smile.gif
Daria
Цитата(rezident @ Aug 31 2008, 22:39) *
В полностью заполненном циклическом буфере фильтра индекс указывает на тот элемент, куда нужно записать новое значение, которое замещает самое старое значение.

Ага, ясно. Спасибо за очень подробное разъяснение smile.gif
Цитата(rezident @ Aug 31 2008, 22:39) *
Это особенности целочисленной математики. Хотя пожалуй в данном конкретном случае (единственная операция в выражении) это рояли не играет. Я просто перестраховался. Отставить сдвиги! smile.gif

Есть "отставить сдвиги" smile.gif
Я теперь неделю буду в отпуске 08.gif так что можете от меня недельку отдохнуть biggrin.gif
а через неделю жду вас с новыми ответами на новые вопросы wink.gif
Daria
Ну вот, отпуск кончился, пошли суровые будни crying.gif
И вопросы smile.gif
Такая беда. У меня был iar, версия 4.11в - тридцатидневная демо-версия с официального сайта. Срок лицензии истек, я снесла эту версию, скачала опять и поставила снова. И вот фиг. Удаляю отовсюду, откуда только можно, но в реестр он прописался в закрытую область, которую нельзя удалить. Теперь сколько новый iar не ставь, все бестолку crying.gif
Как быть? переустанавливать винду не хочется. Попробовать какую-нибудь другую версию? Где взять? У меня был ломаный iar 3.2, но он почему-то жутко глючил. Можно как-нибудь почистить и закрытые области?
Вот такая проблема, немного не по теме, но печальная crying.gif
rezident
Цитата(Daria @ Sep 13 2008, 00:04) *
Вот такая проблема, немного не по теме, но печальная crying.gif
Там все дело в волшебных пузырьках biggrin.gif То бишь в лицензии которую вы скармливаете при установке. "Правильную" лицензию можно сгенерить с помощью вот этой штучки wink.gif Инструкция по применению inside package.
P.S. некоторые излишне подозрительные антивирусы (например, AVAST) реагируют на содержимое архива как на вирус. Не стоит волноваться, они перестраховываются.
MrYuran
Цитата(Daria @ Sep 12 2008, 22:04) *
Как быть? переустанавливать винду не хочется. Попробовать какую-нибудь другую версию? Где взять?

Может, лучче сразу GCC осваивать?
Потом не придётся отвыкать от специфических ИАРовских примочек.. И с законностью всё в порядке
rezident
Цитата(MrYuran @ Sep 13 2008, 16:53) *
И с законностью всё в порядке
А вы сами-то при передаче заказчику исходников своей программы строго следуете условиям лицензии GPL? wink.gif
MrYuran
Цитата(rezident @ Sep 13 2008, 20:48) *
А вы сами-то при передаче заказчику исходников своей программы строго следуете условиям лицензии GPL? wink.gif

Заказчику мы обычно передаём только паспорт и РЭ, в крайнем случае схему.
А вообще, как говорил кот Матроскин, холодильник чей - государственный, а холод, который он вырабатывает - наш.

Так же и тут.
Компилятор - GPL, а код, который он вырабатывает - наш.
Сергей Борщ
Цитата(rezident @ Sep 13 2008, 19:48) *
А вы сами-то при передаче заказчику исходников своей программы строго следуете условиям лицензии GPL? wink.gif
Насколько я понимаю, лицензия GPL предписывает предоставлять по первому требованию исходники самого компилятора, но не код, им произведенный. Иначе ее можно было бы распространить и на траффик, зашифрованный с помощью OpenSSH и подобных продуктов.
rezident
Цитата(MrYuran @ Sep 13 2008, 23:31) *
А вообще, как говорил кот Матроскин, холодильник чей - государственный, а холод, который он вырабатывает - наш.

Так же и тут.
Компилятор - GPL, а код, который он вырабатывает - наш.
Вы явно не читали или читали невнимательно текст GNU GENERAL PUBLIC LICENSE sad.gif
Цитата(Сергей Борщ @ Sep 14 2008, 00:20) *
Насколько я понимаю, лицензия GPL предписывает предоставлять по первому требованию исходники самого компилятора, но не код, им произведенный.
При компиляции используются какие-то библиотеки компилятора, так? Так вот, если полученный в результате компиляции код содержит внутри себя хотя бы часть этой библиотеки (например, библиотеки вычислений с "плавучкой"), то весь он попадает под действие лицензии GPL. Если же какие-то части программы, имеющие возможность функционировать самостоятельно и не содержащие компоненты, попадающие под действие GPL, были лишь скомпилированы GNU-тым компилятором, тогда да, они также свободны от действия GPL.

Давайте не будем засорять ветку bb-offtopic.gif. Если вопрос лицензий free software и open source волнует кого-то, то можно завести отдельный топик.
AHTOXA
Цитата(rezident @ Sep 14 2008, 02:13) *
При компиляции используются какие-то библиотеки компилятора, так? Так вот, если полученный в результате компиляции код содержит внутри себя хотя бы часть этой библиотеки (например, библиотеки вычислений с "плавучкой"), то весь он попадает под действие лицензии GPL.


Библиотеки обычно не gpl, а lgpl. Но тут надо конечно быть очень внимательным...

Цитата
Давайте не будем засорять ветку bb-offtopic.gif. Если вопрос лицензий free software и open source волнует кого-то, то можно завести отдельный топик.


Я был бы не против почитать такой топикsmile.gif
Daria
Цитата(rezident @ Sep 12 2008, 22:27) *

rezident, большое спасибо. Все работает. Вы хороший smile.gif
Daria
Здравствуйте. Такие вопросы -
сейчас я прошиваю контроллер самодельной отладкой, схему которой советовали, по-моему, вы, rezident - она питается с платы, 3,3 В. В дальнейшем хочу использовать MSP-FET430PIF, так как требования - либо на свою отладку оформлять докуметацию по всем правилам, либо пользоваться готовой. и вот вопрос - у MSP-FET430PIF питание от LPT - мне сказали, что это опасно, что LPT часто горят, если программатор питается прямо от порта. Это правда? насколько часто? smile.gif Может, лучше не покупать этот MSP-FET430PIF?
И еще - не совсем в по теме. Не подскажите какой-нибудь кварцевый резонатор на 8MГц, как можно меньших размеров? И, желательно, планарный smile.gif Не могу найти, на такую частоту все какие-то здоровые, а нужно сокращать размеры платы sad.gif
rezident
Цитата(Daria @ Sep 24 2008, 00:33) *
В дальнейшем хочу использовать MSP-FET430PIF, так как требования - либо на свою отладку оформлять докуметацию по всем правилам, либо пользоваться готовой. и вот вопрос - у MSP-FET430PIF питание от LPT - мне сказали, что это опасно, что LPT часто горят, если программатор питается прямо от порта. Это правда? насколько часто? smile.gif Может, лучше не покупать этот MSP-FET430PIF?
Согласен. MSP-FET430PIF покупать не нужно в любом случае smile.gif. Если вам нужен индивидуальный отладчик и программатор, то купите лучше MSP-FET430UIF или его полнофункциональный клон MSPLink. Olimex-овский USB-FET покупать не рекомендую.
Если же вы хотите передать прошивку кристаллов на производство, то лучше сразу купить MSP-GANG430. Мы покупали в Терраэлектронике.
Преимущества:
- можно программировать до 8ми кристаллов одновременно.
- все кристаллы можно запитать непосредственно от MSP-GANG430.
- поддерживает функцию прожигания fuse.
- можно загрузить прошивку в программатор и использовать его автономно, т.е. он не требует обязательного наличия компьютера. С компьютера вы только загружаете образ прошивки и конфигурацию программирования через последовательный интерфейс RS-232. Соответственно при отсутствии в компе RS-232 можно дополнить программатор любым готовым кабелем USB-COM и работать дальше. В случае же LPT-ного MSP-FET430PIF и отсутствия LPT-порта вы получите массу трудностей.
- MSP-GANG430 поддерживает все предыдущие и последующие серии MSP430, т.е. у него есть перспективы техподдержки. Например, аналогичный по функциям MSP-PRGS430 уже сейчас не поддерживает интерфейс Spy-Bi-Wire и некоторые кристаллы из серии MSP430x2xx.
- чуть не забыл упомянуть главное достоинство MSP-GANG430 для производства, на котором не всегда адекватные по знаниям люди работают smile.gif У MSP-GANG430 из органов управления всего ОДНА кнопка! wink.gif Из индикации два ряда светодиодов (красные и зеленые). Обучить нажатию на кнопку можно даже неквалифицированный персонал. biggrin.gif
Кстати, раз вы планируете программировать кристаллы уже запаянные в плату, то обдумайте стоит ли для этого использовать именно JTAG? Я, например, в серийных устройствах на MSP430 вывожу для программирования сигналы BSL. Во-первых, требуется меньше контактов (всего 6). Во-вторых, BSL позволяет и в дальнейшем менять firmware, когда уже установлена защита (fuse уже пережжен) и JTAG не работает.
Цитата(Daria @ Sep 24 2008, 00:33) *
И еще - не совсем в по теме. Не подскажите какой-нибудь кварцевый резонатор на 8MГц, как можно меньших размеров? И, желательно, планарный smile.gif Не могу найти, на такую частоту все какие-то здоровые, а нужно сокращать размеры платы sad.gif
Посмотрите резонаторы фирм Geyer Electronic и Golledge. Мы часовой (32768Гц) KX-327LT от Geyer недавно начали применять, размеры его всего 1,5х7мм. Продукцией Geyer Electronic торгует Компел и Терраэлектроника, а продукцию Golledge представляет фирма ЭФО.
Сергей Борщ
Цитата(Daria @ Sep 23 2008, 21:33) *
мне сказали, что это опасно, что LPT часто горят, если программатор питается прямо от порта. Это правда?
Нет, неправда. Горит не от питания, а от бестолковости питающего. Когда корпус компьютера не заземлен, когда втыкают в запитанное устройство, питающееся от незаземленного блока питания, ну и т.д. Для MSP-FET430PIF питание от порта - один из штатных режимов.
Цитата(Daria @ Sep 23 2008, 21:33) *
Может, лучше не покупать этот MSP-FET430PIF?
Да. Лучше купите MSP-FET430UIF. Это почти то же самое, только от USB. И питание от него тоже можно брать.
Цитата(Daria @ Sep 23 2008, 21:33) *
Не подскажите какой-нибудь кварцевый резонатор на 8MГц, как можно меньших размеров?
Выбирайте: "Чип И Дип", Кварцевые резонаторы (Всего товаров: 357)
Daria
Ага, но мне, как пока неквалифицированному программисту, хотелось бы все же программить именно на плате, сразу непосредсственно смотреть сигналы с датчиков. Возможность BSL заложу, но с JTAG мне гораздо проще - удобно отлаживать все это дело, то так, то так попробовать smile.gif А с полноценным отладчиком не знаю, как и работать biggrin.gif такой парадокс. Пробовать ведь надо на реальной плате 05.gif а так - вставить кристалл и... чего дальше? biggrin.gif Мое парадоксальное мышление проявляется тут с новой силой biggrin.gif Когда прога будет уже окончательно выверена, тогда, конечно - вставил кристалл, прошил - давай следующий. Но окончательно - это еще неизвестно когда, к тому же задание постоянно меняется biggrin.gif
Значит PIF - не пойдет? A UIF - разве позволяет программировать прямо на плате?
Резонаторы посмотрю, спасибо
rezident
Цитата(Daria @ Sep 24 2008, 02:12) *
Значит PIF - не пойдет? A UIF - это ведь тоже отдельная коробка smile.gif
Для вашего нынешнего случая (MSP430F149) подойдет и PIF и UIF. Я вам на будущее/перспективу рекомендации давал. Для отладки конечно же лучше нормальный отладчик. BSL это для серии и техподдержки.
Daria
Цитата(rezident @ Sep 24 2008, 00:47) *
Для вашего нынешнего случая (MSP430F149) подойдет и PIF и UIF. Я вам на будущее/перспективу рекомендации давал. Для отладки конечно же лучше нормальный отладчик. BSL это для серии и техподдержки.

А UIF позволяет программировать прямо на плате? Как-то он так выглядит... я думала. что нет. по его внешнему виду biggrin.gif
rezident
Цитата(Daria @ Sep 24 2008, 02:56) *
А UIF позволяет программировать прямо на плате? Как-то он так выглядит... я думала. что нет. по его внешнему виду biggrin.gif
Конечно позволяет. Он функционально более расширен по сравнению с MSP-FET430PIF. В принципе вы даже сами можете изготовить MSP-FET430UIF wink.gif Схема его имеется в slau138, а прошивку тут в форуме где-то выкладывали.
Сергей Борщ
Цитата(Daria @ Sep 23 2008, 23:56) *
Как-то он так выглядит... я думала. что нет. по его внешнему виду biggrin.gif
Эээ... А вы его случайно с ez430 (USB-"свистком") не перепутали? FET430-UIF внешне отличается от FET430-PIF (если не изменяет память) только кабелем к компьютеру.
Daria
Цитата(Сергей Борщ @ Sep 24 2008, 01:52) *
Эээ... А вы его случайно с ez430 (USB-"свистком") не перепутали?

Ага, точно biggrin.gif Теперь понятно, спасибо. Кварц, кстати, подходящий нашла у Murata - CSTCE8M0G53 - нормальный? smile.gif
Теперь дальше.
rezident, пытаюсь воспроизвести что-то вроде протоколоа SLIP, который вы упоминали. Вот текст.
Код
#define sizeBufTx 16
#define sizeBufRx 16

unsigned char bufRx[sizeBufRx];
unsigned char bufTx[sizeBufTx];

typedef struct CharBuffer
{
    unsigned char* Data;            
    int NData;                        
    int cData;                        
    int pWrite;                        
    int pRead;                        
}
CharBuffer;
void BufferReset(CharBuffer* pBuffer)
{
    pBuffer->pWrite = 0;
    pBuffer->pRead = 0;
    pBuffer->cData = 0;
}
int    BufferWrite(CharBuffer* pBuffer,unsigned char Byte)
{
    if(pBuffer->cData == pBuffer->NData - 1)
        return 1;                    
    pBuffer->Data[pBuffer->pWrite] = Byte;
    if(pBuffer->pWrite == pBuffer->NData - 1)
        pBuffer->pWrite = 0;
    else
        pBuffer->pWrite++;
    pBuffer->cData++;
    return 0;
}
int BufferRead(CharBuffer* pBuffer, unsigned char* Byte)
{
    if(pBuffer->cData == 0)
       return 1;                    
    *Byte = pBuffer->Data[pBuffer->pRead];
    if(pBuffer->pRead == pBuffer->NData - 1)
        pBuffer->pRead = 0;
    else
        pBuffer->pRead++;
    pBuffer->cData--;
    return 0;
}

struct CharBuffer UARTTxBuf, UARTRxBuf;
void WriteTxbuf(int* data, char size)
{
    unsigned char a, j;
    if ((IE1 & UTXIE0) == 0)        
    {
        BufferWrite(&UARTTxBuf, 0xC0);
        for(j = 0; j < size; j++)
        {
          
            a = data[j] & 0xFF;
            switch (a)
            {
                case 0xC0:
                {
                    BufferWrite(&UARTTxBuf, 0xDB);
                    BufferWrite(&UARTTxBuf, 0xDC);
                    break;
                }
                case 0xDB:
                {
                    BufferWrite(&UARTTxBuf, 0xDB);
                    BufferWrite(&UARTTxBuf, 0xDD);
                    break;
                }
                default:
                    BufferWrite(&UARTTxBuf, a);
            }
            
            a = data[j] >> 8;
            switch (a)
            {
                case 0xC0:
                {
                    BufferWrite(&UARTTxBuf, 0xDB);
                    BufferWrite(&UARTTxBuf, 0xDC);
                    break;
                }
                case 0xDB:
                {
                    BufferWrite(&UARTTxBuf, 0xDB);
                    BufferWrite(&UARTTxBuf, 0xDD);
                    break;
                }
                default:
                    BufferWrite(&UARTTxBuf, a);
            }
            BufferWrite(&UARTTxBuf, 0xC0);
        }
        
        IE1 |= UTXIE0;                    
        IFG1 |= UTXIFG0;            
    }
}


void ReadRxbuf(unsigned char *data)
{
    IE1 &= ~URXIE0;
    BufferRead(&UARTRxBuf, data);
    
    IE1 |= URXIE0;
}

Потом в main
Код
char i, txsize;
    unsigned char rxdata;
    int txdata[sizeBufTx];
BufferReset(&UARTRxBuf);
    UARTRxBuf.NData = sizeBufRx;
    UARTRxBuf.Data = bufRx;
    BufferReset(&UARTTxBuf);
    UARTTxBuf.NData = sizeBufTx;
    UARTTxBuf.Data = bufTx;

Ну. и вся остальная настройка всего , потом

Код
IE1 |= URXIE0;
_BIS_SR(GIE);    
for(;;)
    {
        rxdata = 0;
        txsize = 0;
        ReadRxbuf(&rxdata);
        if (rxdata)
        {
            txdata[txsize++] = rxdata;

            WriteTxbuf(txdata, txsize);
            
        }
    }
}

#pragma vector = UART0RX_VECTOR
__interrupt void usart0_rx (void)
{
    BufferWrite(&UARTRxBuf, U0RXBUF);
}


#pragma vector = USART0TX_VECTOR
__interrupt void usart0_tx (void)
{
    unsigned char data;
    if (!BufferRead(&UARTTxBuf, &data))        
        U0TXBUF = data;
    else
        IE1 &= ~UTXIE0;                        
}


Байты C0 - END, начало и конец посылки, DB - ESC. Если такой байт встречается в самой посылке, то он заменяется на два - DB,DС или DB, DD - ну, вы-то уж. наверное, знаете этот протокол.
В чем проблема -
вроде бы все работает, но -
при сбросе питания всегда присылается 0 или 0,1. При включении - тоже. откуда это берется - не понятно sad.gif И в первой после включения питания посылке теряется первый стартовый C0 - т.е. теряется-то вся посылка, а это недопустимо для меня - моя плата должна отсылать управляющие команды на другую - потеря одной команды приведет к проблемам. почему теряется - тоже никак не могу понять sad.gif
Вот. Будет время - спаите. помогите smile.gif
rezident
Я не вижу функции инициализации UART, но попробуйте перед тем как разрешать прерывание от приемника UART (по)чистить его флаги.
В строках
Цитата
IE1 |= UTXIE0;
IFG1 |= UTXIFG0;

следует поменять их очередность.
Кроме того, функции работы с буфером у вас не полностью реентерабельные. Они не обеспечивают атомарности доступа к переменным индекса и счетчика.
LCD
Цитата(Daria @ Sep 23 2008, 22:33) *
Не подскажите какой-нибудь кварцевый резонатор на 8MГц, как можно меньших размеров?
А не лучше ли использовать DCO с внешним резистором, если толщина схемы важнее стабильности частоты?
VAI
Цитата
Кварц, кстати, подходящий нашла у Murata - CSTCE8M0G53 - нормальный?


Мы используем Муратовские керамические трёхногие SMD-шные резонаторы с установлеными в них емкостями.
CSTCE8M00G55A-R0 - на 8МГц
CSTCR6M00G53-R0 - на 6МГц
И довольны.Нажмите для просмотра прикрепленного файла
Daria
Цитата(rezident @ Sep 24 2008, 22:12) *
Я не вижу функции инициализации UART, но попробуйте перед тем как разрешать прерывание от приемника UART (по)чистить его флаги.
В строках

следует поменять их очередность.
Кроме того, функции работы с буфером у вас не полностью реентерабельные. Они не обеспечивают атомарности доступа к переменным индекса и счетчика.

Ну, теряться байты перестали, спасибо. Но нули все равно приходят при включении питания. Не могу понять, откуда они берутся 05.gif а функции, значит, не очень? smile.gif


Цитата(LCD @ Sep 24 2008, 23:14) *
А не лучше ли использовать DCO с внешним резистором, если толщина схемы важнее стабильности частоты?

Не, не лучше. Во-первых, хочется все же высокой частоты, от DCO - это 800кГц, а, во-вторых, не важнее, конечно, просто уменьшение размеров желательно

Цитата(VAI @ Sep 25 2008, 10:57) *
Мы используем Муратовские керамические трёхногие SMD-шные резонаторы с установлеными в них емкостями.
CSTCE8M00G55A-R0 - на 8МГц
CSTCR6M00G53-R0 - на 6МГц
И довольны

Спасибо! Я так и думала, что это хорошие smile.gif Надеюсь, мы тоже будем довольны smile.gif
rezident
Цитата(Daria @ Sep 26 2008, 00:43) *
Ну, теряться байты перестали, спасибо. Но нули все равно приходят при включении питания. Не могу понять, откуда они берутся 05.gif
Покажите функцию инициализации UART.
Цитата(Daria @ Sep 26 2008, 00:43) *
Не, не лучше. Во-первых, хочется все же высокой частоты, от DCO - это 800кГц, а, во-вторых, не важнее, конечно, просто уменьшение размеров желательно
Вы опять что-то недочитали в User's Guide wink.gif Частоту DCO можно изменить программно вплоть до 6,5МГц. А если использовать внешний резистор ROSC, то DCO можно легко разогнать МГц эдак до 50 одной левой. biggrin.gif На такой частоте работать кристалл конечно же не сможет, но DCO такую частоту генерировать будет. Самолично проверял smile.gif Проблема с DCO в том, что частота его зависит от температуры и напряжения питания. Для связи требуется стабильность битовой частоты не хуже 1-2%, 0,5% это вообще для любого случая подойдет. Если напряжения питания стабильно, используется внешний резистор ROSC с хорошим ТКС (не хуже скажем 50ppm/°C), DCO при старте калибруется по часовому кварцу (а при возникновении ошибок по связи происходит перекалибровка), то вполне можно обойтись и без внешнего высокочастотного кварца, одним лишь часовым.
Daria
Цитата(rezident @ Sep 25 2008, 23:30) *
Покажите функцию инициализации UART.

Код
               U0CTL |= CHAR;                    // 8-bit character
    U0TCTL = SSEL0;                    // UCLK = ACLK
    U0BR0 = 0xA0;                    // 8.00Mhz 19200 bps (416)
    U0BR1 = 0x01;
    U0MCTL = 0x00;                    // no modulation
    U0CTL &= ~SWRST;
    ME1 |= UTXE0 + URXE0;            // Enable USART0 TXD/RXD
    IE1 |= URXIE0;

Флаги не сбрасываю, потому что не помогло smile.gif

Цитата(rezident @ Sep 25 2008, 23:30) *
Вы опять что-то недочитали в User's Guide wink.gif

Видимо, да biggrin.gif
Цитата(rezident @ Sep 25 2008, 23:30) *
Частоту DCO можно изменить программно вплоть до 6,5МГц. А если использовать внешний резистор ROSC, то DCO можно легко разогнать МГц эдак до 50 одной левой. biggrin.gif На такой частоте работать кристалл конечно же не сможет, но DCO такую частоту генерировать будет. Самолично проверял smile.gif Проблема с DCO в том, что частота его зависит от температуры и напряжения питания. Для связи требуется стабильность битовой частоты не хуже 1-2%, 0,5% это вообще для любого случая подойдет. Если напряжения питания стабильно, используется внешний резистор ROSC с хорошим ТКС (не хуже скажем 50ppm/°C), DCO при старте калибруется по часовому кварцу (а при возникновении ошибок по связи происходит перекалибровка), то вполне можно обойтись и без внешнего высокочастотного кварца, одним лишь часовым.

Спасибо, буду иметь ввиду
rezident
Ну вот она и ошибка. Первой командой инициализации USART должна быть установка бита SWRST, как это и указано в User's Guide. Вставьте в процедуру инициализации первой командой
Код
U0CTL = SWRST;

А дальше по вашему тексту.
Код
    U0CTL |= CHAR;                    // 8-bit character
    U0TCTL = SSEL0;                    // UCLK = ACLK
    U0BR0 = 0xA0;                    // 8.00Mhz 19200 bps (416)
    U0BR1 = 0x01;
    U0MCTL = 0x00;                    // no modulation
    ME1 |= UTXE0 | URXE0;            // Enable USART0 TXD/RXD
    U0CTL &= ~SWRST;
    IE1 |= URXIE0;
и все лишние нули пропадут.
Daria
Цитата(rezident @ Sep 26 2008, 19:33) *
Ну вот она и ошибка. Первой командой инициализации USART должна быть установка бита SWRST, как это и указано в User's Guide. Вставьте в процедуру инициализации первой командой
Код
U0CTL = SWRST;

не-а, не помогло smile.gif
rezident
Цитата(Daria @ Sep 30 2008, 01:16) *
не-а, не помогло smile.gif

Делайте функции работы с буфером реентерабельными. Потому, что работа с ними в том числе из прерываний идет. По крайней мере атомарность доступа к указателям и счетчику буфера обеспечить нужно.
Кстати, что у вас такое NData и cData в структуре буфера?
Daria
Цитата(rezident @ Sep 30 2008, 00:23) *
Делайте функции работы с буфером реентерабельными. Потому, что работа с ними в том числе из прерываний идет. По крайней мере атомарность доступа к указателям и счетчику буфера обеспечить нужно.
Кстати, что у вас такое NData и cData в структуре буфера?

NData - максимальный размер буфера, инициализируется UARTTxBuf.NData = sizeBufTx(16), СData - счетчик.
Такое дело. Как выяснилось, такая работа буфера тоже занимает кучу лишнего времени, так как байты загружаются в буфер, только после того, как будет отправлена предыдущая посылка
if ((IE1 & UTXIE0) == 0)
Т.е. пока 6(в данном случае) байт не передастся, запись в буфер не произойдет. Это же не правильно? smile.gif Хочу сделать так, что бы запись в буфер и отправка были независимы. Т.е. теперь
Код
int WriteTxbuf(int* data, char size)
{
    unsigned char a, j;
//        BufferReset(&UARTTxBuf);

    if((UARTTxBuf.NData-UARTTxBuf.cData)<6)return -1;

        
        BufferWrite(&UARTTxBuf, 0xC0);
        for(j = 0; j < size; j++)
        {
          
            
            a = data[j] & 0xFF;
            switch (a)
            {
                case 0xC0:
                {
                    BufferWrite(&UARTTxBuf, 0xDB);
                    BufferWrite(&UARTTxBuf, 0xDC);
                    break;
                }
                case 0xDB:
                {
                    BufferWrite(&UARTTxBuf, 0xDB);
                    BufferWrite(&UARTTxBuf, 0xDD);
                    break;
                }
                default:
                    BufferWrite(&UARTTxBuf, a);
            }
            
            
            a = data[j] >> 8;
            switch (a)
            {
                case 0xC0:
                {
                    BufferWrite(&UARTTxBuf, 0xDB);
                    BufferWrite(&UARTTxBuf, 0xDC);
                    break;
                }
                case 0xDB:
                {
                    BufferWrite(&UARTTxBuf, 0xDB);
                    BufferWrite(&UARTTxBuf, 0xDD);
                    break;
                }
                default:
                    BufferWrite(&UARTTxBuf, a);
            }
        }
        BufferWrite(&UARTTxBuf, 0x3F);
        return 0;
}

А в основной порграмме
Код
if(state!=(-1)){
            ReadRxbuf(&rxdata);
            txsize = 0;
            txdata[txsize++] = -4;
            txdata[txsize++] = -6;
        }
            if(WriteTxbuf(txdata, txsize))
                  state=-1;
            else
                state=0;

          
        if ((IE1 & UTXIE0) == 0)        
        {
            IFG1 |= UTXIFG0;                                                 IE1 |= UTXIE0;                        
        }

Почему <6? Потому, что сейчас посылки по 6 байт.
Т.е., запись происходит только если есть место для следующей посылки(6 байт), а отправка начинается, если предыдущая посылка отправлена - эти два действия независимы. Но - в отладчике все хорошо, а на практике, при большой скорости передачи(т.е. когда идет непрерывная загрузка в буфер), последний байт в посылке теряется. Отчего это происходит? 07.gif Если делать задержку между посылками, то все нормально, но это же жутко не функционально. тогда вообще нет смысла в буфере sad.gif а, кстати, не имеет ли смысла перед сбросом IE1 &= ~UTXIE0 проверять бит UTXEPT?
такой вопрос smile.gif
rezident
Цитата(Daria @ Oct 1 2008, 01:00) *
NData - максимальный размер буфера, инициализируется UARTTxBuf.NData = sizeBufTx(16), СData - счетчик.

Шо це таке "sizeBufTx(16)"? cranky.gif Функция? Или размер буфера?
Цитата(Daria @ Oct 1 2008, 01:00) *
Такое дело. Как выяснилось, такая работа буфера тоже занимает кучу лишнего времени, так как байты загружаются в буфер, только после того, как будет отправлена предыдущая посылка
if ((IE1 & UTXIE0) == 0)
Т.е. пока 6(в данном случае) байт не передастся, запись в буфер не произойдет. Это же не правильно? smile.gif Хочу сделать так, что бы запись в буфер и отправка были независимы.
Дык буфер-то один или буферы для записи и для чтения разные? Если даже один, но размер его больше 12, то почему мешает одно другому?
Цитата(Daria @ Oct 1 2008, 01:00) *
Если делать задержку между посылками, то все нормально, но это же жутко не функционально. тогда вообще нет смысла в буфере sad.gif
Раз у вас канал полнодуплексный и прием с передачей независимы, то сделайте вы два разных буфера и всех делов. laughing.gif
Цитата(Daria @ Oct 1 2008, 01:00) *
а, кстати, не имеет ли смысла перед сбросом IE1 &= ~UTXIE0 проверять бит UTXEPT?
Не имеет. Запрет прерываний не влияет ни на текущую передачу байта, находящегося в сдвиговом регистре, ни на передачу следующего байта, находящегося в буфере передатчика USART.
По поводу кода. Извините, но я уже перестал что-либо понимать в этих огрызках функций sad.gif А отрицательные числа, возвращаемые функцией (как код ошибки?), вместо привычных 0 и 1 или чисел натурального ряда, это вообще нечто cranky.gif
Daria
05.gif
Код
typedef struct CharBuffer
{
    unsigned char* Data;        
int NData;                            
int cData;                    
int pWrite;                
int pRead;                        
}
CharBuffer;

#define sizeBufTx 16
struct CharBuffer UARTTxBuf;
unsigned char bufTx[sizeBufTx];

#define sizeBufRx 16
struct CharBuffer UARTRxBuf;
unsigned char bufRx[sizeBufRx];

почти весь код два сообщения назад smile.gif
Раньше делала отправку примерно так, как вы советовали(ссобщений эдак 7-8 назад),
if ((IE1 & UTXIE0) == 0)
запись в буфер
IFG1 |= UTXIFG0;
IE1 |= UTXIE0;
В обработчике прерываний
Код
#pragma vector = USART0TX_VECTOR
__interrupt void usart0_tx (void)
{
    unsigned char data;
    if (!BufferRead(&UARTTxBuf, &data))                
                     U0TXBUF = data;
    else
        IE1 &= ~UTXIE0;                        
}

но так получается, что запись следующей посылки идет только после того, как отправится текущая посылка , условие if ((IE1 & UTXIE0) == 0) - куча времени впустую.
но я пониаю, что вам некогда разбираться во всем этом 05.gif Ну и ладно, и так помогли уже нехило smile.gif разберусь. надеюсь smile.gif
А что касается return -1... случайно smile.gif return 1, но по большому-то счету есть разница? wink.gif смысл такой, что не ноль.
rezident
Цитата(Daria @ Oct 1 2008, 02:26) *
но так получается, что запись следующей посылки идет только после того, как отправится текущая посылка , условие if ((IE1 & UTXIE0) == 0) - куча времени впустую.
Почему впустую? if это ведь не while, т.е. если условие не выполняется идем дальше, а не ждем его выполнения.
Цитата(Daria @ Oct 1 2008, 02:26) *
но я пониаю, что вам некогда разбираться во всем этом 05.gif Ну и ладно, и так помогли уже нехило smile.gif разберусь. надеюсь smile.gif
тут уже сам замысел, алгоритм непонятен. То ли вы реализуете пакетный протокол, который подразумевает запрос-ответ? То ли у вас информационный канал с контролем управления, построенный в "обертке" пакетного протокола? Если пакетный протокол точка-точка, то все так и должно быть: сначала передача запроса, затем прием ответа. Если же нужно постоянно гнать поток информации, лишь изредка, получая какие-то команды управления, то при наличии раздельных буферов чтения и записи, прерывание передатчика не нужно запрещать вообще. И опрос бита TXEPT тогда как раз нужен перед тем, как программно установить TXIFG для инициации прерываний.
При передаче работайте непосредственно с кольцевым буфером передатчика записывая в него по факту его опустошения. Т.е. в майне, где формируется пакет, счетчик буфера лишь увеличивается, а в прерывании передатчика счетчик буфера уменьшается. Индекс, естественно, только инкрементируется, учитывая переход его в начало буфера.
С буфером приемника аналогично, но наоборот. В прерывании приемника счетчик буфера увеличивается, а в майне вы буфер вычитываете и уменьшаете счетчик буфера. Прерывания ни приемника, ни передатчика при при этом запрещать не нужно. В прерывании приемника запись в буфер по факту наличия свободного места происходит.
Daria
Цитата(rezident @ Oct 1 2008, 03:05) *
Почему впустую? if это ведь не while, т.е. если условие не выполняется идем дальше, а не ждем его выполнения.

Да, но данные обновляются очень быстро, а запись в буфер не идет, пока не отправится предыдущая посылка, в результате данные теряются и сам буфер немного теряет смысл smile.gif
Цитата(rezident @ Oct 1 2008, 03:05) *
тут уже сам замысел, алгоритм непонятен. То ли вы реализуете пакетный протокол, который подразумевает запрос-ответ? То ли у вас информационный канал с контролем управления, построенный в "обертке" пакетного протокола? Если пакетный протокол точка-точка, то все так и должно быть: сначала передача запроса, затем прием ответа. Если же нужно постоянно гнать поток информации, лишь изредка, получая какие-то команды управления, то при наличии раздельных буферов чтения и записи, прерывание передатчика не нужно запрещать вообще.

Будут две платы, на одной пакетный протокол запрос-ответ, на другой - постоянный поток информации, изредка получая команды biggrin.gif пока второе
Цитата(rezident @ Oct 1 2008, 03:05) *
И опрос бита TXEPT тогда как раз нужен перед тем, как программно установить TXIFG для инициации прерываний.
При передаче работайте непосредственно с кольцевым буфером передатчика записывая в него по факту его опустошения. Т.е. в майне, где формируется пакет, счетчик буфера лишь увеличивается, а в прерывании передатчика счетчик буфера уменьшается. Индекс, естественно, только инкрементируется, учитывая переход его в начало буфера.
С буфером приемника аналогично, но наоборот. В прерывании приемника счетчик буфера увеличивается, а в майне вы буфер вычитываете и уменьшаете счетчик буфера. Прерывания ни приемника, ни передатчика при при этом запрещать не нужно. В прерывании приемника запись в буфер по факту наличия свободного места происходит.

ну, вроде работает, спасибо
rezident
Цитата(Daria @ Oct 2 2008, 00:23) *
Да, но данные обновляются очень быстро, а запись в буфер не идет, пока не отправится предыдущая посылка, в результате данные теряются и сам буфер немного теряет смысл smile.gif
Я вам уже объяснял области применения буферов: а) синхронизация асинхронных потоков, б) сглаживание неравномерностей поступления данных в потоках.
Если у вас данные обновляются быстрее, чем уходят в канал связи и при этом требуется "не потерять" их, то это лишь означает, что у вас канал слишком "узкий" и "тормозной". Причем тут буфера?
Daria
Цитата(rezident @ Oct 1 2008, 23:34) *
Если у вас данные обновляются быстрее, чем уходят в канал связи и при этом требуется "не потерять" их, то это лишь означает, что у вас канал слишком "узкий" и "тормозной". Причем тут буфера?

Буферы, а не буфера biggrin.gif канал вроде наладила smile.gif
VAI
Кстати, по уартам, я как-то выкладывал свои исходники работы с последовательными портами по прерыванию.
Там использую циклические "буфера" :-) своего изготовления.
http://electronix.ru/forum/index.php?showt...mp;#entry194257
Может пригодится...
Daria
Цитата(VAI @ Oct 3 2008, 05:12) *
Кстати, по уартам, я как-то выкладывал свои исходники работы с последовательными портами по прерыванию.
Там использую циклические "буфера" :-) своего изготовления.
http://electronix.ru/forum/index.php?showt...mp;#entry194257
Может пригодится...

Наверняка пригодится! yeah.gif Большое спасибо, VAI
Daria
Опять я smile.gif теперь нужен еще буфер - для АЦП. посмотрите, пожалуйста, нормально ли написана функция чтения? smile.gif
Та же структура
Код
typedef struct CharBuffer
{
    unsigned char* Data;            
    int NData;                        
    int cData;            
    int pWrite;                        
    int pRead;                        
}
CharBuffer;
#define sizeADCBufR 100
struct CharBuffer stADCBufR;
unsigned char ADCBufR[sizeADCBufR];

stADCBufR.NData = sizeADCBufR;
    stADCBufR.Data = ADCBufR;
    BufferReset(&stADCBufR);


Функция записи - записывает по байтам два int числа, функции записи и чтения байта описаны выше
Код
int WriteADCbuf(CharBuffer* pBuffer, int* data, int size)    
{    if((pBuffer->NData-pBuffer->cData)<2*size+1)return 1;
    for( int j = 0; j < size; j++)    
    {        
        BufferWrite(pBuffer, (data[j]&0xFF));
        BufferWrite(pBuffer, (data[j]>>8));
    }
    return 0;
}

Чтение в две переменных
Код
void ReadADCbuf(CharBuffer* pBuffer, int* data0, int* data1)
{    
  unsigned char Dat[4];
   BufferRead(pBuffer, &Dat[0]);
  BufferRead(pBuffer, &Dat[1]);
  *data0=((Dat[0]&0x00FF)|((Dat[1]<<8)&0xFF00));
   BufferRead(pBuffer, &Dat[2]);
  BufferRead(pBuffer, &Dat[3]);
*data1=((Dat[2]&0x00FF)|((Dat[3]<<8)&0xFF00));
  
}

Вызов
ReadADCbuf(&stADCBufR, &Vr0, &Vr1)
Правильно ли склеиваю? И вообще - что-то с ней, по-моему, не то smile.gif
Еще вопрос - как правильно работать с WDT? Я просто останавливаю его при начальной инициализации, и все. Но говорят, что это не правильно, нужно постоянно обращаться к нему, чтобы избежать зависания процессора. Как это делать - обращаться постоянно в цикле for(;;)?
Daria
И еще smile.gif Мне нужно обмениваться с двумя устройствами. Что лучше - использовать второй модуль USART1 или можно просто многопроцессорный формат в USART0? Нужно уже рисовать схему
Dog Pawlowa
Цитата(Daria @ Oct 5 2008, 22:35) *
И еще smile.gif Мне нужно обмениваться с двумя устройствами.

Обычно при обмене кто-то главный (master), а кто-то подчиненный (slave).
Как старшинство распределено среди этого трио?
Daria
Цитата(Dog Pawlowa @ Oct 6 2008, 10:04) *
Обычно при обмене кто-то главный (master), а кто-то подчиненный (slave).
Как старшинство распределено среди этого трио?

одно устройство принимает команды с компьютера(от оператора) и на основании их руководит вторым устройством(передает команды и принимает ответные данные). smile.gif Как-то так
Вопрос про функцию снимается, а вот про WDT? Что, если перезапускать его в прерываниях таймера через каждые сколько-то мс? Как вообще обычно им пользуются?
rezident
Цитата(Daria @ Oct 6 2008, 23:45) *
одно устройство принимает команды с компьютера(от оператора) и на основании их руководит вторым устройством(передает команды и принимает ответные данные). smile.gif Как-то так
Раз есть второй аппаратный UART, то грешнО его не использовать.
Цитата(Daria @ Oct 6 2008, 23:45) *
а вот про WDT? Что, если перезапускать его в прерываниях таймера через каждые сколько-то мс? Как вообще обычно им пользуются?
Лично я его обычно использую как таймер системных тиков, т.к. у него приоритет прерывания один из самых высоких smile.gif Если же вас интересует теория, то где бы вы не сбрасывали WatchDog он должен сбрасываться только после анализа нескольких флагов, которые устанавливаются в разных ответственных местах программы. Вы можете сбрасывать WDT в прерывании таймера, но не просто по факту попадания в это прерывания, а только если выполняются все условия "попадания" в различные другие части программы. В те, куда программный код обязательно должен привести в промежутках между сбросом WDT.
Кстати, от "защелкивания" или экстремальных случаев воздействия статики на MSP430 внутренний WatchDog не спасает.
Daria
Цитата(rezident @ Oct 6 2008, 23:04) *
Лично я его обычно использую как таймер системных тиков, т.к. у него приоритет прерывания один из самых высоких smile.gif Если же вас интересует теория, то где бы вы не сбрасывали WatchDog он должен сбрасываться только после анализа нескольких флагов, которые устанавливаются в разных ответственных местах программы. Вы можете сбрасывать WDT в прерывании таймера, но не просто по факту попадания в это прерывания, а только если выполняются все условия "попадания" в различные другие части программы. В те, куда программный код обязательно должен привести в промежутках между сбросом WDT.
Кстати, от "защелкивания" или экстремальных случаев воздействия статики на MSP430 внутренний WatchDog не спасает.

Ага, а я вот как раз хотела сначала настроить в сторожевом режиме, а потом просто сбрасывать WDTCNTCL в прерываниях таймера smile.gif Не все так просто...
То есть, вы не используете WDT в сторожевом режиме, и ничего страшного не случается? smile.gif
И вот еще более важные вопросы -
У меня куча массивов, если объявлять их в main, они начинают забивать стек, если как глобальные - то ведь память, отведенная под глобальные константы ограничена. Как быть? Можно ли как-то программно увеличить размер стека?
Нужно либо увеличивать стек, либо как-то хитро объявлять все эти массивы... подскажите. и не ругайтесь, если опять сморозила глупость smile.gif
rezident
Цитата(Daria @ Oct 7 2008, 23:09) *
Ага, а я вот как раз хотела сначала настроить в сторожевом режиме, а потом просто сбрасывать WDTCNTCL в прерываниях таймера smile.gif Не все так просто...
То есть, вы не используете WDT в сторожевом режиме, и ничего страшного не случается? smile.gif
А что там должно "страшного" случиться? cranky.gif Режим интервального таймера для WDT является штатным и документированным. Если вы сомневаетесь в помехоустойчивости, то вообще-то помехоустойчивость устройства в бОльшей степени определяется конструктивными и схемотехническими (трассировка платы, расположение и подключение внешних и внутренних цепей и т.п.) особенностями устройства, а не использованием WatchDog wink.gif
Цитата(Daria @ Oct 7 2008, 23:09) *
И вот еще более важные вопросы -
У меня куча массивов, если объявлять их в main, они начинают забивать стек, если как глобальные - то ведь память, отведенная под глобальные константы ограничена. Как быть? Можно ли как-то программно увеличить размер стека?
Нужно либо увеличивать стек, либо как-то хитро объявлять все эти массивы... подскажите. и не ругайтесь, если опять сморозила глупость smile.gif
В Plain C и ANSI C используются четыре типа переменных:
1. register (регистровые), размещаются в регистрах (хотя компиляторы чаще всего плюют на это указание). Область "видимости" текущая функция/контейнер. При выходе из функции/контейнера не сохраняются.
2. auto (автоматические или локальные), размещаются на стеке (или в регистрах, опять же по прихоти компилятора). Область "видимости" текущая функция, контейнер. При выходе из функции/контейнера не сохраняются.
3. global (глобальные), размещаются на постоянной основе в ОЗУ, в области данных. Область видимости весь текущий модуль. А объявленные с квалификатором extern могут быть "видны" в любом другом модуле проекта.
4. static (статические), размещаются на постоянной основе в ОЗУ, в области данных. Область "видимости" текущая функция (если объявление внутри функции) или текущий модуль (если объявление как глобальной снаружи какой-либо функции). При выходе из функции сохраняются. Но статические переменные не могут быть использованы в других модулях проекта и квалификатор extern к ним неприменим.
В IAR для MSP430 принято, что область данных (глобальных и статических переменных) располагается "снизу" ОЗУ, а стек "сверху" и "растет" ей навстречу. Для того, чтобы хоть как-то контролировать стек в Plain C, вы можете сами организовать "кучу" (HEAP). Для этого создайте большой глобальный массив и располагайте свои временные "массивчики" внутри его. Но для этого нужно будет научиться (если еще не научились) пользоваться указателями, обязательно контролируя выходы их (указателей) за границы выделенных "массивчиков" и глобального массива кучи.
А вообще в map-файле, который можно генерировать с помощью конфигурирования опций IAR, указан размер стека при использовании каждой функции.
Daria
Цитата(rezident @ Oct 7 2008, 21:41) *
В IAR для MSP430 принято, что область данных (глобальных и статических переменных) располагается "снизу" ОЗУ, а стек "сверху" и "растет" ей навстречу. Для того, чтобы хоть как-то контролировать стек в Plain C, вы можете сами организовать "кучу" (HEAP). Для этого создайте большой глобальный массив и располагайте свои временные "массивчики" внутри его. Но для этого нужно будет научиться (если еще не научились) пользоваться указателями, обязательно контролируя выходы их (указателей) за границы выделенных "массивчиков" и глобального массива кучи.
А вообще в map-файле, который можно генерировать с помощью конфигурирования опций IAR, указан размер стека при использовании каждой функции.

Все же пока не ясно 05.gif Есть массивы, которые объявлены в main, они висят в стеке, потом при вызове какой-нибудь функции, создаются еще локальные - и забивают в этот момент стек. я вижу размер стека, вижу, что заполнен, но как же быть, если массив нужен? Объявить большой глобальный - да, но если не хватит памяти, отведенной под глобальные переменные?
Кстати, в руководстве, которое вы часто поминаете, сказано, что при начальной инициализации, нужно инициализировать указатель стека(указав вершину ОЗУ). Как записывается инициализация SP? smile.gif
rezident
Цитата(Daria @ Oct 8 2008, 00:12) *
Все же пока не ясно 05.gif Есть массивы, которые объявлены в main, они висят в стеке, потом при вызове какой-нибудь функции, создаются еще локальные - и забивают в этот момент стек.
Пример из программы можете привести, где по-вашему создаются локальные копии массивов локальных переменных?
Цитата(Daria @ Oct 8 2008, 00:12) *
я вижу размер стека, вижу, что заполнен, но как же быть, если массив нужен? Объявить большой глобальный - да, но если не хватит памяти, отведенной под глобальные переменные?
Либо вы не совсем аккуратно программируете, либо выбранный кристалл (размер имеющегося у него ОЗУ) не соответствует вашей задаче.
Цитата(Daria @ Oct 8 2008, 00:12) *
Кстати, в руководстве, которое вы часто поминаете, сказано, что при начальной инициализации, нужно инициализировать указатель стека(указав вершину ОЗУ). Как записывается инициализация SP? smile.gif
Поскольку вы программируете на Си, а не на ассемблере, то задачей инициализации указателя стека и очисткой/инициализацией глобальных и статических переменных, находящихся в сегменте DATA_Z, занимается сам компилятор. Все это делается в процедуре StartUp, которая выполняется ДО вызова функции main. Надеюсь вы в курсе, что main это тоже функция и у нее есть пролог и эпилог, как и у подавляющего большинства других функций? Вот если бы вы писали программу полностью на ASM, то инициализацию указателя стека и инициализацию/очистку глобальных переменных пришлось бы писать тоже вам. Вручную wink.gif
Daria
Цитата(rezident @ Oct 7 2008, 23:07) *
Либо вы не совсем аккуратно программируете, либо выбранный кристалл (размер имеющегося у него ОЗУ) не соответствует вашей задаче.

Однозначно, первое smile.gif ОЗУ = 2 КВ. Но я поняла, в чем дело - это не стек забивался, а размер stack heap был по умолчанию задан 50 байт. smile.gif Я не тормоз, я медленный газ biggrin.gif Но теперь все вроде в порядке.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.