USART-PC Arduino Mega 2560 rev3

Hi everyone. I have a problem with data transmission from Arduino Mega2560 Rev3 via USART to my computer. It uses the C language to keep the program light and to let me see exactly what's going on. I want to send input capture value (ICR4) s with every edge change to rising.I used USB-USART converter FTDI with RT232RL and normal printer cable to check difference. With both of cables i get the same output. Here is code. Please help someone.

#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

#include <stddef.h>
#include <stdint.h>
#include <string.h>
#define F_CPU 16000000
#define _NOP()                   \
  do {                           \
    __asm__ __volatile__("nop"); \
  } while (0)

static constexpr uint32_t UART_BAUD_RATE{1000000};
const uint16_t test =6411;
volatile uint16_t startseq = 2;
volatile uint16_t endseq = 3;

void UARTSetup(uint32_t baudrate) {
  // UART settings:
  // * 8 data bits
  // * No parity bits (default)
  // * 1 stop bit (default)
  // * Asynchronous Normal mode (default)

  uint32_t const baseClockFrequency = F_CPU;
  uint32_t const uartClockDivider = 16;
  uint16_t const UBRRValue = static_cast<uint16_t>(
      (baseClockFrequency / (uartClockDivider * baudrate)) - 1);

  // Setup TX0 pin as output (PE1)
  DDRE |= _BV(PE1);
  // Set baudrate
  UBRR0 = UBRRValue;
  // Enable transmitter
  UCSR0B |= _BV(TXEN0);
  // Set 8-bit frame format
  UCSR0C |= (1<<UMSEL01)|_BV(UCSZ01) | _BV(UCSZ00);
}

void UARTSendByte(uint8_t value) {
  // Wait until the previous transmission has ended
  while (!(UCSR0A & _BV(UDRE0)))
    ;
  // Put the data into buffer
  UDR0 = value;
}
void UARTSendBytes(uint8_t const* data, size_t length) {
  for (uint8_t const* ptr = data; ptr != (data + length); ptr++) {
    UARTSendByte(*ptr);
  }
}
void UARTSendString(char const* string) {
  UARTSendBytes(reinterpret_cast<uint8_t const*>(string), strlen(string));
}
template <typename T>
void UARTSendValue(T value) {
  UARTSendBytes((uint8_t const*)&value, sizeof(value));
}
/// Timer-related functions ///
void ICTimerInit() {
  // Use Timer4, because only ICP4 and ICP5 are accessible on Arduino Mega
  // (which is bullshit)
  // Set capture on rising edge, and prescaler to 1 (timer should be clocked at
  // F_CLK)
  TCCR4B |= _BV(ICES4) | _BV(CS40);
  // Enable input capture and overflow interrupts
  TIMSK4 |= _BV(ICIE4) | _BV(TOIE4);
}
/// General functions ///
// This function configures Timer 1 Channel A (OC1A) as PWM
// with maximum frequency, so you can connect an oscilloscope
// and check the real timer clock
void enableClockTestOutput() {
  // Enable Fast PWM mode with OCR1A as TOP for TIM1
  // Enable pin output on PB5 (OC1A pin)
  DDRB |= _BV(PB5);
  // Toggle OC1A on compare match, for 50% PWM.
  // Also, Fast PWM mode bits.
  TCCR1A |= _BV(COM1A0) | _BV(WGM11) | _BV(WGM10);
  // Fast PWM mode bits, also prescaler disabled
  TCCR1B |= _BV(WGM12) | _BV(WGM13) | _BV(CS10);
  // Set OCR1A to 0, so the PWM will have maximum frequency
  // Measure the time of high or low signal part to check the frequency.
  OCR1A = 0x0;
}

void resetSystemTimerPrescaler() {
  // Make sure that there's no prescaler on Fclk
  // To change prescaler, set CLKPCE bit in CLKPR register to 1,
  // while simultanously setting the prescaler bits - here, we
  // set them to 0 because we don't want any prescaler
  CLKPR = _BV(CLKPCE);
  // Wait 4 cycles to make sure the change is applied before proceeding
  _NOP();
  _NOP();
  _NOP();
  _NOP();
}

// Input-capture event
ISR(TIMER4_CAPT_vect) {
  // Send the value over UART
  UARTSendValue(static_cast<uint16_t>(test));
}

// Overflow event
ISR(TIMER4_OVF_vect) {
  // Add the max value of ICR register
  // to indicate that overflow happened
  // timeBetweenCaptures += 0xFFFF;
}

int main() {
  cli();  // disable interrupts

  resetSystemTimerPrescaler();
  LEDSetup();
  UARTSetup(UART_BAUD_RATE);
  ICTimerInit();
  // enableClockTestOutput();

  sei();  // enable interrupts

  while (true)
    ;
}

Which development environment are you using? Why don't you use the Arduino IDE?

Do you want to write your own framework? If so then start with simpler examples before hacking timers.

Why do you post in "Sensors"?

Your description is quite confusing mixing up USART (UART?), USB, RS-232, printer cable...

That's not C, that's C++.

Interrupt handlers (ISR) should terminate very fast, sending bytes out a serial interface is definitely not something to be done inside an ISR!

I doubt that your wiring is made for 1MHz.

The Arduino IDE includes a really well working serial interface library. You should use that until you know enough about the board to do such "academic challenges".

Thank you for your answer. I am using VS Code and I am not going to write new frameworks. Perhaps I incorrectly put in the wrong section. If I am using USART with a USB cable, the connection to the computer is correct, right? The Arduino Mega has a USB port, but if I set the configuration in C, I have to use the USART registers to set it up correctly.

Thanks for answer. My first project was created with arduino lib and wont work properly ( propably i wrote wrong code from documentations), so for now i wrote this code to better understand how USART working. I chooise 1MHz bcs this baudrate have almost 0% errors ( table from documentations)

Interrupt handlers (ISR) should terminate very fast, sending bytes out a serial interface is definitely not something to be done inside an ISR!

If i send data outside ISR i get double value in terminal

Please distinguish USART from UART. The hardware can handle both the Synchronous and Asynchronous protocol, but the USB Serial implementation uses UART. It's your responsibility to set the Arduino and PC ports to the same baudrates.

Okay, so if i set in PC code configuration 8N1, and baudrate the same in arduino and PC it should work, right ?

Right. Any problems then arise from your code and cables.

So then, if i use USB-UART FTDI FT232RL converter and i have the same output, then i must find another code or program to storage bytes as int in file to make sure if cable/arduino code work properly ?

You can test your hardware with an Arduino example program and the Serial Monitor.

A cable isn't enough, you need an USB2UART converter. Fortunately the Mega2560 contains one in the form of the ATmega16U2 co-processor on the board. Although the ATmega16U2 theoretically can drive that speed I have some doubts that it can handle the USB traffic at that speed.

If not USB, then what ?

I didn't tell you not to use USB, I just pointed out that the Mega2560 doesn't have a native USB connection.

Do did you decrease the serial speed and try again?

Yes, if i do that, i get properly valye, but if i send ICR4 value via decrease speed, i miss 1-2 ICR4 value

In the posted code ICR4 isn't read, a constant value is sent every time an edge is detected.

Maybe it's time to tell us what you're actually trying to achieve, what circuit you're using and why using the IDE libraries isn't an option for you.

Fixed value, my mistake. What am I trying to achieve? I am trying to send an ICR4 value (or even a constant) without losing any data. Why won't I use IDE libraries? I have tried to make the same program with the arduino IDE and I am getting the same results so I am trying to make the same program in C ++ as the Arduino libraries work with the same methods I use there. What circuit am I using? Arduino Mega receives a square signal from the generator, between arduino and computer, I used everything I mentioned at the beginning of the post

You're doing an academic approach to reprogram the Arduino basics?

Does this have a practical value?

What frequency does that square signal have?

You're doing an academic approach to reprogram the Arduino basics?

not really, only in calculations i use formula from academic books

Does this have a practical value?

well, period of signal so maybe in few examples

What frequency does that square signal have?

Range 250Hz to 10kHz

And from a 10kHz signal you need to transfer every single wave period?

If you want to use 1 Mbaud to transfer to the PC you must not use the onboard USB2Serial adapter (based on a ATmega16U2), it won't be able to reach that speed. A hardware based approach might fit better, the FTDI ft232rl supports up to 3 Mbaud, so you can try with such a board.