Skocz do zawartości

ATmega328P tryb power-save sleep mode i błędy usarta


Anonim

Pomocna odpowiedź

Ostatnio torturuję się płytką arduino pro mini z kwarcem zegarkowym i już na wstępie natknąłem się na dziwny problem. Przed wejściem w power-save sleep mode wysyłane usartem komunikaty wyświetlają się w terminalu prawidłowo, natomiast po pierwszym wybudzeniu kolejne komunikaty już są nieco zmienione, sam tekst pozostał bez zmian ale formatowanie się zmieniło co może znaczyć że gubi znaki. Problemu nie ma kiedy wybrana jest opcja idle mode więc doszedłem do wniosku, że może to być spowodowane czasem dostępu do pamięci. Niestety nie pomaga tu żaden delay i skończyły mi się pomysły co z tym zrobić. Nie chodzi mi tu o sam usart ale pokazuje to, że coś nie jest w porządku i może mieć wpływ również na inne funkcje.

Konfiguracja wygląda tak:

#define _NBV(b) ~_BV(b)
#define _SLEEP_ SMCR |= _BV(SE);asm("sleep");SMCR &= _NBV(SE) 
  
void 
rswrite(char *ch){

	for(; *ch; ch++){
		while (!(UCSR0A & _BV(UDRE0)));
		UDR0 = *ch;
	}
}

int 
main(void){
// rtc z kwarcu 32.786kHz
  	ASSR 		|= _BV(AS2);
	TCNT2 		= 0;
  	TCCR2B 		|= _BV(CS21);//presc 8 -> 0.0625s (1/16s)
  	TIFR2 		|= _BV(TOV2);// !
	TIMSK2		|= _BV(TOIE2);

// sleep
    SMCR |= _BV(SM1)|_BV(SM0);
  
// usart 9600
  	UBRR0H = 0;
	UBRR0L = 51;
	UCSR0A &= _NBV(U2X0);
	
	UCSR0C |= _BV(UPM01)|_BV(UCSZ01) | _BV(UCSZ00); // even parity, 8bit char size, 1 bit stop 
	UCSR0B |= _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);
  
// zmienne  
 	uint8_t txtbuff[4];
  	uint8_t	seconds;
	uint8_t	minuts;
	uint8_t hour;
	uint8_t day;
  
// Loop  
  while(1){
    
    if(MAIN_FLAG_REG & _BV(RTC_SEC_FLAG)){
      
			MAIN_FLAG_REG &= _NBV(RTC_SEC_FLAG);
			seconds++;
			if(seconds == 60){
				seconds = 0;
				minuts++;
				if(minuts == 60){
					minuts = 0;
					hours++;
					if(hours == 24){
						hours = 0;
						days++;
					}
				}
			}
			rswrite("day: ");
			rswrite(itoa(days,txtbuff,10));
			rswrite("\r\n");
    		
      		if(hours < 10) rswrite("0"); 
      		rswrite(itoa(hours,txtbuff,10)); rswrite(":");
      		if(minuts < 10) rswrite("0");
      		rswrite(itoa(minutss,txtbuff,10)); rswrite(":");
      		if(seconds < 10) rswrite("0");
      		rswrite(itoa(seconds,txtbuff,10));
			rswrite("\r\n");
    }
   _SLEEP_;
  }
  
}

ISR(TIMER2_OVF_vect, ISR_NAKED){
 
	asm volatile(
		"push r24 						\n\t"
		"push __tmp_reg__ 				\n\t"
		"in __tmp_reg__,__SREG__		\n\t" 
		"in r24, %0						\n\t"
		"andi r24, 0x1F					\n\t"
		"inc r24						\n\t"
		"cpi r24, 16					\n\t"
		"brne exit						\n\t"
			"ori r24, (1<<5)			\n\t"
			"andi r24, 0xE0				\n\t"
"exit:									\n\t"
		"out %0, r24					\n\t"
		"out __SREG__,__tmp_reg__ 		\n\t"  
		"pop __tmp_reg__				\n\t"
		"pop r24						\n\t"
		"reti							\n\t"
		:
		: "I" (_SFR_IO_ADDR(GPIOR0)) // główny rejestr flag
		:"r24"
	);
};

 

W kodzie jest drobny błąd dot. rejestru flag ale nie ma on znaczenia w tym konkretnym przypadku ponieważ nic innego z tego rejestru na razie nie korzysta.

Link do komentarza
Share on other sites

"Nieco zmienione", "może znaczyć"... to forum onetu czy forbot? Co znaczy "nieco"? Podepnij sobie jakąś sondę (jak nie masz to zrób sobie choćby z Arduino), popatrz co jest nie tak - bo raczej operatorów szklanej kuli tu nie znajdziesz. Szczególnie jeśli powiesz tylko że coś się zepsuło...

Link do komentarza
Share on other sites

@ethanak nie każdy ma wszechstronnie wyposażony warsztat elektroniczny w sypialni gotowy do pracy o każdej porze dnia i nocy. 

W tym przypadku brakuje nowej linii zaraz po "days". To samo się dzieje w każdym innym trybie sleep oprócz idle. Dodam, że bod jest wyłączony w fusach.

Link do komentarza
Share on other sites

Czyli naprawdę nie możesz zanalizować sobie tego, co wypluwa Twoje Arduino? To kto to ma zrobić?

Wiesz... ja mam takiego dyżurnego klona Uno, co go używam do różnych nietypowych rzeczy. Również w nocy.

Co znaczy brakuje nowej linii? Znak \n w ogóle nie jest wysyłany? Czy wysyłany błędnie? Kogo jak kogo, ale Ciebie bym nie podejrzewał o prośbę o wróżenie z fusów.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Więc raz jeszcze: przed wejściem w power-save terminal odbiera dokładnie to co jest wpisane, po wyjściu ze sleep mode zamiast \n jest jakiś krzak albo inny znak specjalny w rezultacie czego komunikat jest wyświetlany w całości w jednej linii ale pozostaje przerwa pomiędzy komunikatami. To samo dzieje się nawet w noice reduction, jedynie idle mode nie powoduje tego błędu. Dlatego nie jestem pewny czy to z powodu niewłaściwej konfiguracji sleep mode lub braku np. jakiegoś opóźnienia (choć i tak próbowałem nawet w przerwaniu) czy może jakiś niepełnosprawny okaz arduino mi się trafił bo nigdy wcześniej nie miałem takiego problemu nawet na medze8.

Na listingu brakuje sei();  u siebie mam, musiałem zgubić kopiując.

Link do komentarza
Share on other sites

1 minutę temu, ethanak napisał:

odpowiedź: "chyba spier^wpopsułeś".

tyle to sam wiem i bez wnikliwej analizy. w sumie to nie ma znaczenia co toto z siebie wydziela. Znaczenia ma, że nie to co powinno i ma to jakiś związek ze sleepem ale nie wiem jaki.

Link do komentarza
Share on other sites

no to powodzenia - jak Ci się  nie chce sprawdzić co jest nie tak, to może odpocznij, zastanów się... może ładnie śpiewasz? zostaniesz wokalistą rockowym (ech, sława) albo discopolo (ech, kasa)...

 

Link do komentarza
Share on other sites

badam temat [ [][][][][][][]------------------  analysis in progress  --------------------- ]

Edytowano przez Anonim
Link do komentarza
Share on other sites

Nie wiemy kilku podstawowych rzeczy:

  • z którego zegara pracuje CPU (wewn-zewn)
  • jak masz ustawione fusy związane z oczekiwaniem na restart zegara

Ty także nie wiesz kilku rzeczy:

  • oscylator 32kHz startuje tak ze 2 sekundy od zawłączenia wzmacniacza do pełnej amplitudy
  • procedura zmiany źródła taktowania Timera 2 na asynchroniczne 32kHz jest inna (do znalezienia w datasheet)
  • w związku w powyższym Twój zegar 32kHz jeszcze stoi gdy procesor już idzie spać
  • funkcja pisząca do UARTa zapisuje znak i ma gdzieś co się z nim stanie bo od razu wraca a znak się wysyła
  • program główny widząc, że otrzymał sterowanie z powrotem po wypisaniu tekstu (to tylko jemu się wydaje, że tekst wyszedł w całości) od razu wyłącza zegar wszystkim, UARTowi także
  • znak wisi w nadajniku w przypadkowym stanie (np. zero na linii nadajnika) aż do ponownego odpalenia zegara głównego

 

 

Link do komentarza
Share on other sites

  • Wewnętrzny oscylator taktuje rdzeń.
  • ext: 0x03; H: 0xD7; L: 0xD2. Startup time 14ck + 4.1ms
  • Nie zauważyłem aby były z nim jakieś problemy po resecie, pewnie ma już wystarczającą amplitudę po 4ms
  • (!) Tu możesz mieć rację, trzeba poczekać aż powysyła znaki do końca tylko, że to nie ostatnia transmisja jest błędna.
  • Początek wysyłania po włączeniu taktowania jest w porządku.

To zdaje się ma związek z dostępem do pamięci, niestety nie pomaga dodanie delaya na tych 5ms zaraz po przebudzeniu. Jedynie w idle mode nie ma problemu.

Bez wchodzenia w sleep mode, Timer2 działa zgodnie z założeniami.

Link do komentarza
Share on other sites

7 minut temu, atMegaTona napisał:

nie pomaga dodanie delaya na tych 5ms zaraz po przebudzeniu. Jedynie w idle mode nie ma problemu.

W poniedziałek kąpała się w smole.

We wtorek w rosole.

(resztę wierszyka sobie wyguglasz).

Link do komentarza
Share on other sites

10 minut temu, atMegaTona napisał:

Nie zauważyłem aby były z nim jakieś problemy po resecie, pewnie ma już wystarczającą amplitudę po 4ms

Tak, mi też się odechciewa czytając takie teksty.. Po jakich 4ms? Po tym czasie to procesor rusza i dopiero wtedy włączasz wzmacniacz generatora 32k. Nie dajesz mu nawet 100us. Czy dla Ciebie czas np.10000x krótszy jest bez znaczenia? Na jakiej podstawie twierdzisz, że " pewnie ma już wystarczającą amplitudę"? Wiele projektów tak robisz? A próbowałeś z zamkniętymi oczami przechodzić przez przejście z sygnalizacją? Wystarczy policzyć do 153 i "pewnie jest już wystarczająco zielone"? A przy jakim stosunku czasów startu oscylatora 32k do tego który mu na to dajesz zastanowiłbyś się chwilę, może puknął w głowę i poszukał prawidłowej sekwencji przełączania? Ciekaw jestem jakiejś liczby. Albo nie, nie kłopocz się, są tu na pewno jakieś bardziej obiecujące watki..

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.