Страница 1 из 1
Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Вт мар 15, 2011 20:47:45
AndyKorg
Дорогие любители рыбы!
Помогите поймать золотую рыбку, ну или хотя бы малька.
Требуется принимать на ATMega328 поток байт по протоколу RS232 на скорости 9600. Причем штатный UART занят своими делами и его трогать нельзя.
Вот накропал шедевр, а он не пашет. Может кто чего подскажет?
Код: Выделить всё
#include <avr\io.h>
#include <util/delay.h>
#define BIT_DELAY 104 //Это длительность бита на скорости 9600 в микросекундах
unsigned char RxByte(void){//Функция которая принимает битики на лапе PB1
unsigned char buf = 0, //Холодильник для рыбы, он же буфер куда битики принимаются
i;//Просто счетчик
while(1){
buf = 0;
while(PINB & 2);//Ждем кода приплывает рыба-лоцман, он же старт-бит
_delay_us(BIT_DELAY/4);//Обождем 1/4 от длительности бита
for (i = 7; i!=0; i--){//Как говорится - пошла вода по трубам!
_delay_us(BIT_DELAY);//Обождем еще длительность бита
if (PINB & 2)//Как оно? рыба или пусто?
buf |= 0b10000000;//Есть рыбка
else
buf &= 0b01111111;//Нету ничего
buf >>= 1;//Пихаем в холодильник, то бишь в буфер
}
//Все! Косяк прошел, проверим замыкающую акулу
_delay_us(BIT_DELAY);//через длительность бита
if (PINB & 2)//Акула проплыла, усе нормально. Холодильник закрываем
return(buf);
}
}
Так вот. Косяк байт представляет собой четкую последовательность:
символ "R" - начало тела косяка
три байта цифр - собственно промысловая рыба
и 0x0D - хвостик косяка
А принимается вот что: 0x1f, 0x4f, 0x68, 0x68, 0x30,, 0x3, 0x, 0x72, 0x36, 0x3, 0x19, 0x0 и т.д.
Че-то я уже измучился ловить не то, что надо. Гуглосетью забредал - ничего толкового не выловил.
Помогите пожалуйста найти косяк!
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 07:55:04
-==MAXCELERON==-
Чтобы выполнить задержку с помощью переменной нужно делать ее через дополнительную функцию задержки:
delay(x); // делаем задержку продолжительностью x мкс
void delay(int us){
for(;us;us--)
_delay_us(1);
}
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 09:09:40
ARV
мне кажется, у вас не получается синхронизироваться... т.е. ваш цикл ожидания "косяка" ловит не старт-бит, а один из битов передаваемого байта, и далее пошло уже все шиворот-навыворот.
если известно, что пакет всегда начинается с символа 'R', то надо терпеливо дожидаться его приема для синхронизации. т.е. алгорит такой примерно:
1. принимаем байт
2. байт == 'R' ? если да - переходим к приему пакета
3. если нет, то принимаем (пропускаем) 1 БИТ
4. переходим к п.1
этот алгоритм будет пропускать кучу пакетов, пока наконец не поймает синхронизацию, после чего уже дело пойдет нормально. смысл в том, что каждый новый пакет принимается с пропуском 1 бита перед ним - рано или поздно (можете посчитать максимальное время синхронизации) программа поймает именно первый бит начала пакета и далее все пойдет как по маслу.
эта процедура должна делаться 1 раз - в начале приема, или каждый раз после длительного перерыва в приеме пакетов.
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 09:53:15
AndyKorg
ARV писал(а):.....
1. принимаем байт
2. байт == 'R' ? если да - переходим к приему пакета
3. если нет, то принимаем (пропускаем) 1 БИТ
4. переходим к п.1
.......
Эх, я так делал. Но увы, в течение получаса ни разу не приходило "R". Где то глубже в алгоритме плавает моя рыбка.
-==MAXCELERON==- писал(а):.....
Чтобы выполнить задержку с помощью переменной нужно делать ее через дополнительную функцию задержки:.......
дык как раз препроцессор и отдает компилятору строку после обработки:
_delay_us(104); или _delay_us(26);
Так что не вижу смысла в такой подстановке.
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 11:22:09
uk8amk
1)Кажись у вас код кривой, сначала так:
buf |= 0b10000000;//Есть рыбка
затем вот так:
buf >>= 1;//Пихаем в холодильник, то бишь в буфер
Распишите в линейный код. Что произошло на восьмой итерации цикла?
2)Это полный код программы или только прилизанная его часть для данного случая? Я имею в виду что у вас могуть быть обработчики прерываний которые влияют на длительность выполнения _delay_us(BIT_DELAY); Если есть свободный таймер, то положите на него функцию захвата бита.
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 11:30:25
AndyKorg
uk8amk писал(а):1)Кажись у вас код кривой, сначала так:
buf |= 0b10000000;//Есть рыбка
затем вот так:
buf >>= 1;//Пихаем в холодильник, то бишь в буфер
Распишите в линейный код. Что произошло на восьмой итерации цикла?
Да действительно, одна итерация лишняя. Вы правы, спасибо за подсказку. Подправил, но не помогло
uk8amk писал(а):
2)Это полный код программы или только прилизанная его часть для данного случая? Я имею в виду что у вас могуть быть обработчики прерываний которые влияют на длительность выполнения _delay_us(BIT_DELAY); Если есть свободный таймер, то положите на него функцию захвата бита.
[/quote]
К сожалению все запрещено - таймеры, прерывания и прочее безобразия. Так что на это грешить не могу. Таймер кончено задействую в конченой реализации, но я думаю что ошибка в плюс минус 5 микросекунд (на частоте 16Мгц это чертова туча команд даже если используются прерывания) не должна влиять на косяк, рыба то толстая, аж в 104 микросекунды.
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 11:55:46
uk8amk
Итерация то не лишняя, а вот один сдвиг как раз лишний. Попробуйте тупо записать:
if(PINB.2) buf=0x01;
delay_us(BIT_DELAY);
if(PINB.2) buf|=0x02;
belay_us(BIT_DELAY);
и т.д., может вскроется какая-нибудь ошибка которую мы из вида упускаем...
Еще как вы определяете значение которое захватили, выводите куда-то, на LCD например, есть уверенность что там тоже без косяков?
Правильно ли выставлена тактовая частота процессора для функций delay.h?
Upd:
Обновив код вы выкинули одну итерацию а вместе с ней и прием восьмого бита. У вас формат кадра 8N1? Тогда после цикла добавить:
if(PINB.2) buf|=0x80;
delay_us(BIT_DELAY);
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 13:04:47
AndyKorg
uk8amk писал(а):Итерация то не лишняя, а вот один сдвиг как раз лишний. Попробуйте тупо записать:
....
Upd:
Обновив код вы выкинули одну итерацию а вместе с ней и прием восьмого бита. У вас формат кадра 8N1? Тогда после цикла добавить:
if(PINB.2) buf|=0x80;
delay_us(BIT_DELAY);
Ах ты черт! Точно! Спасибо за наводку! Вечером попробую - отпишусь.
uk8amk писал(а):
Правильно ли выставлена тактовая частота процессора для функций delay.h?
Насчет этого нет сомнений - проверено генерацией меандра.
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 20:10:30
AndyKorg
Не выходит каменный цветок!
Код: Выделить всё
#include <avr\io.h>
#include <util/delay.h>
#define BIT_DELAY 104
unsigned char RxByte(void){
unsigned char buf = 0, i;
while(1){
buf = 0;
while(PINB & 2);
_delay_us(BIT_DELAY/4);
for (i = 0; i!=8; i++){
buf >>= 1;
buf &= 0x7f;
_delay_us(BIT_DELAY);
if (PINB & 2)
buf |= 0x80;
}
_delay_us(BIT_DELAY);
if (PINB & 2)
return(buf);
}
}
Все равно гонит какие-то байты непонятные.
Буду еще головой думать. Может кто еще чего подскажет?
Re: Прием rs232 без UART на AVR - сети не ловят.
Добавлено: Ср мар 16, 2011 20:32:01
phanis
Код: Выделить всё
#include <avr\io.h>
#include <util/delay.h>
#define BIT_DELAY 104
unsigned char RxByte(void){
unsigned char buf = 0, i;
PORTB |= 2; // подтяжка к +
DDRB |=1; // какой нибудь выход здесь PORTB0
while(1){
buf = 0;
while(PINB & 2);
_delay_us(BIT_DELAY/4);
for (i = 0; i!=8; i++){
buf >>= 1;
buf &= 0x7f;
PORTB &= 0xFE; //PORTB0 в ноль
_delay_us(BIT_DELAY);
PORTB |= 0x01 ;//PORTB0 в единичку
if (PINB & 2)
buf |= 0x80;
}
_delay_us(BIT_DELAY);
if (PINB & 2)
return(buf);
}
}
Отправляем 0xAA( 10101010 ) или 0x55 ( 01010101 ) по ком порту в мк
В это время двухканальным осциллографом (можно в протеусе) наблюдаем за импульсами на PB0 PB1
Т.е определяем на сколько все синхронно работает..