Skip to content

Instantly share code, notes, and snippets.

@shiva-karthick
Last active March 6, 2023 18:40
Show Gist options
  • Save shiva-karthick/a65e2ed496131185abe6fbd482680784 to your computer and use it in GitHub Desktop.
Save shiva-karthick/a65e2ed496131185abe6fbd482680784 to your computer and use it in GitHub Desktop.
USART initialisation for ATmega48A/PA/88A/PA/168A/PA/328/P
/* An example that shows how to use the above USART functions */
/*
* main.c
* Links for Further learning :
* 1) https://www.youtube.com/watch?v=1mmkA-m4aKU&list=PLtQdQmNK_0DRhBWYZ32BEILOykXLpJ8tP&index=21
* 2) https://www.avrfreaks.net/forum/tut-soft-using-usart-serial-communications?page=all
* 3) https://www.avrfreaks.net/forum/how-use-printf-uart
* 4) https://stackoverflow.com/questions/42744280/error-unknown-type-name-file/42744341
* Author : Shankar
*/
#include <avr/io.h>
#include <avr/delay.h>
#include <stdio.h>
#include "USART.h"
// ********************************************************************************
// Global Variables
// ********************************************************************************
static FILE mystdout = FDEV_SETUP_STREAM(usart_putchar_printf, NULL, _FDEV_SETUP_WRITE);
int main(void)
{
initUSART();
// setup our stdio stream
stdout = &mystdout;
uint8_t var = 10;
while (1)
{
printf("HI %u\r\n", var);
_delay_ms(100);
}
}
/*
Quick and dirty functions that make serial communications work.
Note that receiveByte() blocks -- it sits and waits _forever_ for
a byte to come in. If you're doing anything that's more interesting,
you'll want to implement this with interrupts.
initUSART requires BAUDRATE to be defined in order to calculate
the bit-rate multiplier. 9600 is a reasonable default.
May not work with some of the older chips:
Tiny2313, Mega8, Mega16, Mega32 have different pin macros
If you're using these chips, see (e.g.) iom8.h for how it's done.
These old chips don't specify UDR0 vs UDR1.
Correspondingly, the macros will just be defined as UDR.
*/
#include <avr/io.h>
#include "USART.h"
#include "setbaud.h"
#include <stdio.h>
#define F_CPU 8000000
#define BAUD 9600
void initUSART(void) { /* requires BAUD */
UBRR0H = UBRRH_VALUE; /* defined in setbaud.h */
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
/* Enable USART transmitter/receiver */
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /* 8 data bits, 1 stop bit */
}
void transmitByte(uint8_t data) {
/* Wait for empty transmit buffer */
//loop_until_bit_is_set(UCSR0A, UDRE0);
//UDR0 = data; /* send data */
// Wait for empty transmit buffer
while ( !(UCSR0A & (_BV(UDRE0))) );
// Start transmission
UDR0 = data;
}
uint8_t receiveByte(void) {
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait for incoming data */
return UDR0; /* return register value */
}
/* Here are a bunch of useful printing commands */
/*The function printString() just loops through all the characters in a string until the end,
transmitting them one at a time.*/
void printString(const char myString[]) {
uint8_t i = 0;
while (myString[i]) { // Test for a null character
transmitByte(myString[i]);
i++;
}
}
void readString(char myString[], uint8_t maxLength) {
char response;
uint8_t i;
i = 0;
while (i < (maxLength - 1)) { /* prevent over-runs */
response = receiveByte();
transmitByte(response); /* echo */
if (response == '\r') { /* enter marks the end */
break;
}
else {
myString[i] = response; /* add in a letter */
i++;
}
}
myString[i] = 0; /* terminal NULL character */
}
void printByte(uint8_t byte) {
// Input : Numeric value of an 8-bit byte
// Output : 3 ASCII digits
/* For example : if a = 56; printByte() sends "0" an then "5" and then "6" across the serial line*/
/* Converts a byte to a string of decimal text, sends it */
transmitByte('0' + (byte / 100)); /* Hundreds */
transmitByte('0' + ((byte / 10) % 10)); /* Tens */
transmitByte('0' + (byte % 10)); /* Ones */
}
void printWord(uint16_t word) {
transmitByte('0' + (word / 10000)); /* Ten-thousands */
transmitByte('0' + ((word / 1000) % 10)); /* Thousands */
transmitByte('0' + ((word / 100) % 10)); /* Hundreds */
transmitByte('0' + ((word / 10) % 10)); /* Tens */
transmitByte('0' + (word % 10)); /* Ones */
}
void printBinaryByte(uint8_t byte) {
/* Prints out a byte as a series of 1's and 0's */
uint8_t bit;
for (bit = 7; bit < 255; bit--) {
if (bit_is_set(byte, bit))
transmitByte('1');
else
transmitByte('0');
}
}
char nibbleToHexCharacter(uint8_t nibble) {
/* Converts 4 bits into hexadecimal */
if (nibble < 10) {
return ('0' + nibble);
}
else {
return ('A' + nibble - 10);
}
}
void printHexByte(uint8_t byte) {
/* Prints a byte as its hexadecimal equivalent */
uint8_t nibble;
nibble = (byte & 0b11110000) >> 4;
transmitByte(nibbleToHexCharacter(nibble));
nibble = byte & 0b00001111;
transmitByte(nibbleToHexCharacter(nibble));
}
uint8_t getNumber(void) {
// Gets a numerical 0-255 from the serial port.
// Converts from string to number.
char hundreds = '0';
char tens = '0';
char ones = '0';
char thisChar = '0';
do { /* shift over */
hundreds = tens;
tens = ones;
ones = thisChar;
thisChar = receiveByte(); /* get a new character */
transmitByte(thisChar); /* echo */
} while (thisChar != '\r'); /* until type return */
return (100 * (hundreds - '0') + 10 * (tens - '0') + ones - '0');
}
// this function is called by printf as a stream handler
int usart_putchar_printf(char var, FILE *stream) {
// translate \n to \r for br@y++ terminal
if (var == '\n') transmitByte('\r');
transmitByte(var);
return 0;
}
/* Functions to initialize, send, receive over USART
initUSART requires BAUD to be defined in order to calculate
the bit-rate multiplier.
*/
#include <stdio.h>
#ifndef BAUD /* if not defined in Makefile... */
#define BAUD 9600 /* set a safe default baud rate */
#endif
/* These are defined for convenience */
#define USART_HAS_DATA bit_is_set(UCSR0A, RXC0)
#define USART_READY bit_is_set(UCSR0A, UDRE0)
/* Takes the defined BAUD and F_CPU defined in setbaud.h,
calculates the bit-clock multiplier,
and configures the hardware USART */
void initUSART(void);
/* Blocking transmit and receive functions.
When you call receiveByte() your program will hang until
data comes through. We'll improve on this later. Hint : Use an interrupt*/
void transmitByte(uint8_t data);
uint8_t receiveByte(void);
void printString(const char myString[]);
/* Utility function to transmit an entire string from RAM */
void readString(char myString[], uint8_t maxLength);
/* Define a string variable, pass it to this function
The string will contain whatever you typed over serial */
void printByte(uint8_t byte);
/* Prints a byte out as its 3-digit ascii equivalent */
void printWord(uint16_t word);
/* Prints a word (16-bits) out as its 5-digit ascii equivalent */
void printBinaryByte(uint8_t byte);
/* Prints a byte out in 1s and 0s */
char nibbleToHex(uint8_t nibble);
char nibbleToHexCharacter(uint8_t nibble);
void printHexByte(uint8_t byte);
/* Prints a byte out in hexadecimal */
uint8_t getNumber(void);
/* takes in up to three ascii digits,
converts them to a byte when press enter */
int usart_putchar_printf(char var, FILE *stream);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment