Lazarus

Programming => Embedded => Operating Systems => Embedded - AVR => Topic started by: pascalbythree on September 26, 2022, 06:11:44 pm

Title: Does anybody have example code for UART for the ATMEGA16A ?
Post by: pascalbythree on September 26, 2022, 06:11:44 pm
I only get it to work for the ATMEGA328P

Does anybody have a example code for the serial port for ATMEGA16A ?

That will be  a great thanks, Groet, Wouter
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: d.ioannidis on September 26, 2022, 07:54:18 pm
Hi,

you could try this :

Code: Pascal  [Select][+][-]
  1. unit ufp_uartserial;
  2.  
  3. {
  4.  
  5.   UART AVR.
  6.  
  7.   Copyright (C) 2022 Dimitrios Chr. Ioannidis.
  8.     Nephelae - https://www.nephelae.eu
  9.  
  10.   https://www.nephelae.eu/
  11.  
  12.   Licensed under the MIT License (MIT).
  13.   See licence file in root directory.
  14.  
  15.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
  16.   ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  17.   TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  18.   PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
  19.   SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  20.   ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  21.   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.   OTHER DEALINGS IN THE SOFTWARE.
  24.  
  25. }
  26.  
  27. {$mode objfpc}
  28. {$modeswitch result-}
  29. {$modeswitch advancedrecords}
  30. {$longstrings off}
  31. {$writeableconst off}
  32. {$inline on}
  33. {$macro on}
  34.  
  35. {$if defined(fpc_mcu_atmega328p) }
  36.   {$DEFINE UART_UCSRA := UCSR0A }
  37.   {$DEFINE UART_UCSRB := UCSR0B }
  38.   {$DEFINE UART_UCSRC := UCSR0C }
  39.   {$DEFINE UART_UBRRL := UBRR0L }
  40.   {$DEFINE UART_UBRRH := UBRR0H }
  41.   {$DEFINE UART_UDR   := UDR0   }
  42.   {$DEFINE UART_UDRE  := UDRE0  }
  43.   {$DEFINE UART_TXEN  := TXEN0  }
  44.   {$DEFINE UART_RXEN  := RXEN0  }
  45.   {$DEFINE UART_RXC   := RXC0   }
  46.   {$DEFINE UART_U2X   := U2X0   }
  47. {$elseif defined(fpc_mcu_atmega16a) or defined(fpc_mcu_attiny2313)}
  48.   {$DEFINE UART_UCSRA := UCSRA }
  49.   {$DEFINE UART_UCSRB := UCSRB }
  50.   {$DEFINE UART_UCSRC := UCSRC }
  51.   {$DEFINE UART_UBRRL := UBRRL }
  52.   {$DEFINE UART_UBRRH := UBRRH }
  53.   {$DEFINE UART_UDR   := UDR   }
  54.   {$DEFINE UART_UDRE  := UDRE  }
  55.   {$DEFINE UART_TXEN  := TXEN  }
  56.   {$DEFINE UART_RXEN  := RXEN  }
  57.   {$DEFINE UART_RXC   := RXC   }
  58.   {$DEFINE UART_U2X   := U2X   }
  59. {$endif}
  60.  
  61.  
  62. interface
  63.  
  64. type
  65.  
  66.   { TUART }
  67.  
  68.   TUART = packed record
  69.   public
  70.     procedure Init(const ABaudRate: UInt32 = 57600);
  71.     function ReadChar: Char;
  72.     procedure WriteChar(const AChar: char);
  73.     procedure WriteStr(const s: ShortString = '');
  74.     procedure WriteStrLn(const s: ShortString = '');
  75.   end;
  76.  
  77. var
  78.   UART: TUART;
  79.  
  80. implementation
  81.  
  82. { TUART }
  83.  
  84. procedure TUART.Init(const ABaudRate: UInt32);
  85. var
  86.   Prescaler: UInt16;
  87. begin
  88.   //Prescaler := ((F_CPU div 4) div ABaudRate - 1) div 2;
  89.   Prescaler := F_CPU div 8 div ABaudRate - 1;
  90.  
  91.   UART_UBRRL  :=  Prescaler;
  92.   UART_UCSRA := (1 shl UART_U2X);
  93.   UART_UCSRB := (1 shl UART_TXEN) or (1 shl UART_RXEN);
  94.   UART_UCSRC := %10000110;
  95. end;
  96.  
  97. procedure TUART.WriteChar(const AChar: char); inline;
  98. begin
  99.   while ((UART_UCSRA and (1 shl UART_UDRE)) = 0) do ;
  100.   UART_UDR := byte(AChar);
  101. end;
  102.  
  103. function TUART.ReadChar: Char;
  104. begin
  105.   while ((UART_UCSRA and (1 shl UART_RXC)) = 0) do ;
  106.   ReadChar := Char(UART_UDR);
  107. end;
  108.  
  109. procedure TUART.WriteStr(const s: ShortString);
  110. var
  111.   i: integer;
  112. begin
  113.   if length(s) > 0 then
  114.   begin
  115.     for i := 1 to length(s) do
  116.        WriteChar(s[i]);
  117.   end;
  118. end;
  119.  
  120. procedure TUART.WriteStrLn(const s: ShortString);
  121. begin
  122.   WriteStr(s);
  123.   WriteStr(#13#10);
  124. end;
  125.  
  126. end.

I quickly added the ifdef's didn't test it with a physical mcu .

Forgot to add that its hardcoded 8bit, no parity and 1 stop bit . Also there is a global variable UART so you just add the unit to the uses clause.

Code: Pascal  [Select][+][-]
  1. program fp_uart_test;
  2.  
  3. {$mode objfpc}
  4. {$writeableconst off}
  5. {$longstrings off}
  6.  
  7. uses
  8.   ufp_uartserial;
  9.  
  10. const
  11.   BannerTopStr: string[27] = #13#10'-------------------------';
  12.   BannerStr: string[17] = 'Free Pascal Rocks';
  13.  
  14. begin
  15.   UART.Init(9600);
  16.  
  17.   UART.WriteStrLn(BannerTopStr);
  18.   UART.WriteStrLn(BannerStr);
  19.  
  20. end.

If it doesn't work I have a DIP atmega16a I could try in a breadboard .... ;)

EDIT: Added sample project ....

EDIT2: Added attiny2313 ;)

regards,
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: d.ioannidis on September 26, 2022, 11:47:05 pm
Hi,

  also forgot to mention, the fpc_mcu_* define ( fpc_mcu_atmega328p, fpc_mcu_attiny861 etc ) is generated by the compiler with the Wp target-specific option, so don't try to define it your self.

regards,
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: pascalbythree on September 27, 2022, 03:09:44 pm
Does not seem to work on my NT4 machine and PUTTY on it. Anybody got more example code for the UART on the ATMEGA16A?

PS: I just bought 5 pcs of Attiny2313 on a dutch webshop

When they arrive i maybe also need some extra help getting this attiny and his UART to run.

Example program from fpc-avr

Code: Pascal  [Select][+][-]
  1. program uart1;
  2.  
  3. uses uart, delay{, integermath};
  4.  
  5. const
  6.   baud = 115200;
  7.   // UseU2X = true
  8.   ub = (((F_CPU + 4*BAUD) shr 3) div BAUD) - 1;
  9.   PB5 = 1 shl 5;
  10.  
  11. var
  12.   c: byte;
  13.   pinport: byte absolute PORTB;
  14.   pindir: byte absolute DDRB;
  15.  
  16. begin
  17.   uart_init1(BAUD, false);
  18.   //uart_init(ub);
  19.   pindir := PB5;
  20.  
  21.   repeat
  22.     c := uart_receive();    // blocking
  23.     pinport := pinport XOR PB5; // toggle LED
  24.     uart_transmit(ord('#'));
  25.  
  26.     uart_transmit(c);
  27.     uart_transmit(13);
  28.   until false;
  29. end.
  30.  

default unit from FPC-AVR
Code: Pascal  [Select][+][-]
  1. unit uart;
  2.  
  3. interface
  4. // Automatically use U2X
  5. procedure uart_init(const UBRR: word);
  6.  
  7. procedure uart_init1(const BAUD: dword; const useU2X: boolean = false);
  8.  
  9. // Blocking functions
  10. procedure uart_transmit(const data: byte); overload;
  11. procedure uart_transmit_hex(const data: byte); overload;
  12. procedure uart_transmit_hex(const data: word); overload;
  13. procedure uart_transmit_hex(const data: dword); overload;
  14. procedure uart_transmit(const s: shortstring); overload;
  15.  
  16. procedure uart_transmit_asstring(b: byte); overload;
  17. procedure uart_transmit_asstring(b: int8); overload;
  18. procedure uart_transmit_asstring(b: word); overload;
  19. procedure uart_transmit_asstring(b: int16); overload;
  20. procedure uart_transmit_asstring(b: dword); overload;
  21. procedure uart_transmit_asstring(b: int32); overload;
  22.  
  23. function uart_receive: byte;
  24. function uart_peek(out c: byte): boolean;
  25.  
  26. implementation
  27.  
  28. uses
  29.   simplemath;
  30.  
  31. {$ifdef CPUAVRXMEGA3}
  32. procedure uart_init(const UBRR: word);
  33. begin
  34.   // RX
  35.   PORTB.DIRCLR := PIN1bm;
  36.   // TX
  37.   PORTB.OUTSET := Pin0bm;
  38.   PORTB.DIRSET := Pin0bm;
  39.  
  40.   USART3.BAUD := UBRR;
  41.   //USART3.CTRLA := TUSART.RXCIEbm;  // RX is interrupt driven
  42.   USART3.CTRLB := TUSART.RXENbm or TUSART.TXENbm;
  43. end;
  44.  
  45. procedure uart_init1(const BAUD: dword; const useU2X: boolean = false);
  46. var
  47.   ubrr: word;
  48. begin
  49.   // RX
  50.   PORTB.DIRCLR := PIN1bm;
  51.   // TX
  52.   PORTB.OUTSET := Pin0bm;
  53.   PORTB.DIRSET := Pin0bm;
  54.  
  55.   if useU2X then
  56.     ubrr := (F_CPU * 64 + 4 * BAUD) div (8 * BAUD)
  57.   else
  58.     //ubrr := (F_CPU * 64 + 8 * BAUD) div (16 * BAUD);
  59.     ubrr := (F_CPU * 8 + BAUD) div (2 * BAUD);
  60.  
  61.   USART3.BAUD := ubrr;
  62.   USART3.CTRLB := TUSART.RXENbm or TUSART.TXENbm;
  63. end;
  64.  
  65. // Blocking functions
  66. procedure uart_transmit(const data: byte);
  67. begin
  68.   repeat
  69.   until (USART3.STATUS and TUSART.DREIFbm = TUSART.DREIFbm);
  70.   USART3.TXDATAL := data;
  71. end;
  72.  
  73. function uart_receive(): byte;
  74. begin
  75.   repeat
  76.   until (USART3.STATUS and TUSART.RXCIFbm = TUSART.RXCIFbm);
  77.   result := USART3.RXDATAL;
  78. end;
  79.  
  80. function uart_peek(c: byte): byte;
  81. begin
  82.   result := (USART3.STATUS and TUSART.RXCIFbm) = TUSART.RXCIFbm;
  83.   c := USART3.RXDATAL;
  84. end;
  85.  
  86. {$else}
  87. procedure uart_init1(const BAUD: dword; const useU2X: boolean = false);
  88. var
  89.   ubrr: word;
  90. begin
  91.   if useU2X then
  92.     ubrr := ((F_CPU + 4*BAUD) shr 3) div BAUD
  93.   else
  94.     ubrr := ((F_CPU + 8*BAUD) shr 4) div BAUD;
  95.  
  96.   UBRR0 := ubrr-1;
  97.  
  98.   // Set U2X as specified
  99.   UCSR0A := UCSR0A or (byte(useU2X) shl U2X0);
  100.  
  101.   // Enable receiver and transmitter
  102.   UCSR0B := (1 shl RXEN0) or (1 shl TXEN0);
  103.  
  104.   // Set frame format: 8data, 1stop bit, no parity
  105.   UCSR0C := (3 shl UCSZ0);
  106. end;
  107.  
  108. procedure uart_init(const UBRR: word);
  109. begin
  110.   UBRR0H := UBRR shr 8;
  111.   UBRR0L := byte(UBRR);
  112.  
  113.   // Set U2X bit
  114.   UCSR0A := UCSR0A or (1 shl U2X0);
  115.  
  116.   // Enable receiver and transmitter
  117.   UCSR0B := (1 shl RXEN0) or (1 shl TXEN0);
  118.  
  119.   // Set frame format: 8data, 1stop bit, no parity
  120.   UCSR0C := (3 shl UCSZ0);
  121. end;
  122.  
  123. procedure uart_transmit(const data: byte);
  124. begin
  125.   // Wait for empty transmit buffer
  126.   while ((UCSR0A and (1 shl UDRE0)) = 0) do;
  127.  
  128.   // Put data into buffer, sends the data
  129.   UDR0 := data;
  130. end;
  131.  
  132. function uart_receive: byte;
  133. begin
  134.   // Wait for data to be received
  135.   while ((UCSR0A and (1 shl RXC0)) = 0) do;
  136.  
  137.   // Get and return received data from buffer
  138.   result := UDR0;
  139. end;
  140.  
  141. function uart_peek(out c: byte): boolean;
  142. begin
  143.   result := UCSR0A and (1 shl RXC0) > 0;
  144.   c := UDR0;
  145. end;
  146.  
  147. {$endif CPUAVRXMEGA3}
  148.  
  149. procedure uart_transmit_hex(const data: byte);
  150. var
  151.   n, d: byte; // nibbles 1&2
  152. begin
  153.   n := data shr 4;
  154.   if n < 10 then
  155.     d := $30 + n
  156.   else
  157.     d := ord('A') + (n - 10);
  158.   uart_transmit(d);
  159.  
  160.   n := data and $0F;
  161.   if n < 10 then
  162.     d := $30 + n
  163.   else
  164.     d := ord('A') + (n - 10);
  165.   uart_transmit(d);
  166. end;
  167.  
  168. procedure uart_transmit_hex(const data: word);
  169. begin
  170.   uart_transmit_hex(hi(data));
  171.   uart_transmit_hex(lo(data));
  172. end;
  173.  
  174. procedure uart_transmit_hex(const data: dword);
  175. begin
  176.   uart_transmit_hex(hi(data));
  177.   uart_transmit_hex(lo(data));
  178. end;
  179.  
  180. procedure uart_transmit(const s: shortstring);
  181. var
  182.   i: byte;
  183. begin
  184.   for i := 1 to length(s) do
  185.     uart_transmit(ord(s[i]));
  186. end;
  187.  
  188. procedure uart_transmit_asstring(b: byte);
  189. var
  190.   d, temp: byte;
  191.   skipLeadingZero: boolean;
  192. begin
  193.   if b = 0 then
  194.     uart_transmit(ord('0'))
  195.   else
  196.   begin
  197.     skipLeadingZero := true;
  198.     d := 2;  // 100 = 10^2
  199.     repeat
  200.       temp := b;
  201.       decimalDivMod(temp, b, d);
  202.       if not skipLeadingZero or (temp > 0) then
  203.       begin
  204.         skipLeadingZero := false;
  205.         uart_transmit(temp + ord('0'));
  206.       end;
  207.       dec(d);
  208.       if d = 0 then
  209.         uart_transmit(b + ord('0'));
  210.     until d = 0;
  211.   end;
  212. end;
  213.  
  214. procedure uart_transmit_asstring(b: int8);
  215. begin
  216.   if b < 0 then
  217.   begin
  218.     b := -b;
  219.     uart_transmit(ord('-'));
  220.   end;
  221.   uart_transmit_asstring(byte(b));
  222. end;
  223.  
  224. procedure uart_transmit_asstring(b: word);
  225. var
  226.   d, temp: word;
  227.   skipLeadingZero: boolean;
  228. begin
  229.   if b = 0 then
  230.     uart_transmit(ord('0'))
  231.   else
  232.   begin
  233.     skipLeadingZero := true;
  234.     d := 4;  // 10000 = 10^4
  235.     repeat
  236.       temp := b;
  237.       decimalDivMod(temp, b, d);
  238.       if not skipLeadingZero or (temp > 0) then
  239.       begin
  240.         skipLeadingZero := false;
  241.         uart_transmit(temp + ord('0'));
  242.       end;
  243.       dec(d);
  244.       if d = 0 then
  245.         uart_transmit(b + ord('0'));
  246.     until d = 0;
  247.   end;
  248. end;
  249.  
  250. procedure uart_transmit_asstring(b: int16);
  251. begin
  252.   if b < 0 then
  253.   begin
  254.     b := -b;
  255.     uart_transmit(ord('-'));
  256.   end;
  257.   uart_transmit_asstring(word(b));
  258. end;
  259.  
  260. procedure uart_transmit_asstring(b: dword);
  261. var
  262.   d, temp: dword;
  263.   skipLeadingZero: boolean;
  264. begin
  265.   if b = 0 then
  266.     uart_transmit(ord('0'))
  267.   else
  268.   begin
  269.     skipLeadingZero := true;
  270.     d := 10;
  271.     repeat
  272.       temp := b;
  273.       decimalDivMod(temp, b, d);
  274.       if not skipLeadingZero or (temp > 0) then
  275.       begin
  276.         skipLeadingZero := false;
  277.         uart_transmit(byte(temp) + ord('0'));
  278.       end;
  279.       dec(d);
  280.       if d = 0 then
  281.         uart_transmit(byte(b) + ord('0'));
  282.     until d = 0;
  283.   end;
  284. end;
  285.  
  286. procedure uart_transmit_asstring(b: int32);
  287. begin
  288.   if b < 0 then
  289.   begin
  290.     b := -b;
  291.     uart_transmit(ord('-'));
  292.   end;
  293.   uart_transmit_asstring(dword(b));
  294. end;
  295.  
  296. end.
  297.  

Anybody know what to change to get it to run on the ATMEGA16A instead of atmega328p ?

That you for your time in advance and greets, Wouter !
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: d.ioannidis on September 27, 2022, 04:41:01 pm
Hi,

Does not seem to work on my NT4 machine and PUTTY on it. Anybody got more example code for the UART on the ATMEGA16A?
<snip>

Just tested it on a breadboard with a breakout atmega16 board and it works .
( The atmega16 I have wasn't DIP but that's ok ).

Are macros enabled ( -Sm ) ?
Is the F_CPU define present and correct ? ( If your mcu runs at 8MHz you need to use -dF_CPU:=8000000 )

Here is a copy of my Lazarus custom options :

Code: Pascal  [Select][+][-]
  1. -a
  2. -al
  3. -Xe
  4. -Xm
  5. -Sm
  6. -WpATMEGA16A
  7. -CpAVR5
  8. -dF_CPU:=1000000

Notice that the mcu I tested runs at 1MHz with the internal osc.

regards,
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: d.ioannidis on September 27, 2022, 05:24:20 pm

< snip >

Anybody know what to change to get it to run on the ATMEGA16A instead of atmega328p ?

If you look in my first post, the main difference between atmega328p and atmega16a, is that the UART registers in atmega328p have a zero 0 in their name .

Code: Pascal  [Select][+][-]
  1. {$if defined(fpc_mcu_atmega328p) }
  2.   {$DEFINE UART_UCSRA := UCSR0A }
  3. ......
  4. {$elseif defined (fpc_mcu_atmega16a) }
  5.   {$DEFINE UART_UCSRA := UCSRA }
  6. ......
  7.  

Look at the ifdef in my code and substitute the atmega328p register names with the atmega16a register names in the code you posted. It should work.

regards,
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: d.ioannidis on September 28, 2022, 10:28:21 pm
Hi,

PS: I just bought 5 pcs of Attiny2313 on a dutch webshop

When they arrive i maybe also need some extra help getting this attiny and his UART to run.
< snip >

in my first post, I edit the code to support also attiny2313 ( added a define and switched the Prescaler calculation to use less memory ;)  ) .

Tested with a physical mcu  ....

regards,
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: pascalbythree on August 06, 2023, 07:16:47 pm
Thank you very much, Can not get it to work yet, anybody got another version? For the ATTINY2313 ?
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: ccrause on August 07, 2023, 07:48:27 am
Can not get it to work yet
This description isn't much help for troubleshooting.

Does your code compile? Show your code and compiler parameters.
Did you check clock speed with something simple like a blinking LED?
Do you receive anything over serial, even if it is garbage?
Did you capture the signal on the transmitting line with an oscilloscope or logic analyzer?
Are the connections between controller and serial converter correct (TX of controller to Rx on serial converter)? Show photo of wiring so that we can verify the pin to pin connections.
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: d.ioannidis on August 09, 2023, 08:15:01 am
Hi,

< snip > Can not get it to work yet, < snip >

I can't test it right now, but as @ccrause wrote, can you please share more information ?

regards,
Title: Correct values to UART on your ATtiny841
Post by: pascalbythree on November 27, 2023, 12:19:47 pm
in:

Code: Pascal  [Select][+][-]
  1.  unit ufp_uartserial;

Code: Pascal  [Select][+][-]
  1.     {$if defined(fpc_mcu_attiny841)}
  2.       {$DEFINE UART_UCSRA := UCSR0A }
  3.       {$DEFINE UART_UCSRB := UCSR0B }
  4.       {$DEFINE UART_UCSRC := UCSR0C }
  5.       {$DEFINE UART_UBRRL := UBRR0L }
  6.       {$DEFINE UART_UBRRH := UBRR0H }
  7.       {$DEFINE UART_UDR   := UDR0   }
  8.       {$DEFINE UART_UDRE  := UDR0  }
  9.       {$DEFINE UART_TXEN  := TXEN0  }
  10.       {$DEFINE UART_RXEN  := RXEN0  }
  11.       {$DEFINE UART_RXC   := RXC0   }
  12.       {$DEFINE UART_U2X   := U2X0   }
  13.     {$endif}

Can somebody check if these are the right addresses to use the ufp_uartserial unit.

PS: Case to got it to run on the default FPC-AVR uart.pas, that will also be fine.

To UART on your ATtiny841

Thanks Again, Greets, Wouter van Wegen, Pascal ByThree


Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: Hartmut on November 28, 2023, 08:59:08 am
Hello pascalbythree, you started your post asking for ATmega16A, then switched to Attiny2313 and ATtiny841. I have working UART code for ATmega16A (with comments in German) and a link to a ATmega16A-Datasheet (PDF with 335 pages in Englisch). Are you still interested?
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: pascalbythree on November 28, 2023, 10:05:16 am
Still interested!

But the attiny841 is more important at this moment. Otherwise i can not continue.
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: Hartmut on November 28, 2023, 11:10:00 am
Ok, here comes my UART-Unit for the ATmega16A. The link to the mentioned Datasheet is https://ww1.microchip.com/downloads/en/devicedoc/atmel-8154-8-bit-avr-atmega16a_datasheet.pdf

About attiny841 I have no knowledge so I can't help you there.

Code: Pascal  [Select][+][-]
  1. unit uart; {UART-Routinen für ATmega16A}
  2.  
  3. {$mode objfpc}
  4.  
  5. {$O-} {erstmal nur zur Sicherheit: Optimizer aus}
  6. {$H-} {keine Ansistrings}
  7. {$R-} {RangeChecks = KZP -Cr}
  8. {$Q-} {OverflowChecks = KZP -Co}
  9. {$S-} {StackOverflow = KZP -Ct = macht ca. 1800d Bytes Unterschied}
  10.  
  11. {********************************} interface {*********************************}
  12.  
  13. type bool = boolean;
  14.      s255 = string[255];
  15.  
  16. {============================ Allgemeiner V24-Kram: ===========================}
  17.  
  18. {$IFDEF FPC_MCU_ATMEGA16}  {wenn CPU = ATMega16: }
  19.  
  20. const UART_RXerrBits: byte = 0; {merkt evtl. Error-Bits aus UART_checkChar():
  21.                                  Bit 2: Frame Error;
  22.                                  Bit 1: Data Overrun;
  23.                                  Bit 0: Parity Error;
  24.                                  Wird in UART_checkChar() gesetzt bzw. geleert}
  25.  
  26. procedure UART_init(baudDiv: word);            {init: }
  27.  
  28. function UART_checkChar(out c: char): bool;    {get: }
  29. function UART_readChar: char;
  30.  
  31. function UART_tryTX(c: char): bool;            {put: }
  32. procedure UART_sendChar(c: char);
  33. procedure UART_sendByte(b: byte);
  34. procedure UART_sendString(s: s255);
  35.  
  36. procedure UART_terminal1;                      {Terminal}
  37. {$ENDIF}
  38.  
  39. {*****************************} implementation {*******************************}
  40.  
  41. {============================ Allgemeiner V24-Kram: ===========================}
  42.  
  43. {$IFDEF FPC_MCU_ATMEGA16} {wenn CPU = ATMega16: }
  44.  
  45. {Port D, Bit 1 = TxD (USART Output)
  46.  Port D, Bit 0 = RxD (USART Input)
  47.  
  48.  Quelle: https://wiki.freepascal.org/AVR_Embedded_Tutorial_-_Entry_Lazarus_and_Arduino#Serial_input.2Foutput
  49.  Doku zum USART: "16_atmel-avr-atmega16a_datasheet.pdf"
  50.   - S.158..162 = USART Register Description}
  51.  
  52.                                      {alle verwendeten Ports: }
  53. var UART_BaudH: byte absolute UBRRH; {Baudraten-Register-High (4 Bits)}
  54.     UART_BaudL: byte absolute UBRRL; {Baudraten-Register-Low}
  55.     UART_A:     byte absolute UCSRA; {USART Control and Status Register A}
  56.     UART_B:     byte absolute UCSRB; {USART Control and Status Register B}
  57.     UART_C:     byte absolute UCSRC; {USART Control and Status Register C}
  58.     UART_Data:  byte absolute UDR;   {USART I/O Data Register}
  59.  
  60.     {für diverse Bits werden folgende const benutzt:
  61.       - RXEN  = 4; // Receiver Enable
  62.       - TXEN  = 3; // Transmitter Enable
  63.       - URSEL = 7; // USART Register Select
  64.       - RXC   = 7; // USART Receive Complete
  65.       - UDRE  = 5; // USART Data Register Empty
  66.       - UPE   = 2; // Parity Error (maskiert 3 Error-Bits)}
  67.  
  68. procedure UART_init(baudDiv: word);
  69.    {initialisiert die V24 mit 8 Bits, Even parity, 1 Stop Bits;
  70.     I: baudDiv: Formel = CPU_Clock div(16 * BaudRate) - 1;
  71.     ex O: UART_RXerrBits;
  72.     Wurde für den ATMega16 entwickelt und bisher nur dort getestet!}
  73.    begin
  74.    UART_BaudH:=hi(baudDiv); {zuerst: set Baudrate-High und set Bit 'URSEL=0'}
  75.    UART_BaudL:=lo(baudDiv); {danach: set Baudrate-Low = start Prescaler}
  76.  
  77.    UART_A:=0; {Bit7=0: read only bit;
  78.                   6=0: nothing to do (USART Transmit Complete);
  79.                   5=0: read only bit;
  80.                   4=0: read only bit;
  81.                   3=0: read only bit;
  82.                   2=0: read only bit;
  83.                   1=0: synchronous mode => use 0 /
  84.                        asynchronous mode: 1=verdoppelt die Baudrate;
  85.                   0=0: kein Multi-processor Communication Mode}
  86.  
  87.    UART_B:=(1 shl RXEN) or (1 shl TXEN);
  88.               {Bit7=0: disable RX Complete Interrupt;
  89.                   6=0: disable TX Complete Interrupt;
  90.                   5=0: disable USART Data Register Empty Interrupt;
  91.                   4=1: RXEN=enables the USART Receiver;
  92.                   3=1: TXEN=enables the USART Transmitter;
  93.                   2=0: wählt 5..8 Daten-Bits / 1=wählt 9 Datenbits;
  94.                   1=0: read only bit;
  95.                   0=0: setzt das 9. Bit im 9-Bit Datenbetrieb}
  96.  
  97.    UART_C:=(1 shl URSEL) or $20 or $06;
  98.               {Bit7=1: URSEL=enables Register 'UART_C' statt 'UART_BaudH';
  99.                   6=0: wählt Asynchronous Mode (erlaubt Pausen zw. den Bytes);
  100.                   5+4=10: wählt Even Parity/ 00=None / 11=Odd;
  101.                   3=0: wählt 1 Stop-Bit / 1=wählt 2 Stop-Bits;
  102.                   2+1=11: wählt 8 Daten-Bits / 10=7 Daten-Bits;
  103.                   0=0: clock polarity in synchronous mode}
  104.  
  105.    UART_RXerrBits:=0; {reset Error-Bits für UART_checkChar()}
  106.    end; {UART_init}
  107.  
  108. function UART_checkChar(out c: char): bool;
  109.    {liefert nur dann ein empfangenes char, falls eins da ist; Falls ja, werden
  110.     evtl. RX-Errors in 'UART_RXerrBits' gemerkt}
  111.    begin
  112.    c:=#0;
  113.    if UART_A and (1 shl RXC) = 0 then exit(false); {wenn nix da}
  114.  
  115.    UART_RXerrBits:=(UART_A shr UPE) and $07; {lese evtl. RX-Errors}
  116.    c:=char(UART_Data); {das Lesen hier löscht die 3 Error-Bits}
  117.    exit(true);
  118.    end;
  119.  
  120. function UART_readChar: char;
  121.    {wartet bis 1 char empfangen wurde; Evtl. RX-Errors werden in
  122.     'UART_RXerrBits' gemerkt}
  123.    var c: char;
  124.    begin
  125.    while not UART_checkChar(c) do  begin end; {warte bis was da ist}
  126.    exit(c);
  127.    end;
  128.  
  129. function UART_tryTX(c: char): bool;
  130.    {versucht char 'c' zu senden, falls der TX-Buffer frei ist}
  131.    begin
  132.    if UART_A and (1 shl UDRE) = 0 then exit(false); {wenn TX-Buffer belegt ist}
  133.  
  134.    UART_Data:=byte(c);
  135.    exit(true);
  136.    end;
  137.  
  138. procedure UART_sendChar(c: char);
  139.    {sendet char 'c' und wartet vorher, bis der TX-Buffer frei ist}
  140.    begin
  141.    while not UART_tryTX(c) do  begin end; {warte bis TX-Buffer auch frei war}
  142.    end;
  143.  
  144. procedure UART_sendByte(b: byte);
  145.    {sendet Byte 'b' und wartet vorher, bis der TX-Buffer frei ist}
  146.    begin
  147.    UART_sendChar(char(b));
  148.    end;
  149.  
  150. procedure UART_sendString(s: s255);
  151.    var i: byte;
  152.    begin
  153.    for i:=1 to length(s) do  UART_sendChar(s[i]);
  154.    end;
  155.  
  156. procedure UART_terminal1;
  157.    {wartet auf empfangene Bytes und sendet diese zurück}
  158.    const BaudR     = 2400;    {wanted Baudrate}
  159.          CPU_Clock = 1000000; {Default CPU clock frequency = 1 MHz}
  160.          BaudDiv   = CPU_Clock div(16 * BaudR) - 1; {Teiler für die Baudrate}
  161.    var c: char;
  162.        ok: bool;
  163.    begin
  164.    UART_init(BaudDiv); {initialisiert die V24}
  165.    repeat ok:=UART_checkChar(c);
  166.           if ok then UART_sendChar(c);
  167.    until false;
  168.    end; {UART_terminal1}
  169.  
  170. {$ENDIF FPC_MCU_ATMEGA16}
  171.  
  172. {****************************** Initialisierung *******************************}
  173.  
  174. end.
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: pascalbythree on November 28, 2023, 01:05:31 pm
Like this ? :
Code: Pascal  [Select][+][-]
  1.  
  2. {$elseif defined(fpc_mcu_atmega16a) or defined(fpc_mcu_attiny841)}
  3. {$DEFINE UART_UCSRA := 0x86}
  4. {$DEFINE UART_UCSRB := 0x85 }
  5. {$DEFINE UART_UCSRC := 0x84 }
  6. {$DEFINE UART_UBRRL := 0x81 }
  7. {$DEFINE UART_UBRRH := 0x82 }
  8. {$DEFINE UART_UDR := 0x80}
  9. {$DEFINE UART_UDRE := UDRE }
  10. {$DEFINE UART_TXEN := TXEN }
  11. {$DEFINE UART_RXEN := RXEN }
  12. {$DEFINE UART_RXC := RXC }
  13. {$DEFINE UART_U2X := U2X }
  14. {$endif}
  15.  

Afther UART.Init(19200); the main program loop does not make my status LED blink.


Are there still wrong values ? Greets, Wouter

Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: Hartmut on November 28, 2023, 03:44:50 pm
...
{$DEFINE UART_UCSRA := 0x86}
{$DEFINE UART_UCSRB := 0x85 }
{$DEFINE UART_UCSRC := 0x84 }
{$DEFINE UART_UBRRL := 0x81 }
{$DEFINE UART_UBRRH := 0x82 }
{$DEFINE UART_UDR := 0x80}
...

Some remarks to this:
1) I'm not sure whether "0x86" etc. works correctly. On my system it's not allowed. I would use "$86" instead.

2) FPC has already a file which contains those constants which you IMHO should use:
Code: Pascal  [Select][+][-]
  1. ...
  2. // USART
  3. var
  4.   UDR : byte absolute $00+$2C; // USART I/O Data Register
  5.   UCSRA : byte absolute $00+$2B; // USART Control and Status Register A
  6.   UCSRB : byte absolute $00+$2A; // USART Control and Status Register B
  7.   UCSRC : byte absolute $00+$40; // USART Control and Status Register C
  8.   UBRRH : byte absolute $00+$40; // USART Baud Rate Register Hight Byte
  9.   UBRRL : byte absolute $00+$29; // USART Baud Rate Register Low Byte
  10. ...
On my system this file is located in <installdir>/fpcsrc/rtl/embedded/avr/atmega16.pp and is automaticly included, when you have correctly selected ATMega16A CPU.

3) You see, that your values do not correspond with above file atmega16.pp. A difference of $20 may be correct, depending on how you adress these ports:
Quote
When using the I/O specific commands IN and OUT, the I/O addresses $00 - $3F must be used. When addressing I/O Registers as data space using LD and ST instructions, $20 must be added to these addresses => use $20 - $5F.
From page 19 of my Link in reply #13.
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: pascalbythree on November 28, 2023, 04:54:39 pm
I am afraid something got confused...

I need the values for the ATtiny841

to many problems with the list of values from here.

Using ufp_uartserial.pas

Anybody crazy enough to send me up the complete list ? to compile at once ?

Because i am confused.
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: Hartmut on November 28, 2023, 05:27:35 pm
On my different Lazarus-Installations I found only 1 file for ATtiny841: <installdir>/fpcsrc/rtl/embedded/avr/attiny841.pp
It is from Lazarus ver=2.1.0 rev=64456 / FPC ver=3.3.1 rev=48497
It contains e.g.:

Code: Pascal  [Select][+][-]
  1. ...
  2. var
  3.   UDR0: byte absolute $80;  // USART I/O Data Register
  4.   UBRR0: word absolute $81;  // USART Baud Rate Register Bytes
  5.   UBRR0L: byte absolute $81;  // USART Baud Rate Register Bytes
  6.   UBRR0H: byte absolute $82;  // USART Baud Rate Register Bytes;
  7.   UCSR0D: byte absolute $83;  // USART Control and Status Register D
  8.   UCSR0C: byte absolute $84;  // USART Control and Status Register C
  9.   UCSR0B: byte absolute $85;  // USART Control and Status Register B
  10.   UCSR0A: byte absolute $86;  // USART Control and Status Register A
  11. ...
  12.  
I attached this file. HTH.
Title: Re: Does anybody have example code for UART for the ATMEGA16A ?
Post by: pascalbythree on November 28, 2023, 06:01:21 pm
Yay!

It got to work! thank you for your time...
TinyPortal © 2005-2018