Ich erhalte Bytes von meinem UART als uint8. Wie konvertiere ich diese Bytes in ASCII? Ich verwende Atmel 6.0 und mein Mikrocontroller ist ATMega16L.
BEARBEITEN
Ich verwende ein Android-Telefon, um Informationen von Roving-Netzwerken an ein WLAN-Modul (RN-131) zu senden und zu empfangen. Das WLAN-Modul verbindet sich über UART mit dem Mikrocontroller (atmega16L). Was auch immer das WLAN-Modul vom Telefon empfängt, wird über seinen UART übertragen. In ähnlicher Weise wird alles, was in seinen UART geschrieben wird, über WLAN übertragen.
Jetzt versuche ich, eine Zeichenfolge vom Telefon zu senden, die in Bytes umgewandelt wird. Der Code ist unten dargestellt:
PrintWriter out = new PrintWriter(new BufferedWriter(new outputStreamWriter(socket.getOutputStream())), true);
out.println("Eclipse");
hier der ' BufferedWriter ' - Konstruiert einen neuen BufferedWriter, der einen Puffer von 8192 Bytes bereitstellt. und ' PrintWriter ' - Konstruiert einen neuen PrintWriter mit out als Zielschreiber. Der Parameter autoFlush bestimmt, ob der Druck-Writer seinen Inhalt automatisch an den Ziel-Writer löscht, wenn ein Zeilenumbruch auftritt.
Jetzt zum Programmieren des Mikrocontrollers verwende ich AVR Studio 6.0
uint8_t data;
char arr[32];
data = UDR;
length = strlen(data);
itoa(data, arr, 10);
Aber was ich bekomme, ist "50, 53, 52", selbst wenn ich "Eclipse" sende.
EDIT 20. Juni 2012
Hier ist mein Code bis jetzt. Hinweis: Der Code wurde in AVR Studio 6.0 geschrieben, daher sieht er etwas anders aus als andere Codes, die in AVR Studio 4.18 geschrieben wurden.
/**************************************************
* Includes
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include "../../../../../../Program Files (x86)/Atmel/Atmel Studio 6.0/extensions/Atmel/AVRGCC/3.4.0.65/AVRToolchain/avr/include/avr/iom16.h"
/**************************************************
* Global Variables
*/
int trigger=0, length=0;
int i=0, n=0;
uint8_t data;
char arr[8];
/**************************************************
* Defines
*/
#define LED_PORT PORTA
#define RED_ON (PORTA | 0x01)
#define RED_OFF (PORTA & ~0x01)
#define YELLOW_ON (PORTA | 0x02)
#define YELLOW_OFF (PORTA & ~0x02)
#define GREEN_ON (PORTA | 0x04)
#define GREEN_OFF (PORTA & ~0x04)
/**************************************************
* Function Prototypes
*/
void initialize(void);
void time_display(void);
int main(void){
initialize();
while(1){
//TODO:: Please write your application code
}
}
void initialize(void){
DDRA = 0x07; //PORTA pins 0,1,2 set as outputs
// DDRD = 0x02; //PORTD pin 1 is output (TX) and pin 0 is input (RX)
//Timer SETUP
TCCR1A = 0x80; //OCR1A enable in CTC mode
TCCR1B = 0x0C; //CTC mode, 256 prescale
TIMSK = 0x10; //CTC on OCR1A enabled, overflow disabled
OCR1A = 2000; //OCR value set to get an interrupt every 1 second (15624)
//USART SETUP
UCSRA = 0x00; //no Frame Error, no parity error, no Data OverRun
UCSRB = 0xE0; //receiver enable, transmitter enable (0x18)
UCSRC = 0x8E; //Asynchronous USART mode, no parity, 1 stop bit, 8-bit character size, Data transmitted on rising edge and received on falling edge of the clock
UBRRL = 51; //Baud rate of 9600bps
UBRRH = 0;
sei(); //Global interrupt enable
}
//timer capture interrupt
ISR(TIMER1_COMPA_vect){
}
ISR(USART_RXC_vect){
LED_PORT = RED_ON;
_delay_ms(100);
for(int x=0; x<5; x++){
arr[x] = UDR;
}
LED_PORT = RED_OFF;
_delay_ms(100);
trigger = 1;
}
ISR(USART_UDRE_vect){
if(trigger >= 1){
LED_PORT = GREEN_ON;
_delay_ms(200);
LED_PORT = GREEN_OFF;
_delay_ms(200);
UDR = data; //transmit the data
trigger = 0;
}
}
**BEARBEITEN 19.06.2012******************************************** *****************
Ok, nachdem Sie Ihren Code hinzugefügt haben, habe ich ein paar Änderungen vorgenommen, die Sie ausprobieren (und verstehen!)
Zunächst haben wir unser Zeichenarray als flüchtig deklariert, damit der Compiler weiß, dass es sich unerwartet durch einen Interrupt ändern kann. Ebenso haben wir eine Variable erstellt, um unsere Indexposition im Array zu verfolgen:
/**************************************************
* Global Variables
*/
int trigger=0, length=0;
int i=0, n=0;
uint8_t data;
volatile char arr[8];
volatile char arr_idx = 0;
Als nächstes habe ich Ihren UART-Initialisierungscode basierend auf dem ATMega16L-Datenblatt und Ihren Kommentaren bearbeitet:
//USART SETUP
UCSRA = 0x00; //no Frame Error, no parity error, no Data OverRun
UCSRB = 0xD8; //receiver enable, transmitter enable (0x18)
UCSRC = 0x86; //Asynchronous USART mode, no parity, 1 stop bit, 8-bit character size, Data transmitted on rising edge and received on falling edge of the clock
UBRRL = 51; //Baud rate of 9600bps (8MHz clock?)
UBRRH = 0;
Sehen Sie sich das Datenblatt genau an (Seite ~166). Ich glaube, ich habe den UART jetzt basierend auf Ihren Kommentaren richtig konfiguriert. Ich werde nicht jedes Bit durchgehen, aber Sie sollten. Bitte stellen Sie Fragen, wenn Sie glauben, dass ich einen Fehler gemacht habe oder Sie etwas nicht verstanden haben.
Schließlich habe ich Ihre ISR-Routine bearbeitet:
ISR(USART_RXC_vect){
arr[arr_idx] = UDR;
arr_idx++;
arr_idx %= 7; //make sure index stays within array
trigger = 1;
}
Beachten Sie, dass die ISR jedes Mal ausgeführt wird, wenn ein einzelnes Byte (oder Zeichen) empfangen wird. Das bedeutet, dass wir das einzelne Zeichen verarbeiten (zu unserem Array hinzufügen), unsere Indexposition erhöhen und es schnell verlassen möchten, damit wir für das nächste Zeichen bereit sind.
Sie müssen sich nun den arr[] mit der von Ihnen verwendeten Methode ansehen und sehen, ob er Ihre Zeichen jetzt korrekt empfängt.
**ENDE DER BEARBEITUNG****************************************
Eine Möglichkeit besteht darin, einfach eine der verfügbaren Bibliotheken zu verwenden, die in AVR Studio enthalten sind:
#include <stdlib.h>
und dann irgendwo in deinem Code ...
char num2[5]; //create a buffer for the ascii string
itoa(num1,num2,10); //convert the integer (num1) to an ascii string (num2) in base 10
Wenn Sie dies dann auf einem Zeichen-LCD anzeigen, können Sie das Array num2 an die von Ihnen verwendete LCD-Druckfunktion senden.
Wenn Sie sich Sorgen um den Coderaum machen, können Sie ziemlich einfach Ihre eigene einfache Itoa-Funktion (Integer to Ascii) schreiben. Sie müssen jede "Zehner"-Position aus Ihrer Ganzzahl mit den Operatoren "/" und "%" abrufen und in ASCII konvertieren:
(Quelle: asciitable.com )
Aus der obigen Tabelle können Sie ersehen, dass Sie nach dem Erfassen jedes Ziffernwerts (0-9) einfach 48 hinzufügen müssen, um ihn in die ASCII-Zeichendarstellung umzuwandeln.
BEARBEITEN
Ok, nachdem Sie Ihre Informationen hinzugefügt und angenommen haben:
Dann sollte der Mikrocontroller diese Zeichen bereits als Ascii empfangen, und die ITOA-Funktion wird hier nicht benötigt und würde tatsächlich Ihre eingehenden String-Daten durcheinander bringen.
Es könnte jedoch immer noch eine Menge verschiedener Dinge sein ... Wie sehen Sie die UART-Daten, die von Ihrem Mikrocontroller empfangen werden?
Note that, the ISR is executed every time a single byte (or character) is received
. Jedes Mal, wenn das passiert, UDR
wird es einen neuen Wert haben. Sie müssen die Schleife nicht innerhalb der ISR haben. Hoffentlich gibt Ihnen das genug Einblick, um das Problem zu lösen.Ein ASCII-Zeichen ist einfach eine 8-Bit-Zahl, die als Zeichen angezeigt wird, wenn Sie Funktionen wie "printf" aufrufen, die Zeichen anzeigen sollen.
In C ist ein String ein Array dieser Zeichen (oder 8-Bit-Zahlen), das mit dem Wert 0
oder "nullterminiert" abgeschlossen wird.
Wenn Sie also eine Zeichenfolge wie „Eclipse“ senden, senden Sie tatsächlich bereits Zahlen. Tatsächlich sieht es so aus, wenn Sie es senden:
[69, 99, 108, 105, 112, 115, 101, 0]
Wenn Sie dies printf
beispielsweise an übergeben, wird "Eclipse" ausgegeben. Beachten Sie das Null-Terminator. Beachten Sie auch, dass Sie keine Funktion benötigen, um dies zu konvertieren.
itoa
ist eine Funktion, die verwendet wird, um Zahlen in ihre Zeichenfolgendarstellung umzuwandeln. Zum Beispiel:
char str[32];
itoa(223, str, 10);
printf("%s", str);
Dies würde "223" ausgeben. Die tatsächlichen Zahlenwerte, die sich darin befinden str[]
, sind uns sicher bekannt: [50, 50, 51, 0]
. Nach deiner Beschreibung bin ich mir ziemlich sicher, dass das nicht das ist, was du willst.
Gehen Sie nicht immer von einer ASCII -Codierung aus. Hier ist eine extrem weit verbreitete Zeichencodierung, die auf Anwendungsebene und in der Webentwicklung verwendet wird: UTF-8 - Diese Zeichen sind nicht immer 8-Bit, einige von ihnen sind 16-Bit, um beispielsweise Zeichen in anderen Sprachen darzustellen.
BEARBEITEN:
Es gibt etwas, das Sie über ein typisches UART-Peripheriegerät auf einem AVR wissen müssen (nicht als pauschale Aussage für alle UARTs auf allen uCs gedacht, sondern nur für die Familie, die Sie verwenden). Sie funktionieren wie folgt: Wenn ein Byte hereinkommt, wird es in einen Single-Byte-Speicherort gelegt: UDR
- Wenn Sie dieses Register lesen, wird es gelöscht. Wenn neue Daten auf dem UART eingehen und Sie noch nicht aus diesem Register gelesen haben? Es wird mit dem neuen Wert überschrieben. Ganze Saiten werden hier nicht platziert. Nur einzelne Zeichen. All dies ist im Datenblatt für Ihr uC beschrieben, ich empfehle dringend, sich damit vertraut zu machen.
Hoffentlich gibt Ihnen das genügend Informationen, um zu verstehen, warum strlen(data)
es nicht funktioniert. Wenn Sie sich immer noch nicht sicher sind, warum, lesen Sie das Datenblatt noch einmal durch, lesen Sie nach, was passiert, wenn Sie diese Zuweisung in C vornehmen, data = UDR;
und lesen Sie auch, was strlen
die Parameter von sind, und beachten Sie, dass einer von ihnen ein Zeiger auf eine Zeichenfolge ist. Wenn Sie Zeiger nicht gut verstehen, empfehle ich Folgendes: http://www.cplusplus.com/doc/tutorial/pointers/
Wenn Ihnen das alles nach zu viel Arbeit klingt, dann schlage ich vor, stattdessen zu einem Arduino zu greifen. Verstehen Sie mich nicht falsch, es wäre großartig, wenn Sie all dies verstehen und einfaches C auf Ihrem AVR verwenden könnten, aber wenn Ihr Wissen im Moment zu viele Lücken aufweist, kann es ein bisschen überwältigend sein.
Nun zu dem, was Sie erreichen möchten. Sie haben in Ihrem Kommentar erwähnt, dass Sie eine Schleife ausführen wollten, bis Sie eine vollständige Zeichenfolge aus dem UART erhalten und in einem Puffer speichern, wo Sie sie dann als Befehl verarbeiten. Ok. Völlig machbar, in der Tat eine ziemlich verbreitete Technik.
Hier ist etwas Pseudo-Code für Sie:
i = 0;
char str[32];
while(forever) {
if (data_byte_is_available) {
if (i == 31)
i = 0;
str[i] = UDR;
i++;
}
print(str);
}
Versuchen Sie herauszufinden, was Sie für eine data_byte_is_available
Funktion tun müssen. Das Datenblatt ist dein Freund. Wie zeigen Sie außerdem an, was auf dem UART des uC eingeht? Was auch immer das ist, ersetze das, was print
ich da oben habe, damit. Ich hoffe, es gibt keine Probleme mit dem, was Sie dort verwenden ...
Adam Lawrence
David Norman
MickeyfAgain_BeforeExitOfSO
Adam Lawrence
David Norman
data = (uint16_t) tx; length = strlen(data); UDR = data;
Connor Wolf
David Norman
justieren
justieren
David Norman
Jon L
length = strlen(data);
Das könnte ziemlich gefährlich werden ... Was dort passiert, ist, dass es sich die Speicheradresse "data" ansieht und versucht, dort eine nullterminierte Zeichenfolge zu finden. Da wir nicht wissen, was da ist, könnte es zählen, bis es abstürzt.David Norman
Jon L
strlen
dort anrufen. Wenn Sie zum einen die Länge der eingehenden Zeichenfolge erhalten möchten, wird dies nicht so funktionieren, wie Sie es haben.UDR
Hier befindet sich ein einzelnes Byte, nicht Ihre gesamte Zeichenfolge. Zweitens wirdstrlen
ein Zeiger auf den Speicher benötigt, in dem sich die gewünschte Zeichenfolge zum Messen befindet. Sie haben ihm einen Wert übergeben, keinen Zeiger. Dies wird als Speicheradresse interpretiert und beginnt an einem Ort zu zählen, an dem wer weiß, was dort sein wird ...David Norman
Jon L
Jon L
sternenblau
CharSet
in Java aufgerufen wird) in angebennew OutputStringWriter(stream, charset)
, da sonst ein Standardwert verwendet wird, der falsch sein könnte. Obwohl es sich höchstwahrscheinlich um UTF-8 handelt, das ASCII als Teilmenge enthält und funktionieren würde. Ich bezweifle also, dass dies die Wurzel Ihres Problems ist.Kenny
David Norman
Jamiro14