Forum > Embedded - AVR
Does anybody have example code for UART for the ATMEGA16A ?
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