Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Timer Counter in ATMEGA328PU is not working

Status
Not open for further replies.

ki@n

Newbie level 5
Newbie level 5
Joined
Aug 13, 2022
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
64
Hi everyone

I don't know what's happened but it seems that the time/counter unit is not working
I'm writing code for atmega328pu in arduino uno with codevision,I was working on a project with 7 segment(counting up from 0 to 9 with 1 second delay) and everything was ok until the 7 segment stopped working correctly and it just started blinking rapidly

Now I've written this code,the clock is set to 8Mhz,an led(connected to port B.0) must blink with a 1 sec delay,it works properly in proteus but in arduino board the led just turns on and nothing happens after that

C:
#include <mega328p.h>

interrupt [13] void ext_int(void)
{
    PORTB ^= (1<<0);
}

void main(void)
{
    DDRB.0 = 1;
    PORTB.0 = 0;
    TCCR1B = (1<<WGM12)|(1<<CS12);
    TCNT1H = 0;
    OCR1BH = 31249;
    TIMSK1 = (1<<OCIE1B);
    #asm ("sei");
    
    while(1) {}
    
}
 

Datasheet says CTC mode uses OCR1A rather than OCR1B. Presonally I don't remember, too long that I did AVR programming.
 

    thannara123

    Points: 2
    Helpful Answer Positive Rating
Datasheet says CTC mode uses OCR1A rather than OCR1B. Presonally I don't remember, too long that I did AVR programming.
There was no difference,in proteus both OCR1A and B work
Even Timer/Counter2 works
 
Last edited:

Hi,


Then proteus simulation is wrong.

--> Use CTC according datasheet informations.

Klaus
 

I just set WGM12 in TCCR1A, not TCCR1B(in datasheet WGM12 is in TCCR1B), and it is solved now(now i can see there is no difference between OCR1A and B)
 

Hi,

It may work "by accident" ... if OCR1A still contains the correct value from a previous program
--> power off the AVR completely for more than 10 seconds.
Then check if the timing still is correct.

Show your actual complete code.

Klaus
 

Surprizing, as there's no WGM12 bit in TCC1RA according to datasheet. Setting bit 3 in TCC1RA does nothing, so normal timer mode is selected, doesn't use OCRx.
 

Hi,

It may work "by accident" ... if OCR1A still contains the correct value from a previous program
--> power off the AVR completely for more than 10 seconds.
Then check if the timing still is correct.

Show your actual complete code.

Klaus
Hi
I set WGM12 in TCCR1B but again nothing happens
Also I disconnected the AVR for more than 10 seconds and changed the OCR1A value so the delay time must be less than 1 sec but it still blinks every second(OCCR1A = 200 NOT 31249)
C:
#include <mega328p.h>

void TCT(void)
{
    TCCR1A = (1<<WGM12);
    TCCR1B = (1<<CS12);
    TCNT1H = 0;
    OCR1AH = 200;
    TIMSK1 |= (1<<OCIE1B);
    #asm("sei");
}

interrupt [13] void ext_int(void)
{
    PORTB ^= (1<<0);
}

void main(void)
{
    DDRB.0 = 1;
    PORTB.1 = 0;
    TCT();
    while(1) {}   
}
 

Hi

I see some issues: (my code is pseudo code)
(BTW: I´m not familiar with M328, thus I had to read the datasheet. The same you need to do)
TCCR1A = (1<<WGM12);
WGM12 isn´t part of TCCR1A .. it belongs to TCCR1B
--> set TCCR1A = 0

TCCR1B = (1<<CS12);
--> now should be: TCCR1B = (1<<CS12 | 1<<WGM12)

OCR1AH = 200;
I recommend to use ful 16 bit register
--> OCR1A = ...

TIMSK1 |= (1<<OCIE1B);
CTC uses OCIE1A
--> TIMSK1 |= (1<<OCIE1A);

interrupt [13] void ext_int(void)
CTC usues OCIE1A
--> use int 12

*****
Your solution needs interrupt, writing an ISR and processing power.
You could do the same without interrupt, without ISR and without processing power by connecting the LED to an PWM output and using the PWM feature.
This is no problem for low frequency blinking a LED. But it could be used - for example - with LED brightness control... which basically is the same as blinking a LED, but with much higher frequency and variable duty cycle.

Klaus
 

Hi

I see some issues: (my code is pseudo code)
(BTW: I´m not familiar with M328, thus I had to read the datasheet. The same you need to do)

WGM12 isn´t part of TCCR1A .. it belongs to TCCR1B
--> set TCCR1A = 0


--> now should be: TCCR1B = (1<<CS12 | 1<<WGM12)


I recommend to use ful 16 bit register
--> OCR1A = ...


CTC uses OCIE1A
--> TIMSK1 |= (1<<OCIE1A);


CTC usues OCIE1A
--> use int 12

*****
Your solution needs interrupt, writing an ISR and processing power.
You could do the same without interrupt, without ISR and without processing power by connecting the LED to an PWM output and using the PWM feature.
This is no problem for low frequency blinking a LED. But it could be used - for example - with LED brightness control... which basically is the same as blinking a LED, but with much higher frequency and variable duty cycle.

Klaus
There are 2 problems:
1:As I said before,when i set WGM12 in TCCR1B nothing happens but when i set it in TCCR1A it works(although datasheet says it is in TCCR1B) and i can't figure it out
2:In codevision, for atmega328p i can't use full 16 bit reg OCR1A(in spite of mega16 and 32) and i have to write H or L
 

Hi,

first you have to be sure that you use the correct device (exact part name) and use the correct compiler setup for this device. Sadly there are many different ATMEGA328xx around with (slightly different periferal setup).
(for example: Atmega328PB-U does not have WGM12 at all)

Setting WGM12 in TCCR1A simply just sets the unused bit 3. I doubt it has any impact at all (assuming correct device and compiler setup)

Then you have to do all the modifcations I told. Doing only a part of the modifications is likely to fail.

Show the whole modified code.

Klaus
 

Hi again
I don't know maybe I'm using wring datasheet anyway it is an arduino uno and as far as I know it has an atmega328p micro(on my micro it is written
ATMEGA328P U and i think it is atmega32pu).
I also checked ATMEGA328,ATMEGA328P,ATMEGA328PB,ATMEGA328PU and they all have WGM12 in TCCR1B
 

Hi,

I also checked ATMEGA328,ATMEGA328P,ATMEGA328PB,ATMEGA328PU and they all have WGM12 in TCCR1B
I´m sorry for this. This is my mistake. You are right, they all have WGM12 in the TCCR1B
(indeed the difference is in the timer count. So the one has TCCR3x, the other not)

So, if "Atmega328P U" is written on the chip, then you have to use the Atmega328P datasheet and the Atmega328P compiler setup.

.. and you have to do all modifications in your code according the datasheet.
I'm sure the datasheet is correct ... there is a chance that the compiler makes mistakes ... but it´s more likely that your code is wrong.

If you want to check the compiler for mistakes then you have to check the assembler output of the compiler.

Again:
* do all the modifications
* show us your code
* show us your test setup
* show us what happens

Klaus
 

    ki@n

    Points: 2
    Helpful Answer Positive Rating
Can you briefly describe which timer mode you want to setup? The combination of register settings in your latest code (post #8) makes no sense, I think.
 

Hi again
It seems the problem was my compiler i was using Codevision but now I've switched to AtmelStudio 7 and the problem is solved
The only way that the timer counter 1 can work properly in CTC mode is setting WGM12 in TCCR1B
Here is my code:
C:
#define F_CPU 8000000UL

#include <avr/io.h>

#include <avr/interrupt.h>


void TCT(void)

{

    TCCR1A = 0x00;

    TCCR1B = (1<<WGM12)|(1<<CS12);

    TCNT1 = 0;

    OCR1A = 31249;

    TIMSK1 |= (1<<OCIE1A);

    asm("sei");

}


ISR (TIMER1_COMPA_vect)

{

    PORTB ^= (1<<0);

}


int main()

{

    DDRB= (1<<DDB0);

    PORTB = (0<<PORTB0);

    TCT();

    while(1);

}
 

Hi,

In post#13 I wrote:
If you want to check the compiler for mistakes then you have to check the assembler output of the compiler.

This is always a valid method ... if you think you´ve done everything right in your code.
Especially in your case where the assembler code is rather small.

So it´s on you whether to stay with CODEVISION or AtmelStudio.

Klaus
 
  • Like
Reactions: ki@n

    ki@n

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top