Forum: Mikrocontroller und Digitale Elektronik das erste Byte der seriellen Schnittstelle ist stets falsch


von Owen S. (senmeis)


Lesenswert?

Hallo,

man möchte die serielle Schnittstelle ASC0 vom XC16x verwenden, und zwar 
mit dem Transmit Interrupt.

Die Sendefunktion sieht wie folgt aus:
1
void ASC0_vSendData_LCD(unsigned char *lcd_data, unsigned char lcd_number)
2
  {
3
  ASC0_vSendData(lcd_data[0]);
4
  rest_number = lcd_number - 1;
5
  }
Diese soll nur das erste Byte senden. Danach wird die folgende ISR 
automatisch aufgerufen:
1
void ASC0_viTx(void) interrupt ASC0_TINT using RB_LEVEL15
2
{
3
  static unsigned char i = 1;
4
  if (i <= rest_number)
5
  {  
6
  ASC0_TBUF = lcd_data[i];
7
    i++;
8
  }
9
  else
10
  {
11
    i = 1;
12
  }
13
}
Das Problem ist, das erste Byte ist immer falsch, ab dem zweiten ist 
alles OK.

Beispiel:
1
static unsigned char lcd_text1[] = {0xAA, 0x55, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xA2, 0xB6, 0xAF, 0xBB, 0xFA, 0xD7, 0xAA, 0xCB, 0xD9, 0xA3, 0xBA, 0xCC, 0x33, 0xC3, 0x3C};
2
3
unsigned char *lcd_data = &lcd_text1[0];
4
ASC0_vSendData_LCD(lcd_data, 22);
Aus der seriellen Schnittstelle wird folgendes abgelesen:

0x54, 0x55, 0x00, 0x00, 0x00, 0x00, 0xB7, 0xA2, 0xB6, 0xAF, 0xBB, 0xFA, 
0xD7, 0xAA, 0xCB, 0xD9, 0xA3, 0xBA, 0xCC, 0x33, 0xC3, 0x3C

Woran liegt das?

Cu
Senmeis

von Michael S. (schiko)


Lesenswert?

Owen Senmeis schrieb:
>
1
> void ASC0_vSendData_LCD(unsigned char *lcd_data, unsigned char
2
> lcd_number)
3
>   {
4
>   ASC0_vSendData(lcd_data[0]);
5
>   rest_number = lcd_number - 1;
6
>   }
7
>

willst Du nicht rest_number lieber schon setzen,
bevor Deine ASC0_vSendData_LCD von irgendeinem Interrupt
unterbrochen werden kann?

von Namenlos (Gast)


Lesenswert?

und ausserdem: Warum nicht gleich das erste
Byte aus dem Interupt senden?


Namenlos

von Owen S. (senmeis)


Lesenswert?

Sorry, ich habe vergessen, die Methode "ASC0_vSendData()" hier zu 
posten:
1
void ASC0_vSendData(uword uwData)
2
{
3
  ASC0_TBUF    = uwData;   //  load transmit buffer register
4
}

Ist es möglich, das erste Byte aus dem Interrupt zu senden? Eigentlich 
wird die Methode "ASC0_vSendData()" eingesetzt, um weitere Senden zu 
triggern. Die Methode wird aus dem Tool "Dave" generiert mit der 
Beschreibung:

This function writes a send data initialization word into the transmit 
buffer register.

Ich interessiere mich sehr für das erste Senden aus dem Interrupt.

Cu
Senmeis

von tom (Gast)


Lesenswert?

...entsprechendes interrupt request bit per sw setzen, und schon wird 
der tx-interrupt ausgelöst ;o).
vorher aber ggf. abtesten, ob der uart tx-seitig leer ist ;o).

gutt lack, tom.

von Sascha W. (sascha-w)


Lesenswert?

Owen Senmeis schrieb:
>
1
> void ASC0_vSendData(uword uwData)
2
> {
3
>   ASC0_TBUF    = uwData;   //  load transmit buffer register
4
> }
mach mal aus dem uword was sinnvolles mit 8-Bit!

Sascha

von Owen S. (senmeis)


Lesenswert?

Nun wird das erste Byte aus dem Interrupt gesendet. Das scheint 
funktioniert zu sein, aber ich verstehe den alten Fehler immer noch 
nicht.
1
void ASC0_vSendData_LCD(unsigned char *lcd_data, unsigned char lcd_number)
2
  {
3
  //ASC0_vSendData(lcd_data[0]);
4
  //rest_number = lcd_number - 1;
5
  ASC0_TIC_IR = 1;
6
  rest_number = lcd_number;
7
  }
8
9
void ASC0_viTx(void) interrupt ASC0_TINT using RB_LEVEL15
10
{
11
  //static unsigned char i = 1;
12
  static unsigned char i = 0;
13
  if (i < rest_number)
14
  {  
15
  ASC0_TBUF = lcd_data[i];
16
    i++;
17
  }
18
  else
19
  {
20
    //i = 1;
21
  i = 0;
22
  }
23
}
Cu
Senmeis

von Sascha W. (sascha-w)


Lesenswert?

siehe mein Post vom 27.02.

wenn du beim Aufruf deiner "ASC0_vSendData()" ein Byte übergibst und 
dieses der Word-Vaiable uwData zuweist, dann landet das Byte in den 
unteren 8-Bit.
Bei der Übergabe des 16-Bit-Werts an ASC0_TBUF das ja wieder nur 8-Bit 
breit ist kommen dort warscheinlich die oberen 8-Bit von uwData an. 
Dort müsstest du dan schon einen Typecast machen (ASC0_TBUF = 
(char)uwData;) oder uwData als char deklarieren.

Sascha

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.