AVR_ATMEGA_USART/avr_usart.c

306 lines
5.8 KiB
C

/*
* Author: Jake Goodwin
* Date: 2023
* Description: Small library to communicate with the AT-09 bluetooth module.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include "avr_usart.h"
//#############################
//Globals
//#############################
int main() {
led_blink();
led_blink();
led_blink();
_delay_ms(1000);
init_usart0();
//enable parity, because the internal
//crystal is garbage
serial0_enable_parity_bit(2);
//enable interrupts
sei();
unsigned char data[8] = "AT+BAUD3";
unsigned char data_cmd[2] = "AT";
uint8_t data_len = 8;
uint8_t data_cmd_len = 2;
while(1) {
led_blink();
serial0_write(data, data_len);
//_delay_ms(1000);
_delay_ms(500);
}
return 0;
}
//#############################
//FUNCTIONS
//#############################
/*
* Input: None
* Output: None
* Description: init usart0 hardware in async mode,
* This sets up the connection with default params 8-n-1
*/
void init_usart0(void) {
//setup stuff for usart communications.
UBRR0H |= (uint8_t) (BT_UBRR>>8);
UBRR0L |= (uint8_t) BT_UBRR;
//Enable recv and Transmit pins, overrides other uses.
//IN the usart control and status register 0B
UCSR0B = (1<<RXEN0) | (1<<TXEN0);
#if USE_U2X
UCSR0A |= (1<<U2X0);
#else
UCSR0A &= ~(1<<U2X0);
#endif
//setting the data frame format
UCSR0C = (0<<UMSEL01)|(0<<UMSEL00)| //Async
(0<<UPM01)|(0<<UPM00)| //Parity bits
(1<<USBS0)| //Stop bits
(0<<UCSZ02)|(1<<UCSZ01)|(1<<UCSZ00)| //Set the number of bits.
(0<<UCPOL0); //Clock polarity, 0=falling 1=rising
}
/*
* Input: a 8bit char
* Output: None
* Description: Sends a char over usart0
*/
void tx_usart0(unsigned char data) {
//first wait for the transmit buffer to be empty
while(!(UCSR0A & (1<<UDRE0))) {
;//Equiv of continue
}
//now that it's empty, fill buffer with TX data.
UDR0 = data;
}
/*
* Input:None
* Output: a 8bit char
* Description: Recvs a char over usart0
*/
unsigned char rx_usart0(void) {
//first wait for the data to be received.
while( !(UCSR0A & (1<<RXC0)) ) {
;//Equiv of continue
}
//now return the data
return UDR0;
}
void serial0_flush_rxbuf(void) {
uint8_t none;
while( UCSR0A & (1<<RXC0)) {
none = UDR0;
}
}
/*
* Inupt: None
* Output: None
* Description: Nothing right now.
*/
void serial0_enable_timeouts(uint8_t ms) {
;
}
/*
* Inupt: None
* Output: None
* Description:
*/
void serial0_write(unsigned char* buffer, uint8_t write_length) {
for(uint8_t i = 0; i < write_length; i++) {
tx_usart0(buffer[i]);
}
#if CARRIAGE_RETURN
tx_usart0(0x0d);
#endif
#if LINE_FEED
tx_usart0(0x0a);
#endif
}
/*
* Input: none
* Output: none
* Description:
*/
void serial0_enable_line_feeds(void) {
;
}
/*
* Input: none
* Output: none
* Description:
*/
void serial0_enable_carriage_returns(void) {
;
}
/*
* Input: A parity setting as a 8bit uint
* Output: none
* Description: 0val clears for no parity
* 1val sets positive parity
* 2val sets negative parity
*/
void serial0_enable_parity_bit(uint8_t pos) {
switch(pos) {
case 0:
UCSR0C &= ~((1<<UPM01)|(1<<UPM00)); //Clear all.
case 1:
UCSR0C &= ~(1<<UPM00); //Make sure that the negative parity if off.
UCSR0C |= (1<<UPM01); //Set the positive parity
case 2:
UCSR0C |= (1<<UPM01)|(1<<UPM00); //Set both bits for neg parity
default:
;//Do nothing, just put here because
}
}
/*
* Input: number of stop bits
* Output: none
* Description:
*/
void serial0_set_stop_bits(uint8_t number) {
//clear all the set bits to start off.
UCSR0C &= ~(1<<USBS0);
switch(number) {
case 0:
;
case 1:
;
case 2:
UCSR0C |= (1<<USBS0);
default:
;
}
}
/*
* Inupt: A serialbuffer and length
* Output: None
* Description: Reads the serial data into a buffer of x length.
*/
void serial0_read(unsigned char* buffer, uint8_t buf_length) {
//clear buffer out?
//buffer = 0;
for(uint8_t i = 0; i < buf_length; i++) {
buffer[i] = rx_usart0();
}
}
/*
* Inupt: A serialbuffer and length
* Output: None
* Description: Reads the serial data into a buffer of x length,
* it does error checking from the register first.
*/
void serial0_read_with_err_checking(unsigned char* buffer, uint8_t buf_length) {
//first wait for the data to be received.
while( !(UCSR0A & (1<<RXC0)) ) {
;//Equiv of continue
}
//check for errors in the register.
//Check for frame error.
if(UCSR0A & (1<<FE0)) {
led_blink();
}
//check for data over-run
else if(UCSR0A & (1<<DOR0)) {
led_blink();
led_blink();
}
//check for parity error
else if(UCSR0A & (1<<UPE0)) {
led_blink();
led_blink();
led_blink();
}
//now return the data
buffer[0] = UDR0;
}
/*
* Inupt: BUAD RATE as uint8_t
* Output: None
* Description: Sets the baud rate of the serial usart0
* VALUES @ 1Mhz:
* 207 --> 300bps
* 103 --> 600bps
* 51 --> 1200bps
* 25 --> 2400bps
* 12 --> 4800bps
* 6 --> 9600bps !!! 7% error rate
*/
void serial0_set_baud(uint8_t baud) {
UBRR0H |= (uint8_t) (baud>>8);
UBRR0L |= (uint8_t) baud;
}
/*
* Input: None
* Output: None
* Description: Toggles the pin for the LED indicator.
*/
static void led_blink(void) {
//Set the DDR for output.
DDRC |= (1<<LED_PIN);
PORTC ^= (1<<LED_PIN);
_delay_ms(250);
PORTC ^= (1<<LED_PIN);
_delay_ms(250);
}