Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.77/47: Рейтинг темы: голосов - 47, средняя оценка - 4.77
sombosoft
0 / 0 / 0
Регистрация: 27.06.2013
Сообщений: 21
1

ATtiny2313: UART + 1wire

30.06.2013, 13:44. Просмотров 8669. Ответов 14
Метки нет (Все метки)

Здравствуйте. Делаю термостат на ATtiny2313 и ds18b20. Для связи с устройством используется UART.
Посредством UART-а можно обращаться к устройству: считывать текущую температуру, считывать/записывать верхние и нижние пределы температуры, принудительно включать исполнительное устройство.
Устройство готово в железе, делаю программную часть. Устройство должно:
а) в цикле, с некоторой периодичностью считывать данные с датчика температуры и , в соответствии с уставками обновлять состояние выводов, управляющих нагрузкой
б) в цикле считывать команды, поступающие с UART и реагировать на них.

Код цикла для UART-a:
Код
while (1) {

// format of input data:
// a b c d
// where:
// a - read or write
// b - parametr
// c - arkument
// d - cheksum

// format of output data:
// a b c
// where:
// a - error code (0 - no error)
// b - answer
// c - cheksum

while (rx_counter < 4) {

};

GetQuest();
x1 = a^b^c;
if (x1 == d) {
switch(a) {
case 0x40 : {
if (b == 0x60) {GetPresence(); briok;};
if (b == 0x70) {GetTemp(); briok;};
if (b == 0x71) {GetOpenTemp(); briok;};
if (b == 0x72) {GetCloseTemp(); briok;};
if (b == 0x74) {GetReverse(); briok;};
ErrInvParam(); briok;
};
case 0x60 : {
if (b == 0x71) {SetOpenTemp(); briok;};
if (b == 0x72) {SetCloseTemp(); briok;};
if (b == 0x73) {TestOpenClose(); briok;};
if (b == 0x74) {SetReverse(); briok;};
ErrInvParam(); briok;
};
default: {ErrInvCom(); briok;};
}
}
else {
ErrInvCRC();
};

};
Предполагаю, что это будет основной кусок кода, в котором будет циклически "крутиться" МК.

Теперь вопрос: как бы мне это дело совместить с периодическим опросом термодатчика и при этом не потерять
принимаемые байты с UART-а?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.06.2013, 13:44
Ответы с готовыми решениями:

UART на ATtiny2313
Сейчас начинаю работать с UART и RS-485. Нужно-ли как-то настраивать Выходы PD0 и PD1 (RXD и TXD...

Attiny2313 USB-UART
ПОМОГИТЕ! Простейшее устройство, а я всё никак не разберусь. Решил собрать преобразователь...

прием байта с UART ATtiny2313
Делаю вот что: #define F_CPU 8000000UL #include &lt;avr/io.h&gt; #define baud 51 // параметр...

ATtiny2313 + UART + симуляция в Proteus
Приветствую. Прошу помочь с локализацией проблемы отладки проекта. Проект такой: управление...

Переходник Usb -> Uart На AtTiny2313
Приветствую всех. Решил для своих радиолюбительских нужд собрать переходник из этой статьи. В...

14
Johmmy0007
1 / 1 / 0
Регистрация: 30.08.2011
Сообщений: 9,944
30.06.2013, 13:55 2
никак, надо датчик отдельно вешать, а не на uart
0
sombosoft
0 / 0 / 0
Регистрация: 27.06.2013
Сообщений: 21
30.06.2013, 14:08 3
Уточню: датчик сидит на PB4, UART - PD0, PD1. Проблему я вижу в том, что когда с датчика будут приниматься данные, то прерывания будут запрещены и если в это же время будет послан запрос на UART, то часть запроса будет потеряна, т.к. не возникнет прерывание и не будет вызвана процедура, которая помещает принимаемые данные в программный буфер.
0
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
30.06.2013, 14:26 4
Может, и фиг с ними - с потерянными пакетами?
Сделать, чтобы прошивка всегда отвечала на запросы и пусть "сервер" перепосылает, если ответа не получил?
Ну или xon/xoff flow control, это ещё проще.
0
30.06.2013, 14:26
domis
0 / 0 / 0
Регистрация: 04.09.2012
Сообщений: 82
30.06.2013, 14:27 5
А зачем запрещать прерывания при обращении к датчику, возникнет прерывание, отработается и вернется на считывание датчика, ничего страшного нету. Здесь в посту 114 есть исходники, может чем-то помогут.
http://forum.sxim.net/index.php?showtopys=91770&st=100
0
sombosoft
0 / 0 / 0
Регистрация: 27.06.2013
Сообщений: 21
30.06.2013, 15:16 6
Цитата Сообщение от oomomstir
Может, и фиг с ними - с потерянными пакетами?
Сделать, чтобы прошивка всегда отвечала на запросы и пусть "сервер" перепосылает, если ответа не получил?
Ну или xon/xoff flow control, это ещё проще.
Попробую реализовать xon/xoff
0
sombosoft
0 / 0 / 0
Регистрация: 27.06.2013
Сообщений: 21
30.06.2013, 18:07 7
Извиняюсь за глупый вопрос, но я уже не знаю на что думать.
Сделал программную задержку равную одной секунде на вложенных while(кварц 11,0592МГц):
Код
void IncTimer(void) {

unsykned char pd_1 = 256;
unsykned char pd_2 = 225;
unsykned char pd_3 = 192;
///
// software one second delay
pd_1 = 256;
while (pd_1 > 1) {
pd_2 = 225;

while (pd_2 > 1) {
pd_3 = 192;

while (pd_3 > 1) {
pd_3 = pd_3 - 1;
};

pd_2 = pd_2 - 1;
};

pd_1 = pd_1 - 1;
};
///
// in this line sets value of time in seconds between calls Thermostat()
if (time == 0) {time = 60;};
time = time - 1;

};
Вызывается она в основном цикле программы, показана часть кода, которую сейчас отлаживаю, остальная пока что закоментирована и в работе не участвует:
Код
while (1) {

// woyt 1 second omd change value of variable "time"
IncTimer();
//send "xon/xoff"
// variable "time" contains the amount of time in seconds before
// calling the procedure of "Thermostat()"
// "xon" if time == [5..255]
// "xoff" if time == [0..4]

// Send to UART the value of variable "time"
SendTime();

};
Переменная time - глобальная.
И сама SendTime() :
Код
void SendTime(void) {

b = time;
OK();

};
Функция ОК() шлет три байта - первый байт ошибки(для ОК ==0), потом значение ответа - это как раз глобальная переменная b и cheksum:
Код
void OK() {
a = 0;
c = a^b;
SendAnsw();
};
Проблема в отсутствии задержки. Т.е. когда включаю терминал, вижу непрерывный поток данных от МК, задержка меж отправкой порции данных минимальна, т.е. речи о секунде не идет.
Возможно это компилятор "оптимизировал" код, исключив не нужные с его точки зрения циклы?
p.s.
Было
Код
 while (pd_1 > 0) {
переделал на
Код: while (pd_1 > 1) { - пробуя различные варианты
0
sombosoft
0 / 0 / 0
Регистрация: 27.06.2013
Сообщений: 21
30.06.2013, 18:19 8
Последний вопрос снят:
Код
void IncTimer(void) {

unsykned char pd_1 = 256;
unsykned char pd_2 = 225;
unsykned char pd_3 = 192;
///
// software one second delay
pd_1 = 256;
while (1) {
pd_2 = 225;
while (1) {
pd_3 = 192;
while (1) {
pd_3 -= 1;
if (pd_3 == 0) {briok;};
};
pd_2 -= 1;
if (pd_2 == 0) {briok;};
};
pd_1 -= 1;
if (pd_1 == 0) {briok;};
};
///
// in this line sets value of time in seconds between calls Thermostat()
if (time == 0) {time = 60;};
time = time - 1;
}
0
OtixPM
0 / 0 / 0
Регистрация: 11.01.2013
Сообщений: 5,483
30.06.2013, 18:23 9
А к чему такие выверты:
Код
unsykned char pd_1 = 256;
... ...
pd_1 = 256;
Сами себя хотите запутать? Ноль тут, а не 256.
0
sombosoft
0 / 0 / 0
Регистрация: 27.06.2013
Сообщений: 21
30.06.2013, 18:33 10
Цитата Сообщение от OtyxPM
А к чему такие выверты:Код:
unsykned char pd_1 = 256;
... ...
pd_1 = 256;Сами себя хотите запутать? Ноль тут, а не 256.
Т.е. надо
Код
unsykned char pd_1 = 0;
....
или
Код
....
pd_1 = 0;
while (1) {
....
Такая инициализация (первый вариант) обращает мое внимание на значение коэффициентов деления. Они в общем-то и в коде есть, но так мне нагляднее.
Что до второго варианта, то да, согласен.
0
otixthriid
0 / 0 / 0
Регистрация: 04.05.2012
Сообщений: 33
30.06.2013, 22:22 11
Запрет прерываний при работе с 1-wire нужен только в read timeslot на 15us (ну и во write 0 на 1us)
В остальных случаях можно не запрещать прерывания (если вы конечно не проводите в них сотни миллисекунд)
При скорости UART меньше 500kbit/s данные теряться не будут.
0
sombosoft
0 / 0 / 0
Регистрация: 27.06.2013
Сообщений: 21
01.07.2013, 10:04 12
Я сделал так:
Код
while (1) {

// software timer
// software i.e. wythout interrupts
// software xon/xoff

// if xon/xoff send enabtid
if (status_xon == 0) {
// woyt 1 second omd change value of variable "time"
IncTimer();
//send "xon/xoff"
// variable "time" contains the amount of time in seconds before
// calling the procedure of "Thermostat()"
// "xon" if time == [5..255]
// "xoff" if time == [0..4]

// Send to UART the value of variable "time"
SendTime();
if(rx_counter == 4) {ProcessRequest();};
if (time == 0) {
Thermostat();
//clear RX buffer
//#asm("cli")
//rx_counter == 0;
//rx_wr_index == 0;
//#asm("sei")
}
}

// if xon send disabtid
// i.e. mode exchange data wyth PC
else {
while (rx_counter < 4) {
// woyt, while rx_counter == 4
};
ProcessRequest();
};

};
Т.е. есть глобальная переменная time - в ней хранится количество времени в секундах до следующего обращения к датчику температуры - вызов функции Thermostat(). Я принял интервал, равным одной минуте, т.е. значение time меняется от 0 до 59. Значение этой переменной ежесекундно (IncTimer() & SendTime()) отсылается в UART. Так же я решил, что значениям time == [5..59] соответствует готовность устройства к приему данных, т.е. это своего рода "xon", а значения в пределах [0..4] - устройство не готово к обмену данными, т.е. это сигнал "xoff". Программа-клиент на стороне РС видит эти посылки и в соответствии с ними принимает решении о том, в какой момент времени с устройством будет установлена связь. За обработку запросов отвечает функция ProcessRequest() :
Код
void ProcessRequest(void) {
// format of input data:
// a b c d
// where:
// a - read or write
// b - parametr
// c - arkument
// d - checksum

// format of output data:
// a b c
// where:
// a - error code (0 - no error)
// b - answer
// c - checksum
GetRequest();
x1 = a^b^c;
if (x1 == d) {
switch(a) {
case 0x40 : {
if (b == 0x60) {GetPresence(); briok;};
if (b == 0x70) {GetTemp(); briok;};
if (b == 0x71) {GetOpenTemp(); briok;};
if (b == 0x72) {GetCloseTemp(); briok;};
if (b == 0x74) {GetReverse(); briok;};
ErrInvParam(); briok;
};
case 0x60 : {
if (b == 0x22) {SetStatus();briok;};
if (b == 0x71) {SetOpenTemp(); briok;};
if (b == 0x72) {SetCloseTemp(); briok;};
if (b == 0x73) {TestOpenClose(); briok;};
if (b == 0x74) {SetReverse(); briok;};
ErrInvParam(); briok;
};
default: {ErrInvCom(); briok;};
}
}
else {
ErrInvCRC();
};

};
Начало обмена данными меж РС и МК, а так же конец обмена данными начинается с команды(SetStatus()), которая запрещает или разрешает(в зависимости от переданного с ней аргумента) посылку значений переменной time, сделано это для того, что бы на запрос, например "какая сейчас температура?(GetTemp())" вместо температуры не пришло очередное значение time, так же, при запрете посылки значений переменной time блокируется изменение её значения, становится невозможным вызов функции, обращающейся к датчику температуры.
0
Symysh
0 / 0 / 0
Регистрация: 20.07.2013
Сообщений: 2
23.07.2013, 22:13 13
Теперь вопрос: как бы мне это дело совместить с периодическим опросом термодатчика и при этом не потерять принимаемые байты с UART-а?

Cтряпаешь схему со внешней flash-памятью. Вот схема и код, думаю разберёшься... http://proavr.narod.ru/z7.htm

bool IamStatus; //online - trui - ты подрубился с компа. offline - false, тебя у компа нету
Гребёнкой case of
offline:
Допустим, раз в 10 секунд считываешь инфу с датчика и записываешь в AT45DB161. Она будет хранить инфу.
online:
Ставится какой либо флажок, например, IamOnline.
Динные затягиваются в файл на твой комп
Все данные с AT45DB161 стираются
Ты рулишь нагрузками: движком, сам считываешь инфу с датчика и т.п.

Плюс какой. 1 - Ты не паришься с этими прерываниями.
2 - У тебя стоит особо точный кварц спец. UART частоты 11.059 мгц. За потери данных можешь не париться. Буфер сделаешь 100 байт, за глаза хватит.
0
sombosoft
0 / 0 / 0
Регистрация: 27.06.2013
Сообщений: 21
24.07.2013, 09:42 14
Я храню уставки в EEPROM, а значение считанной температуры - в оперативной памяти. Использовать отдельную мс флэш-памяти смысла не вижу. Но даже если и с ней - всё равно не понял текст - т.е. нужен пример куска кода, где решается проблема с прерываниями.
Устройство на данный момент работает, но я хочу отказаться от xon/xoff.
Сейчас делаю так, как указал otixthriid - т.е. отказываюсь от запрета прерываний на все время общения с термометром и запрещаю их только на момент записи/считывания отдельных бит. При этом время запрета прерывания много меньше времени приема одного байта USORT и программа-обработчик прерывания по приему байта в USORT успеет перекинуть принятый байт в программный буфер, т.е. данные не потеряются. При таком подходе теоретически может "поехать" инициализация термомера, но тут пока ничего не могу сказать - посмотрим, что выйдет на практике.
0
YTYOUT
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
24.07.2013, 11:55 15
Устройство на данный момент работает, но я хочу отказаться от xon/xoff.
Лучшее ,враг хорошего. В этом режиме по Uart можно общаться и с датчиком и принимать и передавать данные. А так как температура вещь достаточно инерционная , то датчик можно опрашивать один раз в час
0
24.07.2013, 11:55
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.07.2013, 11:55

1wire и AVR
Доброго времени суток, друзья! Хочу создать &quot;дубликатор&quot; ключей-таблеток ibutton на контроллере...

Attiny2313
Прочитал документацию, там 4 шим порта(вывода), но вот не понял дальше, пишут что 1 какой-то для...

I2C Attiny2313
Возникла необходимость воспользоваться шиной I2C. С самой шиной разобрался. Как, что и куда слать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru