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.

Proteus simulation ATmega32 UART

Status
Not open for further replies.

o_0

Member level 3
Joined
Sep 30, 2009
Messages
58
Helped
2
Reputation
4
Reaction score
2
Trophy points
1,288
Activity points
1,873
I am trying to do a Proteus simulation of UART using ATmega32.
I'm using the sample code given here: winavr.scienceprog.com/example-avr-projects/running-tx433-and-rx433-rf-modules-with-avr-microcontrollers.html

My problem is the receiver micro seems to be dead, TXD remains low all the time even though something is coming into RXD. For input, I used the pattern generator, just had it count from 1 to 0x0F and back down, then alternate between 0 and 0x55 a few times.
The transmitter is transmitting, but I put a virtual terminal at the receiver input and it seems to be the same garbage all the time. As I said, nothing's coming out of the receiver.

I know it's probably the baudrate, because I get different garbage depending on the clock frequency. The sample code has the transmitter at 8 MHz and the receiver at 4 MHz, can someone please tell me why they are not the same? All I know is that for the ATmega32 the maximum recommended clock frequency is 16 MHz. I would like the baudrate to be 1200 but as far as the clock frequency I will use whatever works.

I even tried using itoa(); but it didn't help, and I didn't really expect it to because if the problem was the character display, at least I would be seeing different nonsense chars not just the same sequence repeated. I didn't test it very thoroughly though, so if someone thinks that's the problem I'll try that again.

I've attached all my files, as well as these pictures:

"regular settings.jpg" shows output when transmitter=8MHz, receiver=4MHz.
I've tried various frequencies and this is what I get for most of them.

"12mhz.jpg" shows that I get different garbage for both micros set to 12MHz.

Can someone please help me get this to work? Thanks in advance.

If it's that the baudrate/frequency is mismatched, please explain how to fix it because I have tried many different settings.

(The proteus is inside simulation.zip)
 

Attachments

  • simulation.zip
    28.7 KB · Views: 140
  • rx.zip
    12.4 KB · Views: 122
  • 12mhz.JPG
    12mhz.JPG
    185.7 KB · Views: 195
  • regular settings.JPG
    regular settings.JPG
    165.7 KB · Views: 182

May I know what's your compiler?

---------- Post added at 05:30 ---------- Previous post was at 05:19 ----------

The clock F_CPU is not the clock of oscillator :) It should be the clock after the prescaler :)
 

May I know what's your compiler?

---------- Post added at 05:30 ---------- Previous post was at 05:19 ----------

The clock F_CPU is not the clock of oscillator :) It should be the clock after the prescaler :)


Thanks for the response.
I'm using AVR Studio 4 with AVR GCC. Should be the latest version, recently downloaded it.
Prescaler? I'm not using the timers though I don't think. Could you please clarify?
 



---------- Post added at 07:49 ---------- Previous post was at 07:43 ----------

 



---------- Post added at 07:49 ---------- Previous post was at 07:43 ----------


These are both really nice images, with regard to the first one I'm using an external crystal (CKSEL3:0 1111). Since it's just a simulation I can change the value anytime, and I have tried a bunch of values. The results are shown in the pictures. Regarding the second one, that just shows the formula for baudrate is fosc/16(UBRR+1), which is included in the code I'm using which is found at this website: WinAVR AVR-GCC Tutorial

(On that webpage, scroll down for code) - That formula is actually included in the code. I can post all the code here if you want, or you can go to the website.

Here's the relevant portion:

Code:
#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

#ifndef F_CPU

//define cpu clock speed if not defined

#define F_CPU 4000000

#endif

//set desired baud rate

#define BAUDRATE 1200

//calculate UBRR value

#define UBRRVAL ((F_CPU/(BAUDRATE*16))-1)


It was originally 16ul but it doesn't seem to make a difference.
Does that help?
 

Yup. I am not actually worrying on the formula. Mostly it is the gating that you have to enable for the clock to pass through. And the default setting in the Atmega is ?
 

Yup. I am not actually worrying on the formula. Mostly it is the gating that you have to enable for the clock to pass through. And the default setting in the Atmega is ?

I think I enabled all that stuff. So regardless of what the default setting might be, the code sets it to the correct setting. Here, I'll just post all the code. Why should F_CPU be different for the transmitter and receiver?

Transmitter code:

Code:
#include <avr/io.h>

#include <util/delay.h>

#ifndef F_CPU

//define cpu clock speed if not defined

#define F_CPU 8000000

#endif

//set desired baud rate

#define BAUDRATE 1200

//calculate UBRR value

#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)

//define receive parameters

#define SYNC 0XAA// synchro signal

#define RADDR 0x44

#define LEDON 0x11//switch led on command

#define LEDOFF 0x22//switch led off command

void USART_Init(void)

{

	//Set baud rate

	UBRRL=(uint8_t)UBRRVAL;		//low byte

	UBRRH=(UBRRVAL>>8);	//high byte

	//Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size

	UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|

		(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);	

	//Enable Transmitter and Receiver and Interrupt on receive complete

	UCSRB=(1<<TXEN);

}

void USART_vSendByte(uint8_t u8Data)

{

    // Wait if a byte is being transmitted

    while((UCSRA&(1<<UDRE)) == 0);

    // Transmit data

    UDR = u8Data;  

}

void Send_Packet(uint8_t addr, uint8_t cmd)

{

	USART_vSendByte(SYNC);//send synchro byte	

	USART_vSendByte(addr);//send receiver address

	USART_vSendByte(cmd);//send increment command

	USART_vSendByte((addr+cmd));//send checksum

}

void delayms(uint8_t t)//delay in ms

{

uint8_t i;

for(i=0;i<t;i++)

	_delay_ms(1);

}

int main(void)

{

USART_Init();

while(1)

	{//endless transmission

	//send command to switch led ON

	Send_Packet(RADDR, LEDON);

	delayms(100);

	//send command to switch led ON

	Send_Packet(RADDR, LEDOFF);

	delayms(100);

	}

	return 0;

}

Receiver code:
Code:
#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

#ifndef F_CPU

//define cpu clock speed if not defined

#define F_CPU 4000000

#endif

//set desired baud rate

#define BAUDRATE 1200

//calculate UBRR value

#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)

//define receive parameters

#define SYNC 0XAA// synchro signal

#define RADDR 0x44

#define LEDON 0x11//LED on command

#define LEDOFF 0x22//LED off command

void USART_Init(void)

{

	//Set baud rate

	UBRRL=(uint8_t)UBRRVAL;		//low byte

	UBRRH=(UBRRVAL>>8);	//high byte

	//Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size

	UCSRC=(1<<URSEL)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|

		(0<<USBS)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);	

	//Enable Transmitter and Receiver and Interrupt on receive complete

	UCSRB=(1<<RXEN)|(1<<RXCIE);//|(1<<TXEN);

	//enable global interrupts

}

uint8_t USART_vReceiveByte(void)

{

    // Wait until a byte has been received

    while((UCSRA&(1<<RXC)) == 0);

    // Return received data

    return UDR;

}

ISR(USART_RXC_vect)

{

	//define variables

	uint8_t raddress, data, chk;//transmitter address

	//receive destination address

	raddress=USART_vReceiveByte();

	//receive data

	data=USART_vReceiveByte();

	//receive checksum

	chk=USART_vReceiveByte();

	//compare received checksum with calculated

	if(chk==(raddress+data))//if match perform operations

	{

		//if transmitter address match

		if(raddress==RADDR)

			{

				if(data==LEDON)

					{

						PORTC&=~(1<<0);//LED ON

					}

				else if(data==LEDOFF)

					{

						PORTC|=(1<<0);//LED OFF

					}

				else

				{

					//blink led as error

					PORTC|=(1<<0);//LED OFF

					_delay_ms(10);

					PORTC&=~(1<<0);//LED ON	

				}

			}

	}

}

void Main_Init(void)

{

	PORTC|=(1<<0);//LED OFF

	DDRC=0X001;//define port C pin 0 as output;

	//enable global interrupts

	sei();

}

int main(void)

{

	Main_Init();

	USART_Init();

	while(1)

	{

	}

	//nothing here interrupts are working

	return 0;

}
 

Thanks for the suggestions but they do not really help, if someone would please direct me to some UART code that is known to work for the mega32 that would be greatly appreciated. Further suggestions would be appreciated as well.

Are you saying I should be using the timers? If so, here is some alternate code that uses the timers, but it works even less than the first code. It causes a logic contention at the input of the transmitter.
Transmitter code:


Code:
 * Hardware Connections                                         *
 ****************************************************************/

/*
 * PORTA
 *  A.0 - ADC Channel 0 (y Accelerometer)
 *  A.1 - ADC Channel 1 (x Accelerometer)
 */

/*
 * PORTC
 *  C.0 - Right  Pushbutton
 *  C.1 - Middle Pushbutton
 *  C.2 - Top    Pushbutton (Calibrate)
 *  C.3 - Left   Pushbutton
 */

/*
 * PORTD
 *  D.1 - Wireless transmitter
 */

/****************************************************************
 * Compiler Directives                                          *
 ****************************************************************/

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "txrx.c"

// Wireless definitions
#define data_length  8
#define tx_id        3
#define threshold    17

/****************************************************************
 * Global Declarations                                          *
 ****************************************************************/

// Structure for storing mouse status data to be sent wirelessly
typedef struct {
    uint8_t buttonMask;
    int8_t  dx;
    int8_t  dy;
    int8_t  dWheel;
} report_t;

report_t reportBuffer;

// Wireless variables
char     data[data_length]; 
uint8_t  packet_count;
uint16_t time;

// ADC digital output
uint8_t  Ain;
uint8_t  measured;
uint8_t  measureMode; // 0 for y accelerometer, 1 for x accelerometer

// Timer1 variables for 16.384ms period
uint16_t TCNT1_prev;
uint16_t TCNT1_current;
uint16_t TCNT1_change;

// Acceleration variables
uint8_t Athreshx;
uint8_t Athreshy;
int8_t  ax;
int8_t  ay;

// Switch reading variables
uint8_t SW;
uint8_t SW_prev;
uint8_t SW_debounced;
uint8_t SW_debounced_prev;
uint8_t SW_pressed;
uint8_t calibrate;
uint8_t leftHeld;
uint8_t middleHeld;
uint8_t rightHeld;

void init(void); // initialization method

/****************************************************************
 * Interrupt Service Routines                                   *
 ****************************************************************/

ISR (TIMER0_COMPA_vect) {
    if(time <= threshold) time++;
}

/****************************************************************
 * Helper Functions                                             *
 ****************************************************************/

void generate_data(char count) {
    data[0] = 0x06;                       // IDENTIFIER BYTE
    data[1] = reportBuffer.buttonMask;    // BUTTON BYTE
    data[2] = reportBuffer.dx & 0x0F;     // X BYTE L
    data[3] = reportBuffer.dx >> 4;       // X BYTE H
    data[4] = reportBuffer.dy & 0x0F;     // Y BYTE L
    data[5] = reportBuffer.dy >> 4;       // Y BYTE H
    data[6] = reportBuffer.dWheel & 0x0F; // WHEEL BYTE L
    data[7] = reportBuffer.dWheel >> 4;   // WHEEL BYTE H
}

// Return 1 if SW has transitioned from unpressed to pressed
uint8_t keypress_SW() {
    SW_prev = SW;
    SW_debounced_prev = SW_debounced;
    // Read SW
    SW = (~PINC & 0x0F) ^ 0b00000110; // **** - middle and calibrate buttons are reverse operation
    // Debounce SW
    if(SW == SW_prev) SW_debounced = SW;
    // Detect transition from unpressed to pressed
    return (SW_debounced) && (!SW_debounced_prev);
}


//void USART_vSendByte(uint8_t u8Data)

//{

    // Wait if a byte is being transmitted

//    while((UCSRA&(1<<UDRE)) == 0);

    // Transmit data

 //   UDR = u8Data;  



/****************************************************************
 * Main Routine                                                 *
 ****************************************************************/
int main(void) {
    int8_t tempInt;
    
//    init();
    

	    // Set up ports
    DDRA = 0x00; // ADC inputs
    DDRC = 0x00; // pushbutton inputs
    DDRD = 0xFF; // wireless tx output
    
    // Set up Timer0
    TIMSK = (1<<OCIE0); // Turn on Timer0 comp match ISR
    OCR0  = 250;         // Set the compare reg to 250 time ticks (1ms)
    // Prescalar to 64 and turn on clear-on-match
    TCCR0=0x03;
	TCCR0 = (1<<WGM01);  // Turn on clear-on-match
            // Clock prescalar to 64
    
    // Set up wireless transmitter
    txrx_init(1,0,249,0); // TX only - 4000 baud - led off
    
    // Set up Timer1
    TCCR1B = 0x05; // Timer1 runs at prescalar 1024
    TCNT1_current = TCNT1;
    TCNT1_prev    = TCNT1_current;
    TCNT1_change  = 0;
  
      Ain         = 0;
    measured    = 0;
    measureMode = 0;
    Athreshx    = 131;
    Athreshy    = 129;
    ax          = 0;
    ay          = 0;
    
    SW                = 0;
    SW_prev           = 0;
    SW_debounced      = 0;
    SW_debounced_prev = 0;
    SW_pressed        = 0;
    calibrate         = 0;
    leftHeld          = 0;
    middleHeld        = 0;
    rightHeld         = 0;
    
    reportBuffer.buttonMask = 0;
    reportBuffer.dx         = 0;
    reportBuffer.dy         = 0;
    reportBuffer.dWheel     = 0;
    
    time = 0;
    packet_count = 0;
   // generate_data(packet_count);
    
    // Enable interrupts
    asm("sei");
  
  
    while(1) {
        // Send wireless information every 17ms
        if(time == threshold) {
            // Executes every threshold ms
       //     generate_data(packet_count);
            tx_me(data, data_length, tx_id);
            time = 0;
            packet_count++;
        }
}

Receiver code:

Code:
// Receiver unit consists of USB and wireless RX.
// This file receives data wirelessly and sends it to the USB MCU.

/****************************************************************
 * Hardware Connections                                         *
 ****************************************************************/

/*
 * PORTB
 *  B.0 - Data to USB MCU
 *  B.1 - Data to USB MCU
 *  B.2 - Data to USB MCU
 *  B.3 - Data to USB MCU
 *  B.5 - Addr to USB MCU
 *  B.6 - Addr to USB MCU
 *  B.7 - Addr to USB MCU
 */

/*
 * PORTD
 *  D.0 - Wireless receiver
 *  D.5 - ACK from USB MCU
 *  D.6 - ACK from USB MCU
 *  D.7 - ACK from USB MCU
 */

/****************************************************************
 * Compiler Directives                                          *
 ****************************************************************/

#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "txrx.c"

// Wireless definitions
#define MAX_RX_LENGTH 32
#define data_buffer   32
#define threshold     2000

/****************************************************************
 * Global Declarations                                          *
 ****************************************************************/

// Structure for storing mouse status data to be sent to USB MCU
typedef struct {
    char buttonMask;
    char dxL;
    char dxH;
    char dyL;
    char dyH;
    char dWheelL;
    char dWheelH;
} txrx_usb_buf_t;

txrx_usb_buf_t rx_usb_buf;

// Wireless variables
char     my_rx_data[MAX_RX_LENGTH];
char     length;
uint16_t msSinceLastData;

// Timer1 variables for 1ms period
uint16_t TCNT1_prev;
uint16_t TCNT1_current;
uint16_t TCNT1_change;

void init(void); // initialization method

/****************************************************************
 * Main Routine                                                 *
 ****************************************************************/

int main(void) {
    
    int i;
    int cntr = 0;
    int msCntr = 0;
    uint8_t receivedData;
    
    init();
    
    while(1) {
        
        // Check if received data from wireless receiver
        receivedData = 0;
        if(rxdone() == 1) {
            // Yes, received wireless data - decode it
            i = 0;
            init_getrx();
            while(rx_empty() != 1) {
                my_rx_data[i] = get_next_rx_data();
                i++;
            }
            
            // 0 - 170
            // 1 - start_char
            // 2 - ID
            // 3 - length
            // 4 to 12 - payload
            rx_reset(MAX_RX_LENGTH);
            if(my_rx_data[4] == 6) {
                rx_usb_buf.buttonMask = 0b00100000 | (my_rx_data[5]  & 0x0F);
                rx_usb_buf.dxL        = 0b01000000 | (my_rx_data[6]  & 0x0F);
                rx_usb_buf.dxH        = 0b01100000 | (my_rx_data[7]  & 0x0F);
                rx_usb_buf.dyL        = 0b10000000 | (my_rx_data[8]  & 0x0F);
                rx_usb_buf.dyH        = 0b10100000 | (my_rx_data[9]  & 0x0F);
                rx_usb_buf.dWheelL    = 0b11000000 | (my_rx_data[10] & 0x0F);
                rx_usb_buf.dWheelH    = 0b11100000 | (my_rx_data[11] & 0x0F);
            }
            receivedData = 1;
        }
        
        TCNT1_current = TCNT1;
        TCNT1_change  = TCNT1_current - TCNT1_prev;
        if(TCNT1_change >= 250) {
            // Code runs every 1ms
            TCNT1_prev = TCNT1_current;
            msCntr++;
            if(receivedData) {
                msSinceLastData = 0;
            }
            else {
                msSinceLastData++;
                if(msSinceLastData == 1000) {
                    // If no packets received in past second, zero mouse
                    rx_usb_buf.buttonMask = 0b00100000 | 0x00;
                    rx_usb_buf.dxL        = 0b01000000 | 0x00;
                    rx_usb_buf.dxH        = 0b01100000 | 0x00;
                    rx_usb_buf.dyL        = 0b10000000 | 0x00;
                    rx_usb_buf.dyH        = 0b10100000 | 0x00;
                    rx_usb_buf.dWheelL    = 0b11000000 | 0x00;
                    rx_usb_buf.dWheelH    = 0b11100000 | 0x00;
                }
            }
            if(msCntr >= 500) {
                // Code runs every 500ms - blink LED at 1Hz
                msCntr = 0;
                PORTD = PORTD ^ 0b00000100;
            }
        }
        // Check if USB MCU has received data
        if((PORTB & 0b11100000) == (PIND & 0b11100000)) {
            switch(cntr) {
                case 0:
                    PORTB = rx_usb_buf.buttonMask;
                    cntr++;
                    break;
                case 1:
                    PORTB = rx_usb_buf.dxL;
                    cntr++;
                    break;
                case 2:
                    PORTB = rx_usb_buf.dxH;
                    cntr++;
                    break;
                case 3:
                    PORTB = rx_usb_buf.dyL;
                    cntr++;
                    break;
                case 4:
                    PORTB = rx_usb_buf.dyH;
                    cntr++;
                    break;
                case 5:
                    PORTB = rx_usb_buf.dWheelL;
                    cntr++;
                    break;
                case 6:
                    PORTB = rx_usb_buf.dWheelH;
                    cntr = 0;
                    break;
            }
        }
    }
}

/****************************************************************
 * Initialization Routine                                       *
 ****************************************************************/

void init() {
    
    // Set up ports
    DDRB = 0b11111111; // PORT B is an output
    DDRD = 0b00000111; // LED 0b00000100
    
    // Timer1 runs at prescalar 64
    TCCR1B = 0x03; // Timer1 runs at prescalar 64
    TCNT1_current = TCNT1;
    TCNT1_prev    = TCNT1_current;
    TCNT1_change  = 0;
    
    // Initialize variables
    rx_usb_buf.buttonMask = 0;
    rx_usb_buf.dxL        = 0;
    rx_usb_buf.dxH        = 0;
    rx_usb_buf.dyL        = 0;
    rx_usb_buf.dyH        = 0;
    rx_usb_buf.dWheelL    = 0;
    rx_usb_buf.dWheelH    = 0;
    
    // TXRX init
    txrx_init(0,1,249,0); //832 249 RX only - 4000 baud - led off
    rx_reset(MAX_RX_LENGTH);
    msSinceLastData = 0;
    
    // Enable interrupts
    sei();
    
}
 

Attachments

  • logic contention.JPG
    logic contention.JPG
    173.4 KB · Views: 113

Attachments

  • uart_testcode_results.JPG
    uart_testcode_results.JPG
    169.4 KB · Views: 122

Sorry to keep resurrecting this thread, but seriously does anyone know what to do about the RX frame errors?

I tried introducing a delay (commented out in the code below) but it didn't help. The same code is on both the transmitter and receiver, but the frame errors are only listed for the transmitter. The error might be in between the pattern generator and the input of the transmitter, because those pins stay low all the time, but that doesn't make sense because all the other tx and rx pins blink like they are supposed to. Also, still nothing comes out on the virtual terminals, even though I made a new pattern now that counts from 0x30 to 0x39 then flashes 0x55 a few times then counts back down. I also tried, in the main while loop, switching the rx=USART_Receive(); and USART_Transmit(x);
so that the receiver file had the receive command first and the transmitter file had the transmit command first. However, this produced the exact same results. Also, the frequency is now set to 1.2 MHz because the pattern generator can only do numbers like 12 MHz, 1.2 MHz, etc., and 9600 baud because it's just a simulation anyway. If these are impossible settings please let me know.


Code:
#include <avr/io.h>


#include <util/delay.h>

void USART_Init( unsigned int baud )
{
   /* Set baud rate */
   UBRRH = (unsigned char)(baud>>8);
   UBRRL = (unsigned char)baud;
   /* Enable receiver and transmitter */
   UCSRB = (1<<RXEN)|(1<<TXEN);
   /* Set frame format: 8data, 2stop bit */
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}

void USART_Transmit( unsigned char data )
{
   /* Wait for empty transmit buffer */
   while ( !( UCSRA & (1<<UDRE)) )
   ;
   /* Put data into buffer, sends the data */
   UDR = data;
}

unsigned char USART_Receive( void )
{
   /* Wait for data to be received */
   while ( !(UCSRA & (1<<RXC)) )
   ;
   /* Get and return received data from buffer */
   return UDR;
}

//void delayms(uint8_t t)//delay in ms

//{

//uint8_t i;

//for(i=0;i<t;i++)

//	_delay_ms(1);

//}




int main(void)
{
   char x;
   USART_Init(7); // 9600 baud, 1.2 MHz  init USART 25

   
      while(1)
      {
      x=USART_Receive();
//	  delayms(100);
      USART_Transmit(x);
      }
   return(0);
   }
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top