|
|
  |
Soft RS-232, Ещё два UARTa. Програмно. |
|
|
|
Jan 7 2009, 20:43
|
Частый гость
 
Группа: Участник
Сообщений: 149
Регистрация: 2-06-08
Из: Москва
Пользователь №: 38 003

|
Цитата(viktor4152 @ Jan 7 2009, 23:07)  Всё равно не работает. ... У Вас регистр temp в прерываниях изменяется, а в стеке не сохраняется, в этом может быть проблема. Вообще не очень понятна логика приемника, понятно, что сдвиг, но зачем там сохранения SREG и т.п. - непонятно. Это я к тому, что комментариев маловато, тем более для ассемблера, разбираться в исходнике тяжело.
|
|
|
|
|
Jan 8 2009, 23:09
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(viktor4152 @ Jan 7 2009, 20:07)  Логично предположить, что либо контролер делает что-то ещё между прерываниями от таймера (где-то же он берёт эти лишние биты), либо я неправильно посчитал временные интервалы Ни то, ни другое. У вас имеется несколько ошибок в программе. 1) При вызове Timer0Comp вы сохраняете регистр SREG дважды, но 9 раз вы обходите восстановление второго сохранённого SREG. Из-за этого меняется указатель стека, в итоге вы возвращаетесь не в то место, из которого возвратились, а стек постепенно переполняется и даже может достичь области регистров. 2) При вызове Timer0Comp вы всегда должны обнулять счётчик, иначе будет временная ошибка, а вы обнуляете только после 9-го бита. 3) Вы не обнуляете count0 при первом вызове Receive0, значит прерывания таймера по сравнению могут вызываться до 256 раз, поправьте. 4) Вы обнуляете таймер, а прескалер остаётся нетронутым, может привести к потенциальным ошибкам, поправьте. Вообще, прерывание должно быть максимально быстрым, поэтому несколько советов. Просто сохраняйте SREG в регистре, а а сам регистр сохранять не надо, зачем, вам что в данной задаче регистров не зватает? Далее, зачем обнулять таймер после приёма 9-ти бит, если вы его всё равно устанавливаете в прерывании int0, можно убрать. После того, как вы задвинули в input0 очередной бит, можно разрешить прерывания для второго канала, чтобы уменьшить временную ошибку. Как вариант, попробуйте следующий метод приема 9-ти бит в два регистра, что-то типа LSR input1 ROR input0 В Receive0 задать input1=1, input0=0. Заносить текущий бит командой ORI input1,2 При сдвиге 1 будет двигаться вправо, после принятия 9-ти бит, она вылезет в перенос.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Jan 9 2009, 20:17
|
Группа: Новичок
Сообщений: 14
Регистрация: 8-11-08
Пользователь №: 41 476

|
Учитывая все вышеизложенные мнения, выкладываю всё, что у меня получилось. Т.к. подлая конструкция так и не заработала. Но логика работы изменилась. Хотя вновь завела меня в тупик. Программу переделал. Написал подробные комментарии к каждой строчке (почти). Теперь проверяю правильность принятия старта. До стопа пока не добрался, хоть бы один байт принять. Да, пересмотрел описание модемов, был неправ. Не могут они передавать данные по 9 бит. Меньше могут. Потому буду использовать адресацию. И потому два 9600 пакую в один 38400. То =GM= , по пунктам: 1. Согласен, с SREG намудрил. Всё потёр, под SREG оставил свой регистр. Бит данных копируется через бит Т, потому SREG второй раз не сохраняется. 2. Непонятно, зачем обнулять счётчик, прерывание по совпадению, таймер работает в режиме СТС. 3. Упустил из виду, Count0 теперь обнуляю. 4. Почему могут быть ошибки, разве это не независимые регистры? Ну обнулил таймер, ну и что? Разве он не начнет считать с нуля с тем же прескалером? Теперь самое главное: результат всех переделок. Этот подлый аппарат теперь изменил логику приёма данных. Если раньше была вообще никак не связанная каша с данными (хотя для каждого байта была своя каша), теперь всё подругому. Теперь я принимаю определённое кол-во нулей, а затем идут единицы. Кол-во единиц и нулей опять таки для каждого передаваемого байта свои и опять возможны два принятых байта. Логику чередования 0 и 1 я к исходным значениям привязат так и не смог. Но что самое подлое. Я как-то эксперимента ради перед отправкой на UART принятого байта пробовал отправлять свой фиксированный, заранее известный байт. И он красиво фиксируется. А после него опять начинается 0b11110000. А там где выдаётся по два байта, один байт был ПЕРЕД контрольным байтом, а один после. Это вообще выше моего понимания.
Сообщение отредактировал viktor4152 - Jan 9 2009, 20:34
Прикрепленные файлы
Proga2.txt ( 5.01 килобайт )
Кол-во скачиваний: 65
|
|
|
|
|
Jan 10 2009, 00:15
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(viktor4152 @ Jan 9 2009, 20:17)  То =GM= , по пунктам: 2. Непонятно, зачем обнулять счётчик, прерывание по совпадению, таймер работает в режиме СТС. 4. Почему могут быть ошибки, разве это не независимые регистры? Ну обнулил таймер, ну и что? Разве он не начнет считать с нуля с тем же прескалером? По пункту 2. Упустил режим СТС, можно не обнулять. По пункту 4. Забудьте про прескалер, это меня мысли в другую сторону повели. Посмотрел новую версию вашей программы по диагонали. Зачем вы поставили стартовое ожидание в полбита, а считаете до 8? Вы записываете в input0 стартовый бит, это неверно.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Jan 10 2009, 04:55
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
1. В прерывании по int0 вместо Код in temp, GIMSK;* Запрет INT0 cbr temp, 0b10111111;* out GIMSK, temp;* нужно Код in temp, GIMSK;* Запрет INT0 cbr temp, 0b01000000;* out GIMSK, temp;* а еще лучше cbr temp,1<<Int0 2. 1/период переполнения таймера в режиме СТС равен ZQ/PSK/(OCRA+1), поэтому длительности в 1 бит будет соответствовать значение в ОСRA == 144-1. Соответственно, 1/2 бита == 144/2-1=70 P.S. В качестве счетчика битов можно использовать и сам регистр input0, если по приходу старт-бита (по инт0) в загружать в него 0x80. Признаком окончания приема будет появление "1" в бите переноса при прокрутке регистра input0 вправо Тогда код Код RX0:;* Приём inc count0;* Увеличить на 1 значение счётчика битов lsr input0;* сдвинуть вправо регистр данных clt;* сбросить бит Т sbic PinD,2 set;* Установить бит Т если на входе 1 bld input0,7;* Скопировать бит Т в 7-й бит регистра данных cpi count0,8;* Если принятых бит не 8, то выход brne Exit0 sbi flags0,6;* в противном случае устанавливаем флаг приёма байта данны нужно заменить на Код clc;Входящий бит записываем через бит переноса sbic PinD,2 sec; ror input0; Записываем входящий бит, признак последнего бита - в флаг С brcc Exit0; sbi flags0,6; Если на выходе С==1, то принятый бит - последний. Дальше принимаем стоп-бит
|
|
|
|
|
Jan 10 2009, 15:51
|
Группа: Новичок
Сообщений: 14
Регистрация: 8-11-08
Пользователь №: 41 476

|
ВСЁЁЁЁЁ Работает. Изучал AVR по книге Мортона, там видимо опечатка в описании команды cbr, переписал (спасибо Александру). И спасибо =GM= за поиск ошибок в первом варианте. Без вас тоже ничего бы не вышло.
То rvk: В том то всё и дело, что от программы осталось только програмный UART.
То =GM=: стартовый бит я не записываю, я проверяю по прерыванию от таймера флаг, который устанавливаю только при наличии 0 по истечении 0,5 бита после старта (INT0). Если по прерыванию этот флаг установлен, то только тогда начинаю записывать биты.
To Александр Куличок: Здесь я выложил 2 варианта программы. У меня этих вариантов было штук семь. И предлагаемый Вами метод приёма я тоже испытывал. Но по понятным уже причинам, у меня ничего не заработало. Думаю, вернусь к нему.
Всем, кто хоть как-то пытался помочь, спасибо. Думаю, тема закрыта.
|
|
|
|
|
Jan 19 2009, 18:07
|

Местный
  
Группа: Участник
Сообщений: 322
Регистрация: 21-06-07
Из: СНГ
Пользователь №: 28 596

|
Цитата(andrik.kiev.ua @ Jan 19 2009, 19:51)  У gcc есть один недостаток - большой размер и тормознутость результата... а в мостах желательна производительность... Последнее что переписывал - пинговалку задача вместить в Мега48 gcc - 5.8 Кило пинг 10 мс ASM - 1.7 Кило пинг 3 мс в gcc - оптимизация по размеру в asm - оптимизация по производительности разница в 3 раза, как по размеру, так и по скорости. (как мне тут сказали - просто есть задачи которые трудно решить на СИ)
--------------------
|
|
|
|
|
Jan 30 2009, 09:58
|
Группа: Новичок
Сообщений: 14
Регистрация: 8-11-08
Пользователь №: 41 476

|
Всем привет, как давно я тут не появлялся. Вот програмка, один канал, 9600 перепаковывает в 38400, адресация моя произвольная, тупо кучка единиц. На равильность не претендую, если кто подскажет, как лучше, скажу спасибо. Программа очень сырая, будет работать до первой потери байта, проверить на модемах даже не было времени. Но два COM-порта соединяет, символы с клавы шлются в обе стороны. Для понятия алгоритма вполне достаточно. Как доведу до ума, выложу нормальную программу.
Прикрепленные файлы
_____3.txt ( 7.01 килобайт )
Кол-во скачиваний: 70
|
|
|
|
|
Feb 21 2009, 14:31
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата Последнее что переписывал - пинговалку задача вместить в Мега48 gcc - 5.8 Кило пинг 10 мс ASM - 1.7 Кило пинг 3 мс Судя по картинкам на сайте - обычным 32хбайтным пингом? Стыдно должно быть  У меня с программным MAC'ом менее миллисекунды. Причем, стек писан на Си.
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|