Обсуждаем контроллеры компании Atmel.
Ответить

Как на С "приплюсовать" два символа?

Чт авг 09, 2012 19:33:48

Приветствую вас, уважаемые Коты!
Нужна ваша помощь чайнику в программировании.
Программить начал недавно, по сему на многое пока мозгов не хватает...
Работаю в CVAVR.
Задача такова:
Контроллер опрашивает пины. Если сработал, например, первый - шлет по UART символ Q. Если сработал второй - шлет символ W. А если сработали оба - надо слать строку QW (ну или WQ).
Вот как же мне "склеивать" эти символы в программе?
Дайте пожалуйста пример кода или ткните в место, где можно почитать об этом. А то сам найти ничего не могу... :(
Спасибо Вам огромное!

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 19:48:16

Если просто символы, без "перевода строки", то и посылай их по отдельности. Они просто придут подряд. И всё.

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 19:52:53

А если сработали оба - надо слать строку QW (ну или WQ).


Не ясна ваша проблема. :? Всё, что вы пошлёте по UART'у, никак не разделяется на сообщения. Если вы сперва пошлёте Q, а потом W, то получатель их и получит в таком порядке. Даже если W придёт через час. Что же такое "Вот как же мне "склеивать" эти символы в программе?"?

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 19:54:29

Вот в том-то и проблема (для меня): символов всего может быть 20. И посылаться они могут, как я писал выше, в любой последовательности, в зависимости от сработавших датчиков. Гадость в том, что сперва должны опрашиваться все 20 датчиков, а уж потом зараз отсылаться строка символов. Т.е. сработавшие символы надо как бы склеиль в строку и отослать.
Вот как так сделать я не могу сообразить...

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 20:01:24

Т.е. сработавшие символы надо как бы склеиль в строку и отослать.


Только зачем вам вклеивать? Их всё равно примет абонент ПОСЛЕДОВАТЕЛЬНО в порядке передачи.
Ну сделайте тогда так:

if (сработал_датчик1) послать символ 1
if (сработал_датчик2) послать символ 2
...
if (сработал_датчикN) послать символ N
послать символ '\r'
послать символ '\n'




Или через массив:

unsigned char sensor[100];
int sensor_index=0;
if (сработал датчик1)
{
sensor[sensor_index]='Q';
sensor_index++;
}
...
if (сработал датчикN)
{
sensor[sensor_index]='W';
sensor_index++;
}
//передаём строку
sensor[sensor_index]='\r';
sensor_index++;
sensor[sensor_index]='\n';
sensor_index++;

for(int n=0;n<sensor_index;n++)
{
//отправляете символ из sensor[n] по UART.
}
Вот и всё.


Только, конечно, проверку датчиков лучше в цикл засунуть.

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 20:18:05

Опять же они будут слаться последовательно. Хотя с массивом - это идея хорошая! Спасибо Вам!
Просто я боюсь что могу упустить срабатывание датчика пока буду слать. Датчики могут срабатывать "одновременно", точнее с разницей в несколько микросекунд. И пока я буду слать упущу срабатывание. Или я не прав?
А сколько тактов занимает отправка символа, очистка буфера, выставление флага и т. д. Через сколько вобщем можно будет проверять следующий датчик после отправки?

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 21:04:55

Просто я боюсь что могу упустить срабатывание датчика пока буду слать.


Тогда используйте прерывания. Отправляйте символ по UART, а момент окончания передачи фиксируйте по прерыванию.

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 21:16:31

Тогда я еще больше времени потеряю: пока зашел в прерывание, пока вышел...
Я так понимаю С не умеет делать как я хочу...
Наверно надо тогда создать кучу (по количеству датчиков) переменных типа bit, записывать единовременно в них состояния датчиков на момент опроса,. а потом уж те переменные в которых 1 - датчик сработал, сопостовлять с символом и слать их по очереди, как и советовали.
Мне кажется это единственное решение...

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 21:30:45

Ну вот - достаточно было правильно сформулировать вопрос, как ответ пришел сам собой :)
Хотя решения по существу и нет :( По любому, частота опроса датчиков не может быть выше, чем частота посылок по UART , поэтому если датчик может "мигнуть" на пару микросекунд, то сигнал может быть пропущен.

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 21:35:05

Тогда я еще больше времени потеряю: пока зашел в прерывание, пока вышел...


Вы, если не секрет, что делаете, если у вас микроконтроллер на мегагерцовой и выше частоте не может потратить десяток тактов (т.е. микросекунды!) на прерывания?

Наверно надо тогда создать кучу (по количеству датчиков) переменных типа bit, записывать единовременно в них состояния датчиков на момент опроса,. а потом уж те переменные в которых 1 - датчик сработал, сопоставлять с символом и слать их по очереди, как и советовали.


Опять непонятно, зачем вам это? Вы всё равно на время пересылки за датчиками следить не будете. У вас между опросом датчиков будет задержка в несколько миллисекунд (зависит от скорости COM-порта).

Ну вот - достаточно было правильно сформулировать вопрос, как ответ пришел сам собой


Э, нет. Что хотят сделать до конца всё равно не понятно. Пока что хотят не пропустить ни одного датчика и в то же время делать большие задержки между опросом на передачу всего массива сработавших датчиков. Я предлагал в прерывании UART определять момент завершения передачи и передавать следующий символ, если передача требуется.

По любому, частота опроса датчиков не может быть выше, чем частота посылок по UART , поэтому если датчик может "мигнуть" на пару микросекунд, то сигнал может быть пропущен.


Можно считать, что если за время передачи символа датчик сменил своё состояние на обратное, а потом снова вернулся в начальное на момент начала передачи, то он и не менялся. :)

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 21:45:02

da-nie писал(а):
По любому, частота опроса датчиков не может быть выше, чем частота посылок по UART , поэтому если датчик может "мигнуть" на пару микросекунд, то сигнал может быть пропущен.

Можно считать, что если за время передачи символа датчик сменил своё состояние на обратное, а потом снова вернулся в начальное на момент начала передачи, то он и не менялся. :)

Пять баллов! :beer:

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 21:45:58

DerMeister писал(а):Просто я боюсь что могу упустить срабатывание датчика пока буду слать. Датчики могут срабатывать "одновременно", точнее с разницей в несколько микросекунд. И пока я буду слать упущу срабатывание. Или я не прав?
Абсолютно правы, и боитесь совершенно правильно.

Чтобы не терять данные, нужно несколько усложнить программу добавлением кольцевого буфера FIFO. Программа обработки прерывания от датчика заносит соответствующую литеру в конец буфера. Программа обработки прерывания по готовности UART выводит литеру из начала буфера.

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

Подробнее посмотрите в Bruce Powel Douglass, "Real-Time Design Patterns: Robust Scalable Architecture for Real-Time Systems". Почти готовые к употреблению фрагменты кода найдете в Jean J. Labrosse, "Embedded Systems Building Blocks. Complete and Ready-to-Use Modules in C".

DerMeister писал(а):Я так понимаю С не умеет делать как я хочу...
C вообще никак не умеет. Умеет написанная на нем программа. А уж что именно она сумеет, зависит лишь от Вашего умения и старания.

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 22:09:08

Ну да, наверно я не совсем точно сформулировал, вернее не до конца. Прошу прощения :roll:
Опять непонятно, зачем вам это? Вы всё равно на время пересылки за датчиками следить не будете.

Датчики срабатывают как бы пакетно что ли. То есть в один момент времени может сработать сразу несколько, с разницей в несколько МИКРОсекунд, а после того как это произошло не один не может сработать раньше чем через 10 МИЛИсекунд. Вот поэтому мне и нужно успеть просканировать все дачтики сразу и только потом - в этот перерыв в 10 милисекунд - отсылать состояния этих датчиков.
Поэтому слать первый же сработавший сразу нельзя - можно пропустить следующий сработавший.
А если сперва записать состояние каждого в свою переменную (это всего по одному такту на датчик: a=PINB.0, b=PINB.1....), то потом, в эти десять милисекунд, мне конечно за глаза хватит чтоб отправить сработавшие.
Вот как-то так.
Уж не знаю понятно ли объяснил или нет...
Чтобы не терять данные, нужно несколько усложнить программу добавлением кольцевого буфера FIFO

Да, я читал про это, так и нужно делать чтоб было "красиво". Но честно говоря, до конца пока не разобрался. Я ведь еще только учусь...
Да и в данном случае можно обойтись и без него, благодаря 10и милисекундной задержке.
И спасибо Вам, что подсказали куда заглянуть по поводу буфера!

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 22:34:44

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

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 22:45:22

Интересно, а как Вы собираетесь узнавать сработает ли скоро следующий датчик или нет

А зачем мне знать? Я в цикле проверки датчиков записываю состояние каждого в свою переменную. После скана всех (кстати 20и, но это пока) датчиков смотрю в эти переменные и те из них, где стоит 1 - датчик сработал значит - уже отсылаю по UART. Дальше опять сканируюю и т. д. А слать я буду только если сработает хоть один датчик, и у меня появится 10 милисекунд на отсылку.
Мне кажется это оптимальный вариант. Поправьте если я неправ.

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 23:21:14

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

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 23:27:42

чуть выше постом я описал алгоритм:
Датчики срабатывают как бы пакетно что ли. То есть в один момент времени может сработать сразу несколько, с разницей в несколько МИКРОсекунд, а после того как это произошло не один не может сработать раньше чем через 10 МИЛИсекунд. Вот поэтому мне и нужно успеть просканировать все дачтики сразу и только потом - в этот перерыв в 10 милисекунд - отсылать состояния этих датчиков.

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 23:31:06

DerMeister, какой МК вы хотите использовать для этой цели, какая частота кварца? И куда все это будет посылаться?

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 23:35:41

Ну тогда вообще всё просто. Делайте внешнюю схему "ИЛИ" и заводите на одно внешнее прерывание, а в прерывании уже проверяйте все входы, обновляя буфер. Если нужно перед опросом немного задержаться, то делаем небольшую задержечку (можете на таймере, если обработчик держать - критично), а затем уже проверку.
Кстати, а срабатывают они на сколько, по времени ?

Re: Как на С "приплюсовать" два символа?

Чт авг 09, 2012 23:55:26

Это какую же микруху ИЛИ надо на 20 и более датчиков? И потом, хотелось бы с минимумом внешней обвязки т. к. во-первых: зачем вешать дополнительно детали если с этим один МК может справиться, во-вторых: корпус для устройства уже сделан и размеры его весьма критичны к сожалению. Запихнуть туда еще что-то будет проблематично...
Время срабатывания по идее от 1,5 до 2 микросекунд.
Ответить