Skocz do zawartości
rizone1234

STM32 - wpisywanie słów do terminala

Pomocna odpowiedź

Witam,

Mam problem z tym by wpisać całe słowo do terminala, Wciskam jedną literkę i juz terminal reaguje, nie czeka aż wpisze drugą czy trzecią literkę. Proszę poradźcie mi jak wpisać całe słowo np onlampy, aby załączyć diody. Nie chce by sie uruchamiały po jednej wklepanej literce. Problem jest z uartem na stm32. Korzystam z USART2.

Udostępnij ten post


Link to post
Share on other sites

to nie z uartem jest problem tylko z procedurą odbierającą. Uart działa tak jak działa, czyli wysyła bajt po bajcie aż wyśle wszystko co mu wysłać kazano. Musisz sobie napisać bufor po stronie odbiornika i poczekać aż wszystko zostanie odebrane i dopiero wtedy reagować. Wtedy nie będzie miało znaczenia z jaką prędkością wciskasz literki..

możesz zrobić to np. tak choć odradzam używania poolingu:
 

char bufor[8];

while(1){

	for(c = 0; c<8; c++){

		while(!UART_RX_RDY);
		bufor[c] = UART_REG;
		if(!bufor[c]) break;  // jeśli NULL czyli koniec stringa wyjdź z pętli for

	}

	if(!(strcmp((const char*)bufor, "onlampy"))){ // porównaj ze sysłą predefiniowaną

// włącz lampy

	}else if(!(strcmp((const char*)bufor, "costam"))){

// rób coś tam..

	}else{

// niepasujące polecenie, wyjdź lub podejmij najbardziej sensowne w tym kontekście działanie

	}

}

 

Udostępnij ten post


Link to post
Share on other sites

A to nie jest problem z ustawieniami terminala?

Udostępnij ten post


Link to post
Share on other sites

Bufor może być równie dobrze w terminalu (daleko nie szukać - to coś co robi za terminal w Arduino IDE).

Udostępnij ten post


Link to post
Share on other sites

Dziękuję za odpowiedź, ale w kodzie atMegaTona wyrzuca mi błąd w dwóch linijkach i niestety nie działa:( Chodzi o te dwie linijki:

while(!UART_RX_RDY);

bufor[c] = UART_REG;

Nie wiem czemu nie działa, gdyby można było napisać co nie jest tak...

Cały kod programu wrzucam tutaj:

#include "stm32f10x.h"

#define MCP_IODIR        0x00
#define MCP_IPOL        0x01
#define MCP_GPINTEN        0x02
#define MCP_DEFVAL        0x03
#define MCP_INTCON        0x04
#define MCP_IOCON        0x05
#define MCP_GPPU        0x06
#define MCP_INTF        0x07
#define MCP_INTCAP        0x08
#define MCP_GPIO        0x09
#define MCP_OLAT        0x0a

void send_char(char c)
{

 while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);

     USART_SendData(USART2, c);


}

int __io_putchar(int c)
{
    if (c=='\n')
        send_char('\r');
    send_char(c);
    return c;
}


uint8_t spi_sendrecv(uint8_t byte)
{
    // poczekaj az bufor nadawczy bedzie wolny
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI1, byte);

    // poczekaj na dane w buforze odbiorczym
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_I2S_ReceiveData(SPI1);
}

void mcp_write_reg(uint8_t addr, uint8_t value)
{
    GPIO_ResetBits(GPIOC, GPIO_Pin_0);
    spi_sendrecv(0x40);
    spi_sendrecv(addr);
    spi_sendrecv(value);
    GPIO_SetBits(GPIOC, GPIO_Pin_0);


}

int main(void)
{
    volatile int dly;
    GPIO_InitTypeDef gpio;
    SPI_InitTypeDef spi;
    USART_InitTypeDef uart;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    GPIO_StructInit(&gpio);
    gpio.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_7; // SCK, MOSI
    gpio.GPIO_Mode = GPIO_Mode_AF_PP;
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio);

    gpio.GPIO_Pin = GPIO_Pin_6; // MISO
    gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &gpio);

    gpio.GPIO_Pin = GPIO_Pin_0; // CS
    gpio.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &gpio);
    GPIO_SetBits(GPIOC, GPIO_Pin_0);

     GPIO_StructInit(&gpio);
     gpio.GPIO_Pin = GPIO_Pin_2;
     gpio.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_Init(GPIOA, &gpio);

     gpio.GPIO_Pin = GPIO_Pin_3;
     gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
     GPIO_Init(GPIOA, &gpio);

     USART_StructInit(&uart);
     uart.USART_BaudRate = 115200;
     USART_Init(USART2, &uart);

     USART_Cmd(USART2, ENABLE);


    SPI_StructInit(&spi);
    spi.SPI_Mode = SPI_Mode_Master;
    spi.SPI_NSS = SPI_NSS_Soft;
    spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
    SPI_Init(SPI1, &spi);
    SPI_Cmd(SPI1, ENABLE);

    mcp_write_reg(MCP_IODIR, ~0x0f);


    char bufor[8];

    while(1){

        for(int c = 0; c<8; c++){


            if(!bufor[c]) break;  // jeśli NULL czyli koniec stringa wyjdź z pętli for

        }

        if(!(strcmp((const char*)bufor, "onlampy"))){ // porównaj ze sysłą predefiniowaną

             mcp_write_reg(MCP_OLAT, 0x0f);
        }else if(!(strcmp((const char*)bufor, "oflampy"))){

            mcp_write_reg(MCP_OLAT, 0x00);

        }else{

    printf("Bledny komunikat\n");

        }

    }
}

Jako terminala uzywam TERATERM

Udostępnij ten post


Link to post
Share on other sites

@rizone1234 witam na forum! Pamiętaj, aby kody programów umieszczać za pomocą odpowiedniej opcji w edytorze. Tym razem poprawiłem to za Ciebie 🙂

20 godzin temu, rizone1234 napisał:

Mam problem z tym by wpisać całe słowo do terminala, Wciskam jedną literkę i juz terminal reaguje, nie czeka aż wpisze drugą czy trzecią literkę.

Trochę nie rozumiem... czy Tobie chodzi o problem z programem na PC? Chodzi Ci o to, że chciałbyś, aby dane wysyłały się ciągiem dopiero po wciśnięciu "Enter", a nie po każdym napisanym znaku? To nie ma nic wspólnego z kodem na STM32 - kwestia ustawień terminala na PC 😉

Udostępnij ten post


Link to post
Share on other sites

OK. Postaram się poprawić. Właśnie o to mi chodzi, żeby dane były wysyłane cięgiem po wciśnięciu ENTER. Próbowałem dane wysłać za pomocą  Broadcast Command, ale nie wyszło. Jak mógłbyś mi pomóc jak to trzeba poustawiać w Teraterm.

Udostępnij ten post


Link to post
Share on other sites

W tym artykule powinieneś znaleźć to czego szukasz: 4 alternatywy dla monitora portu szeregowego Arduino (musisz wtedy jednak dostosować program na STM tak, aby reagował na znak końca linii). Alternatywnie możesz np. wykorzystać RealTerma (również opisany w tamtym artykule), wtedy nie będziesz musiał nic zmieniać na STMie.

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
20 godzin temu, rizone1234 napisał:

Dziękuję za odpowiedź, ale w kodzie atMegaTona wyrzuca mi błąd w dwóch linijkach i niestety nie działa:( Chodzi o te dwie linijki:

Musisz sobie przypisać do tego makra własne odniesienie, skąd mam wiedzieć czego używasz jako odniesienia dla aktywności uarta?

coś w tym stylu:

#define UART_RX_RDY (... twoje odniesienie)  // np,  (REJESTR & BIT)  lub zmienna, lub zawartość wskaźnika, lub jakieś porównanie.

Ten if MUSI tam być bo inaczej będzie się bez sensu kręcić w pętli. W rejestrze uarta musi być flaga odbioru i właśnie ją sobie przypisz do tego makra i tyle.

Ten UART_REG to też tylko przykładowa nazwa jako odniesienie do rejestru odbiorczego ale może to być równie dobrze pole struktury frameworka albo adres do tego rejestru/pola. 

@rizone1234 jeśli nie rozumiesz jak to funkcjonuje to poczytaj sobie o uarcie w dokumentacji i polecam poszerzyć wiedzę dot. języka C.

Panowie, nie ma znaczenia jak te dane będą wysyłane czy po jednej literce na sekundę czy 1000, odbiornik uarta i tak odbiera po jednej ramce. O to jak mają być buforowane dane odbierane trzeba zadbać samemu, czy to korzystając z możliwości sprzętu czy też pisząc bufor samemu.

@rizone1234 daj znać jak sobie poradzisz z problemem.

Pozdrawiam

Edytowano przez atMegaTona

Udostępnij ten post


Link to post
Share on other sites

Jeszcze raz to samo tylko po Twojemu:

char bufor[8];

while(1){

	for(c = 0; c<8; c++){
        
        while(!USART_GetFlagStatus(USART2, USART_FLAG_RXNE));
		bufor[c] = (char)USART_ReceiveData(USART2);
		if(!bufor[c]) break;  // jeśli NULL czyli koniec stringa wyjdź z pętli for

	}

	if(!(strcmp((const char*)bufor, "onlampy"))){ // porównaj ze sysłą predefiniowaną

// włącz lampy

	}else if(!(strcmp((const char*)bufor, "costam"))){

// rób coś tam..

	}else{

// niepasujące polecenie, wyjdź lub podejmij najbardziej sensowne w tym kontekście działanie

	}

}

  

Lepiej jednak zastosować do tego przerwanie niż tego whila ale do sprawdzenia starczy.

https://www.st.com/content/ccc/resource/technical/document/user_manual/59/2d/ab/ad/f8/29/49/d6/DM00023896.pdf/files/DM00023896.pdf/jcr:content/translations/en.DM00023896.pdf

str.608

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Przepraszam, że nie odpowiadałem, ale nie miałem czasu. Wszystko gra, przerzucam się teraz na discovery. Cały cza zgłębiam język C oraz stm32.

Edytowano przez rizone1234

Udostępnij ten post


Link to post
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!

Gość
Napisz odpowiedź...

×   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...