Skocz do zawartości

Zdobądź Proxxona FBS 240/E - #4 - Uniwersalna funkcja


Pomocna odpowiedź

OldSkull, muszę Cię zmartwić, ale Bobby ma 100% racji.

Po pierwsze kod:

#ifndef _ADC_CALC_H_ 
#define _ADC_CALC_H_ 

#endif 

Nie ma najmniejszego sensu. Jest to kompilacja warunkowa pustego bloku. Czyli za pierwszym razem ta pusta linijka zostanie dołączona do kodu, za kolejnym razem już nie. Definicja klasy, jak i pozostała zawartość pliku nagłówkowego powinna być między define, a endif.

Jeszcze ciekawiej jest z kodem dla konstruktora w pliku nagłówkowym. Zasada jest taka, że treść metod / funkcji powinna być w plikach c/cpp/cc, a nie nagłówkowych. Czasem niestety konieczne jest odejście od tej reguły. Przyczyny to: użycie szablonów (template), optymalizacja (funkcje rozwijane w miejscu wywołania, include). W Twoim przypadku nie ma żadnego uzasadnienia na włączanie konstruktora do nagłówka. Tym bardziej, że pozostałem metody są w pliku .cpp.

Najciekawsze jest jednak coś innego - dwa błędy, które popełniłeś, ale nie chcesz się przyznać, sprawiają, że nawet kompilator je wychwyci. Otóż nie działa zabezpieczenie przed dwukrotnym włączaniem pliku nagłówkowego AdcCalc.hpp. Gdybyś nie wstawił konstruktora do tego pliku, kompilator by to przeżył. Ale ponieważ w nagłówku jest treść konstruktora, pojawią się dwie implementacje tej samej metody oraz błąd kompilacji.

Jak nie wierzysz, sprawdź:

#include "AdcCalc.hpp"
#include "AdcCalc.hpp"

error: redefinition of 'AdcCalc'

Link do komentarza
Share on other sites

Tu masz rację. Aczkolwiek dalej uważam, że błąd był w bloku ifdef, a nie w klasie. W każdym razie dziękuję za zwrócenie uwagi - już poprawiłem.

A nie przyznaję się, gdyż są to rozwiązania dopuszczalne, nawet jeśli nie zalecane. To tak jak z instrukcjami skoku - niektóre są dobre, a niektóre złe - goto złe, a break i continue dobre. Wszystko zależy od sytuacji. Tutaj ciała funkcji są w miejscach, które nie ograniczają czytelności kodu, a nawet ją zwiększają - tym samym jako dozwolony zapis, można go stosować.

Link do komentarza
Share on other sites

Witam!

Ja z kolei chciałbym przedstawić gotową funkcję, ale dla użytkownikó STM'ów32. Ustawia ona najwyższe taktowanie dla mikrokontrolerów z serii f103(72Mhz), ale po kilku małych zmiannach również dla wielu innych. Odróżnia się ona od reszty tym, że jest napisana na rejestrach i można po kolei zobaczyć co jest ustawiane, oraz (co ja lubię najbardziej) obserwować zmiany bitów w debugerze.

void RCC_cfg(void)
{
RCC->CR |= RCC_CR_HSEON;													//włączamy HSE

 while(((RCC->CR) & RCC_CR_HSERDY) == 0){}									//oczekiwanie na HSE

 RCC->CR |= RCC_CR_CSSON;													// włączamy Clock security system

 RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV1; // ustawiamy taktowania dla szyn AHB, APB1 i APB2
 //HCLK = SYSCLK/1- 72Mhz;    PCLK1 = HCLK/2 - 36Mhz;       PCLK1 = HCLK/1- 72mhz;
 RCC->CFGR |= RCC_CFGR_PLLMULL9 | RCC_CFGR_PLLSRC;                          // ustawienie mnożnika dla PLL (8MHz * 9 = 72MHz) , oraz wejciowego sygnału taktującego dla PLL)

 RCC->CR |= RCC_CR_PLLON;													//włączamy PLL

 while(((RCC->CR) & RCC_CR_PLLRDY)==0){}									//oczekiwanie na włącznie pll

 FLASH->ACR|=FLASH_ACR_LATENCY_2; 											//opóźnienie dla pamięci flash

 RCC->CFGR|=RCC_CFGR_SW_PLL;												// PLL jako źródło taktowania SYSCLK

 while( ((RCC->CFGR) & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL){}                 //oczekiwanie na ustawielnie PLL jako źródła SYSCLK

 RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;	//AFIO WŁ									//włączamy taktowanie dla kolejnych peryferiów kontrolera
 RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; //GPIOC WŁ

}

Dodam, że nie chcę wszczynać dyskusji na temat SPL'a czy rejestrów, bo to jak widać na polskich forach jest wszechobecna walka. Jest to tylko przykład gdyby ktoś był zaciekawiony.

Pozdrawiam.

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

Witam,

dla początkujących programujących swoje pierwsze roboty, przydatna może być funkcja odbierania danych z modułu Bluetooth ( np. HC-05) poprzez interfejs USART. Dane można wysyłać np. z smartfona z systemem Android, a aplikację mobilną, która będzie się komunikowała z modułem Bluetooth umieszonym w robocie można z łatwością napisać dzięki AppInventorowi. Funkcja ta umożliwia w robotach typu Line Follower szybkie i wygodne zmiany nastaw regulatora, podczas testów. Dzięki tej funkcji możemy także zbudować robota zdalnie sterowanego z smartfona.

#define  BUF_MAX 16
volatile uint8_t Bufor[BUF_MAX];
volatile uint8_t status;


void uart_init()
{
#define BAUD 9600
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
UCSR0A = (1<<RXC0);//Przerwanie po odebraniu bajtu danych
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); //8 bitów danych + 1 bit stopu
UCSR0B = (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0); //bez parzystości
}

int main()
{
   uart_init();
   sei();
       while(1){

       if(status){

            if(Bufor[0]==1){
                     //skręć w lewo
            }else if(Bufor[0]==2){
                     //skręć w prawo
            }/*
              itp
               */ 
        status=0;
}
}
}

ISR(USART_RX_vect){

static uint8_t bufpos, n;
if(status) return; //Błąd poprzednia ramka jeszcze nieobsłużona

if(n == 0){		//Pierwszy bajt danych jest informacją jak długa będzie ramka danych, zapisujemy tą liczbę do zmiennej n
	n = UDR0;
	bufpos = 0;
	return;
}
if(bufpos < n){				//Zapisujemy kolejne bajty do tablicy buforu, nastepnie zwiększamy indeks tablicy
	Bufor[bufpos] = UDR0;
	bufpos++;
}

if(bufpos >= n){	//Gdy indeks buforu będzie równy wysłanej wczesniej informacji o długosci ramki
	status = 1;		//przypisujemy 1 do zmiennej globalnej status, konczymy odbieranie i w mainie obsługujemy Bufor
	n = 0;
}
}


Jak widać w programie został zastosowany pewien protokół komunikacyjny. Aby komunikacja przebiegała poprawnie należy się trzymać dwóch zasad:

- pierwszy wysłany bajt musi być liczbą, która informuje ile bajtów wysyłamy,
- aby poprawnie wykonać pożądaną przez nas akcję po wysłaniu ramki, zalecane jest wysłanie jako drugiego bajtu jakiejś cyfry, która zostanie zapisana w Bufor[0], a następnie w mainie Bufor[0] wykorzystać jako element do porównywania w instrukcji warunkowej (Patrz na kod).

Program został napisany na mikrokontroler ATMega88p.

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.