[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/
 

thanks man. love u...
*** BLESS YOU...
 

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

Cookies are required to use this site. You must accept them to continue using the site. Learn more…