ATmega328PB 16-bit Timer TC3 – Fast PWM Mode

Posted

in

by

1 millisecond pulse width
50 Hz Frequency
1.5 millisecond pulse width
50 Hz Frequency
2 millisecond pulse width
50 Hz Frequency

I have used this FAST PWM mode to trigger two interrupt service routines.
The timer compares register A sets the frequency.
I have not enabled the output compare pins. since it was used by some other peripheral. So by doing this, I generate a PWM signal by issuing a command in the ISR.

/*
* main.c
*
* Created: 10 July 2023 10:47:23 PM
*  Author: abhay
*/
#define F_CPU 16000000

#include <xc.h>
#include <stdio.h>
#include "util/delay.h"
#include <avr/interrupt.h>
#include "uart.h"
#define LED_ON PORTB |= (1<<5)
#define LED_OFF PORTB &= ~(1<<5)


// Function to send a character via UART
int UART_putchar(char c, FILE *stream) {
	if (c == '\n')
	UART_putchar('\r', stream);  // Add carriage return before newline
	while (!(UCSR0A & (1 << UDRE0))); // Wait for the transmit buffer to be empty
	UDR0 = c; // Transmit the character
	return 0;
}

// Create a FILE structure to redirect the printf stream to UART
FILE uart_output = FDEV_SETUP_STREAM(UART_putchar, NULL, _FDEV_SETUP_WRITE);

ISR(TIMER3_COMPA_vect){
	PORTD |= (1<<6);
}
ISR(TIMER3_COMPB_vect){
	PORTD &= ~(1<<6);
	
}

int main(void)
{
	

	USART_Init();
	// Redirect stdout stream to UART
	stdout = &uart_output;
	DDRB |= (1<<5);	// set Data direction to output for PB5
	LED_OFF; // set output to high
	DDRD |= (1 << 6);	//set PD6 as output
	
	
	/*
	F_CPU = 16000000
	Prescaler = 64
	Frequency = 50Hz
	Period = 0.020 s
	step time = 1/(F_CPU/Prescaler) = 0.000004 s
	number of steps = 0.020/0.000004 = 5000
	*/
	TCNT3 = 0;		// Timer counter initial value = 0
	// Output Compare A value = 5000 or 20 Milli second
	OCR3A = 5000;
	// Output Compare B value = 500 or 2 Milli second 
	OCR3B = 500;	
	// Fast PWM
	TCCR1A |= (1 << WGM31)|(1 << WGM30);	
	//  Prescaler: 64
	TCCR3B |= (1 << WGM32)|(1<<WGM32)|(1 << CS31)|(1 << CS30);	
	// Enable Timer Interrupt for Overflow, Compare match A and Compare Match B
	TIMSK3 |= (1 << OCIE3B)|(1 << OCIE3A)|(1<<TOIE3);	 
	
	// Enable Global Interrupt
	sei();	
	
	while(1)
	{
		OCR3B = 250;//5% 1ms
		_delay_ms(500);
		OCR3B = 375;//7.5% 1.5ms
		_delay_ms(100);
		OCR3B = 500;//10% 2ms
		_delay_ms(500);

	}
	
	
}

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *