OooO
OooO

Reputation: 13

Where have the missing letters gone?

Only 4 letters are showing up. Like in the example, I send the string "abcdef", but it only shows the 4 letters "abcf". I don't know why the other letters don't show up. I'm using Atmega8 and Bray terminal. I'm already following from the datasheet [http://ww1.microchip.com/downloads/en/DeviceDoc/21822E.pdf][1]. But I've already found a dead end.

Implementation of functions

#include <avr/io.h>
#include <math.h>
#include <util/delay.h>

#define DD_SS       PINB2         //Chip select ON RC2
#define DD_MOSI     PINB3          // Master out - Slave in pin
#define DD_MISO     PINB4          // Master in - Slave out pin
#define DD_SCK      PINB5          // Clock from master
#define DDR_SPI     PORTB          // DDR_SPI

void serial_init(void)
{
    UBRRH = 0x00;
    UBRRL = 7;
    UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)|(1 << UCSZ1); 
    UCSRB = (1 << RXEN) | (1 << TXEN)| (1<<RXCIE);
}
unsigned char Usart_Receive(void)           
{
    while ((UCSRA & (1 << RXC)) == 0) {};
    return UDR;
}


void Usart_Transmit(unsigned char c)   
{

    PORTD= 0b00000100;  //RTS Enable
    while ((UCSRA & (1 << UDRE)) == 0) {};
    UDR = c;
    PORTD= 0b00000000;  //RTS Disable
}
void SPI_MasterInit(void)
{
    DDRB = 0b00101100;
    DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
    SPCR = 0b01010000;
    SPSR = 0b00000001;
}
unsigned char spi_transfer(volatile char data)
{
    SPDR = data;
    while(!(SPSR & (1<<SPIF)));
    {
    }
    return SPDR;
}
void SPI_MasterTransmit (uint8_t Data)    
{
    uint16_t address;
    SPCR = (1<<SPE) | (1<<MSTR) | (0<<CPHA);
    DDR_SPI &= ~(1<<DD_SS);                // Select EEPROM
    spi_transfer(WREN);   // Send WRITE_ENABLE command
    DDR_SPI |= (1<<DD_SS);                // Release EEPROM
    DDR_SPI &= ~(1<<DD_SS);   //ss goes low             
    spi_transfer(WRITE); // write data to memory
    spi_transfer  (address>>8);   
    spi_transfer (address);
    spi_transfer(Data);
    DDR_SPI |= (1<<DD_SS);   //ss goes high
}
unsigned char SPI_MasterReceive(uint16_t address)   
{
    unsigned long data;
    SPCR = (1<<SPE) | (1<<MSTR) | (0<<CPHA);
    //waitBusy();
    DDR_SPI &= ~(1<<DD_SS);   //ss goes low
    spi_transfer(READ);  //enable write operation   
    spi_transfer (address>>8);  
    spi_transfer (address);
    data = spi_transfer(0xff);
    DDR_SPI |= (1<<DD_SS);   //goes high
    return data;
}

and this is main function

int main (void)
{
    char data;  
    unsigned char address;
    serial_init();
    SPI_MasterInit();
    while(1)
    {
      data = Usart_Receive();
      _delay_ms(10);
      SPI_MasterTransmit(data);
      _delay_ms(10);
      data = SPI_MasterReceive(address);    //read data from the memory
      _delay_ms(10); //pause for readability
      Usart_Transmit(data);     
    }           
    return 0;   
} 

I hope someone can help me here. :)

Upvotes: 0

Views: 480

Answers (2)

UncleO
UncleO

Reputation: 8449

Your USART is transmitting too fast for your receiver. By your fourth time through the main loop, the USART transmitter has overwritten the "d" with "e" and then with "f".

A way to get around this is to use interrupts for receiving data, instead of polling like you are doing now. But you won't be able to write to the EEPROM as fast as the interrupts come. Instead, you should queue up the letters into a circular array or linked list or some other data structure as they arrive, and then write them to EEPROM in the main loop as time allows.

Note that this solution will only help with bursty data; you save up the burst and then deal with it as you can. But if the USART is continuously too fast, then you will never be able to keep up.

Upvotes: 2

Ruslan Gerasimov
Ruslan Gerasimov

Reputation: 1782

To debug this issue you need to localise the place of problem and to do this you have to split your experiment on sub-tasks. One of them is to check UART separately, the code gets here like:

   while(1)
    {
      data = Usart_Receive();
      _delay_ms(10);
      Usart_Transmit(data);     
    }   

The second one is to check SPI apart from UART stuff if you have JTAG, or altogether if you get managed with making UART working. For the separate SPI checking just comment Usart_Receive(); and Usart_Transmit(data); initialize data with anything and probably increment it in the while. Hope this idea helps.

Upvotes: 0

Related Questions