|
Покритикуйте алгоритм включения и выключения устройства на AVR |
|
|
|
Mar 29 2011, 09:21
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Господа, есть некое устройство на АТМега, управляющее TFT-дисплеем с тачпанелью и небольшим набором периферии. Подключено к автомобильному аккумулятору постоянно. А значит нужно предусмотреть включение и выкючение устройства. При всем изяществе конструкции, наличии тачпанели слишком жалко будет смотреться механический переключатель для коммутации. Хочется выключать устройство нажав виртуальную кнопку на тачпанели, а включать простым прикосновением к экрану. А посему возникла такая идея: Контроллер управляет дисплеем через специальную плату (если кому интересно TFT-компаньон) Эта плата умеет выходить в режим пониженного потребления и понимает в нем только две команды - выход из режима пониженного энергопотребления и опрос тачпанели. Я планирую по нажатии на виртуальную кнопку на экране переводить его в PowerDown. Затем переводть в PowerDown (именно в этот режим) и сам AVR. Как включать? Предварительно - настроить WatchDog на 1 сек и на генерацию прерывания по переполнению. В прерывании опрашивать тачпанель и если было прикосновение - можно просыпаться. Однако получается следующее - при выключении всего устройства мы его на самом деле не выключаем, а переводим в спящий режим, и при включении оказываемся на том же месте. Хотелось бы перезагрузить и контроллер. А для этого хочу попробовать следующее - если при обработке прерывания от сорожевого таймера выяснится что к тачпанели прикасались - перенастраивать таймер на сброс контроллера и более короткий период (самый короткий 16 мс). После чего ждать следующего переполнения таймера.
Пока не пробовал, идею сочинял на работе, попробую только дома.
Вопросы: 1. Довольно странный алгоритм получился - при выключении устройство на самом деле просто останавливается, а истинная его перезагрузка происходит только при включении. Хотя на самом деле ввсе выглядит благористойно (забыл сказать - в режиме PowerDown TFT компаньон не только меньше жрет, но и подсветку отключает). Может есть какие-то более адекватные истрически сложившиеся алгоритмы? 2. Есть ли какой-то иной способ программного сброса AVR? Цеплять какой-нибудь выход на RESET не предлагайте, плата сделана и детали напаяны. 3. Не происходит ли чего нехорошего с портами ввода вывода в режиме PowerDown АВР? Нужно чтобы пины оставались в том же состоянии. Спасибо.
Сообщение отредактировал zheka - Mar 29 2011, 09:22
|
|
|
|
|
Mar 29 2011, 09:53
|
Местный
  
Группа: Участник
Сообщений: 256
Регистрация: 5-04-09
Из: Москва
Пользователь №: 47 180

|
Цитата(zheka @ Mar 29 2011, 13:21)  ... 2. Есть ли какой-то иной способ программного сброса AVR? Цеплять какой-нибудь выход на RESET не предлагайте, плата сделана и детали напаяны. 3. Не происходит ли чего нехорошего с портами ввода вывода в режиме PowerDown АВР? Нужно чтобы пины оставались в том же состоянии. ... 2. .ORG 0x00 RESET: . . . . JMP RESET 3. Пины останутся в том же состоянии
|
|
|
|
|
Mar 29 2011, 10:45
|
Местный
  
Группа: Участник
Сообщений: 256
Регистрация: 5-04-09
Из: Москва
Пользователь №: 47 180

|
Цитата(zheka @ Mar 29 2011, 14:38)  Извните, ассемблера не знаю. Пишу на С. Но даже глядя на то, что вы написали - это просто уловка для перемещения программы в начало, а не сброс. Если Вам нужно перезагрузить МК после выхода из Powerdown - "уловка" поможет. Если перезагрузить зависший МК - альтернативы WDT не вижу.
|
|
|
|
|
Mar 29 2011, 17:22
|

Частый гость
 
Группа: Участник
Сообщений: 148
Регистрация: 23-02-07
Пользователь №: 25 618

|
Цитата(zheka @ Mar 29 2011, 11:21)  Однако получается следующее - при выключении всего устройства мы его на самом деле не выключаем, а переводим в спящий режим, и при включении оказываемся на том же месте. Хотелось бы перезагрузить и контроллер. Объясните необходимость сброса проца. По идее перезагрузка не нужна, если проц. повиснит его сбросит вачдог. Для надежности поставьте внешний супервизор по питанию. Если все же видите необходимость повысить надежность, после выхода из сна(при касании тачскрина) запустите принудительную инициализацию важных данных. Хотя самый простой метод "JMP 0"
Сообщение отредактировал Marian - Mar 29 2011, 17:24
|
|
|
|
|
Mar 29 2011, 18:27
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(zheka @ Mar 29 2011, 14:38)  Но даже глядя на то, что вы написали - это просто уловка для перемещения программы в начало, а не сброс. Интересно , а что Вы понимаете под сбросом? Или Вы считаете что Цитата .... но я все же предпочту для перезагрузки WDT перемещает программу куда то вдругое место ,а не на 0x0000
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Mar 30 2011, 09:57
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(aaarrr @ Mar 30 2011, 00:44)  Скажите, а как вы инициализируете USART, например?
И сброс как делаете - "JMP 0"? Да так же как и все. Ниже пример Код ;/ *********************** ;/ * * ;/ * ATMega48P * ;/ * Jig for Hotel * ;/ * * ;/ *********************** ;+ Version 1.0 .nolist .include "m48def.inc" .list .listmac .include "macros_Jig.asm" .include "JigHotelTV.inc" ;************************************************* ;* ;;/ Определение командного сегмента;;* * ;************************************************** .cseg .org 0 ;************************************************* ;* ;;/Initialization прерываний;;* * ;************************************************* rjmp RESET; Reset Handler ; rjmp EXT_INT0; IRQ0 Handler ; rjmp EXT_INT1; IRQ1 Handler ; rjmp PCINT0; PCINT0 Handler ; rjmp PCINT1; PCINT1 Handler ; rjmp PCINT2; PCINT2 Handler ; rjmp WDT; Watchdog Timer Handler ; rjmp TIM2_COMPA; Timer2 Compare A Handler ; rjmp TIM2_COMPB; Timer2 Compare B Handler ; rjmp TIM2_OVF; Timer2 Overflow Handler ; rjmp TIM1_CAPT; Timer1 Capture Handler ; rjmp TIM1_COMPA; Timer1 Compare A Handler ; rjmp TIM1_COMPB; Timer1 Compare B Handler ; rjmp TIM1_OVF; Timer1 Overflow Handler ; rjmp TIM0_COMPA; Timer0 Compare A Handler ; rjmp TIM0_COMPB; Timer0 Compare B Handler ; rjmp TIM0_OVF; Timer0 Overflow Handler ; rjmp SPI_STC; SPI Transfer Complete Handler .org URXCaddr rjmp USARTRXC ; USART, RX Complete Handler rjmp USARTUDRE ; USART, UDR Empty Handler ; rjmp USART_TXC; USART, TX Complete Handler ; rjmp ADC; ADC Conversion Complete ; rjmp EE_RDY; EEPROM Ready Handler ; rjmp ANA_COMP; Analog Comparator Handler ; rjmp TWI; 2-wire Serial Interface ; rjmp SPM_RDY; Store Program Memory Ready ;| KOOL .include "Delays.asm" .include "LCD.asm" .include "USART.asm" .include "JIGKeyBoard.asm" ;************************************************* ;* ;;/Установка стека и Очитска регистров;;* * ;************************************************* RESET: cli ; запрет всех прерываний ldi temp,$80 ; Запрещаем работу out ACSR,temp; компаратора .include "1Init_MCU.asm" ; Очистка памяти и всех регистров ;************************************************** ;* ;;/Initialization PORTS;;* * ;************************************************** ldi temp,0b_0000_1111 out DDRD,temp ; ПортD старшие вход Младшие -выход ldi temp,0b_1111_1111 out PORTD,temp ;- На старшие-(1), младшие RX0&RX1-подключены ldi temp,0b_1110_1111 out DDRB,temp ; ПортB старшие PB7-PB5,PB2-PB0 OUTputs, PB4 Input ldi temp,0b_1111_1111 out PORTB,temp ;- Pull resistor down ;************************************************** ;* ;;/Initialization LCD;;* * ;**************************************************
rcall LCD_INIT ;- Инициализация LCD
;************************************************** ;* ;;/Initialization USARTs;;* * ;************************************************** ;- INIT USART0 ldi temp,(SYSCLK/(16*USARTSPEED))-1 sts UBRR0L,temp ldi temp,1<<RXCIE0|0<<UDRIE0|1<<RXEN0|0<<TXEN0 sts UCSR0B,temp ldi temp,1<<USBS0|1<<UCSZ01|1<<UCSZ00 sts UCSR0C,temp ;+ Speed USART0 9600, 8-bit data, 1 STOP Ну и какая будет разница в инит по POWER UP, WDT , внешний сброс или из MAIN rjmp RESET как тут предлагали при определённых условиях
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Mar 30 2011, 11:04
|
Местный
  
Группа: Участник
Сообщений: 256
Регистрация: 5-04-09
Из: Москва
Пользователь №: 47 180

|
Цитата(aaarrr @ Mar 30 2011, 14:45)  ...Логика USART'а сброшена не будет такой инициализацией. Нужно было сначала сбросить RXEN и TXEN в 0, чтобы получить то же состояние, что и после хардварного сброса. То же самое касается SPI и прочих интерфейсов... А что мешает в INIT сначала принудительно присвоить регистрам используемой периферии значения после POWER-UP, а потом инициализировать обычным путем?
|
|
|
|
|
Mar 30 2011, 13:22
|
Местный
  
Группа: Участник
Сообщений: 256
Регистрация: 5-04-09
Из: Москва
Пользователь №: 47 180

|
Цитата(aaarrr @ Mar 30 2011, 16:32)  ...Вы вот всегда так поступаете? И уверены, что сможете просчитать все возможные побочные эффекты?
Определенное состояние всегда следует предпочитать неопределенному, только и всего. Нет, я не всегда так поступаю. Но в некоторых МК WDT с непрограммируемым таймаутом. Ждать ...надцать секунд не всегда хорошо, и если МК не висит - такой сброс помогает.
|
|
|
|
|
Mar 30 2011, 15:04
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Господа, необходимость железного сброса продиктована прежде всего любовью к порядку. Во-первых, есть еще и периферия, есть куча проинициализированных переменных, eeprom в том числе. А во-вторых - с логической точки зрения - клиент хочет чтобы устройство выключалось, дык пусть оно выключается. Ну да ладно. Пока что у меня возникли проблемы со спящим режимом. Код SMCR =(1<<SE)|(1<<SM1); // ВХодим в POwerDown КОнтроллер молча читает эту команду и идет дальше. Может еще что надо? Внимание! В ATMega644p управление спящими режимами возложено на SMCR регистр, в MCUCR другие параметры.
Сообщение отредактировал zheka - Mar 30 2011, 15:10
|
|
|
|
|
Mar 30 2011, 19:05
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
Так... работаю со сторожевым таймером... Господа объясните мне, если контроллер ушел в PowerDown, а собачий таймер настроен на генерацию прерывания, то что происходит при его переполнении? Он будит контроллер только для того чтобы обработать прерывание и усыпляет его дальше? Или же нужно усыплять контроллер в конце обработчика прерывания от таймера У меня примерно такой код: Код interrupt [WDT] void wdt_timeout_isr(void) { //Check(); // #asm("SLEEP"); }
////////////////
if (ButtonNumber==255) { while ((x!=0)&&(y!=0)) {GetTouchStat(touch_x,touch_y);} // При нажатии на виртуальную кнопку на дисплее запускается таймер #asm("cli"); #pragma optsize- #asm("wdr") WDTCSR |= (1<<WDCE) | (1<<WDE); /* Set new prescaler(time-out) value = 64K cycles (~0.5 s) */ WDTCSR = (1<<WDIE) | (1<<WDP2) | (1<<WDP1); #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif #asm("sei");
SMCR =(1<<SE)|(1<<SM1); //А затем усыпляем контроллер в PowerDOwn #asm("SLEEP");
// SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0); // Настройка SPI
}
} Так вот - если в обработчике сторожевого таймера не усыплять контроллер, то основной цикл программы работает, и функция Check() срабатывает раз в 1 секунду. Если же убрать комментарий в обработчике, т.е. усыплять контроллер по окончании обработки - функция Check() срабатывает лишь однажды - видимо усыпление контроллера не позволяет выйти из обработчика... Суть в чем - мне нужно усыпить контроллер, но раз в 1 секунду в обработчике прерывания от сторожевого таймера нужно проверять некое условие и если оно истинно будить контроллер, если ложно - спать дальше. Как нужно сделать?
|
|
|
|
|
Mar 30 2011, 20:02
|
Местный
  
Группа: Участник
Сообщений: 256
Регистрация: 5-04-09
Из: Москва
Пользователь №: 47 180

|
Цитата(zheka @ Mar 30 2011, 23:05)  ...Суть в чем - мне нужно усыпить контроллер, но раз в 1 секунду в обработчике прерывания от сторожевого таймера нужно проверять некое условие и если оно истинно будить контроллер, если ложно - спать дальше. Как нужно сделать? После проверки условия, если оно истинно - ставите флаг. В основном цикле проверяете флаг. Если есть - работаете, нет - засыпаете.
|
|
|
|
|
Mar 31 2011, 11:38
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(aaarrr @ Mar 30 2011, 14:45)  Логика USART'а сброшена не будет такой инициализацией. Нужно было сначала сбросить RXEN и TXEN в 0, чтобы получить то же состояние, что и после хардварного сброса. Не понимаю , а зачем мне логика USART , которая у меня по-сути была , если наступили условия при которых я делаю программный сброс . Ну был включён у меня передатчик и что с того - условия наступили перезапускается вся система. Вы представьте задачку с МЕНЮ , в котором Вы можете вкл. и выкл. устройства и Вы отключили USART совсем, для новых условий задачи он Вам не нужен т.е при программном сбросе - Вы пропишите в него 000 чтобы не мешал. Я не вижу смыла записать сначала 000 USART, а затем ещё раз записать в него же необходимые числа , если преполагается использование USART
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Mar 31 2011, 11:54
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(ILYAUL @ Mar 31 2011, 15:38)  Не понимаю , а зачем мне логика USART , которая у меня по-сути была , если наступили условия при которых я делаю программный сброс . Ну был включён у меня передатчик и что с того - условия наступили перезапускается вся система. Только вот после "сброса" приемный регистр может содержать старые данные, и после разрешения приема вы тут же их получите. А оно надо? С каким-нибудь SPI может быть то же самое - SPIF в "1", первый обмен будет испорчен. Цитата(ILYAUL @ Mar 31 2011, 15:38)  Вы представьте задачку с МЕНЮ , в котором Вы можете вкл. и выкл. устройства и Вы отключили USART совсем, для новых условий задачи он Вам не нужен т.е при программном сбросе - Вы пропишите в него 000 чтобы не мешал. Это о чем? Давайте не будем придумывать меню и другие избыточные сущности в контексте обсуждения проблемы программного сброса. Цитата(ILYAUL @ Mar 31 2011, 15:38)  Я не вижу смыла записать сначала 000 USART, а затем ещё раз записать в него же необходимые числа , если преполагается использование USART А он есть.
|
|
|
|
|
Mar 31 2011, 18:04
|
Гуру
     
Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164

|
defunct, именно так. Дело в том, что питание будет подаваться при подсоедниении к клеммам аккумулятора - а это всерьез и надолго. Выключения и включения физической коммутацией нет, обесточивания при выключении питания не будет. в этом и задумка. Подключили к аккумулятору - нужно еще и на панельку нажать. А далее - нажал кнопку выключения - заработал сторожевой таймер и сбросил контроллер, контроллер стартовал и, ничего не включая сразу в режим сна, просыпаясь раз в секунду, дабы узнать не давит ли кто на тачпанель. Если да - то дальше по тексту программы. Выглядит это все как включение и выключение от тачпанели. ILYAUL, а что вам не понравилось? У вас мобильник от простого нажатия кнопки включается? Правильно, нет, подержать нужно. По этому принципу работают многие современные устройства. К тому же сенсорная панель - это одна большая кнопка, сам бог велел защитить ее от случайного касания. Есть другой минус - человеческие рефлексы. Челове должне привыкнуть, что прикасаться нужно в течение секунды, однако возможны варианты, когда влючение произойдет практически сразу после нажатия (в зависимости от текущего состояния таймера) И вот это будет раздражать. Как это поправить - мыслей нет. МОжно конечно настроить на 16 мс, а потом просто ждать секунду, но тогда теряется смысл засыпаний - опрос тачпанели занимает 1 мс, еще какое -то время на танцы вокруг этого опроса, соотношение рабочего и спящего режимов получается невелико... Выглядит это так: Код StartUP(); PowerDown(); delay_ms(3);
// SetBackLight(0);
#asm("cli"); #pragma optsize- #asm("wdr") WDTCSR |= (1<<WDCE) | (1<<WDE); WDTCSR = (1<<WDIE) | (1<<WDP2) | (1<<WDP1); #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif #asm("sei"); SMCR =(1<<SE)|(1<<SM1); sleep_flag=1; #asm("SLEEP") SPCR_tmp=SPCR; SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0); // Настройка SPI while(sleep_flag) { GetTouchStat(touch_x,touch_y); if ((x==0)||(y==0)) {sleep_flag=1; #asm("SLEEP");} else sleep_flag=0; } PowerUp(); delay_ms(10); SPCR=SPCR_tmp; Повторюсь - в обработчике прерывания то собачьего таймера ничего нет, он просто лает на контроллер и тот просыпается от страха.
|
|
|
|
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|