Buggfix Plus
Aktuellt datum och tid: 12.37 2019-08-22

Alla tidsangivelser är UTC + 1 timme




Svara på tråd  [ 12 inlägg ] 
Författare Meddelande
InläggPostat: 18.01 2019-05-15 
Användarvisningsbild

Blev medlem: 22.59 2012-09-11
Inlägg: 2889
Ort: The U.S - Chicago
I Arduino-miljön så kan man använda ett bibliotek som heter SoftwareSerial för att bestämma en RX ingång och en TX utgång från slumpmässiga GPIO pinnar. Sedan finns det något som heter HardwareSerial, som jag tror är det samma. Rätta mig om jag har fel.

Men finns det något ekvivalent SoftwareSerial för STM32 också? Jag har nämligen en UART function skriven i C som är anpassad för både Windows och Linux. För Windows ser den ut så här:

Kod: [Expandera/Minimera] [Hämta] (Untitled.txt)
#include <windows.h>
#include <Setupapi.h>

HANDLE serial_handle;

int uart_open(char *port) {
   char str[20];

   snprintf(str, sizeof(str) - 1, "\\\\.\\%s", port);
   serial_handle = CreateFileA(str, GENERIC_READ | GENERIC_WRITE,
         FILE_SHARE_READ | FILE_SHARE_WRITE,
         NULL, OPEN_EXISTING, 0, //FILE_FLAG_OVERLAPPED,
         NULL);

   if (serial_handle == INVALID_HANDLE_VALUE) {
      return -1;
   }

   return 0;
}
void uart_close() {
   CloseHandle(serial_handle);
}

int uart_tx(int len, unsigned char *data) {
   DWORD r, written;
   while (len) {

      r = WriteFile(serial_handle, data, len, &written,
      NULL);
      if (!r) {
         return -1;
      }
      len -= written;
      data += len;
   }

   return 0;
}
int uart_rx(int len, unsigned char *data, int timeout_ms) {
   int l = len;
   DWORD r, rread;
   COMMTIMEOUTS timeouts;
   timeouts.ReadIntervalTimeout = MAXDWORD;
   timeouts.ReadTotalTimeoutMultiplier = 0;
   timeouts.ReadTotalTimeoutConstant = timeout_ms;
   timeouts.WriteTotalTimeoutMultiplier = 0;
   timeouts.WriteTotalTimeoutConstant = 0;

   SetCommTimeouts(serial_handle, &timeouts);
   while (len) {
      r = ReadFile(serial_handle, data, len, &rread,
      NULL);

      if (!r) {
         l = GetLastError();
         if (l == ERROR_SUCCESS)
            return 0;
         return -1;
      } else {
         if (rread == 0)
            return 0;
      }
      len -= rread;
      data += len;
   }

   return l;
}


För Linux ser den ut så här:

Kod: [Expandera/Minimera] [Hämta] (Untitled.txt)
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>

int serial_handle;

int uart_open(char *port) {
   struct termios options;
   int i;

   serial_handle = open(port, (O_RDWR | O_NOCTTY /*| O_NDELAY*/));

   if (serial_handle < 0) {
      return -1;
   }

   /*
    * Get the current options for the port...
    */
   tcgetattr(serial_handle, &options);

   /*
    * Set the baud rates to 115200...
    */
   cfsetispeed(&options, B115200);
   cfsetospeed(&options, B115200);

   /*
    * Enable the receiver and set parameters ...
    */
   options.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS | HUPCL);
   options.c_cflag |= (CS8 | CLOCAL | CREAD);
   options.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHONL | ECHOCTL
         | ECHOPRT | ECHOKE | IEXTEN);
   options.c_iflag &= ~(INPCK | IXON | IXOFF | IXANY | ICRNL);
   options.c_oflag &= ~(OPOST | ONLCR);

   //printf( "size of c_cc = %d\n", sizeof( options.c_cc ) );
   for (i = 0; i < sizeof(options.c_cc); i++)
   options.c_cc[i] = _POSIX_VDISABLE;

   options.c_cc[VTIME] = 0;
   options.c_cc[VMIN] = 1;

   /*
    * Set the new options for the port...
    */
   tcsetattr(serial_handle, TCSAFLUSH, &options);

   return 0;
}
void uart_close() {
   close(serial_handle);
}

int uart_tx(int len, unsigned char *data) {
   ssize_t written;

   while (len) {
      written = write(serial_handle, data, len);
      if (!written) {
         return -1;
      }
      len -= written;
      data += len;
   }

   return 0;
}
int uart_rx(int len, unsigned char *data, int timeout_ms) {
   int l = len;
   ssize_t rread;
   struct termios options;

   tcgetattr(serial_handle, &options);
   options.c_cc[VTIME] = timeout_ms / 100;
   options.c_cc[VMIN] = 0;
   tcsetattr(serial_handle, TCSANOW, &options);

   while (len) {
      rread = read(serial_handle, data, len);

      if (!rread) {
         return 0;
      } else if (rread < 0) {
         return -1;
      }
      len -= rread;
      data += len;
   }

   return l;
}


I Arduino så skulle detta se ut så här:
Kod: [Expandera/Minimera] [Hämta] (Untitled.txt)

#include "dinHeaderFil.h"

SoftwareSerial mySerial(1,0); // RX, TX

int uart_open() {
        mySerial.begin(9600);
}
void uart_close(){
       mySerial.end();
}

int uart_tx(uint8_t* data, uint8_t len) {
       size_t written;

   while (len) {
      written = mySerial.write(data, len);
      if (!written) {
         return -1;
      }
      len -= written;
      data += len;
   }

    return 0;
}

int uart_rx(uint8_t* data, uint8_t len) {
       int l = len;
       size_t rread;

       while (len) {
      rread = mySerial.read(data, len);

      if (!rread) {
         return 0;
      } else if (rread < 0) {
         return -1;
      }
      len -= rread;
      data += len;
   }

   return l;
}



Väldigt enkel C kod som direkt talar med hårdvaran. Men jag skulle behöva skriva om dessa så att dom passar med STM32. Har ni några förslag?


Senast redigerad av Al_Bundy 18.36 2019-05-15, redigerad totalt 2 gånger.

Upp
 Profil  
 
InläggPostat: 18.31 2019-05-15 
Användarvisningsbild

Blev medlem: 18.17 2004-02-11
Inlägg: 9251
Ort: Knivsta
Du har fel...
Varför vill du inte använda harvard uart/serial på stm32an?

Softwareserial är något man tar till i nödfall när man har slut på hårdvaru uarts.


Upp
 Profil  
 
InläggPostat: 18.35 2019-05-15 
Användarvisningsbild

Blev medlem: 22.59 2012-09-11
Inlägg: 2889
Ort: The U.S - Chicago
Harvard :o

Hur gör man då? :) Skulle helst vilja använda USB porten för avläsning till datorn också. Men softwareserial måste väll ändå fungera OK, eller finns det risk att det inte riktigt fungerar?


Upp
 Profil  
 
InläggPostat: 18.47 2019-05-15 

Blev medlem: 10.02 2009-05-08
Inlägg: 725
Ort: Lund
AndLi menar nog hårdvaru-USART. Men det var en ganska kul felskrivning eftersom stm32 är en typisk harward-arkitektur.

Hur man gör? Läser manualen eller googlar och hoppas på tur (det är MÅNGA som gjort detta före dig).


Upp
 Profil  
 
InläggPostat: 18.53 2019-05-15 
Användarvisningsbild

Blev medlem: 22.59 2012-09-11
Inlägg: 2889
Ort: The U.S - Chicago
Att använda RX och TX utgångarna på en STM32 finns massvis med filmer och manualer om. Men att använda godtyckliga GPIO pinnar, vet jag inte hur man gör.


Upp
 Profil  
 
InläggPostat: 19.03 2019-05-15 

Blev medlem: 10.02 2009-05-08
Inlägg: 725
Ort: Lund
Det finns ofta ett par alternativa RX/TX för varje USART, så det är ju inte så svårt att få det att passa in. Går det inte det så är det nog lämpligast att gå tillbaks till ruta ett. Vilka resuser behövs? Vilka resurser finns på tänkt MCU? Räcker det till så kan man ju fördela dessa resurser på lämpligt sätt.

Går det verkligen inte att få ihop det med vald MCU så bör man kanske titta på någon annan. Absolut sista nödfall skulle väl vara att välja en mjukvaruimplementation. Det är inte direkt jättesvårt att åstadkomma om man vet hur kommunikationen fungerar. Säkert någon annan som gjort det och delat med sig dessutom.

Edit: det är inte jätteenkelt med Rx.


Upp
 Profil  
 
InläggPostat: 19.25 2019-05-15 
Användarvisningsbild

Blev medlem: 13.58 2016-04-05
Inlägg: 1821
Ort: Helsingfors
Det finns tre att välja på i F401 och de har ett par alternativa pinpar. Ctr-klick i Cube om man inte orkar läsa datablad...
Bilaga:
usart.png


Logga in för att visa de filer som bifogats till detta inlägg.


Upp
 Profil  
 
InläggPostat: 20.25 2019-05-15 

Blev medlem: 10.02 2009-05-08
Inlägg: 725
Ort: Lund
Bara för att jag är uttråkad...

Så har kan man implementera soft send av en byte (eller hur många bitar man nu vill ha i sin "frame").

Skicka strartbit.
Vänta 1/baud
skicka varje bit med 1/baud tidsavstånd mellan varje.
skicka minst en stopp-bit.

Lämpligen slår man av avbrott innan och återställer (till vad det var) efteråt.
Fördelen med hårdvaru-USART är att den sköter allt, oavsett vad MCU'n har för sig för övrigt (avbrott, DMA, bla, bla bla).

För att ta emot en byt kan man t.ex.

Aktivera ett externt interrupt för att detektera startbiten.
När startbiten kommit, aktivera ett timerinterrupt med 1/2 1/baud.
I detta timerinterrupt, håll reda på vilken bit som behandlats, lagra dem. Vid vartannat interrupt efter det första.
Kolla att det faktiskt är en stopp-bit till sist, aktivera ext.int, avaktivera timer int.
"Rapportera" resultatet eller eventuell frame-error (saknad stopp-bit).

Stor fördel med hårdvaru-USART är att allt detta sköts av hårdvara, oavsett vad MCU'n har för sig för övrigt. Mjukvaru-Rx är lite känslig för (relativt) långa avbrott. Det går kanske att avhjälpa med input capture men då blir det lite mer jobb. Hårdvaru-USART samplar dessutom varje bit ett antal gånger och väljer majoritetsresultatet som slutresultat för varje bit.

Sedan, vare sig det är hård- errer mjuk implementation så bör man nog använda en FIFO-buffer på Rx, och kanske Tx också.


Upp
 Profil  
 
InläggPostat: 08.42 2019-05-16 
Användarvisningsbild

Blev medlem: 16.33 2012-07-08
Inlägg: 988
SoftwareSerial på STM32 :
https://www.stm32duino.com/viewtopic.php?t=6

Orkar inte läsa hela, men rätt tidigt i tråden verkar många vara inne på att det är meningslöst med en mjukvarulösning med så många hårdvaruportar tillgängliga. Så deras SoftwareSerial är en wrapper kring en hårdvaruporten... :)


Upp
 Profil  
 
InläggPostat: 15.24 2019-05-16 
Användarvisningsbild

Blev medlem: 14.52 2005-01-10
Inlägg: 23963
Ort: Aabenraa, Danmark
Mjukvara-serieport är till att börja med inte så sinnessjukt smart - men i nödfall kan det fungera.

Men att vilja ha en UART-funktion via mjukvara för att de lediga hårdvara-UART inte är på rätt pinnar är rakt av fel på ett nivå som är ganska högt.

Men vill du använda USB är det väl bara att sätta upp de nödvändiga register och peta in rätt mjukvara så att det fungerar.


Upp
 Profil  
 
InläggPostat: 17.24 2019-05-16 
Användarvisningsbild

Blev medlem: 22.59 2012-09-11
Inlägg: 2889
Ort: The U.S - Chicago
Jag får leta rätt på rätt GPIO pinnar och börja programmera och sätta register.

Finns det inte så att man kan tala med USB Data+ och Data- på t.ex. Arduino, Teensy, STM32?


Upp
 Profil  
 
InläggPostat: 17.29 2019-05-16 

Blev medlem: 13.07 2005-12-30
Inlägg: 443
Jo det går köra USB med stm32 men ge sig på att koda USBstacken är inte rekommendera för nybörjare. Dock finns det färdig STM32 exempel kod för HID dvs mus/tangentbord samt USB mass storage kod. Har själv gjort detta för stm32f1. Fick dock aldrig Virtual COM att funka.

Dock är en UART USB så mycket enklare att jobba med och de kostar 2 dollar/st på ex https://www.electrodragon.com/product/c ... module-v2/
så det brukar jag använda för generell kommunikation mellan stm32 och PC.


Upp
 Profil  
 
Visa inlägg nyare än:  Sortera efter  
Svara på tråd  [ 12 inlägg ] 

Alla tidsangivelser är UTC + 1 timme


Vilka är online

Användare som besöker denna kategori: henkebenke och 2 gäster


Du kan inte skapa nya trådar i denna kategori
Du kan inte svara på trådar i denna kategori
Du kan inte redigera dina inlägg i denna kategori
Du kan inte ta bort dina inlägg i denna kategori
Du kan inte bifoga filer i denna kategori

Sök efter:
Hoppa till:  
   
Drivs av phpBB® Forum Software © phpBB Group
Swedish translation by Peetra & phpBB Sweden © 2006-2010