How to set ATMEGA64a-au USART speed to 115200? - c

As the title impplies, I've ATMEGA64a-au and 12mhz crystal, I set the baud rate to 9600 by these codes:
#define F_CPU 12000000UL
#define FOSC 12000000 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
..
void USART0_Init( unsigned int ubrr )
{
UBRR0H = (unsigned char) (ubrr >> 8);
UBRR0L = (unsigned char) ubrr;
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
// Set frame format: 8data, 1stop bit
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
void USART1_Init( unsigned int ubrr )
{
UBRR1H = (unsigned char) (ubrr >> 8);
UBRR1L = (unsigned char) ubrr;
UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
// Set frame format: 8data, 1stop bit
UCSR1C = (1 << USBS1) | (3 << UCSZ10);
}
..
USART0_Init(MYUBRR);
USART1_Init(MYUBRR);
It is fine when I work with that baud rate but I've recently come a cross a 115200bd device and I need too change it to that, but when I change this line :
#define BAUD 115200
The AVR Micro controller stops communicating, and I've no idea how to fix it. is it too fast for that device or I'm missing something?

#define MYUBRR FOSC/16/BAUD-1
First of all there is an issue with this formula: it rounds always downwards. You need to round it to near integer, e.g. (FOSC / 16 + BAUD / 2) / BAUD-1
By the way why it is FOSC and not F_CPU?
Anyway, you can calculate the error when formula FOSC/16/BAUD-1 is used:
MYUBRR = 12000000/16/115200-1 = 5 (5.51 rounded downwards)
Actual UART speed will be:
F_CPU / 16 / (MYUBRR + 1) = 12000000 / 16 / (5 + 1) = 125000
which is 8.5% higher than required. Communication with receiver-transmitter baud rate difference more than 4.5% is not possible.
But you can set Double Speed Operation mode (refer to section 25.3.2 of the datasheet)
It can be done by setting bit U2X bit in UCSRA.
In that case UART clock will be 1/8 of the CPU clock, thus allowing higher UBRR settings:
// divide by 8, not 16
#define MYUBRR ((FOSC / 8 + BAUD / 2) / BAUD - 1)
...
void USART0_Init( unsigned int ubrr )
{
// you can just assign the value to UBRR, compiler will handle all the thighs
UBRR0 = ubrr;
UCSR0A = (1 << U2X0); // enable 2x mode
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
// Set frame format: 8data, 1stop bit
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
In this case MYUBRR value will be:
(12000000 / 8 + 115200 / 2) / 115200 - 1 = 12
and actual UART speed will be
12000000 / 8 / (12 + 1) = 115384,6
which gives you less than 0.2% error

Related

Why is my Atmega644 TIMER0 running at half the speed of the expected clock speed?

I am trying to build a drum machine using an Atmega644. The drum machine will have 16 LED's which will show which 16th of the beat it is at. The user should be able to set the BPM and therefore the updating of the LED will be different for different BPM.
I have a 16 MHz Crystal set at XTAL1 and XTAL2. I used a FUSE calculator to write the FUSE bits to a "Full Swing Oscillator" and remove the internal clock divide 8. I then set up the TIMER0 to perform this task
#define F_CPU 16000000UL // 1MHz internal clock
unsigned int tempo = 250; // Default BPM of 120.
volatile unsigned int seq_timer = 0;
//set-up timer for 0.5 ms update
TIMSK0 = (1<<OCIE0A);
TCCR0A = (1 << WGM01) |(1<<WGM00);
TCCR0B = (0 << WGM02) | (0<< CS02) | (1 << CS01) | (1 << CS00); //divide by 64
OCR0A = 125;
ISR (TIMER0_COMPA_vect) {
if (seq_timer>0) {seq_timer--;}
}
//Update which 16th note we are at.
void step(void){
update_led();
step_number = step_number < 15 ? step_number +1 : 0;
}
//Shift the LED such that the LED corresponding to step_number is lit up.
void update_led(void) {
for (int j = 16; j>=0; j--)
{
if ((((1 << step_number))>>j) & 0x01) {
PORTD |= (1 << PD5); //Serial Input
}
else {
PORTD &= ~(1 << PD5);
}
PORTD |= (1 << PD4); //Read clock
PORTD &= ~(1<< PD4);
}
PORTD |= (1 << PD3); //Shift clock
_delay_ms(40);
PORTD &= ~(1 << PD3);
}
while (1)
{
if ((seq_timer == 0)) {
seq_timer = tempo;
step();
}
Step functions calls a "update_led()" function which light up the LED corresponding to the step_number. This should according to my calculations occur (16e6 / (64*250*125)) = 8 updates/sec. But instead it does 4 updates/sec.
Am I missing something crucial?

Atmega2560 PWM on PB7

I am trying to get PWM output from PB7 pin with timer0 on Atmega2560 with no luck. It should generate tone for the connected repro.My PWM settings are:
DDRB = 0b11100000;
PORTB = 0b00000000;
OCR0A = 0x04;
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (0 << CS01) | (0 << CS00);
and then I have this function, which should generate the sound:
void SoundOutput(unsigned int uintTone)
{
if (uintTone != 0)
{
LED_2(1);
OCR0A = uintTone;
TCCR0B |= (1 << CS02) | (1 << CS01) | (1 << CS00);
}
else
{
TCCR0B &= ~((1 << CS02) | (1 << CS01) | (1 << CS00));
}
}
but nothing happens when i call it with tone parameter. Can you please help me?
Based on your comments, you are using ~12MHz clock as the input to your timer, and from your code, you are using 8 bit timer 0 in CTC mode with OCR0A as your top. You have OC0A set to toggle on a compare match.
According to the 2560 datasheet, the frequency of your timer is given by:
F_CLK/(2*(1 + OCR0A)) | F_CLK ~= 12MHz
This is an 8 bit timer, so that means that your minimum frequency that your PWM can generate is given by:
12e6/(2*(1 + 255)) ~= 20KHz
You simply aren't going to be able to generate an audible tone with that configuration unless you slow down the clock you are using for your timer or use a timer that can count higher.
1) Use a 16 bit counter (i.e. timer1). That will give you a min frequency of ~90Hz and a max frequency of ~6MHz, which should give you plenty of range to generate tones:
/* WGM BITS = 0100: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 111: External clock source on rising edge */
TCCR1A = (0 << COM1A1) | (1 << COM1A0) | (0 << WGM01) | (0 << WGM00);
TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS02) | (1 << CS01) | (1 << CS00);
2) Use the internal clock source as the timer clock instead of an external source. Unless you changed fuse bits or you are changing it in the code somewhere, the clock will be 1MHz. Prescaling the clock by 8 gives you a frequency range of ~250Hz - ~60KHz.
/* WGM BITS = 010: CTC Mode */
/* COMA BITS = 01: Toggle OC1A on compare match */
/* CS BITS = 010: Prescale the internal clock by 8 */
TCCR0A = (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (0 << WGM00);
TCCR0B = (0 << WGM02) | (0 << CS02) | (1 << CS01) | (0 << CS00);

16-bit Timer PWM LED Dimmer

I am new to AVR C Programming, I am testing a simple PWM using 16-bit timer on Atmega328p Counter/Timers which is suppose to act as a dimmer to an LED.
My Code:
#define F_CPU 16000000UL
void initTimer();
int x = 1;
int n = 1000;
int main(void)
{
initTimer();
DDRB |= (1 << PB1)| (1 << PB2);
while(1)
{
x++;
if(x > 65) {
x = 1;
}
}
}
void initTimer() {
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
// used for TOP, makes for 50 Hz PWM
ICR1 = 40000;
OCR1A = n * x;
}
ISR(TIMER1_OVF_vect)
{
OCR1A = n * x;
}
Problem is that it doesn't display the dimming effect, the brightness of the LED stays constant as to whatever value I set for OCR1A (PB1) output pin initially, its suppose to change value as the interrupt happen but its just not doing this, this is suppose to be simple test what am I doing wrong?
Update:
As advice I enable the interrupts using the TIMSK1 register and SEI(), however still the same issue the LED brightness stays constant as to whatever the original value of OCR1A that was specified in the initTimer().
int main(void)
{
initTimer();
DDRB |= (1 << PB1)| (1 << PB2);
while(1)
{
x++;
if(x > 65) {
x = 1;
}
}
}
void initTimer() {
ICR1 = 40000;
OCR1A = n * x;
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TIMSK1 |= (1 << ICIE1);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
sei();
}
ISR (TIMER1_COMPA_vect)
{
OCR1A = n * x;
}
Although I tried an alternative approach and that gives me the dimming affect:
int main(void)
{
initTimer();
DDRB |= (1 << PB1)| (1 << PB2);
while(1)
{
_delay_ms(20);
OCR1A = n * 4;
_delay_ms(20);
OCR1A = n * 8;
_delay_ms(20);
OCR1A = n * 15;
_delay_ms(20);
OCR1A = n * 25;
_delay_ms(20);
OCR1A = n * 1;
}
}
void initTimer() {
ICR1 = 40000;
OCR1A = n * x;
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
}
So it seems the problem is with the interrupts since PWM affect works but its just not working with the interrupt handler.
The first thing that jumps out at me is x and n should be volatile. You also should enable the interrupt in TIMSK0 register. Also enable interrupts by calling sei.
If I were you, I'd start with some know good sample code. The page I mentioned has a example that fires an interrupt every 4ms. Take that code and toggle the led on and off.
Another problem is you are changing x without regard to whether or not the isr was called. So in effect you will get a random x each time in the isr. This code is simple enough it might get stuck in a simple pattern. Instead move the setting of x to your isr.
Here is a good intro to avr timers: https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
ICR1 = 40000;
OCR1A = n * x;
TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
This is wrong, you need to configure TCCR1A and TCCR1B before initializing ICR1 and OCR1A. See this answer for more details.

How to read 32 bits variable from Software SPI in ATmega32?

it is my first try to set up SPI communication on ATmega32 and MAX31855. I've to read 32 bits from MAX31855 datasheet. I have writen my own function but it seems to read 0 all time (I have checked it on display). Here are my definitions from *.h file:
#ifndef SPI_SOFTWARE_H_
#define SPI_SOFTWARE_H_
#define ilosc_urzadzen 1
#define SoftSPI_MOSI PD0
#define SoftSPI_MISO PD1
#define SoftSPI_SCK PD2
#define SoftSPI_CS1 PD3
#define SoftSPI_CS2 PD4
#define SoftSPI_CS3 PD5
#define SoftSPI_CS4 PD6
#define SoftSPI_CS5 PD7
#define SoftSPI_DDR DDRD
#define SoftSPI_PIN PIND
#define SoftSPI_PORT PORTD
void init_SoftSPI();
uint32_t odczyt32bit(int CSx);
#endif
I have connected MAX31855: SO -> PD1, SCK -> PD2, CS -> PD3.
And here is my code from *.c:
#include <avr/io.h>
#include "SPI_software.h"
void init_SoftSPI(){
SoftSPI_DDR |= (1 << SoftSPI_MOSI) | (1 << SoftSPI_SCK);
if(ilosc_urzadzen == 1) SoftSPI_DDR |= (1 << SoftSPI_CS1);
else if(ilosc_urzadzen == 2) SoftSPI_DDR |= (1 << SoftSPI_CS1) | (1 << SoftSPI_CS2);
else if(ilosc_urzadzen == 3) SoftSPI_DDR |= (1 << SoftSPI_CS1) | (1 << SoftSPI_CS2) | (1 << SoftSPI_CS3);
else if(ilosc_urzadzen == 4) SoftSPI_DDR |= (1 << SoftSPI_CS1) | (1 << SoftSPI_CS2) | (1 << SoftSPI_CS3) | (1 << SoftSPI_CS4);
else if(ilosc_urzadzen == 5) SoftSPI_DDR |= (1 << SoftSPI_CS1) | (1 << SoftSPI_CS2) | (1 << SoftSPI_CS3) | (1 << SoftSPI_CS4) | (1 << SoftSPI_CS5);
}
uint32_t odczyt32bit(int CSx){
uint32_t liczba = 0;
if (CSx == 1){
SoftSPI_PORT &= ~SoftSPI_CS1;
for (int i = 0; i < 32; i++)
{
SoftSPI_PORT |= SoftSPI_SCK;
if (SoftSPI_PIN & (1 << SoftSPI_MISO)) liczba += 1;
liczba = liczba << 1;
SoftSPI_PORT &= ~SoftSPI_SCK;
}
SoftSPI_PORT |= SoftSPI_CS1;
}
return liczba;
}
After reading value from MAX31855 I shift it (20 places no 18 becouse I dont need fraction part):
temp = odczyt32bit(1);
temp = temp >> 20;
Where is my problem?
The clocking timing looks okay, but note that you only need to clock out 14 cycles (or just 12 for less precision) to get the result. You can stop reading the rest of the results whenever you want. (You don't need to read all 32 bits if you aren't using them.) If you do read all the bits, then you can detect any fault codes that indicate the thermocouple is not connected correctly.
Are you giving enough time for the conversion to occur? It needs 100 ms between readings.

ATMEGA168A - Using timer

I am trying to understand how to use timers with my ATMEGA168A, however the example I have (link) doesn't seem to work since it returns 0 all the time.
My idea is to make a HC-SR04 (link) ultra sound sensor work.
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
long measure(){
//Setting up the timer
TCCR1B |= (1 << CS12) | (1 << CS11) | (1 << CS10);
//Setting trigger as output
DDRD |= (1 << PD1);
//Setting echo as input
PORTD |= (1 << PD2);
//Triggering the hardware
PORTD ^= (1 << PD1);
_delay_us(10);
PORTD ^= (1 << PD1);
//Waiting until echo goes low
TCNT1 = 0;
while(bit_is_clear(PIND, PD2));
long timer_value = TCNT1;
//Calculating and returning the distance
long distance = timer_value / 58.82;
return distance;
}
How can I successfully measure the amount of time the PD2 was high?
To measure the amount of time the PD2 was high, write some code to do so, compile, write it to your microcontroller and turn on it.
Not tested, try this:
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
long measure(){
//Setting up the timer
TCCR1B |= (1 << CS12) | (1 << CS11) | (1 << CS10);
//Setting trigger as output
DDRD |= (1 << PD1);
//Setting echo as input
PORTD |= (1 << PD2);
//Triggering the hardware
PORTD ^= (1 << PD1);
_delay_us(10);
PORTD ^= (1 << PD1);
//Waiting until echo goes low (after Initiate)
while(!bit_is_clear(PIND, PD2));
//Waiting until echo goes high (Echo back starts)
while(bit_is_clear(PIND, PD2));
TCNT1 = 0;
//Waiting until echo goes low (Echo back ends)
while(!bit_is_clear(PIND, PD2));
long timer_value = TCNT1;
//Calculating and returning the distance
long distance = timer_value / 58.82;
return distance;
}

Resources