UART empfängt nur 2 zeichen

Gast #4923442
Lesenswert?

Hallo
ich sende mit einem mega328 über uart ein string
1
char* test = "TEST";
2
rs485_puts(test,sizeof(test));
3

4
void rs485_putc(unsigned char c){
5
  while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich */
6
  {
7
  }
8

9
  UDR0 = c;                      /* sende Zeichen */
10
  //return 0;
11
}
12

13
void rs485_puts(char *s, unsigned int len){
14
  while (*s)
15
  {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
16
    rs485_putc(*s);
17
    s++;
18
  }
19
}

Empfangen tue ich mit einem zweiten mega328
1
if((UCSR0A & (1<<RXC0))){
2
      uart_gets(uart_string, sizeof(uart_string));
3
      //uart_readline(uart_string);
4
      
5
    }
6
    if(uart_str_complete == 1){
7
      lcd_gotoxy(0,0);
8
      if(uart_string[0] == 0x42){
9
        UCSR0A &= ~(1<<MPCM0);
10
        PORTD |= (1<<PORTD2);
11
        _delay_ms(20);
12
        PORTD &= ~(1<<PORTD2);
13
        _delay_ms(20);
14
        uart_string[0] = 0xFF;
15
        uart_str_complete = 0;
16
      }else{
17
        UCSR0A |= (1<<MPCM0);
18
        PORTD |= (1<<PORTD4);
19
        _delay_ms(20);
20
        PORTD &= ~(1<<PORTD4);
21
        //uart_string[0]= 0xFF;
22
        uart_str_complete = 0;
23
        lcd_puts(uart_string);
24
      }  
25
      
26
    }
27

28
uint8_t uart_getc(void)
29
{
30
   //while (!(UCSR0A & (1<<RXC0)))   // warten bis Zeichen verfuegbar
31
   //;
32
  return UDR0;                   // Zeichen aus UDR an Aufrufer zurueckgeben
33
}
34

35
void uart_gets( char* Buffer, uint8_t MaxLen )
36
{
37
  uint8_t NextChar;
38
  uint8_t StringLen = 0;
39

40
  NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen
41

42
  // Sammle solange Zeichen, bis:
43
  // * entweder das String Ende Zeichen kam
44
  // * oder das aufnehmende Array voll ist
45
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
46
    *Buffer++ = NextChar;
47
    StringLen++;
48
    NextChar = uart_getc();
49
  }
50

51
  // Noch ein '\0' anhängen um einen Standard
52
  // C-String daraus zu machen
53
  uart_str_complete = 1;
54
  *Buffer = '\0';
55
}


Empfange tue ich aber statt TEST nur TETEEEEEEEE
..

aber wenn ich mich parallel mit Putty drauf hänge sehe ich TEST....

wodran kann es liegen, bin schon am verzweifeln

--

Quelltext in [ c ] [ /c ] -Tags einschließen, dann wird er (etwas) 
lesbarer.

-rufus
Gast #4923722
Lesenswert?

Also habe es jetzt mit der while schleife hinbekommen...
allerdings bekomme ich dennoch nur die ersten beiden Zeichen


uint8_t uart_getc(void)
{
   while (!(UCSR0A & (1<<RXC0)))   // warten bis Zeichen verfuegbar
   ;
  return UDR0;                   // Zeichen aus UDR an Aufrufer 
zurueckgeben
}
Gast #4923724
Lesenswert?

sorry... mir ist noch was aufgefallen...
ich schicke folgenden String
char* test = "123456";

Empfangen tue ich 126B
wenn ich nun aber den String schicke

char* test = "1234567";

dannn empfange ich 127B...

der verschluckt irgendwie alles dazwischen!?
Gast #4923751
Lesenswert?

Rufus Τ. F. schrieb:
> Dennis schrieb:
>> Das würde ich gerne drin lassen....
>
> Weißt Du, wozu das gut ist, und welchen technischen Hintergrund das hat?

Damit ich bei mehreren uC die ich per rs485 anspreche nicht alle 
gleichzeitig belaste wenn ich eine Info an nur ein ziel Sende... kurz 
gesagt.. Adressierung...
Gast #4923766
Lesenswert?

Ohne mich in ein fremdes Programm einarbeiten zu wollen, von dem ich 
ohnehin nur die Hälfte sehe, frage ich mich, welchem Zweck diese 
Umschaltung dient; da muss doch u.a. auch der Rahmen von 8 auf 9 bit 
umgeschaltet werden, das sehe ich nirgendwo. Und ganz naiv hätte ich 
gesagt, entweder immer aus oder immer ein.
Gast #4923783
Lesenswert?

S. Landolt schrieb:
> Ohne mich in ein fremdes Programm einarbeiten zu wollen, von dem
> ich
> ohnehin nur die Hälfte sehe, frage ich mich, welchem Zweck diese
> Umschaltung dient; da muss doch u.a. auch der Rahmen von 8 auf 9 bit
> umgeschaltet werden, das sehe ich nirgendwo. Und ganz naiv hätte ich
> gesagt, entweder immer aus oder immer ein.

so habe ich es mir irgendwo durchgelesen...
erst TXB80 an... und wenn die adresse passt dann wieder aus...

aber naja... ich versuche es nun mit 8 bit!
Gast #4923817
Lesenswert?

also... ich empfange nun meine "1234567"
ABER..... wenn ich auf sende.. dann ist mein uart_string[0] '1'
beim erneuten senden ist er dann '1'
beim 3ten senden '2'

in Putty sehe ich aber dass er immer alle sendet!

uart_str_count ist immer 0 nachdem uart_str_complete = 1 wird


ISR(USART_RX_vect){

  unsigned char nextChar;

  // Daten aus dem Puffer lesen
  nextChar = UDR0;


  //lcd_putc(UDR0);
  if( uart_str_complete == 0 ) {  // wenn uart_string gerade in 
Verwendung, neues Zeichen verwerfen

    // Daten werden erst in uart_string geschrieben, wenn nicht 
String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
    if( nextChar != '\n' &&
    nextChar != '\r' &&
    nextChar != '\0' &&
    uart_str_count < UART_MAXSTRLEN ) {
      uart_string[uart_str_count] = nextChar;
      uart_str_count++;
    }
    else {
      uart_string[uart_str_count] = '\0';
      uart_str_count = 0;
      uart_str_complete = 1;
      lcd_putc(nextChar);
      lcd_putc(' ');
    }
  }
}
Gast #4924128
Lesenswert?

Vorab: Sie hatten Recht, das MPCM0 muss im adressierten Slave 
tatsächlich umgeschaltet werden, da habe ich Sie leider auf eine falsche 
Fährte gelockt.
  Der Fehler muss also anderswo gesteckt haben, und vielleicht hängt das 
jetzige Problem damit zusammen. Das kann aber ein Außenstehender kaum 
beurteilen, da immer nur Teile des Programms gezeigt werden. Zuletzt zum 
Beispiel ist das Rücksetzen von uart_str_complete nicht zu sehen, was 
aber wichtig wäre, denn:
> if( uart_str_complete == 0 ) {  // wenn uart_string
> gerade in Verwendung, neues Zeichen verwerfen
Gast #4924279
Lesenswert?

Marc V. schrieb:
> Dennis schrieb:
>
>  Auch wenn es (wahrscheinlich) nicht die Ursache ist:ISR(USART_RX_vect){
> ...
> ...
>      lcd_putc(nextChar);
>       lcd_putc(' ');
>     }
>   }
>
>  LCD Ausgabe macht man nicht aus der ISR...

das war nur zum debugen:)

hier nun mein kompletter Sende Code...
1
/*
2
 * 1WallSwitch_RS485.c
3
 *
4
 * Created: 27.02.2017 08:15:42
5
 * Author : Mitch
6
 */ 
7

8
#include <avr/io.h>
9
#include <avr/sleep.h>
10
#include <avr/power.h>
11
#include <avr/wdt.h>
12
#include <avr/interrupt.h>
13
#include <stdint.h>
14
#include <string.h>
15
#include "EEPROM.h"
16

17
#define F_CPU 8000000UL
18
#include <util/delay.h>
19

20
#define DEVICE 1
21

22
#define BAUDRATE 19200UL
23
#define USAR_BAUD_CALC 25 //8000000 / (16*19200)
24

25
#define LOW(x) ((x) & 0xFF) //LOWBYTE
26
#define HIGH(x) (((x) >> 8) & 0xFF) //HIGHBYTE
27

28
//RF24 radio(8,7);
29

30
volatile uint8_t fourBtn = 0, initBtn  =0;
31
volatile uint8_t WDT_count    = 0;
32
volatile uint64_t Zeitstempel  = 0;
33
volatile uint8_t id        = 0;
34
volatile uint8_t timer_1s    = 0;
35
volatile uint8_t timer_3s    = 0;
36

37
//Für Spannungsüberwachung
38
volatile uint8_t adc_low, adc_high; //Zwischenspeicher für die Ergebnisse des ADC
39
volatile uint64_t adc_result, vcc; //adc_result Gesamtergebnis der Messung des ADC //VCC Versorgungsspannung
40

41
const uint64_t addresses[2] = {0xF0F0F0F002LL,0xE101000000LL};
42

43
char *sendByte[20];
44
volatile char recByte[10];
45

46
void rs485_putc(unsigned char c){
47
  while (!(UCSR0A & (1<<UDRE0)))  /* warten bis Senden moeglich */
48
  {
49
  }
50

51
  UDR0 = c;                      /* sende Zeichen */
52
  //return 0;
53
}
54

55
void rs485_puts(char *s, unsigned int len){
56
  while (*s)
57
  {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
58
    rs485_putc(*s);
59
    s++;
60
    //_delay_ms(200);
61
  }
62
}
63

64
void rs485_putAddr(uint8_t data){
65
  UCSR0B |= (1<<TXB80);
66
//  _delay_ms(10);
67
  rs485_putc(data);
68
  //rs485_putc('\n');
69
//  _delay_ms(10);
70
  UCSR0B &= ~(1<<TXB80);
71
}
72

73
void config_timer(){
74
  //16Bit Timer1
75
  OCR1A = 31250;
76
  TCCR1B = (1<<CS12) | (1<<WGM12);
77
  TIMSK1 = (1<<OCIE1A);
78
}
79

80
void config_interrupt(){
81
  //PinChange Interrupt
82
  PCMSK1  |= (1<<PCINT11)|(1<<PCINT10)|(1<<PCINT9)|(1<<PCINT8); //4 Taster PC0,PC1,PC2,PC3
83
  PCICR  |= (1<<PCIE1);
84

85
  //PinChange Interrupt PD4 (InitTaster)
86
  PCMSK2  |= (1<<PCINT20);
87
  PCICR  |= (1<<PCIE2);
88
}
89

90
void config_rs485(){
91
  UBRR0H = HIGH(USAR_BAUD_CALC);
92
  UBRR0L = LOW(USAR_BAUD_CALC);
93

94
  //Bei Slave mit Adresse
95
  //  UCSR0A = (1<<MPCM0); //Adressüberprüfung... dann 9Bit Modus
96

97
  //Character
98
  UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); //RX Enable, TX Enable, Empfangsinterrupts erlauben , UCSZ02 und UCSZ01 und 2aus UCSR0C = 9n1 ...(1<<RXCIE0)
99
  UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); //8n1
100
}
101

102
ISR(PCINT1_vect){ //4Taster
103
  fourBtn = 1;
104
}
105

106
ISR(PCINT2_vect){ //InitTaster
107
  initBtn = 1;
108
}
109

110
ISR(TIMER1_COMPA_vect){
111
  timer_1s = 1;
112
  timer_3s++;
113
}
114

115
int main(void){
116
  DDRC  |= (1<<DDC4)|(1<<DDC5); //PC4 & PC5 als Ausgang für LEDs(Tasterleds)
117
  DDRD  |= (1<<DDD2)|(1<<DDD3)|(1<<DDD5); //PD2 & PD3 als Ausgang für LEDs(Tasterleds), PD5 StatusLed
118
  DDRB  |= (1<<DDB2);//PB1 als Ausgang Ansteuerung für RS485
119

120
  config_timer();
121
    config_interrupt();
122
  config_rs485();
123
  sei();
124

125
  //ADC abschalten, verbraucht dann noch weniger
126
  ADCSRA = 0;
127

128
  //Für Batterieüberwachung
129
  ADMUX |= (1<<REFS0); //VCC als Referenzspannung f?r den AD-Wandler
130
  ADMUX |= (1<<MUX3) | (1<<MUX2) | (1<<MUX1);  //1.1V Referenzspannung als Eingang f?r ADC
131
  
132
  _delay_ms(10);  //warten bis sich die Referenzspannung eingestellt hat
133

134
  sendByte[0] = 1;//DEVICE; //Modus
135
  sendByte[1] = 2;//EEPROM_read(0);  ; //lese ID aus EEPROM
136
  sendByte[2] = 5;//EEPROM_read(1);
137
  sendByte[3] = 6;//EEPROM_read(2);
138
  sendByte[4] = 7;//EEPROM_read(3);
139
  sendByte[5] = 8; //CRC
140
  sendByte[6] = 9; //BAT
141
  sendByte[7] = 10; //STATUS
142
  sendByte[8] = 11; //STATUS
143
  sendByte[19] = 0; //STATUS
144
  for(uint8_t i=9; i<19; i++){
145
    sendByte[i] = 0xF1; //DATA i
146
    }
147
  
148
  while(1){    
149
    if(fourBtn == 1){ //wenn einer der 4Taster gedrückt
150
      if(PINC & (1<<PINC0)){ //Btn 1 gedrückt
151
        _delay_ms(60);
152
        PORTC |= (1<<PORTC4);
153
        _delay_ms(60);
154
        PORTC &= ~(1<<PORTC4);
155
        
156
        sendByte[8] = 0x01;
157
        char *test = "1234567";
158

159
      //  rs485_putAddr(0x42);
160
        rs485_puts(test,sizeof(test));
161
        //uart_putstring("\r\n");
162
        //uart_putstring(test);
163
        //_delay_ms(100);
164
      }
165
      if(PINC & (1<<PINC1)){ //Btn 2 gedrückt
166
        PORTC |= (1<<PORTC5);
167
        _delay_ms(100);
168
        PORTC &= ~(1<<PORTC5);
169

170
      //  sendByte[8] = 0x02;
171

172
        rs485_putAddr(0x42);
173
        rs485_puts(sendByte,sizeof(sendByte));
174

175
        //_delay_ms(100);
176
      }
177
      if(PINC & (1<<PINC2)){ //Btn 3 gedrückt
178
        PORTD |= (1<<PORTD2);
179
        _delay_ms(100);
180
        PORTD &= ~(1<<PORTD2);
181

182
      //  sendByte[8] = 0x03;
183

184
        rs485_putAddr(0x42);
185
        rs485_puts(sendByte,sizeof(sendByte));
186

187
        //_delay_ms(100);
188
      }
189
      if(PINC & (1<<PINC3)){ //Btn 4 gedrückt
190
        PORTD |= (1<<PORTD3);
191
        _delay_ms(100);
192
        PORTD &= ~(1<<PORTD3);
193

194
        //sendByte[8] = 0x04;
195

196
        rs485_putAddr(0x42);
197
        rs485_puts(sendByte,sizeof(sendByte));
198

199
        //_delay_ms(100);
200
      }
201
      fourBtn = 0;
202
      //sendByte[8] = 0x00;
203

204
      //rs485_putAddr(0x42);
205
      //rs485_puts(sendByte);
206
    }
207
    //Initialisierung
208
    if(initBtn == 1){
209
      timer_3s = 0; 
210
      while(PIND & (1<<PIND4)){ //InitBtn gedrückt
211
        PORTD |= (1<<PORTD5);
212
        if(timer_3s == 3){  //3sekunden gedrückt
213
          for(int i=0; i<5; i++){
214
            PORTD &= ~(1<<PORTD5);
215
            _delay_ms(100);
216
            PORTD |= (1<<PORTD5);
217
            _delay_ms(100);
218
          }
219
          
220
        }
221
      }
222
      PORTD &= ~(1<<PORTD5);
223
      initBtn = 0;
224
    }
225
  }
226
}

und mein Receive Code
1
/*
2
 * RS485_Test1_Slave.c
3
 *
4
 * Created: 18.02.2017 21:19:24
5
 *  Author: Mitch
6
 */ 
7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
#include <string.h>
10
#include "lcd.h"
11

12
#define F_CPU 8000000UL
13
#include <util/delay.h>
14
#define BAUDRATE 19200UL
15
#define USAR_BAUD_CALC 25 //8000000 / (16*19200)
16

17
#define LOW(x) ((x) & 0xFF) //LOWBYTE
18
#define HIGH(x) (((x) >> 8) & 0xFF) //HIGHBYTE
19

20
#define UART_MAXSTRLEN 20
21

22
volatile uint8_t uart_str_complete = 0;     // 1 .. String komplett empfangen
23
volatile uint8_t uart_str_count = 0;
24
volatile char uart_string[UART_MAXSTRLEN] = "";
25

26
uint8_t uart_getc(void)
27
{
28
    while (!(UCSR0A & (1<<RXC0))){   // warten bis Zeichen verfuegbar
29
     
30
     }   
31
  return UDR0;                   // Zeichen aus UDR an Aufrufer zurueckgeben
32
}
33

34
void uart_gets( char* Buffer, uint8_t MaxLen )
35
{
36
  uint8_t NextChar;
37
  uint8_t StringLen = 0;
38

39
  NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen
40
  
41
  // Sammle solange Zeichen, bis:
42
  // * entweder das String Ende Zeichen kam
43
  // * oder das aufnehmende Array voll ist
44
  while( NextChar != '\n' &&  NextChar != '\0' &&StringLen < MaxLen - 1 ) {
45
    *Buffer++ = NextChar;
46
    StringLen++;
47
    NextChar = uart_getc();
48
  }
49

50
  // Noch ein '\0' anhängen um einen Standard
51
  // C-String daraus zu machen
52
  uart_str_complete = 1;
53
  *Buffer = '\0';
54
}
55

56
ISR(USART_RX_vect){
57
  
58
  unsigned char nextChar;
59

60
  // Daten aus dem Puffer lesen
61
  nextChar = UDR0;
62
  
63
  
64
  //lcd_putc(UDR0);
65
  if( uart_str_complete == 0 ) {  // wenn uart_string gerade in Verwendung, neues Zeichen verwerfen
66

67
    // Daten werden erst in uart_string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
68
    if( nextChar != '\n' &&
69
    nextChar != '\r' &&
70
    nextChar != '\0' &&
71
    uart_str_count < UART_MAXSTRLEN ) {
72
      uart_string[uart_str_count] = nextChar;
73
      uart_str_count++;
74
    }
75
    else {
76
      uart_string[uart_str_count] = '\0';
77
      uart_str_count = 0;
78
      uart_str_complete = 1;
79
      //lcd_putc(nextChar);
80
      //lcd_putc(' ');
81
    }
82
  }
83
}
84

85

86
int main(void){
87
  UBRR0H = HIGH(USAR_BAUD_CALC);
88
  UBRR0L = LOW(USAR_BAUD_CALC);
89

90
  //Bei Slave mit Adresse
91
  //UCSR0A = (1<<MPCM0); //Adressüberprüfung... dann 9Bit Modus
92

93
  //Character 
94
  UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0); //RX Enable, TX Enable, Empfangsinterrupts erlauben , UCSZ02 und UCSZ01 und 2aus UCSR0C = 9n1 ...(1<<RXCIE0)
95
  UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); //8n1
96

97
  DDRD |= (1<<DDD5)|(1<<DDD6)|(1<<DDD7);   //DDRA für LCD Datenleitung als Ausgang
98
  DDRB |= (1<<DDB0)|(1<<DDB1)|(1<<DDB2)|(1<<DDB3);
99

100
  DDRD = (1<<DDD4)|(1<<DDD2); //Ausgang
101
  DDRC = (1<<DDC4); //Ausgang
102
  //Interrupts global aktivieren
103
  sei();
104
  
105
  lcd_init(12);
106
  lcd_clrscr();
107

108
  lcd_puts("A");
109
//  lcd_puts(uart_string);
110

111
    while(1){
112
  //  if((UCSR0A & (1<<RXC0))){
113
      //  uart_gets(uart_string, sizeof(uart_string));
114
    //  }
115
    
116
    if(uart_str_complete == 1){
117
      //  if(uart_string[0] == '1'){
118
          //uart_str_count = 0;
119
          lcd_gotoxy(0,0);
120
          uart_str_complete = 0;
121
          lcd_puts(uart_string);
122
          
123
      //  }  
124
    }
125

126

127
    }
128
}


und hier ist kein Unterschied ob ich jetzt mit ISR arbeite oder die 
uart_gets() Funktion abfrage.

Meine Ausgabe sieht wie folgt aus..

1.Senden > Ausgabe: 1234567
2.Senden > Ausgabe: 2345671
3.Senden > Ausgabe: 3456712
usw.

--
Nochmal zum Mitmeisseln für Dich


Quelltext in [ c ] [ /c ] -Tags einschließen, dann wird er (etwas) 
lesbarer.

-rufus
Gast #4924351
Lesenswert?

Eine einfache Erklärung wäre ja die:
Bei jedem Durchlauf geht ein Zeichen verloren  Und zwar in der ISR. So 
lange uart_str_complete == 1 gilt, macht die ISR ja fast nichts, aber 
sie holt  Zeichen ab.

Was passiert denn bei:
uart_str_complete = 0;
lcd_gotoxy(0,0);  ?
Die beiden Zeilen also vertauschen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren