Ryan Robucci
DDxn | PORTxn | PUD (in MCUCR) | I/O | Pull-Up | Comment |
---|---|---|---|---|---|
0 | 0 | X | Input | No | Tri-state (Hi-Z) |
0 | 1 | 0 | Input | Yes | Pxn will source current if ext. pulled low. |
0 | 1 | 1 | Input | No | Tri-state (Hi-Z) |
1 | 0 | X | Output | No | Output Low (Sink) |
1 | 1 | X | Output | No | Output High (Source) |
All programs will have a line of code to include various utility functions, as well as various value definitions and processor specific definitions
# include <avr/io.h>
which in turn includes <avr/iom169.h>
The files are located at "toolchain-directory/avr/include/avr"
To set the direction of all 8 pins of port D, assign a 8-bit value to DDRD
DDRD = 0xFF; // set all port D pins as outputs DDRD = 0X00; // set all port D pins as inputs DDRD = 0b10101010; // alternating pin directions
To just set pin 2 of port D to output, not touching the others
DDRD = DDRD | 0b00000100;
Or just
DDRD |= 0b00000100; // recommended!
Do not set all 8 bits in register PORTD without regard for directions of each individual pin, i.e. all the bits stored in DDRD
Use bit operations when possible to suggest use of I/O bit assembly commands and to avoid unintentionally setting extra bit values
Set one pin:
PORTD |= (1<<3);
same as:
PORTD |= (1<<PD3);
Clear one pin:
PORTD &= ~((1<<3));
same as:
PORTD &= ~((1<<PD3));
DDRD = (1<<1)|(1<<3)|(1<<5)|(1<<7); \\ set all port D pins as outputs
same as:
DDRD = (1<<7)|(0<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<2)|(1<<1)|(0<<0); \\ alternating pin directions
DDRD = (1<<PD7)|(0<<PD6)|(1<<PD5)|(0<<PD4)|(1<<PD3)|(0<<PD2)|(1<<PD1)|(0<<PD0);
So we can output values to 1, 3, 5 and 7 pins:
PORTD |= (1<<1)|(1<<3)|(1<<5)|(1<<7);
Or clean them:
PORTD &= ~((1<<1)|(1<<3)|(1<<5)|(1<<7));
flag = PIND & (0b00000001 | 0b01000000); if (flag){ // do something when flag either pin is high }
if (flag != 0){ // do something when flag is non-zero }
#include <avr\io.h> int main(void){ DDRD &= ~_BV(0); // set PORTD pin0 to zero as input PORTD |= _BV(0); // enable pull up DDRD |= _BV(1); // set PORTD pin1 to one as output PORTD |= _BV(1); // LED ON while(1){ if (bit_is_clear(PIND,0)){ //if Button is presses while(1){ PORTD &= ~_BV(1); // LED OFF // LED OFF while Button is pressed loop_until_bit_is_det(PIND,0); PORTD |= _BV(1); // LED ON } } } }
Example to set bits TXEN0
and RXEN0
in UCSR0B
UCSR0B = _BV(TXEN0)|_BV(RXEN0); //enable RX and TX
_delay_ms(double_ms)
#define F_CPU 8000000UL // 8MHz
_delay_us(double_us)
Piezo Buzzer is on Pin B5
#include <stdio.h> #include <stdlib.h> #include <avr/io.h> # define F_CPU 8000000UL #include <util/delay.h> int main(void){ //DDRB=0xFF; overdone, change to DDRB|=_BV(PB5); // PORTB |=(1<<5); // PORTB &=~((1<<PB5)); while(1) { _delay_us(200); PORTB |=((1<<PB5)); _delay_us(200); PORTB &=~((1<<PB5)); } }
Set your buad rate for 38400
uart.h
// File uart.h // This is a guard condition so that contents of this file are not included // more than once. #ifndef UART_H #define UART_H #include <xc.h> // include processor files - each processor file is guarded. #include <avr/io.h> #include <stdio.h> #define BAUD_RATE 38400 /* .equ UBRRL = UBRR0L ; For compatibility .equ UBRR = UBRR0L ; For compatibility .equ UBRRH = UBRR0H ; For compatibility .equ UCSRA = UCSR0A ; For compatibility .equ UCSRB = UCSR0B ; For compatibility .equ UDRE = UDRE0 ; For compatibility .equ UCSRC = UCSR0C ; For compatibility .equ UCSZ1 = UCSZ01 ; For compatibility .equ UDR = UDR0 ; For compatibility .equ UCSZ0 = UCSZ00 ; For compatibility .equ RXC = RXC0 ; For compatibility .equ TXEN = TXEN0 ; For compatibility .equ RXEN = RXEN0 ; For compatibility .equ USBS = USBS0 ; For compatibility */ #define UBRRL UBRR0L #define UBRR UBRR0L #define UBRRH UBRR0H #define UCSRA UCSR0A #define UCSRB UCSR0B #define UDRE UDRE0 #define UCSRC UCSR0C #define UCSZ1 UCSZ01 #define UDR UDR0 #define UCSZ0 UCSZ00 #define RXC RXC0 #define TXEN TXEN0 #define RXEN RXEN0 #define USBS USBS0 extern FILE uart_stream; void UARTInit(void); int SerialPutch(char ch); int UARTPutch(char ch, FILE *stream); int UARTGetch(FILE *stream); int UARTIsByteAvailable(FILE *stream); #endif
uart.c
/* * File: uart.c * Author: robucci * * Created on March 1, 2022, 8:26 PM */ #ifndef F_CPU #define F_CPU 8000000UL #endif #include "uart.h" /* Assign I/O stream to UART */ FILE uart_stream = FDEV_SETUP_STREAM(UARTPutch, UARTGetch, _FDEV_SETUP_RW); void UARTInit(void) { //BAUD RATE of 4800 for 8Mhz //UBRRH = 0; //UBRRL = 103; UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate UBRRL = (((F_CPU/BAUD_RATE)/16)-1); UCSRA = 0; //clearing all flags UCSRB = (1<<RXEN0)|(1<<TXEN0); /* Enable Tx and Rx */ // UCSRB = (1<<RXEN)|(1<<TXEN); //UCSR0C =(1<<USBS0)|(3<<UCSZ00); /* Set Frame: Data 8 Bit, No Parity and 2 Stop Bit */ UCSRC = (1<<USBS0)|(3<<UCSZ00); } int SerialPutch(char ch) { while (!(UCSRA & (1<<UDRE))); //loop until bit is set UDR=ch; return 0; } int UARTPutch(char ch, FILE *stream) { if (ch == '\n') UARTPutch('\r', stream); while (!(UCSRA & (1<<UDRE))); //loop until bit is set UDR=ch; return 0; } int UARTGetch(FILE *stream) { unsigned char ch; while (!(UCSRA & (1<<RXC))); //loop until bit is set ch=UDR; /* Echo the output back to the terminal */ UARTPutch(ch,stream); return ch; } int UARTIsByteAvailable(FILE *stream) { return (UCSRA & (1<<RXC)); }
/* * File: main.c * Author: robucci * * Created on March 1, 2022, 7:49 PM */ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <string.h> #include <inttypes.h> #include <ctype.h> #include <unistd.h> #define F_CPU 8000000UL #include <avr/io.h> #include <util/delay.h> #include "uart.h" #define MYDEBUG #ifdef MYDEBUG #define DEBUG_PRINTF(...) printf(__VA_ARGS__) #define DEBUG_PRINTENTER(...) {printf("Entering Function ");int i=0;while(__func__[i]!='\0'){putchar(__func__[i]);i++;};putchar('\n');} #define DEBUG_PRINTEXIT(...) {printf("Leaving Function ");int i=0;while(__func__[i]!='\0'){putchar(__func__[i]);i++;};putchar('\n');} #else #define DEBUG_PRINTF(...) #define DEBUG_PRINTENTER(...) #define DEBUG_PRINTEXIT(...) #endif #define LEN_USER_LINE 4 char userLine[LEN_USER_LINE]; void myFunc(const char str[]); int main(void) { stderr = stdout = stdin = &uart_stream; /* Redirecting the standard I/O */ UARTInit(); DDRB |= _BV(5); for (int i=0;i<100;i++){ PORTB |= (1<<5); _delay_ms(2); PORTB &= ~(1<<5); _delay_ms(2); } printf("*\b"); if (fgets(userLine,LEN_USER_LINE,stdin)!=NULL) { if (strncmp(userLine,"yes",LEN_USER_LINE)==0){ //zero for match myFunc(userLine); } } } void myFunc(const char str[]){ DEBUG_PRINTENTER(); DEBUG_PRINTF("\tUser typed : \"%s\"\n",str); DEBUG_PRINTEXIT(); }