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.

[AVR] Atmega128 how to make several codes work together

Status
Not open for further replies.

Justin Wenger

Newbie level 5
Joined
Sep 18, 2021
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
88
I want to make several codes work together.(ex. seven segment code+ LED code+ timer code + ....)

Each code works properly on its own, but when I try to combine it, problem happens.

Only one code works even though I combined these codes together.

Code below is a code using seven segment + timer + UART at the same time,

and I want it to count it down from 30:00 to 00:00 while I can use UART at the same time.

But only the timer code works and UART code doesn't.

If you know what the problem is, please give me an advice.





Code:
#define F_CPU 1600000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>


const unsigned char Segment_Data[] =
{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x27,0x7F,0x6F};
char COLUMN[4]={0,0,0,0}; 

int Cnt=0;
int SHOW_NUMBER=0, SHOW_NUMBER12=30, SHOW_NUMBER34=0; 

void Show4Digit(int number);
void ShowDigit(int i, int digit);
void uart0_init(void);
int Putchar(char message);
void uart(void);
char getchar1(void);

ISR(TIMER0_OVF_vect) { // TIMER0 has overflowed
    Cnt++;
    if(Cnt==244){
        SHOW_NUMBER34--;
        Cnt=0;
    }
    if(SHOW_NUMBER34<0){
        SHOW_NUMBER12--;
        SHOW_NUMBER34=59;
    }
    if(SHOW_NUMBER12<0){  
        SHOW_NUMBER12=0;
        SHOW_NUMBER34=0;
    }
}


int main(void) {
        
        uart0_init();
        char c;
        fdevopen(Putchar, 0);
        printf("\n\rUART_Test");

    DDRC = 0xff; DDRA = 0xff; PORTC = 0x00;
    TCCR0 = 0x06; // Normal mode, prescale 256, 16M/256=62500Hz
    TCNT0 = 0x00; // n=0, 256 count, 62500Hz/256=244.14Hz
    TIMSK = 0x01; // timer0 OVERFLOW interrupt enable
    SREG |= 0x80; // Global Interrupt Enable
    while (1) {
        SHOW_NUMBER=SHOW_NUMBER12*100+SHOW_NUMBER34;
    Show4Digit(SHOW_NUMBER);

    }

}


void uart(void){
            uart0_init();
            char c;
            fdevopen(Putchar, 0);
            printf("\n\rUART_Test");
          while(1){
                      c = getchar1();
                      printf("%c", c);
                  }
}








void Show4Digit(int number) {          
    COLUMN[0] = number/1000; COLUMN[1] = (number%1000)/100;
    COLUMN[2] = (number%100)/10; COLUMN[3] = (number%10);
    for(int i=0;i<4;i++) {
        ShowDigit(COLUMN[i],i); 
        _delay_ms(2); // wait for a second
    }
}
void ShowDigit(int i, int digit) {
    PORTC=~(0x01<<digit);
    PORTA = Segment_Data[i]; 
}



void uart0_init(void) {
    UCSR0B = 0x00; //disable while setting baud rate
    UCSR0A = 0x00;
    UCSR0C = 0x06;
    UBRR0L = 0x67; //set baud rate lo
    UBRR0H = 0x00; //set baud rate hi
    UCSR0B = 0x18;
}


int Putchar(char message) {// Putchar "P" cVde
    while (((UCSR0A>>UDRE0)&0x01) == 0) ; // UDRE, data register empty
    UDR0 = message;
    return 0;
}

char getchar1(void) {
    while(!(UCSR0A&0x80));
    return UDR0;
}
 

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
23,045
Helped
4,716
Reputation
9,448
Reaction score
5,092
Trophy points
1,393
Activity points
152,663
Hi,

the first you have to do:
* draw a flow chart
* decide timings

*****
General answer:
What you talk about are "tasks".
You need to provide processing time to each task.
Thus a "while (1)" within a task is a no-go, because it comsumes all processing time... not giving any processing power to other tasks.

Each task needs to check whether it needs something to do
* if yes, then do it
* if no: go to the next task
... then to the next ... to the next .. then restart the loop, beginning with the first task.

****
There are several solutions:
* timed tasks
* interrrupt driven tasks
* running a real time OS

Klaus
 

betwixt

Super Moderator
Staff member
Joined
Jul 4, 2009
Messages
15,731
Helped
5,069
Reputation
10,163
Reaction score
4,924
Trophy points
1,393
Location
Aberdyfi, West Wales, UK
Activity points
133,221
Either use the UART interrupt so the serial routine is called when a character is received or poll the UART within the main() loop to see if a character has arrived.

Be careful with 'char c' being declared in both the main() and uart() routines, when you declare a variable inside a function it becomes local to that function and not outside it. You actually declare two different instances of 'c' which are both destroyed as those functions end. If you need 'c' to be available elsewhere, declare it at the top of the program and outside any function.

Brian.
 

danadakk

Advanced Member level 5
Joined
Mar 26, 2018
Messages
2,219
Helped
344
Reputation
706
Reaction score
513
Trophy points
113
Activity points
9,807
Variables modified in ISRs that are used external to ISR need to be declared
as "volatile" -



Your "while(1)" inside main() is perfectly acceptable, common acceptable practice
as you have used it.

Your UART code inside of main() only executes once as it is not inside primary loop
in main(), the while(1) loop. Is that what you want.


Regards, Dana.
 
Last edited:
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top