how use CodeVision CodeWizard for USART Interrupts

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

hi guys :)

here is the code:

/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.4 Standard
Automatic Program Generator
© Copyright 1998-2004 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
e-mail:office@hpinfotech.com

Project : 
Version : 
Date    : 10/29/2009
Author  : intech                       
Company : non                             
Comments: 


Chip type           : ATmega32
Program type        : Application
Clock frequency     : 2.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 512
*****************************************************/

#include 

#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Receiver buffer
#define RX_BUFFER_SIZE 8
char rx_buffer[RX_BUFFER_SIZE];

#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif

// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer[rx_wr_index]=data;
   if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
   if (++rx_counter == RX_BUFFER_SIZE)
      {
      rx_counter=0;
      rx_buffer_overflow=1;
      };
   };
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif

// USART Transmitter buffer
#define TX_BUFFER_SIZE 8
char tx_buffer[TX_BUFFER_SIZE];

#if TX_BUFFER_SIZE<256
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#else
unsigned int tx_wr_index,tx_rd_index,tx_counter;
#endif

// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void)
{
if (tx_counter)
   {
   --tx_counter;
   UDR=tx_buffer[tx_rd_index];
   if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
   };
}

#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar(char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli")
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
   {
   tx_buffer[tx_wr_index]=c;
   if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
   ++tx_counter;
   }
else
   UDR=c;
#asm("sei")
}
#pragma used-
#endif

// Standard Input/Output functions
#include 

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x0C;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

      };
}

where i must use getchar() or putchar() ?
and how i can aware of new input from USART ?

thx

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

For test just add the following line to the while (1) in main:

      if (rx_counter) putchar(getchar());

When a character or more is in the receive buffer rx_counter is greater than zero.
The putchar(getchar()) will echo back received characters. Use a terminal emulator with correct settings, and no flow control.

It all starts with a mental vision.

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

KitCarlson wrote:
For test just add the following line to the while (1) in main:

      if (rx_counter) putchar(getchar());

When a character or more is in the receive buffer rx_counter is greater than zero.
The putchar(getchar()) will echo back received characters. Use a terminal emulator with correct settings, and no flow control.

if again needs while(1) in main() , what's difference between regular USARTs programming and Interrupt driven USARTs programming ?

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

The point of interrupt driven USART is that the byte received is read directly so that it is not overwritten by next incoming char. Meaning faster data rates possible. Each incoming char is put into a input buffer using the interrupt, where it stays until the uC has time to read it.

Interrupt driven transmit is also there for faster data rates. Directly when the TX-buffer in hardware is ready to take another byte it is put there from the transmit buffer in software trough the interrupt.

KitCarlsons code was just for testing that the USART code is working. You can read the bytes any time you like in your code, as long as you don't wait until the buffer is full. Buffer seems to be 8 each for transmit and receive in your case.

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

so , how i can interrupt the program just when new incoming data received , without inspecting buffer ?

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

As Agwanll says, the usual design is that the UART just causes an interrupt each time a character arrives and the handler puts it in a buffer. As that buffer will have two markers, one for where the next received character will be written and one for where the next one to be taken from then the test of whether there are any unused characters is simply whether the two indices are the same or not (if they are there's nothing unused). Back in main, at your leisure, from time to time you check to see if there are any unused characters. If there are you then pick them out and use them.

If there's something that cannot wait until this test in main() is next made and that MUST occur the moment a character arrives then the code for it needs to go into the receive interrupt handler itself. But this is pretty unusual given the low (relative) speed of UART.

Cliff

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

thx for ur answers

i tested these tow :

...
while (1) 
      { 
      if (rx_counter) putchar(getchar());

      }; 
...
interrupt [USART_RXC] void usart_rx_isr(void) 
{ 
char status,data; 
status=UCSRA; 
data=UDR; 
UDR=data+1;//***this is new line***
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0) 
   { 
   rx_buffer[rx_wr_index]=data; 
   if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; 
   if (++rx_counter == RX_BUFFER_SIZE) 
      { 
      rx_counter=0; 
      rx_buffer_overflow=1; 
      }; 
   }; 
} 

but neither of first nor second work correctly , somtimes they send respond but not meaningful ?!

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

You use the Wizard to write your code for interrupts or polled.

You write a suitable macro

#define kbhit()    (UCSRA & (1<<RXD))    // for polled
#define kbhit()    (rx_counter != 0)     // for interrupt
while (1)
      {
      if (kbhit()) putchar(getchar());

      };

You should NEVER interfere with the ISR() functions or try to write to their data.

Your main program logic is the same with a PC or with an AVR ---- use printf(), gets(), etc.

In the unlikely event that you are busy for a long time, you just ask the CodeWizard to give you a larger buffer. 16 will probably be ok for 99% of applications, but you can use as much RAM as you can afford.

David.

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

Are you sure your processor is running at 2 MHz as you told the Wizard?????

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

The checking the interrupt using rx_counter is different than just polling. Without interrupt, simple polling blocks other activities (when you add to main). rx_counter provides a means to use getchar() only when a character is present. Normal polling hangs looking for a character unless a time out, or other means stops it.

It all starts with a mental vision.

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

thx , it works fine :)

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

And when you get something to work after getting help, you tell what you did to get it working. Was it the uC frequency running at wrong speed?

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

AgwanII wrote:
And when you get something to work after getting help, you tell what you did to get it working. Was it the uC frequency running at wrong speed?

sure :)

frequency was OK , this was the key :

#define kbhit()    (rx_counter != 0)     // for interrupt 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi i have error when i want to set up codewizard ,to enable the enterrupt for usart1 ,how can i solve it?

Attachment(s): 

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

,how can i solve it?

Follow what the error windows says, BUY a commercial version of Codevision.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

The generated code won't work for the Transmit interrupt,   TX IRQs happen when the transmit shift register is empty,  which is whenever data is not being sent using the USART.  TX IRQs are different from other IRQs because they are only enabled when there is new chars to be transmitted.  Main() puts the char in the TX buffer and enables the TX interrupt.  The TX IRQ sends the next char in the FIFO and checks if the FIFO is empty.  If there are no more chars to be sent out of the USART, then the TX IRQ disables the TX interrupt.  If the FIFO is not empty, the TX IRQ returns with the IRQ still active.   The code doesn't seem to do that anywhere.

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

5 years too late ?!?

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

clawson wrote:
5 years too late ?!?

And incorrect. 

Simonetta wrote:
The generated code won't work for the Transmit interrupt,   TX IRQs happen when the transmit shift register is empty,  which is whenever data is not being sent using the USART.

Your statements are not correct; or not totally correct.  Did you actually study the code?  Did you notice TXC? CV USART Wizard code has always worked.  Since right around the year 2001.  I have dozens of production apps based on that code.

 

Now, you can decide that you need the extra fractional bit time and want to play the UDRE games.  Fine; can't argue.  But don't say

Simonetta wrote:
The generated code won't work for the Transmit interrupt

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

I too have quite a few apps using the Wizard generated AVR code for USART TX with interrupts and they work fine as well.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user