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

 
 
17 страниц V  < 1 2 3 4 5 > »   
Reply to this topicStart new topic
> MSP430 - снова вопросы от чайника, Вопросы от чайника про MSP и магнитный компас
Daria
сообщение Aug 13 2008, 19:59
Сообщение #31


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Aug 13 2008, 22:19) *

Ясно, спасибо
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 14 2008, 08:09
Сообщение #32


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Ух-х, какие крутые виражи! Ух, как человека мысли колбасят:
Цитата( @ Aug 13 2008, 23:06) *
... Так что совершенно зря разразились такой тирадой smile.gif

И сразу же, не давая осознать -- ба-бах!
Цитата
Впрочем, не зря, ...


Rezident -- восхищаюсь Вашим терпением. Буду счастлив, если даму удастся выдернуть из девичьего восприятия мира. Да, длинный путь предстоит, долго ей топать. Но, человека надо вытаскивать. Тем более, сам чел этого хочет.

Daria, не останавливайтесь на полпути! Мы все за Вас переживаем и хотим получить полноценного товарища. Глупой Вас никто не считает, просто склад ума/логика мышления у Вас несколько иные. Это не плохо и не хорошо, это -- просто имеет быть.

"Не важно -- кто ты и где ты сейчас. Важно -- куда ты живешь" (С) не помню чье.
Всех благ!


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 14 2008, 20:47
Сообщение #33


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(zhevak @ Aug 14 2008, 12:09) *
Rezident -- восхищаюсь Вашим терпением. Буду счастлив, если даму удастся выдернуть из девичьего восприятия мира. Да, длинный путь предстоит, долго ей топать. Но, человека надо вытаскивать. Тем более, сам чел этого хочет.

Я сама восхищаюсь его терпением 07.gif Я бы себя уж давно послала, причем с громкими выкриками biggrin.gif
Цитата(zhevak @ Aug 14 2008, 12:09) *
Daria, не останавливайтесь на полпути!

Ну не знаю, не знаю. мы женщины все такие непоследовательные - то почитать, то пострелять... biggrin.gif
Цитата(zhevak @ Aug 14 2008, 12:09) *
Мы все за Вас переживаем

Надеюсь, аппетит не пропал? wink.gif
Цитата(zhevak @ Aug 14 2008, 12:09) *
Всех благ!

И Вам!! Спасибо за мнение

Rezident, по поводу буфера, пример которого вы приводили. А что, если cbuf.rIdx будет равен cbuf. wIdx +1? Т.е. если считывание "обгонит" запись? Может, стоит поверять if((cbuf.cntr< max_bufsize)&(cbuf.rIdx !=cbuf. wIdx +1))?
Или опять мойс клад ума/логика мышления меня подвел? sad.gif тогда - ой, беда, беда - огорчение.
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 14 2008, 21:01
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 15 2008, 02:47) *
Rezident, по поводу буфера, пример которого вы приводили. А что, если cbuf.rIdx будет равен cbuf. wIdx +1? Т.е. если считывание "обгонит" запись? Может, стоит поверять if((cbuf.cntr< max_bufsize)&(cbuf.rIdx !=cbuf. wIdx +1))?
Или опять мойс клад ума/логика мышления меня подвел? sad.gif тогда - ой, беда, беда - огорчение.
Вы про циклический буфер? Считывание не может обогнать запись, т.к. перед считыванием должен проверяется счетчик записей. Если счетчик равен нулю, то буфер пуст. А если при этом имеется "разбег" индексов, то его нужно обнулить, установив оба индекса в начало буфера. Только при этом конечно же нужно соблюдать атомарность доступа, чтобы не произошло сбоев записей при одновременном доступе к переменным индексов и счетчика. Атомарность доступа можно обеспечить временным запретом прерываний.
В дополнение. Ситуация когда cbuf.rIdx будет равен cbuf. wIdx +1 не исключена. Но она может быть только в случае, когда весь буфер заполнен. При этом счетчик элементов буфера должен иметь значение равное размеру буфера.
Хотя пожалуй нет. Я ошибся. Счетчик в этом случае будет равен размер_буфера-1. Т.к. для полностью заполненного (и для пустого) циклического буфера значения индексов д.б. равны.
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 17 2008, 11:13
Сообщение #35


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Ага, будем считать с буфером приема разобрались smile.gif Теперь что касается передачи. Во-первых, все-таки мой старый вопрос - как в этом случае обойтись без этих циклов while, которые ждут установки флага о готовности? ведь тут тоже пустой простой... Что касается буфера, то у меня как-то не получилось biggrin.gif и даже наверное не буду приводить код, опять будете смеяться biggrin.gif Хотя бы принцип верный? -
Запись в буфер идет в прерывании АЦП, считывается постоянно в цикле for(;;); так как вообще говоря передача должна идти посылками по 4 байт (стартовый символ"*", два байта данных (int) и стоповый "#"), то считывается сначала в массив [4], а этот массив передается по байтам через регистр U0TXBUF. Но, когда передается, как обойтись без этих while?
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 17 2008, 14:49
Сообщение #36


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



О-хо-хо... Ну да ладно!

Даша, я предполагаю, что Вы только-только подходите к понятью принципов работы событийно-управляемых (event-driven) автоматов. Вы уже освоили линейное и процедурное
программирование, теперь перед Вам открывается совершенно другой мир. Другая планета. Здесь все не так.


Извините, маленькая лекция.

Допустим, у нас есть некоторый девайс, который имеет клавиатуру и дислей. Например, нечто типа калькулятора. Наша программа должна считывать клавиатуру, выполнять какие-то определенные действия и результат выводить на экран. Как бы мы написали такую программу?

Во первых, это бесконечный цикл, тело которого состоит из вызова трех функций. Пусть они будут называться так:
GetKey()
DoSomething()
DisplayResult()
чтобы не усложнять, аргументы функций пока опустим из рассмотрения. А вот названия функций говорят сами за себя -- получить код нажатой клавиши, выполнить какое-то действие, вывести результат.

Вот основной цикл нашей программы:
Код
  while (1)
  {
    GetKey();
    DoSomething();
    DisplayResult();
  }


Рассмотрим вызов функция GetKey(). Вроде бы все ясно -- функция должна вернуть код нажатой клавиши. А что делать, если ни одна клавиша не нажата? Значит, функция не вернет управление. Допустим, что это так. Тогда получается, что наше устройство постоянно как-бы зависает на этой функции.

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

Но для этого устройства такое построение программы допустимо. Поскольку предопределенные действия выполняются только тогда, когда юзер соизволит нажать кнопочку. С другой стороны, нет нажатия -- значит, и делать ничего не надо! Пока все срастается.

Так было раньше, когда программы были маленькие, процессоры глупенькие, а деревья большие. Но мир изменился. Сейчас МК стали обладать многими периферийными устройствами и интерфейсами, которые зачастую работают одновременно.

Противоречие в современных устройствах заключается в том, что периферийных устройств много, а "думатель" (АЛУ) -- один.

Давайте-ка теперь к нашему чудо-калькулятору добавим часы, которые раз в секунду должны подновлять свои показания на дисплее, и посмотрим как это повлияет на нашу программу.

Добавляя в цикл две функции GetCurrentTime() и (), мы не решим проблему.
Код
  while (1)
  {
    GetKey();
    DoSomething();
    DisplayResult();
    GetCurrentTime();
    DisplayTime ();
  }


Понятно, что управление, зависая в GetKey(), будет блокировать всю программу. Понятно, что часы будут подновляться только при нажатии какой-либо кнопочки. Страшно неудобно. Такое изделие никто не купит. Что делать?

Можно пойти двумя путями. (Сразу скажу, Вы, Daria, как мне кажется, в своей программе идете первым путем.)


Путь первый (а-ля-DOS): добавить еще пару функций IsKeyHit() и IsTimeChanged(), которые будут возвращать управление сразу. Такие функции еще называют неблокирующими. Эти функции "говорят" только о том, что нажата ли вообще какая-нибудь клавиша или нет, изменилось ли время или еще нет.

Теперь наш цикл будет выглядеть так:

Код
while (1)
{
  if (IsKeyHit())
  {
     GetKey();
     DoSomething();
     DisplayResult();
  }
  if (IsTimeChanged())
  {
    GetCurrentTime();
    DisplayTime();
  }
}


В этом случае, наша программа будет со скоростью света совершать холостые обороты. Вот смотрите, скорость работы МК составляет миллионы инструкций в секунду, скорость нажатия клавиш -- максимум десяток-другой в секунду, а про именение текущего времени, так вообще раз в секунду. Единственное, что напрягает, -- это кпд программы. Но, с другой стороны, прога-то работает! А это есть самое главное. Ибо ведь никому не нужно устройство, которое не выполняет своей функции. А наше устройство свою функцию выполняет. Ведь так? (Заказчика не интересует, как и на какой парадигме строится программа, Его интересует только конечный результат. А мы его, не смотря на дремучесть нашего кода, обеспечиваем.)

Второй путь (а-ля-Windows): Это то, о чем я говорил в самом начале поста, это событийно-управляемый автомат. Работает эта штука следующим образом.

В таком автомате (системе) есть два дуальных механизма.

Первый -- регистрирует происходящие в системе изменения (события) и записывает в очередь соответствующее сообщение об этом событии. Очередь надо понимать чисто в компьютерном смысле -- т.е. бесконечный (кольцевой) буфер.

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

Но в этом случае у нас оказалось, что постановка в очередь и обработка сообщений будут (программно) разнесены в разные части. По началу, это кажется крайне неудобным. Но создав несколько проектов Вы придете к мысли, что так все же намного легче разрабатывать свои программы, а потом их сопровождать. Т.е. даже по прошествии какого-то времени, возвращаясь к коду, его легче понять и добить запоздалыми требованиями заказчика по недостающей функциональности устройства.


Итак, возвращаемся к событийно-управляемым системам. Поставщиками событий в первую очередь являются не что иное, как всевозможные прерывания от периферийных устройств. Во вторую очередь, это могут быть какие-то результаты работы программы. (Я догадываюсь, сейчас это несколько сложно понять. Но что делать? Ведь не всегда бывает легко с первого раза въехать в какие-то новые понятия. Тем более, если эти понятия очень емкие и не вписываются в установившиеся, привычные для нас рамки. Терпите. Учитесь. Другого пути нет.)

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

Еще пару-тройку раз для уяснения:

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

Закончил АЦП измерение -- прерывание. Заходим, сообщение в очередь, выходим.
Очередной байт отправлен (по USART-у) -- прерывание. Заходим, сообщение в очередь, выходим.

Думаю, идея понятна?


С другой стороны программы, имеем опять тот же самый бесконечный цикл. Но работает он уже чуть-чуть по-другому, не совсем так, как в нашем исходном варианте в начале статьи.

Теперь нам не надо периодически пробегать (говорят – заниматься поллингом) по всем нашим ПУ, опрашивать каждое – есть ли нажатие кнопочки или нет, говов ли АЦП или нет, тикнул ли таймер или нет.

Вместо всего этого, теперь имеется единственная функция GetMessage() и вслед за ней располагается так называемый кракер сообщений (т.е. расшифровщик). Задача этой "парочки" -- вытянуть из очереди сообщение, и вызывать соответствующую функцию по его обработке.

Выглядит это намного приятнее:
Код
  unsigned char msg;

  while ()
  {
    if (GetMessage(&msg))
      switch (msg)
      {
        case MSG_KEYPRESS:
          DoKey();
          break;

        case MSG_TICK:
          DisplayCurrentTime();
          break;
  
        case MSG_ADCREADY:
          SendResult();
          break;

        case MSG_TXD:
          SendNextByte();
          break;

        ...
      }

      // а здесь вот -- самое удобное место пинать собаку (WDR)
  }


Теперь пара слов о переменной msg. У меня здесь это -- просто байт, но в случае очень навороченной системы Вам никто не запрещает для кодирования сообщений вместо байта использовать слово или вообще структуру. Важно только одно: важно соблюсти атамарность операций занесения и извлечения из очереди сообщений. Т.е., другими словами, сделать так, чтобы не получилось, что система, начав записывать одно сообщение в очередь, окажется в состоянии другого прерывания, которое запишет свое сообщение. Потом в очередь будет дозаписан остаток от первого сообщения. В результате в очереди сообщений получится фигня полная. Все рухнет.

Есть еще некоторые тонкие моменты. Поскольку обработка сообщений конечна по времени (т.е. они не обрабатываются мгновенно), а источников событий несколько, и они работают асинхронно, то нужно делать очередь сообщений достаточно длинную. Но какую? Ее хоть и называют "бесконечной", но создается-то она на основе обычного линейного буфера, какой-то конкретной длины. И Ваша задача (О-о, это искусство!) найти оптимальную длину буфера. Маленький буфер может быть легко переполнится, большой -- буфер сожрет память, которой и так кот наплакал.

Не надо также забывать, что обработчики сообщений не должны долго работать, т.е. они не должны узурпировать процессорное время. Я как-то занимался одним проектом. Там нужно было выводить инфу на графический LCD, одновременно нужно было оперативно реагировать на кнопочки и держать связь с компом и дюжиной периферых устройств, подцепленных к двух UART'ам. Сложность состояла в том, что LCD подключался по квадратной (I2C) шине. Длина шлейфа была метра полтора. Я не рискнул, "зажигать" его на 400 кГц. А на 100 кГц, обновление экрана занимало почти четверть (или даже более, не помню точно!) секунды. Если бы обновление LCD было реализовано в одной функции-обработчике, то это легко бы привело к переполнению очереди сообщений. В моменты перерисовки дисплея реакция на клавиатуру отсутствовала бы, связь бы с ПУ нарушалась бы. Приятного мало.

Я сделал так, я разбил LCD на несколько областей, и для перерисовки каждой области создавал свое индивидуальное сообщение. В результате, перерисовка LCD выполнялась как серия перерисовок его отдельных областей. Эта серия сообщений, понятно что, могла быть "разбавлена" сообщениями от клавиатуры и от других ПУ. В целом это создало картину практически мгновенной реакции на нажатие клавиш, способности устройства рисовать на экране и одновременно (и без задержек) заниматься периферией, отвечать компу на его запросы.

Не знаю, что еще можно добавить. С одной стороны, сказать еще много чего можно, а с другой... а то-ли это место (форум), где надо много говорить?

Насчет критики. Я, вобщем-то, как-то не рассчитывал на нее. Просто писал и все. Даже не столько пытался ответить Daria, сколько вообще хотел поделиться своим опытом. Но поскольку я тут много чего сказал, критика должна быть.

Сообщение отредактировал zhevak - Aug 17 2008, 15:42


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 17 2008, 15:09
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 17 2008, 17:13) *
Запись в буфер идет в прерывании АЦП, считывается постоянно в цикле for(;;); так как вообще говоря передача должна идти посылками по 4 байт (стартовый символ"*", два байта данных (int) и стоповый "#"), то считывается сначала в массив [4], а этот массив передается по байтам через регистр U0TXBUF. Но, когда передается, как обойтись без этих while?
Дык точно также как вы с АЦП делаете. Использовать передачу по прерываниям.
uart0.h
Код
#ifndef UART0_H
#pragma pack(2)
typedef struct st_uart  //тип структуры данных буфера UART0
{ unsigned int cntr;    //счетчик буфера
  unsigned int idx;     //индекс буфера
  unsigned char buf[10];//буфер UART
} st_uart;
#pragma pack()
#define UART0_H
#endif

main.c
Код
#include "uart0.h"

unsigned int adcRes;//результат преобразования АЦП, который нужно передать
st_uart uart;           //структура данных буфера UART0

void main( void )
{
  while(1)
  {
//  ...
    if ((IE1&UTXIE0)==0); //проверяем готовность UART0 к передаче, бит UTXIE0
    { uart.idx=0;         //используем еще и как признак окончания передачи пакета
      uart.cntr=0;
      uart.buf[uart.cntr++]='*';  //символ начала пакета
      uart.buf[uart.cntr++]=adcRes>>8;  //старший байт результата
      uart.buf[uart.cntr++]=adcRes&0xFF;//младший байт результата
      uart.buf[uart.cntr++]='#';  //символ конца пакета
      IFG1|=UTXIFG0;     //установим флаг, чтобы инициировать прерывания UART0
      IE1|=UTXIE0;        //разрешим прерывания UART0
    }
//  ...
  }
}

#pragma vector=USART0TX_VECTOR
#pragma type_attribute=__interrupt
void UART0TX_ISR(void)
{ if (uart.cntr>0)    //проверяем количество символов в буфере
  { U0TXBUF=uart.buf[uart.idx++]; //передаем текущий символ
    uart.cntr--;      //уменьшаем счетчик количества символов
  }
  else
    IE1&=~UTXIE0;     //если буфер пуст, то сбрасываем бит разреш.прерыв. UART0
}

Я использовал в примере typdef на случай, если вы разбиваете проект на отдельные модули. Если же у вас вся программа в одном файле, то можно объявить структуру uart прямо перед main-ом. Вместо строки
Код
st_uart uart;           //структура данных буфера UART0

Бит разрешения прерывания от передатчика UART0 я использовал как флаг готовности буфера передатчика. Он устанавливается в main, одновременно разрешая прерывания от передатчика и сбрасывается в обработчике прерывания по завершению передачи буфера. Для передачи 4-х байтного пакета будут 5 прерываний от передатчика UART0. В последнем прерывании передачи символа не будет, а будет лишь сброшен UTXIE0.

Цитата(zhevak @ Aug 17 2008, 20:49) *
Интересен вызов функция GetKey(). Вро де бы все ясно -- функция должна вернуть код клавиши. А что делать, если ни одна клавиша не нажата? Получается, функция

управление не должна возвращать. Допустим, что это так. Тогда получается, что наше устройство постоянно как-бы зависает на этой функции. И действительно, посчитать

результат и вывести его, действительно, занимает не так уж и много времени по сравнению с тем, что юзер может вообще пойти попить кофейку. Да?

Но для нашего устройства такое построение программы не страшно. Поскольку предопределенные действия выполняются тогда, когда юзер соизволит нажать кнопочку.
Извините, но у вас ерунда написана. Функция GetKey() никогда не циклится на опросе, а всегда и в любом случае возвращает код нажатой клавиши, иначе она бы называлась не GetKey, а WaitKey biggrin.gif Только в случае когда ни одна клавиша не нажата функций GetKey возвращает скан-код NULL. А если идет запись в буфер клавиатуры, то просто запись туда не производится. Поэтому бесконечный цикл вовсе не зависает на опросе клавиатуры, а крутится себе как и положено wink.gif Естественно, что в функции DoSomething() должна быть предусмотрена обработка скан-кода с кодом NULL.
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 17 2008, 15:51
Сообщение #38


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(rezident @ Aug 17 2008, 21:09) *
Извините, но у вас ерунда написана. Функция GetKey() никогда не циклится на опросе, а всегда и в любом случае возвращает код нажатой клавиши, иначе она бы называлась не GetKey, а WaitKey biggrin.gif Только в случае когда ни одна клавиша не нажата функций GetKey возвращает скан-код NULL. А если идет запись в буфер клавиатуры, то просто запись туда не производится. Поэтому бесконечный цикл вовсе не зависает на опросе клавиатуры, а крутится себе как и положено wink.gif Естественно, что в функции DoSomething() должна быть предусмотрена обработка скан-кода с кодом NULL.


Не, не! Не стоит так сильно реагировать на имя!

Функция GetKey() -- это моя функция, не библиотечная. Про библиотеки не говорю. Более того, я не писал готовый коупи-пэйст код, а излагал парадигму. Жаль что Вы зацепились за эту мелочь. Если Вас это очень смущает, ну замените что-ли название функции на GetPressedKey().


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 17 2008, 15:56
Сообщение #39


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zhevak @ Aug 17 2008, 21:51) *
Не, не! Не стоит так сильно реагировать на имя!

Функция GetKey() -- это моя функция, не библиотечная. Про библиотеки не говорю. Более того, я не писал готовый коупи-пэйст код, а излагал парадигму. Жаль что Вы зацепились за эту мелочь. Если Вас это очень смущает, ну замените что-ли название функции на GetPressedKey().
Да меня вообще не волнует названия функций smile.gif, а "прицепился" я как раз а вашей "парадигме", то бишь к описанию алгоритма "вечного цикла". Я бы еще понял зацикливаение на опросе клавиатуры, если бы перед этим MCU ушел в режим "спячки" для энергосбережения. Вы же описали другой алгоритм, который я не считаю оптимальным в частности и верным в общем. А если вы хотели описать "парадигму" расслоения на os, driver и application, то извините, сделали это не очень внятно. laughing.gif
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 17 2008, 16:38
Сообщение #40


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(rezident @ Aug 17 2008, 21:56) *
Да меня вообще не волнует названия функций smile.gif, а "прицепился" я как раз а вашей "парадигме", то бишь к описанию алгоритма "вечного цикла". Я бы еще понял зацикливаение на опросе клавиатуры, если бы перед этим MCU ушел в режим "спячки" для энергосбережения. Вы же описали другой алгоритм, который я не считаю оптимальным в частности и верным в общем. А если вы хотели описать "парадигму" расслоения на os, driver и application, то извините, сделали это не очень внятно. laughing.gif

не надо laughing.gif -- Я не описывал расслоение. Я описывал только парадигму событийно-управляемой системы. Т.е. ситему, которая работает на принципе реагирования на какие-либо события. Система не занимается поллингом. Система ждет событий, в свободное от работы время совершает холостые циклы. Если хотите -- может вообще спать. Не проблема!

Если Вас не устраивает энергопотребление, то в цикле после кракера и после того, как пнете собаку, поставьте команду для спячки. Проц должен проснутся либо по какому-либо событию, либо по таймеру. Использование таймера (для системного времени), я думаю, в таких системах должно быть предусмотрено. Само собой разумеется, что тайм-аут собаки должен превышать тайм-аут таймера.

Изложенная мною (но не я автор!) парадигма построения программ, предполагает, что она применяется к устройствам, которые намного сложнее, чем простой генератор прямоугольных импульсов. Да, действительно, там проще и легче в основном цикле программы сначала проверять конкретное ПУ (UART, ADC, таймер,...) и, если оно готово, вызывать соответствующую функцию. После чего переходить к проверке следующего ПУ. И т.д. до конца цикла.


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 17 2008, 20:49
Сообщение #41


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



smile.gif Да-а-а 07.gif утром отправляю вопрос, иде себе спокойненько по своим делам, захожу вечером, а тут!... 07.gif Целая переписка Маркса и Энгельса! Я, когда защищалась на своем матфаке, то у меня доп. диплом был по квалификации "преподаватель" smile.gif Этот диплом представлял собой цикл лекций по истории развития теории вероятностей. Там тоже было много всяких примеров, баек и исторических справок. к чему это я? biggrin.gif А к тому, что вам, господа, особенно вам, zhevak, можно не только диплом защищать по специальности "преподаватель программирования контроллеров" , а целую кандидатскую по теме "история развития программирования контроллеров и ваще программирования" biggrin.gif
Но - если чел находит столько времени, сил и желания помочь и рассказать, то - большое спасибо, заходите еще, буду рада и все такое. Rezident, ваша лекция про детей и песочницы тоже была просто класс biggrin.gif a14.gif
Да, rezident, я давно знала, что вы хороший, но вы - ПРОСТО СУПЕР! biggrin.gif Большое спасибо за помощь. Даже не знаю, как вас благодарить за месяцы мучений со мной(а еще сколько предстоит... smile.gif )
На досуге подумаю об этом smile.gif (ну, ну - утихомирьтесь, случайно заглянувшие сюда пошляки) Будут пожелания - высказывайтесь biggrin.gif Есть пара непоняток по вашему коду, но пока не буду спрашивать - вдруг в процессе внедрения сама пойму biggrin.gif
заходите обязательно еще!
Эх, кто бы мне еще по поводу датчиком HMC помог - непонятки все же с калибровкой... т.е. самый простой способ понятен и почти работает, но при таком ТЗ он никак не годится... В разделе "датчики, метрологи и т.п." все на эту тему молчат crying.gif но это так, мысли вслух, и к теме не отностится
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 19 2008, 17:42
Сообщение #42


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



здравствуйте снова. Такой вопрос - во время работы проги, для того, чтобы выполнить калибровку, хочу перенастроить АЦП из однократно-последовательного режима в повторно-последовательный. И для калибровки работать без прерываний. Это ведь делается редко и при выполнении калибровки все остальное вообще не работает, можно же тогда и с циклами while, правильно? smile.gif Дело в том, что все остальное делается теперь по прерываниям и, запрещая их, очень легко и просто все останавливаю. Так вот. Могу я написать так:
ADC12CTL0&= ~ ENC;
ADC12CTL1 &= ~ CONSEQ_1
ADC12CTL1 |= CONSEQ_3
Ну и после калибровки
ADC12CTL0&= ~ ENC;
ADC12CTL1 &= ~ CONSEQ_3
ADC12CTL1 |= CONSEQ_1
Нет тут какого-нибудь недопустимого действия? А то мало ли, чего мое альтернативное мышление натворит smile.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 19 2008, 21:40
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Aug 19 2008, 23:42) *
можно же тогда и с циклами while, правильно? smile.gif
Можно. Даже нужно. Чтобы не переопределять основной алгоритм измерения в прерывании.
Цитата(Daria @ Aug 19 2008, 23:42) *
Могу я написать так:
ADC12CTL0&= ~ ENC;
ADC12CTL1 &= ~ CONSEQ_1
ADC12CTL1 |= CONSEQ_3
Ну и после калибровки
ADC12CTL0&= ~ ENC;
ADC12CTL1 &= ~ CONSEQ_3
ADC12CTL1 |= CONSEQ_1
Нет тут какого-нибудь недопустимого действия? А то мало ли, чего мое альтернативное мышление натворит smile.gif
Можно, только аккуратнее с битовыми масками. Чистить биты CONSEQx лучше всегда так
Код
ADC12CTL1 &=~CONSEQ_3;

чтобы каждый раз не задумываться и случайно не "пролететь", ошибившись с предыдущим режимом измерения ADC12. Ну и конечно после изменения режима, не забыть вновь разрешить преобразование, установив ENC. А так, все верно, за исключением того, что хорошо бы изменить порядок сброса CONSEQx и ENC. Сначала останов последовательности преобразований сбросом CONSEQx, а потом сброс ENC. Это может быть существенным когда вы используете (разрешили) прерывание ADC12.
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 20 2008, 18:20
Сообщение #44


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Aug 20 2008, 01:40) *
А так, все верно, за исключением того, что хорошо бы изменить порядок сброса CONSEQx и ENC. Сначала останов последовательности преобразований сбросом CONSEQx, а потом сброс ENC. Это может быть существенным когда вы используете (разрешили) прерывание ADC12.

Спасибо!
Go to the top of the page
 
+Quote Post
Daria
сообщение Aug 21 2008, 18:01
Сообщение #45


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Здравствуйте. rezident, по поводу примера буфера передачи, который Вы написали smile.gif
для чего делается вот это
#pragma pack(2)
...
#pragma pack()
Как я понимаю, это выравнивание? т.е. #pragma pack(2) - теперь структура будет иметь четное количество байтов, а #pragma pack() - возвращение к установке "по умолчанию"? Так или не совсем? А зачем тогда именно pack(2)? Если написать pack(1) - то будет ровно то количество байт, которое задается, т.е. четыре.
? Объясните чуть подробнее, пожалуйста. smile.gif И еще - почему именно buf[10], чем обусловлено 10 и как его выбирать? smile.gif

И вообще мне не понятно, при таком протоколе, а это вроде довольно распространенный: *, данные, #- как быть при приеме? Вот цифровое значение # - 35, а если приходит такое число? Вот азимут у меня, допустим, 35 - тогда же путаница получится?
Вот у меня такой флажок 0хFF - уникален, учитывая, что передаю по 6 бит smile.gif А как обычно делают?
Go to the top of the page
 
+Quote Post

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

 


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


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