Reply by Meindert Sprang●December 10, 20042004-12-10
"Roman Mashak" <mrv@tusur.ru> wrote in message
news:cpbeu5$2mtm$1@mpeks.tomsk.su...
> Hello, Meindert!
> You wrote on Fri, 10 Dec 2004 07:02:42 +0100:
>
> MS>>> Almost. You do not detect whether you are at the end of the array
or
> MS>>> ready sending data.
> ??>> I don't have any array, I'm sending just 1 byte.
>
> MS> Yes, but you're sending it over and over again until you hit the
reset
> MS> button.
> Do you mean, some flag indicating the status of process should be included
> in code?
Well, it depends on what you want to achieve. Your original code sent out a
string, there you have to test for the end of the string. Later, you changed
your code to send only one byte, to see what went wrong. But that code keeps
sending indefinately because of the interrupt routine that gets called after
you send the first and only byte 'manually'. Oh, and as other already
pointed out: in an interrupt routine that runs very frequently (do you
actually know how often it is executed? You should!), you cannot blink a LED
and then wait in a nested loop. During that loop, the interrupt routine
might get called another few 10-100 thousand times but not executed because
the processor inhibits interrupts unless you enable them explicitly within
the interrupt handler. If all this sounds like chinese to you, with all
respect try something more easy to achive until you thoroughly understand
what the processor is doing during interrupts.
Meindert
Reply by Roman Mashak●December 10, 20042004-12-10
Hello, Meindert!
You wrote on Fri, 10 Dec 2004 07:02:42 +0100:
MS>>> Almost. You do not detect whether you are at the end of the array or
MS>>> ready sending data.
??>> I don't have any array, I'm sending just 1 byte.
MS> Yes, but you're sending it over and over again until you hit the reset
MS> button.
Do you mean, some flag indicating the status of process should be included
in code?
With best regards, Roman Mashak. E-mail: mrv@tusur.ru
Reply by Meindert Sprang●December 10, 20042004-12-10
"Roman Mashak" <mrv@tusur.ru> wrote in message
news:cpas34$1u4i$1@mpeks.tomsk.su...
> Hello, Meindert!
> You wrote on Thu, 9 Dec 2004 15:27:20 +0100:
>
> ??>>
> MS> Almost. You do not detect whether you are at the end of the array or
> MS> ready sending data.
> I don't have any array, I'm sending just 1 byte.
Yes, but you're sending it over and over again until you hit the reset
button.
Meindert
Reply by Roman Mashak●December 9, 20042004-12-09
Hello, Mark!
You wrote on Thu, 09 Dec 2004 15:35:51 GMT:
MB> And if the LED0_blink() takes longer than 8 SCK cycles to execute,
MB> you're going to have problems with continuous data. If LED0_Blink()
MB> simply sets a flag so that the main routine can blink the LED,
MB> you may be OK.
Yeah,, may be that's the main issue. My LED0_blink() function is pretty
dumb and I'm not sure it's fast enought to jump out of ISR:
void LED0_blink(void)
{
uint8_t i=0;
DDRC = 0x01;
// flash LED (LED is inverse)
PORTC &= ~(1 << PC0);
for (i = 0; i < 50; i++) {
_delay_loop_2(100);
}
// down LED
PORTC |= (1 << PC0);
for (i = 0; i < 50; i++) {
_delay_loop_2(100);
}
}
MB> You haven't said what SCK rate is being used by the master. If
MB> the slave is being implemented on an 8MHz machine, I suspect it
MB> may not like SCK signals in excess of 2MHz. If the SCK is
MB> 2Mhz, You don't have a lot of machine cycles to respond
MB> to the interrupts.
SCK rate of master is 500KHz
MB> I would suggest starting with a clock rate in the 100KHz region,
MB> with perhaps a millisecond between transfers at the host end.
MB> When that works, you can start increasing the SCK rate.
MB> One of the nice things about being an SPI slave is that you
MB> don't really have to worry about slow clock rates.
With best regards, Roman Mashak. E-mail: mrv@tusur.ru
Reply by Roman Mashak●December 9, 20042004-12-09
Hello, Meindert!
You wrote on Thu, 9 Dec 2004 15:27:20 +0100:
??>>
MS> Almost. You do not detect whether you are at the end of the array or
MS> ready sending data.
I don't have any array, I'm sending just 1 byte.
With best regards, Roman Mashak. E-mail: mrv@tusur.ru
It is more efficient to do other things while the transmitter
becomes ready, i.e. use:
while (!(SPSR % (1 << SPIF))) continue;
SPDR = data;
--
Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Reply by Mark Borgerson●December 9, 20042004-12-09
In article <10rgo4fm7tdtfa4@corp.supernews.com>,
mhsprang@NOcustomSPAMware.nl says...
> "Roman Mashak" <mrv@tusur.ru> wrote in message
> news:cp9mce$bj5$1@mpeks.tomsk.su...
> > char *t_data = "1";
> > ...
> >
> > SIGNAL(SIG_SPI)
> > {
> > SPDR = *t_data;
> > LED0_blink(); // debugging feature
> > }
> >
> > void SPI_SlaveInit(void)
> > {
> > DDRB = (1 << PB6);
> > SPCR = (1 << SPIE) | (1 << SPE); // select slave and enable SPI
> >
> > PORTB |= (1 << PB6);
> > }
> >
>
> Almost. You do not detect whether you are at the end of the array or ready
> sending data.
>
And if the LED0_blink() takes longer than 8 SCK cycles to execute,
you're going to have problems with continuous data. If LED0_Blink()
simply sets a flag so that the main routine can blink the LED,
you may be OK.
You haven't said what SCK rate is being used by the master. If
the slave is being implemented on an 8MHz machine, I suspect it
may not like SCK signals in excess of 2MHz. If the SCK is
2Mhz, You don't have a lot of machine cycles to respond
to the interrupts.
I would suggest starting with a clock rate in the 100KHz region,
with perhaps a millisecond between transfers at the host end.
When that works, you can start increasing the SCK rate.
One of the nice things about being an SPI slave is that you
don't really have to worry about slow clock rates.
Mark Borgerson
Reply by Mark Borgerson●December 9, 20042004-12-09
In article <cp98r7$2ocg$1@mpeks.tomsk.su>, mrv@tusur.ru says...
> Hello, All!
>
> I keep fighting with atmega162 and its SPI :)
>
> So now I configured slave mode. The purpose is to send 8 bytes one after
> another. I tested and debugged all code in simulator hundreds of times, I
> watched MCU registers, SPI registers and etc., everything seems to be fine,
> but after burning in chip - some weird problem.
What is the frequency of the SCK signal from the master? Sometimes
simulators will respond to clock signals too fast for the actual
hardware.
>
> After receiving data from me, master is logging them onto the screen, so I
> can watch what's going on. Indeed it happenes, data got by master are
> strange and not what I sent.
>
Most of the SPI systems I've worked with use a separate signal as
a chip select. An SPI slave device will generally require a
low-going chip select from the master device to inform it that
a transfer is pending. In your case, you could use that
incoming low-going CS signal to start the transfers. However,
you will need to ensure that there is enough time between the
CS signal and the start of the transfer. As noted in another
post, you may have to 'pre load' the SPI data register
so that the hardware can send the byte as soon as the
master starts SCK. The CS interrupt service routine then simply
loads the NEXT byte when the first transfer is done and
polls the SPIF bit to determine when to load subsequent
bytes.
If you rely on an SPIF interrupt, you need VERY fast
interrupt service to get the next byte into the output
register before clocking starts, if the master is
requesting bytes one after the other in continuous
fashion.
> My chip is ATmega162, frequency 8MHz. Here is code:
>
> char *data = "123456780";
> ...
>
> /*
> SPI init
> Mode: slave
> MISO: output
> MOSI: input
> SS: input
> SCK: input
> */
> void SPI_SlaveInit(void)
> {
> DDRB = (1 << PB6);
> SPCR = (1 << SPIE) | (1 << SPE); // slave and enable SPI
>
> PORTB |= (1 << PB6);
> }
>
> void SPI_SendByte(char *data)
> {
> SPDR = *data;
> while ( !(SPSR & (1 << SPIF)) )
> ;
> }
>
> SIGNAL(SIG_SPI)
> {
> char *t;
>
> t = data;
> while ( *data != 0 ) {
> SPI_SendByte((char *)data);
> data++;
> }
>
> data = t;
>
> LED0_blink(); // for debug: flush LED
> }
>
>
> int main(void)
> {
> sei();
> SPI_SlaveInit();
> ........
> return 1;
> }
>
> And now I don't know, where is my problem has hidden.
>
Mark Borgerson
Reply by Meindert Sprang●December 9, 20042004-12-09
"Roman Mashak" <mrv@tusur.ru> wrote in message
news:cp9mce$bj5$1@mpeks.tomsk.su...
Almost. You do not detect whether you are at the end of the array or ready
sending data.
Meindert
Reply by Roman Mashak●December 9, 20042004-12-09
Hello, Meindert!
You wrote on Thu, 9 Dec 2004 14:40:44 +0100:
MS> The problem with the code above (I assume it is the code for the
MS> master) is that you call spi_sendbyte from within the interrupt
this is code for slave
MS> handler. Spi_sendbyte waits for the SPIF flag. The moment this flag is
MS> set, another interrupt is issued while you are still inside
MS> spi_sendbyte. You can safely remove the while loop in spi_sendbyte
Alright, I understand you. Here is changed version, I hope is correct :)
MS> because you only call it once at the start of the communication. After
MS> that it is called from the interrupt handler only when the shifter is
MS> empty. So, no need to wait for the SPIF flag. And when the while loop
MS> is removed, you'll that the only line left in spi_sendbyte can be put
MS> in the interrupt handler to save a pair of unnecessary call/return.
char *t_data = "1";
...
SIGNAL(SIG_SPI)
{
SPDR = *t_data;
LED0_blink(); // debugging feature
}
void SPI_SlaveInit(void)
{
DDRB = (1 << PB6);
SPCR = (1 << SPIE) | (1 << SPE); // select slave and enable SPI
PORTB |= (1 << PB6);
}
int main(void)
{
sei();
SPI_SlaveInit();
SPDR = *t_data; //write byte to trigger interrupt
while (1)
{
.....
}
return 1;
}
With best regards, Roman Mashak. E-mail: mrv@tusur.ru