Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[stm32] Podłączenie UART/RS232

adkadk 09 Lut 2012 15:46 5048 17
  • #1 09 Lut 2012 15:46
    adkadk
    Poziom 8  

    Witam. Bawię się płytką Kamami Buttefly2 z Cortexem M3. Próbuję "pogadać" z procesorem poprzez RS-232. Posiadam chyba działającą :) (zwarcie spinaczem daje echo w terminalu) przejściówkę RS-USB na Prolificu. Przejściówka daje napięcie TTL, na płytce rozwojowej zainstalowali MAX232 - więc bezpośrednie podłączenie pod DB9 nie działa. Zastanawiam się, czy będzie to można podłączyć do komputera bez kombinowania z MAX232. Na płytce znajdują się bowiem zwory, które łączą linie Tx i Rx wychodzące z USART z układem MAX232. Dodatkowo linie GPIO są wyprowadzone na goldpiny - tak więc mam dostęp do UART z pominięciem MAX232. Moje pytanie teraz brzmi: czy mogę przejściówkę z PL-2303 podłączyć bezpośrednio pod USART? Nic się wtedy nie uszkodzi, będzie to miało szansę działać? Czy trzeba wyprowadzać masę, czy wystarczy Tx i Rx?

    Z góry dziękuję za poradę :-)

    0 17
  • #2 09 Lut 2012 16:23
    opamp
    Użytkownik obserwowany

    Przejściówka ma sterownie 3.3V czy 5V?

    0
  • #3 09 Lut 2012 18:23
    adkadk
    Poziom 8  

    A da się to jakoś pomierzyć bez oscyloskopu? Są we wtyczce jakieś wyjścia dające sygnał który ogarnie tani multimetr? Producent kabla (Unitek Y-105) nic nie podaje, w data sheecie od PL2303 jest napisane, iż może on pracować z wyjściami w standardzie 3, 3.3 oraz 5V w zależności od napięcia VDD. Jako iż pracuje to z USB to śmiem przypuszczać iż będzie to standard 5V.

    0
  • #4 09 Lut 2012 19:49
    opamp
    Użytkownik obserwowany

    adkadk napisał:
    Jako iż pracuje to z USB to śmiem przypuszczać iż będzie to standard 5V.

    USB Ma logikę 3.3V podpowiem. Zmierz napięciue na PL2303 VDD.

    0
  • #5 09 Lut 2012 20:04
    Krauser
    Poziom 26  

    Jeśli PL2303 jest zasilony z 5V to będzie tylko komunikacja w jedną stronę do STM32F107. Nic się nie uszkodzi, bo akurat użyte piny tolerują 5V.

    0
  • #6 10 Lut 2012 14:59
    adkadk
    Poziom 8  

    Cytat:
    Zmierz napięciue na PL2303 VDD.

    Na razie chciałbym uniknąć konieczności rozbierania zaklejonej wtyczki, której już potem pewnie nie złożę :-)

    Dobra, to będę kombinował ze zrobieniem sobie wtyczki. Rozumiem że wyjście Tx USART'a podłączam pod Rx przejściówki i vice versa. Zapewne potrzebna też będzie masa (napięcie na liniach jest do masy a nie różnicowe?). Jeśli tak, to która masa: ta, którą mam na płytce wyprowadzoną przy porcie GPIO, czy wyprowadzona masa "całej" płytki (jest tam taki pin osobny). Czy poza tym będę potrzebował jakieś dodatkowe linie (sprzętowa kontrola przepływu nie jest stosowana).

    Wybaczcie może i głupie pytania, ale każdy kiedyś zaczynał :-)

    0
  • #7 11 Lut 2012 07:59
    Krauser
    Poziom 26  

    Tak linie Rx do Tx.
    Tak masa jest potrzebna i możesz użyć tej ze złącza GPIO.
    Tylko Rx Tx i GND możesz tutaj wykorzystać.

    0
  • #8 11 Lut 2012 22:44
    adkadk
    Poziom 8  

    Skonstruowałem sobie kabel, wygląda na to, że podłączyłem go poprawnie (posprawdzałem multimetrem, wszystko łączy, zwarć niby nie ma), niemniej jednak nie mam łączności ani w jedną, ani w drugą stronę (używam HyperTerminal i RealTerm). Czy mógłbym jeszcze poprosić o sprawdzenie kodu? Chciałem napisać najbardziej banalne wysyłanie/odbieranie bez przerwań, żeby w ogóle zobaczyć o co chodzi. Piszę w Keilu. Funkcja main() w wersji 1 (zakomentowanej) ma za zadanie zapalić diodę, gdy coś przyjdzie na Rx, wersja 2 wysyła w kółko literkę 'a' mrugając diodą. Oczywiście diody działają, tyko nie RS232.
    Według instrukcji do płytki na zewnątrz wyprowadzony jest UART2, TX jest na GPIO D5, RX na GPIO D6.

    Code:

    #include "stm32f10x.h"

    void GPIO_Configuration(void);
    void Delay(__IO uint32_t nCount);
    void USART_Configuration(void);
    char getch(void);

    //diody LED
    #define LED_PORT            GPIOB
    #define LED_PORT1           GPIOC
    #define LED_PORT_CLK        RCC_APB2Periph_GPIOB
    #define LED_PORT1_CLK       RCC_APB2Periph_GPIOC
    #define LED1_PIN            GPIO_Pin_0
    #define LED2_PIN            GPIO_Pin_1
    #define LED3_PIN            GPIO_Pin_4
    #define LED4_PIN            GPIO_Pin_5
    //joystick
    #define JOY_PORT            GPIOC
    #define JOY_PORT_CLK        RCC_APB2Periph_GPIOC
    #define JOY_OK                GPIO_Pin_7
    #define JOY_UP             GPIO_Pin_8
    #define JOY_DOWN            GPIO_Pin_9
    #define JOY_LEFT            GPIO_Pin_11
    #define JOY_RIGHT           GPIO_Pin_10
    //USART
    #define USART_PORT         GPIOD
    #define USART_PORT_CLK      RCC_APB2Periph_GPIOD
    #define USART_CLK         RCC_APB1Periph_USART2
    #define USART_TX         GPIO_Pin_5
    #define USART_RX         GPIO_Pin_6
    #define USART_NUMBER      USART2

    //zmienne
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef   USART_InitStructure;
    char znak;

    int main(void)
    {
       GPIO_Configuration();
       //Odpalamy RS
       USART_Configuration();





    znak='a';

      while (1)
      {
      //Wersja 1
    //  GPIO_SetBits(LED_PORT, LED1_PIN); //zgas lampke 1
    //  znak=getch(); //czekaj az cos przyjdzie
    //  GPIO_ResetBits(LED_PORT, LED1_PIN);   //jak przyszlo zapal lampke 1 
    //  Delay(0x0FFFFF); //poczekaj

    // Wersja 2
       GPIO_SetBits(LED_PORT, LED1_PIN); //zgas lampke 1
       Delay(0x0FFFFF);   //poczekaj
       USART_SendData(USART_NUMBER,znak); //nadaj
       GPIO_ResetBits(LED_PORT, LED1_PIN); //zapal lampke po nadaniu
       Delay(0x0FFFFF);            //poczekaj
     
      }      //while(1)
    } //main()


    void GPIO_Configuration(void)
    {
     //włączenie zegara portu
      RCC_APB2PeriphClockCmd(LED_PORT_CLK | LED_PORT1_CLK, ENABLE);
      //LED na porcie B
      GPIO_InitStructure.GPIO_Pin = LED1_PIN | LED2_PIN;    //piny które chcemy skonfigurować
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //tryb wyjść portu - wyjście push-pull
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;  //szybkość wyjścia
      GPIO_Init(LED_PORT, &GPIO_InitStructure);
      //LED an porcie C
      GPIO_InitStructure.GPIO_Pin = LED3_PIN | LED4_PIN;    //piny które chcemy skonfigurować
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //tryb wyjść portu - wyjście push-pull
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;  //szybkość wyjścia
      GPIO_Init(LED_PORT1, &GPIO_InitStructure);
      //Joystick
      GPIO_InitStructure.GPIO_Pin = JOY_UP | JOY_DOWN | JOY_LEFT | JOY_RIGHT;   //piny które chcemy skonfigurować
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;    //tryb wyjść portu - wejście z podciąganiem do plusa
      GPIO_Init(JOY_PORT, &GPIO_InitStructure); 
    }

    void USART_Configuration(void) {
      //Zegar
      RCC_APB2PeriphClockCmd(USART_PORT_CLK,ENABLE);
      RCC_APB1PeriphClockCmd(USART_CLK,ENABLE);
      //USART TX
      GPIO_InitStructure.GPIO_Pin = USART_TX;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(USART_PORT, &GPIO_InitStructure);
      //USART RX
      GPIO_InitStructure.GPIO_Pin = USART_RX;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    //  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(USART_PORT, &GPIO_InitStructure);
      //USART
      USART_InitStructure.USART_BaudRate=9600;
      USART_InitStructure.USART_WordLength= USART_WordLength_8b;
      USART_InitStructure.USART_StopBits = USART_StopBits_1;
      USART_InitStructure.USART_Parity = USART_Parity_No;
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //czy uzywamy linii DTR itd
      USART_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx;
      USART_Init(USART_NUMBER, &USART_InitStructure);
      USART_Cmd(USART_NUMBER,ENABLE);
    }


    void Delay(__IO uint32_t nCount)
    {
      for(; nCount != 0; nCount--);
    }

    char getch(void) {
    char tmp;
    while (USART_GetFlagStatus(USART_NUMBER,USART_FLAG_RXNE)==RESET); //nie rob nic dopoki cos nie przyjdzie
    tmp=USART_ReceiveData(USART_NUMBER);
    return tmp;
    }


    0
  • #9 12 Lut 2012 10:36
    Krauser
    Poziom 26  

    1. W funkcji USART_Configuration brakuje za włączeniem taktowania takiej linijki kodu:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    normalnie USART2 jest na PA2 i PA3, a dopiero po przemapowaniu można używać ich na PD5 i PD6.
    2. Nie przełączasz się na kwarc, a to jest raczej potrzebne przy komunikacji poprzez RS232, ale może na niskich prędkościach będzie działać.
    3. Nie wiem czy konfiguracja USARTA dla 8MHz dobrze ustawi prędkość transmisji. Radzę zajrzeć co robi biblioteka tzn. skąd bierze informację o zegarze dla USART2. Możliwe, że trzeba zdefiniować stałą FREQUENCY albo coś podobnego.

    0
  • #10 14 Lut 2012 22:42
    adkadk
    Poziom 8  

    No dobra. Nie jest źle :-) Po dłuższym procesie kombinowania oraz użerania się z nie do końca chcącym mnie słuchać µVisionem udało mi się spłodzić prawie działający kod.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wersja 1 mruga diodą w rytm przychodzących danych, wersja 2 wysyła na terminal krzaczki w rytm mrugania diody. I właśnie o te krzaczki się rozchodzi. Co innego wysyłam, co innego dostaję na komputerze. I to zarówno wysyłając i dekodując char jak i uint8 (używam programu Realterm, tam można wybrać typ przychodzących znaków). Co może być tego przyczyną? Rzecz jasna parametry transmisji na komputerze takie same jak na procesorze.

    0
  • #11 15 Lut 2012 00:31
    nibbit
    Poziom 19  

    Korzystając z tej biblioteki gdzieś w jakimś pliku nagłówkowym trzeba było zdefiniować HSE_Value i ustawiony zegar systemowy. Na podstawie tych definicji funkcja ustawiająca USART liczy BRR. Bez tej biblioteki zrobisz cały init w 4 liniach ;]

    0
  • #12 15 Lut 2012 10:29
    Freddie Chopin
    Specjalista - Mikrokontrolery

    nibbit napisał:
    Bez tej biblioteki zrobisz cały init w 4 liniach ;]

    To na pewno zbyt skomplikowane...

    4\/3!!

    0
  • #13 15 Lut 2012 19:38
    Krauser
    Poziom 26  

    14.7456 MHz * 5 = 73,728 MHz, a nie 72 MHz.
    Jeśli zdefiniowałeś częstotliwość niezgodną z rzeczywistą to prędkość USARTA jest źle wyliczona przez funkcje, która to robi. W tym przypadku nie ma znaczenia czy korzystasz z biblioteki czy wpisujesz bezpośrednio do rejestru. Przetaktowanie mikrokontrolera to inna sprawa. Nie przekraczaj 72MHz.

    0
  • #14 15 Lut 2012 21:02
    adkadk
    Poziom 8  

    Pobawiłem się z tym trochę, niestety coś mi dalej nie wychodzi.
    W pliku stm32f10x.h przedefiniowałem częstotliwość HSE (domyślnie do Connectivity Line była 25000000, zmieniłem na 14745600). Zmieniło to tyle, że na terminalu wyskakiwały inne krzaczki, niż wcześniej. Pogrzebałem dalej. Częstotliwość mnożona przez 5 faktycznie wychodzi za duża. Puściłem z mniejszym taktowaniem (mnożone przez 4) - dalej na terminalu wyskakuje ten sam krzaczek, bynajmniej nie będący literą 'b'. Spróbowałem wyłączyć swoją funkcję aktywującą RCC i wykorzystać funkcję SystemInit() z biblioteki. Efekt był taki, iż dalej leciał ten sam krzak, tylko trochę wolniej. Zrobiłem sobie debug z funkcją RCC_GetClocksFreq() i breakpointem. Okazało się, że biblioteka standardowa przy zdefiniowanym taktowaniu 70Mhz ustawiła SYSCLK na 42.5 Mhz - nie wpłynęło to jednak na gatunek krzaka pokazywanego na terminalu.

    Pokusiłem się nawet o całkowite wyłączenie konfiguracji zegarów - UART nadawał dalej, tylko z bardzo małą częstotliwością i wciąż tego samego krzaczka. Nadawany znak zmienia się tylko jeżeli zmieniam HSE_Value, ustawię zły baudrate w porównaniu z terminalem albo zmienię nadawanego chara.

    Próbowałem też takiego numeru, żeby ustawić HSE_Value na okrągłe 14 Mhz aby po pomnożeniu przez 5 dało okrągłe 70Mhz - też nic, tylko inny znaczek przychodzi.

    Co teraz?...

    0
  • #15 15 Lut 2012 21:58
    Freddie Chopin
    Specjalista - Mikrokontrolery

    adkadk napisał:
    Co teraz?...

    Nic - dalej będziesz pewnie męczył się próbując za pomocą tej "biblioteki" zrobić coś co zajmuje autentycznie 4 linijki.

    4\/3!!

    0
  • #16 15 Lut 2012 22:47
    nibbit
    Poziom 19  

    Cytat:
    Okazało się, że biblioteka standardowa przy zdefiniowanym taktowaniu 70Mhz ustawiła SYSCLK na 42.5 Mhz - nie wpłynęło to jednak na gatunek krzaka pokazywanego na terminalu.


    Dopóki ta biblioteka, która wyłącza myślenie nie będzie wiedzieć jaką masz częstotliwość SYSCLK i APBCLK to funkcja, która liczy BRR na pewno nie ustawi prawidłowej prędkości. Także szukaj w tamtym miejscu bo w sumie nie wiadomo z jaką prędkością chodzi Ci układ.

    A jeszcze nie więcej jak pół roku temu myślałem, że ta biblioteka może komuś coś ułatwić. Po ostatniej aktywności jej użytkowników na tym forum widzę, że jedyne co ona robi to wyłącza myślenie i zwalnia z czytania DS. Zrobisz nam przyjemność a wierz mi, że jeszcze większą sobie jak na podstawie stm32f10x.h z CMSIS uruchomisz to na rejestrach. W przeciwnym wypadku się będziesz zastanawiać co autor biblioteki miał na myśli.

    Cytat:
    Przetaktowanie mikrokontrolera to inna sprawa. Nie przekraczaj 72MHz.

    Osobiście nie sprawdzałem ale koledzy tu na forum pisali że przetaktowywali tego procka na ponad 100 MHz i proste peryferia (m.in. SPI działały). Myślę, że USART też by dał radę ;].

    0
  • #17 16 Lut 2012 10:39
    Krauser
    Poziom 26  

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Chodzi o to, że biblioteka została stworzona by pokazać możliwości zestawów produkowanych przez ST. Jak można wyczytać jak nie masz kwarcu 8MHz dla STM32F103 albo 25MHz dla STM32F107 to sam musisz ją sobie przerobić. Co nie jest łatwe, bo kod nie jest przejrzysty. Jak już ustawisz jakiś zegar sysclk dla swojego kwarcu dodając nową funkcję static void SetSysClockToXXX(void) to musisz zabrać się za edycje funkcji do konfiguracji USARTa. Łatwiej jest zrezygnować z jej używania. Sam zobaczysz jak spróbujesz.

    0
  • #18 19 Lut 2012 12:27
    adkadk
    Poziom 8  

    OK, działa. Po kolei:

    - poczytałem Reference Manual. Wbrew temu, co pisał autor książki "STM32 w praktyce" z której się uczyłem, operacje na rejestrach nie są nie wiadomo jak skomplikowane a sam manual nie jest wielce niestrawny :-)
    - niestety, po napisaniu kodu na rejestrach doszedłem do tego samego, co na bibliotece
    - oglądnąłem płytkę. W data sheecie jet napisane, iż kwarc ma częstotliwość 14.7456Mhz, banieczka na płytce podpisana jest 16000! Przerobiłem kod, dalej nie działa.
    - Postanowiłem spróbować jeszcze raz co się stanie, jeżeli podłączę swoją przejściówkę TTLową za MAX232. Założyłem zworki, podłączam... działa, pokazują się poprawne znaki! Włączyłem program odbierający - też działa :) Czyli nie ma co się podpinać bezpośrednio pod UART, przynajmniej przy posiadanym przeze mnie kablu.
    - Spróbowałem wrócić do wersji pisanej z nielubianą na tym forum biblioteką. W stm32f10x.h podmieniłem HSE_Value na 16000000 - też zaczęło działać. Czyli nie ma co psów wieszać na tej bibliotece, zwłaszcza, że podglądając rejestry w debuggerze widzę, że ustawia je tak samo, jak ja idąc za manualem.

    W każdym razie dziękuję za pomoc, przynajmniej coś się ciekawego z RM mogłem dowiedzieć.


    [stm32] Podłączenie UART/RS232

    0