application design of serial interface SPI interface
The synchronous serial three-wire SPI interface is used, which can be conveniently connected with the peripheral of SPI Communication protocol or another AVR MCU, realizing high speed synchronous communication in a short distance. ATMEGA128 SPI uses hardware to achieve byte-oriented Full-duplex 3-line synchronous communication, support host, from the machine and 2 different polarity of the SPI time series, the communication rate has 7 choices, the host mode of the highest speed of 1/2 system clock, from the machine mode maximum speed of 1/4 system clock.
ATmega128 internal SPI interface is also used in program memory and data e2prom programming download and upload. However, it is particularly important to note that at this point the SPI Mosi and miso interfaces are no longer corresponding to the PB2, PB3 pins, but to the PE0, PE1 pins (PDI, PDO), which is detailed in chapter II of the program Memory serial programming and verification part of the content.
ATmega128 SPI is the hardware interface and transmission complete interrupt request, so the effective way to use SPI to transmit data is to use the interrupt mode + data buffer design method. The following points should be noted when initializing the SPI:
The correct selection and setting of the host or the machine, as well as the operating mode (polarity), data transmission rate;
. Note the order of the bytes sent, which is low priority (LSB first) or high priority (MSB Frist);
Correctly set the input and output direction of Mosi and miso interface, the input pin uses the pull resistor, can save the high resistance on the bus.
The following section is a routine of the SPI host to send (receive) bytes continuously:
#define SIZE 100
unsigned char spi_rx_buff[size];
unsigned char spi_tx_buff[size];
unsigned char rx_wr_index,rx_rd_index,rx_counter,rx_buffer_overflow;
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#pragma interrupt_handler spi_stc_isr:18
void Spi_stc_isr (void)
{
Spi_rx_buff[rx_wr_index] = SPDR; Read the bytes received from the ISP's mouth
if (++rx_wr_index = = SIZE) Rx_wr_index = 0; Put in the receive buffer and adjust the queue pointer
if (++rx_counter = SIZE)
{
Rx_counter = 0;
Rx_buffer_overflow = 1;
}
if (tx_counter)//If data in the sending buffer is to be sent
{
--tx_counter;
SPDR = Spi_tx_buff[tx_rd_index]; Send a byte data and adjust the pointer
if (++tx_rd_index = = SIZE) Tx_rd_index = 0;
}
}
unsigned char getspichar (void)
{
unsigned char data;
while (Rx_counter = = 0); No receive data, wait
data = Spi_rx_buff[rx_rd_index]; Extract data received from an SPI from the receive buffer
if (++rx_rd_index = = SIZE) Rx_rd_index = 0; Adjust pointer
CLI ();
--rx_counter;
SEI ();
return data;
}
void Putspichar (char c)
{
while (tx_counter = SIZE);/Send buffer full, wait
CLI ();
if (Tx_counter | | ((SPSR & 0x80) = = 0)) Send buffer already in data to be sent
{//or SPI is sending data
Spi_tx_buffer[tx_wr_index] = c; To queue data into a send buffer
if (++tx_wr_index = = SIZE) Tx_wr_index = 0; Adjust pointer
++tx_counter;
}
Else
SPDR = C; The send buffer is hollow and the SPI port is idle, directly into the SPDR and sent by SIP port
SEI ();
}
void Spi_init (void)
{
unsigned chat temp;
DDRB |= 0x080; Miso=input and mosi,sck,ss = output
PORTB |= 0x80; Miso Tensile Resistance effective
SPCR = 0xd5; SPI allow, host mode, MSB, allow SPI interrupt, polarity mode 01,1/16 system clock rate
SPSR = 0x00;
temp = SPSR;
temp = SPDR; Empty SPI, and break flag to make SPI idle
}
void Main (void)
{
unsigned char I;
CLI (); Off interrupt
Spi_init (); Initializing the SPI interface
SEI (); Open Interrupt
while ()
{
Putspichat (i); Send a Byte
i++;
Getspichar (); Receives a byte (the first byte is a null byte)
.........
}
}
This typical SPI routine is simple, and the ATmega128 hardware SPI is initialized first in the main program. During initialization, the Mosi, SCLK, and SS pins of the PORTB are used as outputs, while the miso is used as the input pin and the pull resistor is turned on. Then the register of the SPI is initialized and the SPSR, SPDR registers (read SPSR and then SPDR operation will automatically clear 0 SPI interrupt flag automatically 0), so that the ISP is idle waiting to send data.
The AVR SPI is composed of a 16-bit cyclic shift register, and when data is moved from the host side, the data from the machine is also moved in, so that the sending and receiving of the SPI is done in an interrupt service. In the SPI Interrupt service program, first read a received byte from the SPDR into the receive data buffer, and then remove a byte from the sending data buffer to write to the SPDR, sent by the ISP to the machine. Once the data is written to the SPDR,ISP hardware begins to send the data. The next time the ISP breaks, it indicates that the send is complete and that a data is received at the same time. Similar to the use of the Usart interface described in this chapter, the Putspichar () and Getspichar () in the program are the underlying interface functions for the application (the SPI driver is the SPI Interrupt Service program), and two data buffers are used to form the loop queue respectively. The design of the program, not only the structural integrity of the procedure, but also appropriate to solve the high-speed MCU and low speed serial port between the contradictions, to achieve the task of parallel operation of the program, improve the operating efficiency of the MCU.
This routine is through the SPI batch output, the input data example, the user may use one ATmega128, will its mosi and the miso two pins link up, forms the ISP interface spontaneous self collection system, the demonstration verification to the program. Note that the byte actually received is the data that was emitted at the last interrupt, that is, the first byte received is a null byte.
Read and understand the process of processing ideas, readers can be based on the needs of the program to change, suitable for the actual system use. such as in the practical application of the machine is a SPI interface temperature chip, the protocol is: the host to send 3 consecutive bytes of the command, and then from the machine to return a byte of data. Then the user program can loop the call to the Putspichar () function 4 times, send the 3-byte command and a byte of NULL data to the machine, wait a while, or handle some other operation, and then loop the call to the Getspichar () function 4 times, Reads 4 bytes continuously from the receive data buffer, discards the first 3 empty bytes, and the 4th byte is the returned data from the machine.
Reproduced from: http://www.21cstar.com/dhome/2007/0823/content_1556.html