Files
2025-03-09 02:34:11 +01:00

64 lines
2.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "utils.h"
#include "bitmanip.h"
#include "timer.h"
#include "usart.h"
#include "interrupt.h"
// TIMER
#define PERIOD 2000
#define PRESCALE_VALUE 1024 // can be 1, 8, 64, 256, 1024
// USART
#define USART_BAUDRATE 115200 // Table 20-1 : Baud Rate Calculation
// END MACROS
void uart_init() {
UBRR0H = (unsigned char) (BAUD_PRESCALER(USART_BAUDRATE) >> 8); // 20.11.5 : UBRRnL and UBRRnH USART Baud Rate Registers
UBRR0L = (unsigned char) BAUD_PRESCALER(USART_BAUDRATE);
UCSR0C |= ASYNCHRONOUS | PARITY_DISABLED | STOP_ONE_BIT | DATA_EIGHT_BIT; // 20.11.4 : set Frame Format
UCSR0B |= RECEIVER_DISABLED | TRANSMITTER_ENABLED; // 20.11.3 : enable Receiver and/or Transmitter
}
void uart_tx(char c) {
while (TEST(UCSR0A, UDRE0) == 0); // 20.11.2 : do nothing until UDR emission buffer is empty, if UDREn flag is 1, UCSRnA register is empty
UDR0 = (unsigned char) c; // 20.11.1 : Put data into buffer, UDRn USART I/O Data Register (read and write)
}
void uart_printstr(const char* str) {
while (*str) {
uart_tx(*str);
str++;
}
}
// print "Hello World!\n", on serial port, every 2 seconds, with empty infinite loop
// `screen /dev/ttyUSB0 115200`
int main() {
uart_init();
TCCR1A |= CTC_TOP_OCR1A_IN_TCCR1A; // Table 16-4 : set timer in CTC (Clear Time on Compare) mode
TCCR1B |= CTC_TOP_OCR1A_IN_TCCR1B;
SREG |= ENABLE_GLOBAL_INTERRUPT; // 7.3.1 : Status Register, bit 7 : I Global Interrupt Enable
TIMSK1 |= INTERRUPT_ENABLE_CHANNEL_A; // 16.11.8 : enables the Timer1 Compare Match A interrupt, this makes the MCU react when OCR1A == TCNT1 by calling TIMER1_COMPA_vect
OCR1A = TIME_MS(PERIOD, PRESCALE_VALUE); // Table 16-4 : set CTC compare value on channel A, the counter is cleared to zero when the counter value (TCNT1) matches the OCR1A register
TCCR1B |= (PRESCALE_SET(PRESCALE_VALUE)); // 16.4 : set timer according to prescale value, in register TCCR1B, table 16-5 : prescale sets
while(1);
}
// ISR interrupt macro : https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
ISR(TIMER1_COMPA_vect) { // Table 12-7 : we select the code for timer 1 on channel A
uart_printstr("Hello World!\r\n"); // \n and \r : https://stackoverflow.com/questions/7812142/how-to-toggle-cr-lf-in-gnu-screen
}