Dicussion 04 C Intro with Piezo and UART

Ryan Robucci

Objectives

PORTx and DDRx Review

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)

Micro-Controller Specific Constants/Defines

Setting Up the Direction Bits

Outputting Values to PORTx

Set one pin:

PORTD |= (1<<3);

same as:

PORTD |= (1<<PD3);

Clear one pin:

PORTD &= ~((1<<3));

same as:

PORTD &= ~((1<<PD3));

Setting Multiple Pins

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));

Checking Multiple Bits

flag = PIND & (0b00000001 | 0b01000000);

if (flag){
    // do something when flag either pin is high
}

if (flag != 0){
    // do something when flag is non-zero
}

Special Functions

#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

            }
        }
    }
}

Using Predefined Bits

Example to set bits TXEN0 and RXEN0 in UCSR0B

UCSR0B = _BV(TXEN0)|_BV(RXEN0);     //enable RX and TX

Software Delay Functions

AVR C Code

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));
    }
}

Uart Communications

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();
}