Forum > Embedded - AVR

Does anybody have example code for UART for the ATMEGA16A ?

(1/4) > >>

pascalbythree:
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

d.ioannidis:
Hi,

you could try this :


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit ufp_uartserial; {   UART AVR.   Copyright (C) 2022 Dimitrios Chr. Ioannidis.    Nephelae - https://www.nephelae.eu   https://www.nephelae.eu/   Licensed under the MIT License (MIT).  See licence file in root directory.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF  ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED  TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A  PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT  SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR  OTHER DEALINGS IN THE SOFTWARE. } {$mode objfpc}{$modeswitch result-}{$modeswitch advancedrecords}{$longstrings off}{$writeableconst off}{$inline on}{$macro on} {$if defined(fpc_mcu_atmega328p) }  {$DEFINE UART_UCSRA := UCSR0A }  {$DEFINE UART_UCSRB := UCSR0B }  {$DEFINE UART_UCSRC := UCSR0C }  {$DEFINE UART_UBRRL := UBRR0L }  {$DEFINE UART_UBRRH := UBRR0H }  {$DEFINE UART_UDR   := UDR0   }  {$DEFINE UART_UDRE  := UDRE0  }  {$DEFINE UART_TXEN  := TXEN0  }  {$DEFINE UART_RXEN  := RXEN0  }  {$DEFINE UART_RXC   := RXC0   }  {$DEFINE UART_U2X   := U2X0   }{$elseif defined(fpc_mcu_atmega16a) or defined(fpc_mcu_attiny2313)}  {$DEFINE UART_UCSRA := UCSRA }  {$DEFINE UART_UCSRB := UCSRB }  {$DEFINE UART_UCSRC := UCSRC }  {$DEFINE UART_UBRRL := UBRRL }  {$DEFINE UART_UBRRH := UBRRH }  {$DEFINE UART_UDR   := UDR   }  {$DEFINE UART_UDRE  := UDRE  }  {$DEFINE UART_TXEN  := TXEN  }  {$DEFINE UART_RXEN  := RXEN  }  {$DEFINE UART_RXC   := RXC   }  {$DEFINE UART_U2X   := U2X   }{$endif}  interface type   { TUART }   TUART = packed record  public    procedure Init(const ABaudRate: UInt32 = 57600);    function ReadChar: Char;    procedure WriteChar(const AChar: char);    procedure WriteStr(const s: ShortString = '');    procedure WriteStrLn(const s: ShortString = '');  end; var  UART: TUART; implementation { TUART } procedure TUART.Init(const ABaudRate: UInt32);var  Prescaler: UInt16;begin  //Prescaler := ((F_CPU div 4) div ABaudRate - 1) div 2;  Prescaler := F_CPU div 8 div ABaudRate - 1;   UART_UBRRL  :=  Prescaler;  UART_UCSRA := (1 shl UART_U2X);  UART_UCSRB := (1 shl UART_TXEN) or (1 shl UART_RXEN);  UART_UCSRC := %10000110;end; procedure TUART.WriteChar(const AChar: char); inline;begin  while ((UART_UCSRA and (1 shl UART_UDRE)) = 0) do ;  UART_UDR := byte(AChar);end; function TUART.ReadChar: Char;begin  while ((UART_UCSRA and (1 shl UART_RXC)) = 0) do ;  ReadChar := Char(UART_UDR);end; procedure TUART.WriteStr(const s: ShortString);var  i: integer;begin  if length(s) > 0 then  begin    for i := 1 to length(s) do       WriteChar(s[i]);  end;end; procedure TUART.WriteStrLn(const s: ShortString);begin  WriteStr(s);  WriteStr(#13#10);end; 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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program fp_uart_test; {$mode objfpc}{$writeableconst off}{$longstrings off} uses  ufp_uartserial; const  BannerTopStr: string[27] = #13#10'-------------------------';  BannerStr: string[17] = 'Free Pascal Rocks'; begin  UART.Init(9600);   UART.WriteStrLn(BannerTopStr);  UART.WriteStrLn(BannerStr); 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,

d.ioannidis:
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,

pascalbythree:
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program uart1; uses uart, delay{, integermath}; const  baud = 115200;  // UseU2X = true  ub = (((F_CPU + 4*BAUD) shr 3) div BAUD) - 1;  PB5 = 1 shl 5; var  c: byte;  pinport: byte absolute PORTB;  pindir: byte absolute DDRB; begin  uart_init1(BAUD, false);  //uart_init(ub);  pindir := PB5;   repeat    c := uart_receive();    // blocking    pinport := pinport XOR PB5; // toggle LED    uart_transmit(ord('#'));     uart_transmit(c);    uart_transmit(13);  until false;end. 
default unit from FPC-AVR

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit uart; interface// Automatically use U2Xprocedure uart_init(const UBRR: word); procedure uart_init1(const BAUD: dword; const useU2X: boolean = false); // Blocking functionsprocedure uart_transmit(const data: byte); overload;procedure uart_transmit_hex(const data: byte); overload;procedure uart_transmit_hex(const data: word); overload;procedure uart_transmit_hex(const data: dword); overload;procedure uart_transmit(const s: shortstring); overload; procedure uart_transmit_asstring(b: byte); overload;procedure uart_transmit_asstring(b: int8); overload;procedure uart_transmit_asstring(b: word); overload;procedure uart_transmit_asstring(b: int16); overload;procedure uart_transmit_asstring(b: dword); overload;procedure uart_transmit_asstring(b: int32); overload; function uart_receive: byte;function uart_peek(out c: byte): boolean; implementation uses  simplemath; {$ifdef CPUAVRXMEGA3}procedure uart_init(const UBRR: word);begin  // RX  PORTB.DIRCLR := PIN1bm;  // TX  PORTB.OUTSET := Pin0bm;  PORTB.DIRSET := Pin0bm;   USART3.BAUD := UBRR;  //USART3.CTRLA := TUSART.RXCIEbm;  // RX is interrupt driven  USART3.CTRLB := TUSART.RXENbm or TUSART.TXENbm;end; procedure uart_init1(const BAUD: dword; const useU2X: boolean = false);var  ubrr: word;begin  // RX  PORTB.DIRCLR := PIN1bm;  // TX  PORTB.OUTSET := Pin0bm;  PORTB.DIRSET := Pin0bm;   if useU2X then    ubrr := (F_CPU * 64 + 4 * BAUD) div (8 * BAUD)  else    //ubrr := (F_CPU * 64 + 8 * BAUD) div (16 * BAUD);    ubrr := (F_CPU * 8 + BAUD) div (2 * BAUD);   USART3.BAUD := ubrr;  USART3.CTRLB := TUSART.RXENbm or TUSART.TXENbm;end; // Blocking functionsprocedure uart_transmit(const data: byte);begin  repeat  until (USART3.STATUS and TUSART.DREIFbm = TUSART.DREIFbm);  USART3.TXDATAL := data;end; function uart_receive(): byte;begin  repeat  until (USART3.STATUS and TUSART.RXCIFbm = TUSART.RXCIFbm);  result := USART3.RXDATAL;end; function uart_peek(c: byte): byte;begin  result := (USART3.STATUS and TUSART.RXCIFbm) = TUSART.RXCIFbm;  c := USART3.RXDATAL;end; {$else}procedure uart_init1(const BAUD: dword; const useU2X: boolean = false);var  ubrr: word;begin  if useU2X then    ubrr := ((F_CPU + 4*BAUD) shr 3) div BAUD  else    ubrr := ((F_CPU + 8*BAUD) shr 4) div BAUD;   UBRR0 := ubrr-1;   // Set U2X as specified  UCSR0A := UCSR0A or (byte(useU2X) shl U2X0);   // Enable receiver and transmitter  UCSR0B := (1 shl RXEN0) or (1 shl TXEN0);   // Set frame format: 8data, 1stop bit, no parity  UCSR0C := (3 shl UCSZ0);end; procedure uart_init(const UBRR: word);begin  UBRR0H := UBRR shr 8;  UBRR0L := byte(UBRR);   // Set U2X bit  UCSR0A := UCSR0A or (1 shl U2X0);   // Enable receiver and transmitter  UCSR0B := (1 shl RXEN0) or (1 shl TXEN0);   // Set frame format: 8data, 1stop bit, no parity  UCSR0C := (3 shl UCSZ0);end; procedure uart_transmit(const data: byte);begin  // Wait for empty transmit buffer  while ((UCSR0A and (1 shl UDRE0)) = 0) do;   // Put data into buffer, sends the data  UDR0 := data;end; function uart_receive: byte;begin  // Wait for data to be received  while ((UCSR0A and (1 shl RXC0)) = 0) do;   // Get and return received data from buffer  result := UDR0;end; function uart_peek(out c: byte): boolean;begin  result := UCSR0A and (1 shl RXC0) > 0;  c := UDR0;end; {$endif CPUAVRXMEGA3} procedure uart_transmit_hex(const data: byte);var  n, d: byte; // nibbles 1&2begin  n := data shr 4;  if n < 10 then    d := $30 + n  else    d := ord('A') + (n - 10);  uart_transmit(d);   n := data and $0F;  if n < 10 then    d := $30 + n  else    d := ord('A') + (n - 10);  uart_transmit(d);end; procedure uart_transmit_hex(const data: word);begin  uart_transmit_hex(hi(data));  uart_transmit_hex(lo(data));end; procedure uart_transmit_hex(const data: dword);begin  uart_transmit_hex(hi(data));  uart_transmit_hex(lo(data));end; procedure uart_transmit(const s: shortstring);var  i: byte;begin  for i := 1 to length(s) do    uart_transmit(ord(s[i]));end; procedure uart_transmit_asstring(b: byte);var  d, temp: byte;  skipLeadingZero: boolean;begin  if b = 0 then    uart_transmit(ord('0'))  else  begin    skipLeadingZero := true;    d := 2;  // 100 = 10^2    repeat      temp := b;      decimalDivMod(temp, b, d);      if not skipLeadingZero or (temp > 0) then      begin        skipLeadingZero := false;        uart_transmit(temp + ord('0'));      end;      dec(d);      if d = 0 then        uart_transmit(b + ord('0'));    until d = 0;  end;end; procedure uart_transmit_asstring(b: int8);begin  if b < 0 then  begin    b := -b;    uart_transmit(ord('-'));  end;  uart_transmit_asstring(byte(b));end; procedure uart_transmit_asstring(b: word);var  d, temp: word;  skipLeadingZero: boolean;begin  if b = 0 then    uart_transmit(ord('0'))  else  begin    skipLeadingZero := true;    d := 4;  // 10000 = 10^4    repeat      temp := b;      decimalDivMod(temp, b, d);      if not skipLeadingZero or (temp > 0) then      begin        skipLeadingZero := false;        uart_transmit(temp + ord('0'));      end;      dec(d);      if d = 0 then        uart_transmit(b + ord('0'));    until d = 0;  end;end; procedure uart_transmit_asstring(b: int16);begin  if b < 0 then  begin    b := -b;    uart_transmit(ord('-'));  end;  uart_transmit_asstring(word(b));end; procedure uart_transmit_asstring(b: dword);var  d, temp: dword;  skipLeadingZero: boolean;begin  if b = 0 then    uart_transmit(ord('0'))  else  begin    skipLeadingZero := true;    d := 10;    repeat      temp := b;      decimalDivMod(temp, b, d);      if not skipLeadingZero or (temp > 0) then      begin        skipLeadingZero := false;        uart_transmit(byte(temp) + ord('0'));      end;      dec(d);      if d = 0 then        uart_transmit(byte(b) + ord('0'));    until d = 0;  end;end; procedure uart_transmit_asstring(b: int32);begin  if b < 0 then  begin    b := -b;    uart_transmit(ord('-'));  end;  uart_transmit_asstring(dword(b));end; end. 
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 !

d.ioannidis:
Hi,


--- Quote from: 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?
<snip>

--- End quote ---

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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ----a-al-Xe-Xm-Sm-WpATMEGA16A-CpAVR5-dF_CPU:=1000000
Notice that the mcu I tested runs at 1MHz with the internal osc.

regards,

Navigation

[0] Message Index

[#] Next page

Go to full version