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.

[SOLVED] atmega16 serial communication

Status
Not open for further replies.

numair_noor

Member level 2
Joined
Mar 15, 2012
Messages
50
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,288
Activity points
1,715
hi, i m new to atmega 16 programming. i want to send an ascii character say 'B' when an interrupt comes on the PORTB^2. WHICH IS WORKING PROPERLY. AND WHEN A CHARACTER IS RECEIVED SERIALLY,AN INTERRUPT INVOKES, PORTA^0 TO BE = 1 FOR SOME TIME (FOR EXAMPLE 1 SECOND) AND THEN AGAIN PORTA^0 = 0 (AFTER 1 SECOND). CYCLE CONTINUEUS...
PLEASE HELP ME WITH THE FOLLOWING CODE:
(I AM USING AVR STUDIO 5)


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <avr/io.h>
#include <avr/interrupt.h>
void usart_init(void);
 
void usart_init (void)
{
    UCSRB= (1<<RXEN)| (1<<TXEN) |(1<<RXCIE)  ;      //ENABLE RECEIVER,TRANSMITTER AND RECEIVE INTERRUPT
    UCSRC= (1 << UCSZ1)|(1 << UCSZ0)|(1 << URSEL);  //USE 8 BIT DATA TRANSFER AND ONE START ONE STOP BITS WITH 9600 BAUDRATE    
    UBRRL=0x33;
}
 
int main(void)
{   
    
    while(1)            //continue the following process 
    {//cli();
    DDRA=0xFF;          //PORT A IS OUTPUT 
    //UDR=0x00;
    //PORTA=0x00;
    usart_init();
    //while (!(UCSRA & (1<<RXC)));  //WAIT UNTIL USART DATA REGISTER IS EMPTY AND TRANSMIT 'g'
    GICR=(1<<INT2);     //ENABLE EXTERNAL INTERRUPT 2 ON PORT B^2
    MCUCSR=(1<<ISC2);   //whenever the interrupt 2 is high to low(negative edge triggered)
    sei();
    }   
}
ISR(INT2_vect)
{
        usart_send('B');    //JUMP TO VOID USART_SEND TO SEND THE ASCII CHRACTER B
        //for(unsigned int i=0;i<=300;i++);
            
}
void usart_send (unsigned char g)
{
    //while(!(UCSRA & (1<<UDRE)));
    UDR=g;  //PUT CHRACTER B IN USART DATA REGISTER TO TRANSMITT
    
    //PORTA=0x01;   
}
ISR(USART_RXC_vect)     //RECEIVE INTERRUPT
{
 unsigned int C,d;          
    d=UDR;
    //d=0;
    //cli();
    
    for(C=0;C<=60000;C++)
    {
        PORTA=0x01;     //FOR SOME TIME MAKE PORTA^0 TO BE 1 , AND THEN RESET IT.(HERE IS SOME PROBLEM I GUESS)
    }
    //break;
//PORTA=0x00;
    //return 0;
}



---------- Post added at 22:28 ---------- Previous post was at 22:24 ----------

I forgot to mention that the problem is, when ever first time atmega16 receives a character serially, it keeps on giving 1 on porta^0. Which i want to control...(on it for 1 second)
 
Last edited by a moderator:

The first point is


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
while(1)            //continue the following process 
    {//cli();
    DDRA=0xFF;          //PORT A IS OUTPUT 
    //UDR=0x00;
    //PORTA=0x00;
    usart_init();
    //while (!(UCSRA & (1<<RXC)));  //WAIT UNTIL USART DATA REGISTER IS EMPTY AND TRANSMIT 'g'
    GICR=(1<<INT2);     //ENABLE EXTERNAL INTERRUPT 2 ON PORT B^2
    MCUCSR=(1<<ISC2);   //whenever the interrupt 2 is high to low(negative edge triggered)
    sei();
    }



You don't want the initialization code to be inside a loop and be executed over and over again, what you should use it

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//cli();
DDRA = 0xFF;        //PORT A IS OUTPUT
//UDR=0x00;
//PORTA=0x00;
usart_init();
//while (!(UCSRA & (1<<RXC)));  //WAIT UNTIL USART DATA REGISTER IS EMPTY AND TRANSMIT 'g'
GICR = (1 << INT2); //ENABLE EXTERNAL INTERRUPT 2 ON PORT B^2
MCUCSR = (1 << ISC2); //whenever the interrupt 2 is high to low(negative edge triggered)
sei();
 
while(1)            //continue the following process
{
 
}



I would also not suggest your style of coding , avoid any delay inside interrupts and use the delay.h that has delay functions, try


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
 
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define WRITEBIT(RADDRESS,RBIT,WADDRESS,WBIT) (CHECKBIT(RADDRESS,RBIT) ? SETBIT(WADDRESS,WBIT) : CLEARBIT(WADDRESS,WBIT))
 
volatile uint8_t my_flag;
 
void usart_init(void);
 
void usart_init(void)
{
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE)  ; //ENABLE RECEIVER,TRANSMITTER AND RECEIVE INTERRUPT
    UCSRC = (1 << UCSZ1) | (1 << UCSZ0) | (1 << URSEL); //USE 8 BIT DATA TRANSFER AND ONE START ONE STOP BITS WITH 9600 BAUDRATE
    UBRRL = 0x33;
}
 
int main(void)
{
    //cli();
    DDRA = 0xFF;        //PORT A IS OUTPUT
    //UDR=0x00;
    //PORTA=0x00;
    usart_init();
    //while (!(UCSRA & (1<<RXC)));  //WAIT UNTIL USART DATA REGISTER IS EMPTY AND TRANSMIT 'g'
    GICR = (1 << INT2); //ENABLE EXTERNAL INTERRUPT 2 ON PORT B^2
    MCUCSR = (1 << ISC2); //whenever the interrupt 2 is high to low(negative edge triggered)
    sei();
}
 
while(1)            //continue the following process
{
    if(my_flag == 1)    // check if flag is 1 and execute the following code
    {
        my_flag = 0;    // reset the flag
        SETBIT(PORTA, 0); // set bit0 of PORTA to 1
        _delay_ms(1000);    // delay 1000ms or as much as you want
        CLEARBIT(PORTA, 0); // set bit0 of PORTA to 0
    }
}
 
ISR(INT2_vect)
{
    usart_send('B');    //JUMP TO VOID USART_SEND TO SEND THE ASCII CHRACTER B
    //for(unsigned int i=0;i<=300;i++);
}
void usart_send(unsigned char g)
{
    //while(!(UCSRA & (1<<UDRE)));
    UDR = g; //PUT CHRACTER B IN USART DATA REGISTER TO TRANSMITT
    //PORTA=0x01;
}
 
ISR(USART_RXC_vect)     //RECEIVE INTERRUPT
{
    unsigned int d;
    d = UDR;
    //d=0;
    //cli();
    my_flag=1; // set the flag when the interrupt occurs
    //break;
    //PORTA=0x00;
    //return 0;
}



The SETBIT, CLEARBIT etc are explained https://www.edaboard.com/blog/861/
 

The code is not tested , I have only made a few changed in your code.

The delay lib functions are described https://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
basically there is a _delay_ms() for delay in milliseconds and _delay_us() for delay in microseconds, in order for these to work correctly you have to set the core freq. in the project properties.

Note that when you want to set a bit of a port you should use
Code:
PORTA |= (1<<0); // for bit0 
PORTA |= (1<<1); // for bit1
....
and not
Code:
PORTA = 1

The first line sets bit 0 and leaves the rest of the bits unchanged while the second line sets bit0 to 1 and all the rest to 0

the same when you want to clear a bit
Code:
PORTA &= ~(1<<0) // for bit0
PORTA &= ~(1<<1) // for bit1
PORTA &= ~(1<<2) // for bit2
....

The easier alternative are the SETBIT, CLEARBIT, FLIPBIT macro

---------- Post added at 20:42 ---------- Previous post was at 20:39 ----------

You can read about bitwise operators https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=37871
 

thanks, the code still had some bracket errors:)
here is the running one:


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
 
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define WRITEBIT(RADDRESS,RBIT,WADDRESS,WBIT) (CHECKBIT(RADDRESS,RBIT) ? SETBIT(WADDRESS,WBIT) : CLEARBIT(WADDRESS,WBIT))
 
volatile uint8_t my_flag;
 
void usart_init(void);
 
void usart_init(void)
{
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE)  ; //ENABLE RECEIVER,TRANSMITTER AND RECEIVE INTERRUPT
    UCSRC = (1 << UCSZ1) | (1 << UCSZ0) | (1 << URSEL); //USE 8 BIT DATA TRANSFER AND ONE START ONE STOP BITS WITH 9600 BAUDRATE
    UBRRL = 0x33;
}
 
int main(void)
{
    
    DDRA = 0xFF;        //PORT A IS OUTPUT
    usart_init();
    
    GICR = (1 << INT2); //ENABLE EXTERNAL INTERRUPT 2 ON PORT B^2
    MCUCSR = (1 << ISC2); //whenever the interrupt 2 is high to low(negative edge triggered)
    sei();
 
 
while(1)            //continue the following process
{
    if(my_flag == 1)    // check if flag is 1 and execute the following code
    {
        my_flag = 0;    // reset the flag
        SETBIT(PORTA, 0); // set bit0 of PORTA to 1
        _delay_ms(1000);    // delay 1000ms or as much as you want
        CLEARBIT(PORTA, 0); // set bit0 of PORTA to 0
    }
}
}
 
ISR(INT2_vect)
{
    usart_send('B');    //JUMP TO VOID USART_SEND TO SEND THE ASCII CHRACTER B   
}
void usart_send(unsigned char g)
{
    UDR = g; //PUT CHRACTER B IN USART DATA REGISTER TO TRANSMITT
}
 
ISR(USART_RXC_vect)     //RECEIVE INTERRUPT
{
    unsigned int d;
    d = UDR;
    my_flag=1; // set the flag when the interrupt occurs
}

 
Last edited by a moderator:

Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
 
#define SETBIT(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define CLEARBIT(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#define FLIPBIT(ADDRESS,BIT) (ADDRESS ^= (1<<BIT))
#define CHECKBIT(ADDRESS,BIT) (ADDRESS & (1<<BIT))
#define WRITEBIT(RADDRESS,RBIT,WADDRESS,WBIT) (CHECKBIT(RADDRESS,RBIT) ? SETBIT(WADDRESS,WBIT) : CLEARBIT(WADDRESS,WBIT))
 
volatile uint8_t my_flag;	//flag created to draw diverter 
volatile uint8_t my_flagSC;	//flag created to stop conveyor
 
void usart_init(void);
 
void usart_init(void)
{
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE)  ; //ENABLE RECEIVER,TRANSMITTER AND RECEIVE INTERRUPT
    UCSRC = (1 << UCSZ1) | (1 << UCSZ0) | (1 << URSEL); //USE 8 BIT DATA TRANSFER AND ONE START ONE STOP BITS WITH 9600 BAUDRATE
    UBRRL = 0x33;
}
 
int main(void)
{
   
    DDRA = 0xFF;        //PORT A IS OUTPUT
    usart_init();
   
    GICR = (1<<INT0)|(1 << INT2); //ENABLE EXTERNAL INTERRUPT 0&2 ON PORT D^2 & B^2
    MCUCSR = (0 << ISC2); //whenever the interrupt 2 is high to low(negative edge triggered)
    MCUCR=0x02;//MAKE INT0 FALLING EDGE TRIGGERED
	sei();

 
while(1)            //continue the following process
{
    if(my_flag == 1)    // check if flag is 1 and execute the following code for running diverter motor after rs232 interrupt
    {
        my_flag = 0;    // reset the flag
        SETBIT(PORTA, 0); // set bit0 of PORTA to 1
        _delay_ms(5000);    // delay 1000ms or as much as you want
        CLEARBIT(PORTA, 0); // set bit0 of PORTA to 0
    }
}
}
 
ISR(INT2_vect)
{
	my_flagSC=1;
    usart_send('C');    //JUMP TO VOID USART_SEND TO SEND THE ASCII CHRACTER C  to matlab from 15th pin of UC FOR CAPTURING FRAME FROM CAMERA
}
void usart_send(unsigned char g)
{
	UDR = g; //PUT CHRACTER B IN USART DATA REGISTER TO TRANSMITT
	if(my_flagSC==1)
	{
	my_flagSC=0;	
	SETBIT(PORTA,4);// set bit4 of PORTA to 1
    _delay_ms(5000);    // delay 10000ms or as much as you want to stop conveyor
    CLEARBIT(PORTA, 4); // set bit0 of PORTA to 0
	}    
	
}
 
ISR(USART_RXC_vect)     //RECEIVE INTERRUPT
{
    unsigned int d;
    d = UDR;
    my_flag=1; // set the flag when the interrupt occurs
}

ISR(INT0_vect)
{
	
    usart_send('D');    //JUMP TO VOID USART_SEND TO SEND THE ASCII CHRACTER B  to matlab from 15th pin of UC
	
}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top