raslmc 0 13 октября, 2008 Опубликовано 13 октября, 2008 (изменено) · Жалоба Всем добрый день. Вот решил выложить свои мучения по данной теме. Может кому нибудь пригодится. В инете так и толком ничего не нашел. Алгоритм следующий: Ногу PD0 и PD2 нужно замкнуть. 1) Устанавливаем внешнее прерывание (INT0) на захват спадающего фронта. 2) Прерывание произошло, устанавливаем внешнее прерывание (INT0) на захват восходящего фронта, устанавливаем счетчик Timer1 на отсчет времени. 3)Прерывание произошло, останавливаем таймер, запрещаем внешнее прерывание. 4)Подсчитываем битрайт, и задерживаемся(delay_us()) до конца данного байта. 5)Настраиваем скорость усарта и принимаем данные. Испытания проводил на Mega8, 16Mhz, на скоростях от 9600-210000. Главные условия, чтобы младший бит первого байта посылки был равен 1. Прием начинается со 2-го байта. Грубо говоря 1-й байт нужен для синхронизации. Также реулизована возможность засыпания процессора. Если это не нужно, просто закомментируйте #define SLEEP. В принципе пока все устраивает, просто хотел узнать Ваше мнение. Вопрос: Теоретически после того как определили битрайт(это в конце старт-бита) нужно сделать delay_us() равный: 1bit time*8(до начала стоп бита), а уже потом устанавливать битрайт. Но вреальности принимается ерунда. Но если написать следущее: for(n=0; n < (char)baudrate-1; n++) delay_us(1);//Ничего не делаем до начала следующего байта for(n=0; n < (char)baudrate-1; n++) delay_us(1); То все работает. Эта задержка примерно равна 2-м битам. Мне так кажется что пока я дохожу до этого момента, проходит время равное 6-ти битам. Вот сам код: #include <ioavr.h> #include <inavr.h> #include "USART.h" //******************************************************************************** ********** #define SLEEP unsigned static char state; unsigned int baudrate; #pragma vector = INT0_vect __interrupt void OnCapt() { if(0==state)//Перехват падения фронта { state = 1; MCUCR |= (1<<ISC01) | (1<<ISC00); //Установка прерывания по восходящему фронту TCNT1H=0;//Обнуляем таймер TCNT1L=0; TCCR1B|=(0<<CS12) |(0<<CS11) | (1<<CS10);//Запускем таймер 1 без делителя } else if(state==1)//Перехват подъема фронта { state = 2; baudrate = TCNT1L; baudrate |= (int)TCNT1H<<8; TCCR1B&=~((0<<CS12) |(0<<CS11) | (1<<CS10));//Запрещяем таймер MCUCR &= ~((1<<ISC01) | (1<<ISC00));//Запрещяем захват по фронту GICR &= ~(1<<INT0);//Запрещаем прерывание по захвату } } unsigned int Usart_autobaud(void) { unsigned char n; state=0; MCUCR |= (1<<ISC01) | (0<<ISC00); //Установка прерывания по спадающему фронту GICR |= (1<<INT0); //Разрешение прерывания #ifdef SLEEP MCUCR |= (1<<SE); //Разрешаем режим сна до первого внешнего прерывания asm("sleep"); MCUCR &= ~(1<<SE); //Запрещаем режим сна до первого внешнего прерывания #endif while(state != 2); //Ждем окончание старт бита(восходящий фронт) //Определяем битрайт baudrate = (baudrate>>3)-1; //baudrate=(baudrate/8)-1 for(n=0; n < (char)baudrate-1; n++) delay_us(1);//Ничего не делаем до начала следующего байта for(n=0; n < (char)baudrate-1; n++) delay_us(1); return baudrate; } //******************************************************************************** ********** void main( void ) { DDRD = 0x00; PORTD = 0x00; DDRB = 0x00; PORTB = 0x00; DDRC = 0x00; PORTC = 0x00; #ifdef SLEEP MCUCR |= (0<<SM2)|(0<<SM1)|(0<<SM0);//Режим сна Idle #endif USART0_init();//Инициализируем уарт __enable_interrupt(); delay_s(1); while(1) { USART0_set_speed(Usart_autobaud()); //Определяем битрайт и устанавливаем скорость UCSRB |= (1 << RXCIE)| (1 << RXEN); //Разрешаем прием и прерывание усарта while(!USARTBuffSize); //Ждем конца приема данных UCSRB &= ~((1 << RXCIE) | (1 << RXEN)); //Запрещаем прием и прерывание усарта USART_SEND_STR(UsartBuff, USARTBuffSize+1); USARTBuffSize = 0; } } И еще вопрос. В даташите написано, что пробуждение от сна по внешнему прерыванию разрешено во всех режимах. Но у меня прерывание происходит только в режиме сна Idle. Что я делаю не так ? Изменено 13 октября, 2008 пользователем Ruslan Konovalov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба Теоретически после того как определили битрайт(это в конце старт-бита) нужно сделать delay_us() равный: 1bit time*8(до начала стоп бита), а уже потом устанавливать битрайт. А зачем вообще ждать, почему нельзя сразу установить скорость уарта? Но вреальности принимается ерунда.Что конкретно принимается? может там происходит ошибка кадрирования и ее надо просто сбросить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба А зачем вообще ждать, почему нельзя сразу установить скорость уарта? Что конкретно принимается? может там происходит ошибка кадрирования и ее надо просто сбросить? Я тоже так думаю. Но как это устранить ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба А не надо устранять, просто сбросьте ошибку, а протокол надо применить с подтверждением. В результате ошибки первая датаграмма не будет правильно принята и устройство не ответит или ответит ошибкой(на уже определенной скорости), на что передающая сторона должна повторить передачу пакета и далее обмен пойдет уже правильно. P.S. В качестве бреда... можно первый байт принять софтово и подставить его в буфер... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба А не надо устранять, просто сбросьте ошибку, а протокол надо применить с подтверждением. В результате ошибки первая датаграмма не будет правильно принята и устройство не ответит или ответит ошибкой(на уже определенной скорости), на что передающая сторона должна повторить передачу пакета и далее обмен пойдет уже правильно. P.S. В качестве бреда... можно первый байт принять софтово и подставить его в буфер... Ксожаление нет возможности изменить протокол. Протокол без подтверждения. Просто устройство отсылает мне пакет, а я должен его принять. Первый байт - начало пакета. Он мне известен. Так что не важно что 1-й байт не принимается. Главное чтобы со второго байта все принималось корректно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба У меня: 1) не задействовано дополнительных ног (это для AVR ни к чему) 2) без разницы что идёт первым символом (в смысле какой нулевой бит 0 или 1) 3) На частоте 7372800 безошибочное восстановление инфы до 115200. У меня может ошибаться UART лишь в том случае если в символе 1 перепад (например 5 мл. =0, потом =1). Это изза того, что восстановление скорости осуществляется по первому байту. Но принципиально, если бы такая задача стояла, то я бы мог полностью восстановить данные. То есть в таком случае ждал бы первого "вменяемого" символа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба У меня: 1) не задействовано дополнительных ног (это для AVR ни к чему) 2) без разницы что идёт первым символом (в смысле какой нулевой бит 0 или 1) 3) На частоте 7372800 безошибочное восстановление инфы до 115200. У меня может ошибаться UART лишь в том случае если в символе 1 перепад (например 5 мл. =0, потом =1). Это изза того, что восстановление скорости осуществляется по первому байту. Но принципиально, если бы такая задача стояла, то я бы мог полностью восстановить данные. То есть в таком случае ждал бы первого "вменяемого" символа. 1) Если не секрет, давайте код в студию, вдруг кому нибудь пригодится(например мне) :) 2) По вашему алгоритму не получится проснуться из режима спячки. А для меня это желательно. Мне кажется разница между Вашим и моим алгоритмом в том что я использую внешние прерывания а Вы while(!(PIND&(1<<PD0)));//Ждем падение фронта ... while((PIND&(1<<PD0)));//Ждем подъем ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба 1) Если не секрет, давайте код в студию, вдруг кому нибудь пригодится(например мне) :) Это я сделать не могу 2) По вашему алгоритму не получится проснуться из режима спячки. А для меня это желательно. Да. Мне это было не нужно. Для этого действительно необходимо дополнительно Int задействовать Мне кажется разница между Вашим и моим алгоритмом в том что я использую внешние прерывания а Вы Нет ну это просто принцип измерения длительности импульса. Это к самому алгоритму не имеет никакого отношения. Алгоритм ваш и мой отличается как телега от мерседеса. Поскольку ничего сверхестественного в нём нет, я его просто сел и выдумал подходя к решению данной задачи. Иными словами я его нигде не заимствовал. Просто смотрел как восстанавливает посылку модем US Robotics Courier. Задумался как это можно сделать, проанализировал и получил результат. Я не знаю так ли делает модем от US Robotics, но я делал след. образом. 1) записывал все длительности импульсов в память. 2) на лету выделял найменьший импульс, а также найменьшую разность 3) на лету определял "текущий прогнозируемый конец байта" 4) по окончанию байта определял скорость, переводил записаное в нужные биты и преобразовывал в байт, переинициализировал UART. Скорость сбрасывал по след признакам: 1) Конец команды 2) Таймер неактивности 3) Снятие готовности терминала Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба Я не знаю так ли делает модем от US Robotics, но я делал след. образом. 1) записывал все длительности импульсов в память. 2) на лету выделял найменьший импульс, а также найменьшую разность 3) на лету определял "текущий прогнозируемый конец байта" 4) по окончанию байта определял скорость, переводил записаное в нужные биты и преобразовывал в байт, переинициализировал UART. В модеме autobaud detect реализовать проще, т.к. там заранее известно, что команда с префикса AT начинается. А вот как предлагается реализовывать это же самое на MSP430. Automatic Baud Rate Detection on the MSP430 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 6 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба Вот решил выложить свои мучения по данной теме. Может кому нибудь пригодится. В инете так и толком ничего не нашел. Э-э-э-э... Может, толком не искали? Например, у Atmel'а - это добро выложено. Ну, например, в исходниках к AVR914. Это - то, что сходу нашёл... Думаю, что эта функция у них качует от примера к примеру: скорость определяется по первому символу (символ U - код символа 55h). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба Э-э-э-э... Может, толком не искали? Например, у Atmel'а - это добро выложено. Ну, например, в исходниках к AVR914. Это - то, что сходу нашёл... Думаю, что эта функция у них качует от примера к примеру: скорость определяется по первому символу (символ U - код символа 55h). Я нашел этот аппноут. Но там на ассемблере. На си найти не удалось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Палыч 6 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба Я нашел этот аппноут. Но там на ассемблере. На си найти не удалось. Ассемблер применять - религия не позволяет? Впрочем, можно переложить и на С. Точность, правда, пострадает... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба Ассемблер применять - религия не позволяет? Впрочем, можно переложить и на С. Точность, правда, пострадает... Я религиозный. Для меня ассемблер глухой лес к сожалению. А вообще кто нибудь работал с режимами сна ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба В модеме autobaud detect реализовать проще, т.к. там заранее известно, что команда с префикса AT начинается. А вот как предлагается реализовывать это же самое на MSP430. Automatic Baud Rate Detection on the MSP430 Я это делал тоже для модема, но это отговорка. На самом деле модем восстанавливает все символы, которые может восстановить. В частности, описанный мной курьер восстанавливает ~ 99% символов. Можете проверить. Мой модем восстанавливает практически так же. Я не пробовал соревноваться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sf9 0 15 октября, 2008 Опубликовано 15 октября, 2008 · Жалоба Господа электронщики, как определять скорость USARTa в случае,когда мы знаем,какой именно байт должен быть принят - дело понятное. Практически у каждого производителя МК есть статья с алгоритмом,который сводится к тому,что просто сравниваем,какой байт получился на приёме с табличными значениями и определяем скорость. ВОПРОС: какой алгоритм должен быть при autobaudrate,если из канала мы получаем произвольные данные и не можем предсказать,что именно. Т.е. могут быть,как все нули, так и все единицы и пр. Sasa из Vitebsk Вы попытались описать данный алгоритм,но не совсем ясно,как он работает. Может у кого есть ещё какие-нибудь идеи????? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться