Fehler bei 9. Datenbit "SerOut" und bei Assembler "out"

Mathias
Benutzer
Avatar
Gender: n/a
Location: Weingarten - Baden
Posts: 310
Registered: 07 / 2003
Subject:

Fehler bei 9. Datenbit "SerOut" und bei Assembler "out"

 · 
Posted: 17.02.2022 - 00:40  ·  #1
Compiler Rev. 5.09.51
Mega328P

Hallo,

es geht um ein ganz einfaches RS485 Protokoll.
Es sollen einfach ein paar Bytes nicht umgewandelt in Strings und ohne irgendeinen weiteren Zusatz wie "carriage return" usw. übertragen werden.
Also nur "nackte" Bytes.
Es ist eine Revision einer alten Baugruppe, es muß so gemacht werden.

Im Beispielcode wäre mir am Liebsten die Pascal Variante (pRS485_Pascal) mit "SerOut".
Im Simulator geht's.
Nur in echt geht's nicht. Es erscheint kein 9. Datenbit auf dem Oszi.
Im Notfall auch die Assembler Variante (pRS485_Assembler).

Hoffe es ist soweit alles Aufschlußreich zum Nachvollziehen.

Danke

Code

program RS485_Test_01;
{
Testprogrammcode wegen Fehlverhalten bei der Einstellung und nicht Übertragung des 9. Datenbits.
Datum: 16.02.2022
}

{$NOSHADOW}
{ $WG}                     {global Warnings off}

Device = mega328p, VCC=5;
{ $BOOTRST $03800}         {Reset Jump to $03800}

Define_Fuses
  Override_Fuses;
//  NoteBook   = A;
  COMport    = USB;
  SPIclk     = 2000000;
  LockBits0 = [];
  FuseBits0  = [CKSEL3, CKDIV8];
  FuseBits1  = [BOOTSZ0, BOOTSZ1];
  FuseBits2  = [BODLEVEL0, BODLEVEL1];
  ProgMode   = SPI;

Import SysTick, SerPort;

Define
  ProcClock      = 14745600;       {Hertz}
  SysTick        = 1;              {msec}
  StackSize      = 100, iData;
  FrameSize      = 100, iData;
  SerPort        = 76800, Stop1;    {Baud, StopBits|Parity}
  RxBuffer       = 10, iData;
  TxBuffer       = 10, iData;
  SerCtrl        = PortD, 2, positive; {control line for RS485 driver}

Implementation

{ Var Declarations }
{$IDATA}
var
  bMadress       : Byte;
  bX             : Byte;
  bZ             : Byte;
  CASE_loop      : byte;
  Timerloop      : SysTimer8;
//--------------------------------------------------------------;
//--------------------------------------------------------------;
{ functions }
procedure InitPorts;
begin
  PortD:= %0000 0000;
  DDRD:=  %0000 0100;    // 1=Ausgang, 0=Eingang
end InitPorts;
//--------------------------------------------------------------;
procedure InitVariablen;
begin
  bMadress:= 127;    // Masteradresse
  bX:= %1010 1010;
  bZ:= %0101 0101;
end InitVariablen;
//--------------------------------------------------------------;
Procedure pRS485_Pascal;
begin
  UCSR0B:= UCSR0B Or %0000 0101;     // umschalten auf Adressbyte für Master mit 9 Bits, 9. Datenbit auf high
  Ser_Enable (true);                 // RS Transceiver-IC auf senden schalten.
  SerOut (bMadress);
  Ser_Enable (false);                // RS Transceiver-IC auf empfangen schalten
  UCSR0B:= UCSR0B And %1111 1010;    // umschalten auf Datenbyte mit 8 Bits
  SerOut (bX);
  SerOut (bZ);
End pRS485_Pascal;
//--------------------------------------------------------------;
// https://www.mikrocontroller.net/articles/AVR_ASM_Befehls%C3%BCbersicht
// https://www.mikrocontroller.net/attachment/highlight/269

Procedure pRS485_Assembler;
begin
  UCSR0B:= UCSR0B Or %0000 0101;     // umschalten auf Adressbyte für Master mit 9 Bits, 9. Datenbit auf high
  Ser_Enable (true);                 // RS Transceiver-IC auf senden schalten.
  ASM;
    ldi r16, 127
    out UDR1, r16
  ENDASM;
  Ser_Enable (false);                // RS Transceiver-IC auf empfangen schalten
  UCSR0B:= UCSR0B And %1111 1010;    // umschalten auf Datenbyte mit 8 Bits
  SerOut (bX);
  SerOut (bZ);
End pRS485_Assembler;
//--------------------------------------------------------------;
//--------------------------------------------------------------;
{ Main Program }
{$IDATA}
begin
  CLKPR:=  %1000 0000;  // Clock Prescaler Change Enable.
  CLKPR:=  %0000 0000;  // Clock Prescale = 1.
  InitPorts;
  InitVariablen;
  EnableInts;
  loop
    Case CASE_loop Of
    0   : SetSysTimer(Timerloop, 100);
          CASE_loop:= 1;
        |
    1   : IF IsSysTimerZero(Timerloop) Then
            pRS485_Pascal;
//            pRS485_Assembler;
            CASE_loop:= 0;
          EndIF;
        |
    EndCase;
  endloop;
end RS485_Test_01.

golf
Benutzer
Avatar
Gender:
Location: Donauwörth
Age: 71
Posts: 256
Registered: 11 / 2009
Subject:

Re: Fehler bei 9. Datenbit "SerOut" und bei Assembler "out"

 · 
Posted: 17.02.2022 - 06:09  ·  #2
Fehlt da nicht das Register UCSR0C, bits UCSZ0[2..0] auf high für 9-bits ?
Merlin
Administrator
Avatar
Gender:
Age: 24
Posts: 1409
Registered: 03 / 2005
Subject:

Re: Fehler bei 9. Datenbit "SerOut" und bei Assembler "out"

 · 
Posted: 17.02.2022 - 11:08  ·  #3
Hi Mathias

Sometimes the obvious is invisible.

In this chip UDR1 is not in IO space, so you cannot use the OUT instruction. Instead you must use

Code
  ASM;
    ldi r16, 127
    sts UDR1, r16
  ENDASM;


Regards

Merlin

=====================================================

Manchmal ist das Offensichtliche unsichtbar.

Bei diesem Chip liegt UDR1 nicht im IO-Bereich, so dass Sie die OUT-Anweisung nicht verwenden können. Stattdessen müssen Sie verwenden

Code
ASM;
    ldi r16, 127
    sts UDR1, r16
  ENDASM;
Mathias
Benutzer
Avatar
Gender: n/a
Location: Weingarten - Baden
Posts: 310
Registered: 07 / 2003
Subject:

Re: Fehler bei 9. Datenbit "SerOut" und bei Assembler "out"

 · 
Posted: 19.02.2022 - 17:10  ·  #4
Danke an alle.
Scheint zu gehen.
Hoffe, daß ich das nie wieder anfassen muß.
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   80   94 · Page-Gen-Time: 0.022113s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI