Sida 1 av 2
Stark behov av hjälp med att skriva och ta emot av USART !
Postat: 14 mars 2015, 23:19:06
av Jennie
Hej!
Har en kod härne på bilderna som jag arbetat med här till min Arduino 2560-mikrokontroller, som jag arbetar med i Atmel Studio.
Jag tänker skriva och ta emot en (ASCII-konverterad) bokstav genom en USB-sladd, men av någon anledning så visas ingenting på mina terminalfönster. Har prövat med Atmel Studios inbyggda terminal och programmet puTTY men det sker ingenting.
Någon som har en hint om vad jag gjort för fel?
När jag sänder koden ner i mikrokontrollern så ser jag att det blinkar snabbt på TX- och RX-lamporna, så något borde väl bli sänt, eller?
Jag har ju satt COM3 och baudraten i terminalprogrammen riktigt (dvs. COM3 och 19200 bps) men kommer ingenstans nu så skulle vara evigt tacksam ifall du ville hjälpa mig i så fall!
Jag har alltså tänkt ställa in för att ha:
1 start och 1 stoppbit
8 databits
19200 baudrate
Ingen paritet eller sånt och asynkroniskt läge
Använda COM3-porten
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 14 mars 2015, 23:54:36
av BEEP
Om du skickar tecken från Arduino till datorn så händer det ingenting?
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 00:07:15
av Jennie
Alltså skriver jag in tecken i terminalfönstret med tangentbordet på datorn så får jag ingenting tillbaka, nej.
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 00:28:53
av BEEP
Börja med att bara skicka tecken från µC och när det fungerar så bråkar du med kommunikationen från dator till µC.
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 00:57:11
av Jennie
^ Hur kan en sådan kod se ut?
Jag vet i alla fall att den där receive-funktion bör fungera då jag ser RX-lampan lysa ifall jag har terminalprogrammet på och trycker på tangentbordet, så någonting tas ju emot i UART0. Men att få tillbaka någonting fungerar ju inte?
Jag vet verkligen inte hur jag ska skriva den där transmit-funktionen på annat vis för att få det till att fungera?
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 01:21:27
av BEEP
Eftersom bägge lysdioderna blinkar så vet vi att det är rätt port på datorn och att µC skickar ut någonting. Prova att skicka tecken från µC genom att göra en funktion som sänder ett tecken eller fler varje sekund och tala om för oss om du ser något i terminalen eller på lysdioden.
Edit:
Ett tecken är kanske för lite för att man ska kunna hinna se något blink på lysdioden.
Edit:
Ändrat texten.
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 01:53:16
av BEEP
När det gäller koden så är det lättare att analysera den om du postar den med kod taggar(klicka på Code och klistra in kopierad text från utvecklingsprogrammet).
Kod: Markera allt
/*
* Created 2015-03-14 21:01:34
*
*/
#define BAUD 19200 // 19 200 baud
#define FOCS 1843200
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 07:54:00
av Muppis
Jag är inget vidare begåvad på C, men i USART_Receive() använder du aldrig data, och det du returnerar från USART_Receive() använder du aldrig i main()!?
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 08:49:59
av baron3d
Funktionen USART_Receive skall se t så här:
int USART_Receive(void) { ......
och i main.c:
data = USART_Receive();
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 08:51:32
av Mupp
Nu har jag inte databladet i handen, utan en äggmacka, men är det verkligen rätt siffra du skriver till UBRR? Länge sen jag petade avr, men det där känns fel. Kollat databladet?
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 16:09:38
av Jennie
Funkar typ nu! Jag gjorde om det ganska mycket och tittade på ett exempel i en bok jag har så jag skriver om en hel sträng nu.
Men nu vill jag försöka få så att...
1. Jag har en sträng som skriver till användaren "Enter time in hh:mm:ss". Någon slags motsvarighet till "printf" här?
2. Sedan skannar av tidsvärdena från användarens värden för hh, mm och ss. Någon slags motsvarighet till "scanf" här?
3. Efter det vill jag att tiden ska uppdatera sig och räkna upp, så någon form av beräkning ska jag ha. Jag vet inte... men jag tänker mig nu en for-loop för varje enhet som börjar om efter räkning med nån slags fördröjning.
Någon som kan ge tips och förklara hur jag kan göra det utifrån den här koden jag har nedan?
Kod: Markera allt
#define BAUDRATE 19200
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/io.h>
#include <stdio.h>
//Deklaration av funktioner
void USART_init(void);
unsigned char getsUSART0(void);
void putchUSART0(unsigned char data);
void putsUSART0(char* str);
void nylinje(void);
char String[]=" Current time now is hh:mm:ss"; //String[] är egentligen an array behandlas som en string av kompilern i och med " "
char string2[]="Enter current time in hh:mm:ss"; //Den här strängen gör ingenting just nu då jag är osäker på hur jag ska använda den
int main(void){
USART_init(); //Kallar på USART0 initialiseringsfunktionen
while(1){ //Oändlig loop
putsUSART0(String); //Passar strängen till putsUSART0-funktion och sänder över det seriella värdet
_delay_ms(1000); //Fördröjer med 1 sekund så den återsänder strängen varje sekund
nylinje(); //Kallar på funktionen som fixar en ny linje
}
return 0;
}
void USART_init(void){
UBRR0 = BAUD_PRESCALLER; //Ställer in baud rate register
//Ställer in frame format: 8bit, 1 stoppbit, UCSZ01 och UCSZ00 båda två höga då de är med och bestämmer framestorleken
UCSR0C = ((1 << UCSZ01) | (1 << UCSZ00));
UCSR0B = (1<<RXEN0)|(1<<TXEN0); //Initaliserar receiver och transmitter
}
unsigned char getsUSART0(void)
{
while(!(UCSR0A & (1<<RXC0))); //Väntar på att data ska tas emot
return UDR0; //Returnera sedan värderna som finns i buffern
}
void putchUSART0(unsigned char data)
{
while(!(UCSR0A & (1<<UDRE0))); // Vänta på att USART0s data register blir tomt
UDR0 = data; //Sätt sedan så här
}
void putsUSART0(char* str)
{
// Här vill jag skriva att användaren ska skriva in tiden (som hh:mm:ss)!
while(*str){
putchUSART0(*str);
str++;
_delay_ms(200);
}
}
void nylinje(void) {
putchUSART0(0x0D); // ASCII-värdena för att göra en ny linje
putchUSART0(0x0A);
}
Så här ser det ut i terminalfönstret just nu btw..

Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 18:38:44
av Icecap
Jag gör sånt ganska mycket. Och det har inget med ATmega eller annan gammal grunka att göra, det är bara programmering.
Jag har dock tagit steget längre och gjort så att man skriver texten "set time hh:mm:ss"<Enter> (utan citationstecken) och programmet klurar sedan ut att det är "set" och att nästa ord är "time" och sedan skipper programmet alla whitespaces till siffrorna.
Kod: Markera allt
case Command_Set_Time:
Work[0] = Value; // Hour
while((*Source >= '0') && (*Source <= '9') && *Source) Source++; // Skip to ':'
if(*Source == ':')
{
Source++;
Work[1] = atoi(Source); // Minute
while((*Source >= '0') && (*Source <= '9') && *Source) Source++; // Skip to ':'
if(*Source == ':')
{
Source++;
if((*Source >= '0') && (*Source <= '9'))
{
Work[2] = atoi(Source); // Second
Local_Time.Year = Date_Time.Year;
Local_Time.Month = Date_Time.Month;
Local_Time.Date = Date_Time.Date;
Local_Time.Hour = Work[0];
Local_Time.Minute = Work[1];
Local_Time.Second = Work[2];
Date_Time_Make_UTC(&Local_Time, Config.Timezone);
Date_Time_Convert2UNIX(&Local_Time, &Check);
Date_Time_Make_Local_Time(&Local_Time, Config.Timezone);
Clock = Check; // Set clock
RTC_Write_Time(&Check);
sprintf(Buffer, "%s %s: %u:%02u:%02u\r\n", Comm_Text_Set, Comm_Text_Time, Local_Time.Hour, Local_Time.Minute, Local_Time.Second); Printout(Buffer);
}
}
}
break; // Command_Set_Time
Lite förklaring:
char* Source pekar på första tecken i timmarna.
unsigned char Work[3] är arbetsvariabler som timmar, minuter och sekunder sparas i till att börja med under omvandlingen.
Value är en variabel som redan håller värdet på första parameter som Source pekar på. Detta då det rör sig om många kommandon och många behöver ett värde och då kan man likaväl göra den omvandling direkt.
Och detta fungerar och är en del av programmet i min kontorsklocka.
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 19:11:53
av Jennie
^^ Najs! Tack. Jag ska pröva att göra likadant. Intressant.
Först behöver jag nog hjälp med hur jag ska kunna kommunicera fram och tillbaka med MCU:n?
Jag har fortfarande problemet att när jag skriver in någonting i terminalprogrammet, så får jag inte några värden tillbaka. Nu skriver ju programmet bara ut "Current time is hh:mm:ss" och jag kan ju som inte kommunicera med det fortfarande. Men den kan i varje fall skriva någonting till mig i den där strängen.
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 19:40:30
av Icecap
Frågan är hur du vill kommunicera med den. När du skriver terminalprogram antar jag att du vill kunde skriva just via ett terminalprogram.
Och då gör jag så att jag definiera en buffer - och lite annat:
Kod: Markera allt
struct
{
char Buffer[50];
unsigned char In, Flag, Chars;
} Rx;
Sedan aktiverar jag Rx-interrupten och gör en ISR:
Kod: Markera allt
void RS232_B_Rx_ISR(void)
{
// Recieve interrupt (if enabled)
_UBYTE Incoming;
Incoming = SCI0.RDR; // A read empties the Rx-buffer and removes the interrupt
switch(Incoming)
{
case '\b':
case 0x7F: // Backspace
if(Rx.In)
{
Rx.Buffer[--Rx.In] = 0x00;
}
break;
case '\r':
case '\n': // Enter
Rx.Chars = Rx.In;
if(Rx.In) Rx.Flag = 10;
Rx.In = 0;
break;
default:
if(Rx.In < sizeof(Rx.Buffer) - 1)
{ // Så länge det finns plats i buffern läggs det mottagna in.
Rx.Buffer[Rx.In++] = Incoming;
Rx.Buffer[Rx.In] = 0;
}
break;
}
}
Rx.Flag är egentligen en flagga som räknas ner av en timer-interrupt. Detta betyder att main-loop bara har en viss tid till att kolla flaggan och utföra ordern. Sker detta inte inom lagom tid kastas meddelandet. Man kan göra det utan timer-delen om man vill.
MEN - när Rx.Flag är icke-noll finns det ett meddelande att jobba med, det är iaf. pressat på <Enter>.
Sedan är det frågan om att dekoda vad som finns i buffern och vill man konde tolka kommandon v typen "set time hh:mm:ss", "get time", "set date yyyy-mm-dd" osv. krävs en hel del mer - men det har jag såklart löst och gjort till en fil jag kan hämta in utan att svettas. Det var dock lite jobb att fixa.
Re: Stark behov av hjälp med att skriva och ta emot av USART
Postat: 15 mars 2015, 20:09:51
av BEEP
Prova att använda USART_Receive funktionen från din första kod som väntar på tecken från terminalen. När programmet går ur while loopen och åtvänder till main så låter du µC skicka några tecken för att se om den går ur loopen. Om detta fungerar så är nästa steg att försöka skicka tillbaka motagen data till terminalen.
Om du har någon ledig lysdiod på Arduino så kan du använda den för debugging(felsökning). Lysdioden kan du t.ex. tända före en loop och släcka den efter loopen för att se om programmet är i funktionen och om den fastnar där.