State machine on ATTiny13A ?

Go To Last Post
22 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys,

I tried to set up state machine on ATTiny13A,
but it 's not doing the task,

Is it because of my timer init ?

void timer0_init()
{
	
	// Initial ATTiny13A Timer/Counter0 Peripheral
	//stop errant interrupts until set up
	cli(); //disable all interrupts
	TCCR0A=(1<<COM0A0)|(0<<COM0A1);			//Toggle OC0A on Compare Match
	//TCCR0A=(0<<WGM00)|(0<<WGM01)|(0<<WGM02); //Normal
	TCCR0B=(1<<CS00)|(0<<CS01)|(1<<CS02);   // Use mINIMUM prescaller: = 1:1024
	TIFR0 = (1<<TOV0);						//Clear pending TOV0 interrupt
	TCNT0 = 0x4E;							// Start counter from 0x4E, overflow at 10 mSec
	//multitask with timer0 setting begin
	MCUCR = 0x00;
	//EICRA = 0x00; //extended ext ints
	//EIMSK = 0x00;
	TIMSK0|=(1<<OCIE0A);
	//multitask with timer0 setting end
	sei(); //re-enable interrupts
	
}

int main(void)
{

  init_devices();
//
//   start at least one task here
//
set_task(7);   //task7 runs
set_task(6);   //task6 runs

//set_task(0);   //task0 runs
//      main loop

  while(1)
    {
    if (tick_flag)
      {
      tick_flag = 0;
     task_dispatch();              // well....
     }
   }
  return 0;
}
	
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

a lot of code is missing, could be any were.
put the timer in ctc mode if available and trigger on the overflow interrupt then you always get 10ms....
might also be a problem in the ISR, or the way you have variables declared....

so post all code, it can not be much as there is only 1K flash space.....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have an interrupt handler for OCIE0A interrupt ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the whole code :

//
// Co-operative multitasking framework tutorial code
// (c)Russell Bull 2010. Free for any use.
// Code built for a Mega168 @ 16MHz
//
// flash two outputs (PORTB.4,PORTB.5) at different speeds - blinky#2.
//
#define _XTAL_FREQ 9600000

#define F_CPU 9600000UL // 9.6 MHz
#define BUTTON_PIN PINB /* PINx - register for button input */
#define BUTTON1 PB3 /* bit for button input/output */
#define BUTTON2 PB4 /* bit for button input/output */
#define BUTTON3 PB5 /* bit for button input/output */
#define DEBOUNCE_TIME 25 /* time to wait while "de-bouncing" button */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

void init_devices(void);
void timer0_init(void);
void reset_task(char tsk);
void set_task(char tsk);
void task_dispatch(void);
void task0(void);
void task1(void);
void task2(void);
void task3(void);
void task4(void);
void task5(void);
void task6(void);
void task7(void);
void task8(void);
void task9(void);

#define NUM_TASKS 10
char task_bits = 0; /* lsb is hi priority task */
volatile char tick_flag = 0; /* if non-zero, a tick has elapsed */
unsigned int task_timers[NUM_TASKS]={0,0,0,0,0,0,0,0,0,0}; /* init the timers to 0 on startup */
static const PROGMEM char bit_mask[]={1,2,4,8,16,32,64,128}; /* value -> bit mask xlate table */

int button_is_pressed();

/*read the button function*/
int
button_is_pressed()
{
/* the button is pressed when BUTTON1 is clear */
if (bit_is_clear(BUTTON_PIN, BUTTON1))
{
_delay_ms(DEBOUNCE_TIME);

if (bit_is_clear(BUTTON_PIN, BUTTON1)) return 1;

}else if (bit_is_clear(BUTTON_PIN, BUTTON2))
{
_delay_ms(DEBOUNCE_TIME);

if (bit_is_clear(BUTTON_PIN, BUTTON2)) return 2;
}
else if (bit_is_clear(BUTTON_PIN, BUTTON3))
{
_delay_ms(DEBOUNCE_TIME);

if (bit_is_clear(BUTTON_PIN, BUTTON3)) return 3;
}

return 0;
}

int main(void)
{

init_devices();
//
// start at least one task here
//
set_task(7); //task7 runs
set_task(6); //task6 runs

//set_task(0); //task0 runs
// main loop

while(1)
{
if (tick_flag)
{
tick_flag = 0;
task_dispatch(); // well....
}
}
return 0;
}
//
// a task gets dispatched on every tick_flag tick (10ms)
//
void task_dispatch(void)
{
/* scan the task bits for an active task and execute it */

char task;

/* take care of the task timers. if the value ==0 skip it
else decrement it. If it decrements to zero, activate the task associated with it */

task=0;
while (task < NUM_TASKS )
{
if (task_timers[task])
{
task_timers[task]--; /* dec the timer */
if (task_timers[task] == 0 )
{
set_task(task); /* if ==0 activate the task bit */
}
}
task++;
}

task = 0; /* start at the most significant task */
while (task <= NUM_TASKS )
{
if ((task_bits & pgm_read_byte(&bit_mask[task])))
{
break; /* if activate task found..*/
}
task++; /* else try the next one */
}
switch(task) /* if task bit is active..execute the task */
{
case 0:
task0();
break;
case 1:
task1();
break;
case 2:
task2();
break;
case 3:
task3();
break;
case 4:
task4();
break;
case 5:
task5();
break;
case 6:
task6();
break;
case 7:
task7();
break;
case 8:
task8();
break;
case 9:
task9();
break;
default:
break; /* no task was active!! */
}
}

// enable a task for execution
void set_task(char tsk)
{
task_bits |= pgm_read_byte(&bit_mask[tsk]); /* sets a task bit */
}
// disable a task from executing
void reset_task(char tsk)
{
task_bits &= (~pgm_read_byte(&bit_mask[tsk])); /* resets a task bit */
}

void task0(void)
{
typedef enum {
LED_1,
LED_2,

} my_states;
static my_states state_var = LED_1;
int button_input;

switch (state_var) {

case LED_1 :
PORTB ^= (1<<0);
_delay_ms(500);
PORTB ^= (1<<1);
_delay_ms(500);
PORTB ^= (1<<2);
_delay_ms(500);
PORTB ^= (1<<3);
_delay_ms(500);
PORTB = 0x00;
_delay_ms(500);

button_input = button_is_pressed();//read button
if (button_input==1)//if button pressed, state = b;
{
PORTB ^= (1<<0);
_delay_ms(50);
PORTB ^= (0<<0);
_delay_ms(50);
PORTB ^= (1<<1);
_delay_ms(50);
PORTB ^= (0<<1);
state_var = LED_2;
}
else
{
state_var = LED_1;
}
break; // break;

case LED_2:
PORTB ^= (1<<0);
_delay_ms(100);
PORTB ^= (1<<1);
_delay_ms(100);
PORTB ^= (1<<2);
_delay_ms(100);
PORTB ^= (1<<3);
_delay_ms(100);
PORTB = 0x00;
_delay_ms(100);

button_input = button_is_pressed();//read button
if (button_input==1)//if button pressed, state = b;
{
PORTB ^= (1<<0);
_delay_ms(50);
PORTB ^= (0<<0);
_delay_ms(50);
PORTB ^= (1<<1);
_delay_ms(50);
PORTB ^= (0<<1);
state_var = LED_1;
}
else
{
state_var = LED_2;
}
break;

}//end switch
task_timers[0] = 10; //every 100ms
reset_task(0);
}
void task1(void)
{
reset_task(1);
}
void task2(void)
{
reset_task(2);
}
void task3(void)
{
reset_task(3);
}
void task4(void)
{
reset_task(4);
}
void task5(void)
{
reset_task(5);
}
//
// flash PORTB.2 at 2hz
//
void task6(void)
{
PORTB ^= (1<<1);
task_timers[6] = 25; //every 250ms
reset_task(6);
}
//
// flash PORTB.3 at 1hz
//
void task7(void)
{
PORTB ^= (1<<2);
task_timers[7] = 50; //every 500ms
reset_task(7);
}
void task8(void)
{
reset_task(8);
}
void task9(void)
{
reset_task(9);
}

//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
cli(); //disable all interrupts

//DDRB = 0x110111;//0xCF; //port 0,1,2 & 3 as outputs ,port 5 as input 110111
DDRB = 0xF7;
//timer0_init();

//PRR = 0x00; //power controller
sei(); //re-enable interrupts
//all peripherals are now initialized
}
//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.048mSec (-0.5%)
void timer0_init()
{

// Initial ATTiny13A Timer/Counter0 Peripheral
//stop errant interrupts until set up
cli(); //disable all interrupts
TCCR0A=(1<<COM0A0)|(0<<COM0A1); //Toggle OC0A on Compare Match
//TCCR0A=(0<<WGM00)|(0<<WGM01)|(0<<WGM02); //Normal
TCCR0B=(1<<CS00)|(0<<CS01)|(1<<CS02); // Use mINIMUM prescaller: = 1:1024
TIFR0 = (1<<TOV0); //Clear pending TOV0 interrupt
TCNT0 = 0x4E; // Start counter from 0x4E, overflow at 10 mSec
//multitask with timer0 setting begin
MCUCR = 0x00;
//EICRA = 0x00; //extended ext ints
//EIMSK = 0x00;
PCMSK = 0x00;
TIMSK0|=(1<<OCIE0A);
//multitask with timer0 setting end
sei(); //re-enable interrupts

}
ISR(TIMER0_COMP_vect)
{
//TIMER0 has overflowed
tick_flag = 1;
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mikech wrote:
Do you have an interrupt handler for OCIE0A interrupt ?

This one ?

ISR(TIMER0_COMP_vect)
{
 //TIMER0 has overflowed
    tick_flag = 1;
} 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I thought that you owned a mega128 board.

Surely it would be simpler to develop all your programs on the 'big' mega128.

Once a program is fully debugged, you can rebuild for a Tiny13.

Incidentally, does your 'massive' program fit on a Tiny13?

Personally, I would re-design it to be more concise. Ideally with it fitting on one screen!

Regarding your Timer0 init():
The code does NOT obey the comments!

CTC mode will work perfectly. Giving you regular interrupts.
'Your' effort will first run from 0x4E-0xFF then matching on 0x00. Subsequent runs go from 0x00-0xFF and matching on 0x00.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks David, it works allright on mega128, but haven't got it working on ATTiny13A.....

So I need CTC...I'll give a try..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

shall I use : "Clear OC0A on Compare Match" ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

like this :

void timer0_init()
{

//Initial ATTiny13A Timer/Counter0 Peripheral
//stop errant interrupts until set up
cli(); //disable all interrupts
TCCR0A=(0<<COM0A0)|(1<<COM0A1); //Toggle OC0A on Compare Match
TCCR0A=(0<<WGM00)|(1<<WGM01)|(0<<WGM02); //CTC
TCCR0B=(1<<CS00)|(0<<CS01)|(1<<CS02); // Use mINIMUM prescaller: = 1:1024
TIFR0 = (1<<TOV0); //Clear pending TOV0 interrupt
TCNT0 = 0x4E; // Start counter from 0x4E, overflow at 10 mSec
//multitask with timer0 setting begin
MCUCR = 0x00;
//EICRA = 0x00; //extended ext ints
//EIMSK = 0x00;
PCMSK = 0x00;
TIMSK0|=(1<<OCIE0A);
//multitask with timer0 setting end
sei(); //re-enable interrupts

}
ISR(TIMER0_COMP_vect)
{
//TIMER0 has overflowed
tick_flag = 1;
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The mega128 and tiny13 work exactly the same in CTC mode.

The OCR0 register holds the match value.
TCNT0 counts from 0 to OCR0 i.e. OCR0+1 ticks

SEriously, you must read your data sheet where it explains CTC mode.

Then you should make sure that your comments are accurate. e.g. the TIMER0_COMP is a match NOT an overflow.
Although if OCR0 is 0xFF, you get both a match and an overflow.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
//Code built for a Mega168 @ 16MHz

Use the correct interrupt-vector for the Compare-A interrupt.
The Tiny13 has 2 compare interrupts on Timer-0

Last Edited: Wed. Jun 11, 2014 - 06:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David, I put on Mega128,

void timer0_init()
{

// Initial ATMega128 Timer/Counter0 Peripheral
//stop errant interrupts until set up
cli(); //disable all interrupts

TCCR0=(1<<CS00)|(1<<CS01)|(1<<CS02); // Use mINIMUM prescaller: = 1:1024
TIFR = (1<<TOV0); //Clear pending TOV0 interrupt
TCNT0=0x4E; // Start counter from 0x4E, overflow at 10 mSec
//multitask with timer0 setting begin
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK|=(1<<OCIE0);
//multitask with timer0 setting end
sei(); //re-enable interrupts

}
ISR(TIMER0_COMP_vect)
{
//TIMER0 has overflowed
tick_flag = 1;
}

it works, what do I miss on ATTiny13 ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ISR(TIM0_COMPA_vect)
{
//TIMER0 has overflowed
tick_flag = 1;
}

from :
[url]http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html[/...

?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok, guys,
it works with this :

void timer0_init()
{

//Initial ATTiny13A Timer/Counter0 Peripheral
//stop errant interrupts until set up
cli(); //disable all interrupts
TCCR0A=(0<<COM0A0)|(1<<COM0A1); //Toggle OC0A on Compare Match
TCCR0A=(0<<WGM00)|(1<<WGM01)|(0<<WGM02); //CTC
TCCR0B=(1<<CS00)|(0<<CS01)|(1<<CS02); // Use mINIMUM prescaller: = 1:1024
TIFR0 = (1<<TOV0); //Clear pending TOV0 interrupt
TCNT0 = 0x4E; // Start counter from 0x4E, overflow at 10 mSec
//multitask with timer0 setting begin
MCUCR = 0x00;
//EICRA = 0x00; //extended ext ints
//EIMSK = 0x00;
PCMSK = 0x00;
TIMSK0|=(1<<OCIE0A);
//multitask with timer0 setting end
sei(); //re-enable interrupts

}
ISR(TIM0_COMPA_vect)
{
//TIMER0 has overflowed
tick_flag = 1;
}

It means 1 period of the timer is 9.6 MHz / 1024

so it will overflow from (FF-4E) * (9.6 MHz /1024) ?

thanks a lot for the clue..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
it works, what do I miss on ATTiny13 ?

I guess flash space to start with......

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I put RSTDISBL to 0, but I can not return to 1, I got chip enable error from USBASP, how can I fix ? thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@bianchi77,

You fix the RSTDISBL by buying a new chip.

Your 'attention span' is not suitable for using chips with RSTDISBL.

The Tiny13 is a very poor chip compared to say a Tiny25.

The mega128 is easier to work with. But first you need to understand how to use CTC.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nearly burnt out my finger scrolling through all of this!
You write to TCCR0A twice thus wiping out what you first wrote. Apart from reading the code, a couple of minutes with the simulator would've highlighted your simple mistake. What has this question got to do with a state machine? And my beautiful code - tainted forever!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
@bianchi77,

You fix the RSTDISBL by buying a new chip.

Your 'attention span' is not suitable for using chips with RSTDISBL.

The Tiny13 is a very poor chip compared to say a Tiny25.

The mega128 is easier to work with. But first you need to understand how to use CTC.

David.


That's allright, I have some spares, anyway, it's only for a simple purpose and experiment...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You should read the warnings:

test.c:349: warning: 'TIMER0_COMP_vect' appears to be a misspelled signal handler

It means TIMER0_COMP_vect was not a valid interrupt name on the Attiny13 and thus never reached.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yup, I didn't read it....
this one is better as David said
Thanks for the advice
[url]http://www.atmel.com/images/atmel-2586-avr-8-bit-microcontroller-attiny2...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

yup, I didn't read it....

We know. That is your default mode. :roll:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]