raslmc 0 7 октября, 2008 Опубликовано 7 октября, 2008 · Жалоба Всем добрый день. Возникла проблема при использовании спящего режима(Idle mode) в Atmega8. Вот код(не полный): void main(void) { MCUCR |= (0<<SM2)|(0<<SM1)|(0<<SM0); //Idle mode init_Usart(); __enable_interrupt(); for(;;) { MCUCR |= (1<<SE); //Разрешение спящего режима asm("sleep"); //Сон Usart_read(); //Читаем строку Usart_Send_Str(UsartBuff); //Возвращаем принятое } } Проблема заключается в том, что при использовании спящего режима Usart читает входящие данные нормально, за исключением первого байта. Я так понимаю он пропускает его из-за того что процессор просыпается и начинает нормально работать в момент прихода 2-го байта. Как решить эту проблему ? А что если соеденить ножку RX и INT0 и будить процессор по этому прирыванию ? Может кто нибудь уже с этим сталкивался ? Заранее спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Николай Иванович Приходько 0 7 октября, 2008 Опубликовано 7 октября, 2008 · Жалоба Проблема заключается в том, что при использовании спящего режима Usart читает входящие данные нормально, за исключением первого байта. Ну так организуйте протокол так, чтобы первый байт не нёс никакой инфы, а использовался только для "побудки" микроконтроллера. В чём проблема-то? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 7 октября, 2008 Опубликовано 7 октября, 2008 · Жалоба Ну так организуйте протокол так, чтобы первый байт не нёс никакой инфы, а использовался только для "побудки" микроконтроллера. В чём проблема-то? К сожалению изменить протокол нет возможности. :05: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladimirYU 0 7 октября, 2008 Опубликовано 7 октября, 2008 · Жалоба Всем добрый день. Возникла проблема при использовании спящего режима(Idle mode) в Atmega8. Вот код(не полный): void main(void) { MCUCR |= (0<<SM2)|(0<<SM1)|(0<<SM0); //Idle mode init_Usart(); __enable_interrupt(); for(;;) { MCUCR |= (1<<SE); //Разрешение спящего режима asm("sleep"); //Сон Usart_read(); //Читаем строку Usart_Send_Str(UsartBuff); //Возвращаем принятое } } Проблема заключается в том, что при использовании спящего режима Usart читает входящие данные нормально, за исключением первого байта. . Idle mode enables the MCU to wake up from external triggered interrupts as well as internal ones like the Timer Overflow and USART Transmit Complete interrupts. If wake-up from the Analog Comparator interrupt is not required, the Analog Comparator can be powered down by setting the ACD bit in the Analog Comparator Control and Status Register – ACSR. This will reduce power consumption in Idle mode. If the ADC is enabled, a conversion starts automatically when this mode is entered. Мне кажется функцию приема нужно организовать по прерыванию от RXC. Idle mode enables the MCU to wake up from external triggered interrupts as well as internal ones like the Timer Overflow and USART Transmit Complete interrupts. If wake-up from the Analog Comparator interrupt is not required, the Analog Comparator can be powered down by setting the ACD bit in the Analog Comparator Control and Status Register – ACSR. This will reduce power consumption in Idle mode. If the ADC is enabled, a conversion starts automatically when this mode is entered. Мне кажется функцию приема нужно организовать по прерыванию от RXC. Немного не так выделил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 7 октября, 2008 Опубликовано 7 октября, 2008 (изменено) · Жалоба Мне кажется функцию приема нужно организовать по прерыванию от RXC. Все верно. Функция Usart_read(); выглядит примерно так: void Usart_read(void) { while(!received); } //А вот само прерывание #pragma vector = USART_RXC_vect __interrupt void Recieve() { unsigned char temp = 0; temp = UDR; UsartBuff[UsartBuffPtr] = temp; UsartBuffPtr++; if(temp == 0x0D) received = 1; //0x0D - конец принимаемых данных. } Изменено 7 октября, 2008 пользователем Ruslan Konovalov Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladimirYU 0 8 октября, 2008 Опубликовано 8 октября, 2008 · Жалоба Все верно. Функция Usart_read(); выглядит примерно так: void Usart_read(void) { while(!received); } //А вот само прерывание #pragma vector = USART_RXC_vect __interrupt void Recieve() { unsigned char temp = 0; temp = UDR; UsartBuff[UsartBuffPtr] = temp; UsartBuffPtr++; if(temp == 0x0D) received = 1; //0x0D - конец принимаемых данных. } Действительно, я примерно делаю также. Попробуйте убрать спячку (заменить, например, на while с условием выхода по приему первого байта пакета ), и убедиться, что потеря 1-го байта связана именно с ней. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 9 октября, 2008 Опубликовано 9 октября, 2008 · Жалоба Действительно, я примерно делаю также. Попробуйте убрать спячку (заменить, например, на while с условием выхода по приему первого байта пакета ), и убедиться, что потеря 1-го байта связана именно с ней. Уже пробовал. Без спячки все прекрасно работает. И еще, как я понял процессор просыпается от прерывания по RXC только в режиме Idle. Пробовал другие режимы. В них процессор спит. :05: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladimirYU 0 9 октября, 2008 Опубликовано 9 октября, 2008 · Жалоба Уже пробовал. Без спячки все прекрасно работает. И еще, как я понял процессор просыпается от прерывания по RXC только в режиме Idle. Пробовал другие режимы. В них процессор спит. :05: Idle mode enables the MCU to wake up from external triggered interrupts as well as internal ones like the Timer Overflow and USART Transmit Complete interrupts. Доки от Атмела, как русский язык по Черономырдину. Ни слова про RXC, является ли оно тем, что выделено, или речь только об интах? Ипользовал сам этот режим, но не помню подробностей, вроде делал в принципе все как у Вас, попробую паоднять старый проект, правда он был на меге128. Но это не принципиально. Может быть задействовал еще одну ногу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 9 октября, 2008 Опубликовано 9 октября, 2008 · Жалоба Спасибо всем, кто откликнулся. Оказалось, что это я как всегда напартачил. Вообщем стыдно даже говорить где была проблема(в кривых руках) :) А RXC прерывание работает корректно и с Idle mode. Ошибку исправил и все заработало. Простите что ввел Вас в заблуждение. Как говориться: "Прежде чем искать баги производителя, поищи свои". Выражаю всем благодарность. Тему можно закрыть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GDI 0 9 октября, 2008 Опубликовано 9 октября, 2008 · Жалоба Все же поборите свой стыд и расскажите в чем была проблема, чтоб другие не напоролись. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladimirYU 0 10 октября, 2008 Опубликовано 10 октября, 2008 · Жалоба Все же поборите свой стыд и расскажите в чем была проблема, чтоб другие не напоролись. +1. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба Ладно. Было вот так: void main(void) { MCUCR |= (0<<SM2)|(0<<SM1)|(0<<SM0); //Idle mode init_Usart(); __enable_interrupt(); UsartRxOn = 0; for(;;) { MCUCR |= (1<<SE); //Разрешение спящего режима asm("sleep"); //Сон UsartRxOn = 1;//Разрешаем прием байтов Usart_read(); //Читаем строку UsartRxOn = 0; //Запрещаем прием байтов Usart_Send_Str(UsartBuff); //Возвращаем принятое } } void Usart_read(void) { while(!received); } //А вот само прерывание #pragma vector = USART_RXC_vect __interrupt void Recieve() { unsigned char temp = 0; temp = UDR; if(UsartRxOn) //Если прием байтов разрешен { UsartBuff[UsartBuffPtr] = temp; UsartBuffPtr++; if(temp == 0x0D) received = 1; //0x0D - конец принимаемых данных. } } Вся проблема была в том, что процессор просыпается по прерыванию RXC, но на тот момент UsartRxOn = 0. И по этому 1-й байт в UsartBuff не заносился. Я просто поставил UsartRxOn = 1; перед функции засыпания и все исправилось. Но по првильному вместо UsartRxOn лучше делать так: UCSRB |= (1 << RXCIE);//Разрешаем прерывание UCSRB |= (1 << RXCIE);//Запрещаем прерывание Вот такие кривые ручки. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladimirYU 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба UCSRB |= (1 << RXCIE);//Разрешаем прерывание UCSRB |= (1 << RXCIE);//Запрещаем прерывание [/code] Вот такие кривые ручки. :) А найдите два отличия в Ваших строчках :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
raslmc 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба UCSRB |= (1 << RXCIE);//Разрешаем прерывание UCSRB |= (1 << RXCIE);//Запрещаем прерывание [/code] Вот такие кривые ручки. :) А найдите два отличия в Ваших строчках :) CTRL+C и CTRL+V рулит. :) Надо так: UCSRB |= (1 << RXCIE); //Разрешаем прерывание UCSRB &=~ (1 << RXCIE); //Запрещаем прерывание А вот теперь думую все. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 13 октября, 2008 Опубликовано 13 октября, 2008 · Жалоба А что если соеденить ножку RX и INT0 и будить процессор по этому прирыванию ? Может кто нибудь уже с этим сталкивался ? Просыпается от прерывания UART'а и нормально вытаскиваются все данные. Ничего не теряется. t2313, 90S2313, m8, m48/88/168. Другие МК с UART'ами у меня не спят. Idle mode enables the MCU to wake up from external triggered interrupts as well as internal ones like the Timer Overflow and USART Transmit Complete interrupts. Доки от Атмела, как русский язык по Черономырдину. Ни слова про RXC, является ли оно тем, что выделено, или речь только об интах? external triggered interrupts as well as internal ones Написано же - пробуждается как внешними так и внутренними источниками прерываний (т.е. любым прерыванием). Или для тех кто "в танке" надо перечислить каждый источник прерываня для каждого проца? Вся проблема была в том, что процессор просыпается по прерыванию RXC, но на тот момент UsartRxOn = 0. И по этому 1-й байт в UsartBuff не заносился. Еще раз убеждаемся, что по чрезмерно сокращенным огрызкам кода (как в самом первом посте) реальную проблему найти просто невозможно. Приводить нужно кусочек реального проекта по принципу "как есть", разве только имена переменных поменять для наглядности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться