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.

ATmega8 doubt switching from ASM to C

Status
Not open for further replies.

MaiGoL7

Newbie level 3
Joined
Dec 18, 2012
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,314
Hello. I'm working on a project with Atmega8 and I'm switching the code from ASM to C (easier to me), and I have one doubt.
It should send 40times a value via UART when it reaches 1sec.
In assembly I used to work with Timer1 cause I needed fosc/PRE * seconds = 1MHz/256 *1sec= 3906 cycles.
Here is my ASM code:

Code:
Timer1_Init: 
	LDI R16,(1<<CS12)|(0<<CS11)|(0<<CS10) ;Prescaler  256 
	OUT TCCR1B,R16
	LDI R16,(1<<TOIE1) 
	OUT TIMSK,R16 
	LDI R20, 0xF0 ; eTimer1  F0BE (FFFF-0F42) 3906 cicles 1 sec 
	LDI R21, 0xBE 
	OUT TR171H, R20 
	OUT TR171L,R21 	
Ret
Code:
int_overflow: 
	IN R1, SREG ; stack 
	ldi R16, (1<<TXEN) ; TXD UART enabled 
	out UCSRB, R16 
	LDI cnt,40 ; send 40 times our value 
loop: 
	LDI R16, 0x38 ; send the value 8 ( HEX ) 
	RCALL USART_Transmit 
	DEC cnt 
	BRNE loop 
	ldi R16, (0<<TXEN) ; turn off TXD UART 
	out UCSRB, R16 
	LDI R20, 0xF0 ; TIMER1 at F0BE for 3906 cycles (1 sec)(FFFF-0F42)  
	LDI R21, 0xBE 
	OUT TR171H, R20 
	OUT TR171L,R21 
	OUT SREG, R1 ; stack
reti

Switching this code to C I have some issues (Also all this code came from ATmega8 datasheet)
Code:
int TIMER_INIT()
{
	unsigned int i;

	/* Set TCNT1 to 0xF0BE */
	TCNT1 = 0xF0BE; // for reach the 3906 cycles
	/* Read TCNT1 into i */
	i = TCNT1;
	
}
Code:
unsigned int TIM16_ReadTCNT1( void )
{
	unsigned char sreg;
	unsigned int i;
	/* Save Global Interrupt Flag */
	sreg = SREG;
	/* Disable interrupts */
	_CLI();
	/* Read TCNT1 into i */
	i = TCNT1;
	/* Restore Global Interrupt Flag */
	SREG = sreg;
	return i;
}
void TIM16_WriteTCNT1( unsigned int i )
{
	unsigned char sreg;
	unsigned int i;
	/* Save Global Interrupt Flag */
	sreg = SREG;
	/* Disable interrupts */
	_CLI();
	/* Set TCNT1 to i */
	TCNT1 = i;
	/* Restore Global Interrupt Flag */
	SREG = sreg;
}

I don't know where to set the prescaler in C code ((1<<CS12)|(0<<CS11)|(0<<CS10)). Nor where to add the counter for send through UART my value 40 times. It should be something like :
Code:
for(i=0,i<40,i++){
uart transmit(value);
}
But as it's said before, I dont know where to place it.

Also what I thought was add a _delay_ms() that aproaches the timer. But I think may be "better" use this way.

Here is the datasheet and it starts at page 75 16BIT-TIMER/COUNTER1
View attachment atmega8l.pdf

Regards, and merry xmas.
 

In order to have a repeated interrupt every 1sec you can use timer1 CTC mode

Code:
// Timer1 output compare A interrupt service routine
ISR(TIMER1_COMPA_vect)
{

}

int main(void)
{
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: 15,625 kHz
    // Mode: CTC top=OCR1A
    // OC1A output: Disconnected
    // OC1B output: Disconnected
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer Period: 1 s
    // Timer1 Overflow Interrupt: Off
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: On
    // Compare B Match Interrupt: Off
    TCCR1A = 0;
    TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10);
    TCNT1H = 0x00;
    TCNT1L = 0x00;
    ICR1H = 0x00;
    ICR1L = 0x00;
    OCR1AH = 0x3D;
    OCR1AL = 0x08;
    OCR1BH = 0x00;
    OCR1BL = 0x00;
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK = (1 << OCIE1A);

    while(1);
}

The transmit code can either be placed in the interrupt or you can use a flag variable set in the interrupt and execute the send code in main when the flag is set.

I'm not sure what were the timer read/write functions supposed to do, if they were just for the delay then you don't need any of them.
 

Thanks for the reply Alexan_e.
What I want to do is a communication between 2 ATmega (128 and 8) via RF modules, but it can be modeled as a simple wire.
I have a main base (ATmega128) and three bases (ATmega8). The main base must send a value (1,2,3) to select which base should transmit and then give back another signal for triangulate (the RF modules can take the RSSI, so with the power of the signal and ADC it's easy). So the main base should send a value for 125secs (or close to it) and then wait until the other micro receives, compares if it is the required value (1,2or3) and gives back another signal.

Main emits X during z seconds (thats the 40cnt in ASM code from above)
base1, base2 and base 3 compares with X (where X is the compare value)
wait until main stop emiting
base1 emits Y during z seconds
Main receives value Y and then change the emit value to change base.

Thats what it must do. But I'm stuck in how to emit during z secs and how to wait until the main base stops.

There is what it does in ASM code (TXD).
osci.jpg
Ciclo Trabajo = duty Cicle
T.Subida = Rising
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top