ATmega32 发表于 2008-5-7 09:42:56

请问:串口和SPI怎么转换?使用ATmega8

使用ATmega8,

半双工,MCU如果从串口接收数据,就把数据从SPI发送出去,
如果SPI收到数据,就把数据从串口发送出去,怎么实现?

ATmega32 发表于 2008-5-7 09:53:23

请问:SPI从机查询方式发送数据后,怎么清除SPIF位??

shenxf 发表于 2008-5-7 12:50:51

可以通过先读SPSR,紧接着访问SPDR来对SPIF清零

zsmbj 发表于 2008-5-7 13:43:02

我以前写的一个SPI<--->UART转换的程序:
中断发送

/**********************************************************************/
/* These are system macros and defines                              */
/**********************************************************************/
#define HIBYT(x)        (x)/256
#define LOBYT(x)        (x)%256

#define F_CPU                7372800                                //oscillator frequency
#define BAUD                115200
#define BAUDRATE        F_CPU/16/BAUD-1                        //baudrate=fosc/16/rate-1

#include <avr/io.h>
#include <avr/interrupt.h>

/**********************************************************************/
/* UART Buffer Defines                                                       */
/**********************************************************************/
#define UART_RX_BUFFER_SIZE 32 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 )
#define UART_TX_BUFFER_SIZE 32 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1 )

#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
#error UART RX buffer size is not a power of 2
#endif
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
#error UART TX buffer size is not a power of 2
#endif

/**********************************************************************/
/* SPI Buffer Defines                                                       */
/**********************************************************************/
#define SPI_RX_BUFFER_SIZE 32 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define SPI_RX_BUFFER_MASK ( SPI_RX_BUFFER_SIZE - 1 )
#define SPI_TX_BUFFER_SIZE 32 /* 1,2,4,8,16,32,64,128 or 256 bytes */
#define SPI_TX_BUFFER_MASK ( SPI_TX_BUFFER_SIZE - 1 )

#if ( SPI_RX_BUFFER_SIZE & SPI_RX_BUFFER_MASK )
#error SPI RX buffer size is not a power of 2
#endif
#if ( SPI_TX_BUFFER_SIZE & SPI_TX_BUFFER_MASK )
#error SPI TX buffer size is not a power of 2
#endif

/**********************************************************************/
/* These are microcontroller port and pin assgin                      */
/**********************************************************************/
//portb define
#define         SS                PB2                        //spi ss input
#define         MOSI                PB3                        //spi mosi input
#define         MISO                PB4                        //spi miso output
#define         SCK                PB5                        //spi sck input

/**********************************************************************/
/* These are the global variables                                     */
/**********************************************************************/
//UART related buffers and variables
unsigned char        UART_RxBuf;
volatile        unsigned char UART_RxHead;
volatile        unsigned char UART_RxTail;

unsigned char        UART_TxBuf;
volatile        unsigned char UART_TxHead;
volatile        unsigned char UART_TxTail;

//SPI related buffers and variables
unsigned char        SPI_RxBuf;
volatile        unsigned char SPI_RxHead;
volatile        unsigned char SPI_RxTail;

unsigned char        SPI_TxBuf;
volatile        unsigned char SPI_TxHead;
volatile        unsigned char SPI_TxTail;

//SPI TX and RX flag
volatile        unsigned char SPI_SendFlag = 0;

/*******************************
       MCU initialize
*******************************/
void init_system(void)
{
        DDRB = 0x00;                //PORTB in,
        PORTB = 0xFF;                //enable pullup

        DDRC = 0x00;                //PORTC in,not used
        PORTC = 0xFF;                //enable pullup

        DDRD = 0x00;                //PORTD in,not used
        PORTD = 0xFF;                //enable pullup

        ACSR |= (1<<ACD);        //close Analog Comparator
}       

/**********************************************************************/
/* initialize SPI */
/**********************************************************************/

/* initialize spi */
void init_SPI( void )
{
        //set MISO as output
        DDRB |= (1<<MISO);
        //set MISO output low
        PORTB &= ~(1<<MISO);
        //set SS as input
        DDRB &= ~(1<<SS);
        //set SS pull high
        PORTB |= (1<<SS);
        //SPI interrupt and SPI enable;
        //Slave SPI,MSB send first,fall edge
        SPCR = (1<<SPIE) | (1<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (1<<CPHA);
       
        SPDR = 0;        //clear SPDR data

        /* flush buffer */
        SPI_RxTail = 0;
        SPI_RxHead = 0;
        SPI_TxTail = 0;
        SPI_TxHead = 0;}


void SPI_DATA(unsigned char dat)
{
        SPDR = dat;
}

/**********************************************************************/
/* interrupt of SPI send complele */
/**********************************************************************/
SIGNAL(SIG_SPI)
{
        unsigned char data;
        unsigned char tmphead,tmptail;
       
//received SPI data,if no data then received 0
        data = SPDR; /* read the received data */
        /* calculate buffer index */
        tmphead = ( SPI_RxHead + 1 ) & SPI_RX_BUFFER_MASK;
        SPI_RxHead = tmphead; /* store new index */
        if ( tmphead == SPI_RxTail )
        {
                /* ERROR! Receive buffer overflow */
        }
        SPI_RxBuf = data; /* store received data in buffer */

//send SPI data,if no data then send 0
        /* check if all data is transmitted */
        if ( SPI_TxHead != SPI_TxTail )
        {
                /* calculate buffer index */
                tmptail = ( SPI_TxTail + 1 ) & SPI_TX_BUFFER_MASK;
                SPI_TxTail = tmptail; /* store new index */
                data = SPI_TxBuf; /* get data */
        }
        else
        {
                data = 0;
                SPI_SendFlag = 0;        //clear send flag
        }
        SPDR = data;                //send spi data
}

/**********************************************************************/
/* SPI Buffer Read and write and Buffer check functions */
/**********************************************************************/
unsigned char SPIReceiveByte( void )
{
        unsigned char tmptail;

        while ( SPI_RxHead == SPI_RxTail ) /* wait for incomming data */
                ;
        tmptail = ( SPI_RxTail + 1 ) & SPI_RX_BUFFER_MASK;/* calculate buffer index */
        SPI_RxTail = tmptail; /* store new index */
        return SPI_RxBuf; /* return data */
}

void SPITransmitByte( unsigned char data )
{
        unsigned char tmphead;
       
        tmphead = ( SPI_TxHead + 1 ) & SPI_TX_BUFFER_MASK; /* calculate buffer index */
        while ( tmphead == SPI_TxTail )/* wait for free space in buffer */
                ;
        SPI_TxBuf = data; /* store data in buffer */
        SPI_TxHead = tmphead; /* store new index */
}

unsigned char SPIDataInReceiveBuffer( void )
{
        return        ( SPI_RxHead != SPI_RxTail );
                /* return 0 (FALSE) if the receive buffer is empty */
}

/**********************************************************************/
/* initialize UART*/
/**********************************************************************/
void init_UART( void )
{
        //UBRR = BAUDRATE; /* set the baud rate */
        UBRRL = LOBYT(BAUDRATE);
        UBRRH = HIBYT(BAUDRATE);
       
        /* enable UART receiver and transmitter, and
        receive interrupt */
        //UART 115200,8,N,1 type
        UCSRA = 0;
        UCSRB = ( (1<<RXCIE) | (1<<RXEN) | (1<<TXEN) );
        UCSRC = ( (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0) );
        /* flush buffer */
        UART_RxTail = 0;
        UART_RxHead = 0;
        UART_TxTail = 0;
        UART_TxHead = 0;
}

/**********************************************************************/
/* interrupt of UART RX. */
/**********************************************************************/
SIGNAL (SIG_UART_RECV)
{
        unsigned char data;
        unsigned char tmphead;
        data = UDR; /* read the received data */
        /* calculate buffer index */
        tmphead = ( UART_RxHead + 1 ) & UART_RX_BUFFER_MASK;
        UART_RxHead = tmphead; /* store new index */
        if ( tmphead == UART_RxTail )
        {
                /* ERROR! Receive buffer overflow */
        }
        UART_RxBuf = data; /* store received data in buffer */
       
}

/**********************************************************************/
/* interrupt of UART UDRIE. */
/**********************************************************************/
SIGNAL (SIG_UART_DATA)
{
        unsigned char tmptail;

        /* check if all data is transmitted */
        if ( UART_TxHead != UART_TxTail )
        {
                /* calculate buffer index */
                tmptail = ( UART_TxTail + 1 ) & UART_TX_BUFFER_MASK;
                UART_TxTail = tmptail; /* store new index */
                UDR = UART_TxBuf; /* start transmition */
        }
        else
        {
                UCSRB &= ~(1<<UDRIE); /* disable UDRE interrupt */
        }
}


/**********************************************************************/
/* UART Buffer Read and write and Buffer check functions */
/**********************************************************************/
unsigned char UARTReceiveByte( void )
{
        unsigned char tmptail;

        while ( UART_RxHead == UART_RxTail ) /* wait for incomming data */
                ;
        tmptail = ( UART_RxTail + 1 ) & UART_RX_BUFFER_MASK;/* calculate buffer index */
        UART_RxTail = tmptail; /* store new index */
        return UART_RxBuf; /* return data */
}

void UARTTransmitByte( unsigned char data )
{
        unsigned char tmphead;
       
        tmphead = ( UART_TxHead + 1 ) & UART_TX_BUFFER_MASK; /* calculate buffer index */
        while ( tmphead == UART_TxTail )/* wait for free space in buffer */
                ;
        UART_TxBuf = data; /* store data in buffer */
        UART_TxHead = tmphead; /* store new index */
        UCSRB |= (1<<UDRIE); /* enable UDRE interrupt */
}

unsigned char UARTDataInReceiveBuffer( void )
{
        return        ( UART_RxHead != UART_RxTail );
                /* return 0 (FALSE) if the receive buffer is empty */
}

/**********************************************************************/
/*main program        */
/**********************************************************************/
int main(void)
{
unsigned char        temp;
       
        init_system();                //init MCU
        init_UART();                //init UART
        init_SPI();                //init SPI

        sei();                      //enable global interrupt

        while(1)
        {
//                wdt_reset();        //reset wdt

                if( SPIDataInReceiveBuffer() )                                //if SPI received data
                {
                        temp = SPIReceiveByte();                        //get SPI data
                        UARTTransmitByte(temp);                                //send to UART buffer
                }

                if( UARTDataInReceiveBuffer() )                                //if UART received data
                {
                        if( SPI_SendFlag == 0 )                                //if send first SPI data
                        {
                                temp = UARTReceiveByte();        //get uart data
                                SPI_DATA(temp);                        //send SPI SPCR to start SPI
                                SPI_SendFlag = 1;                        //SPI send status

                        //        UARTTransmitByte(temp);                //test SPI send
                        }
                        else                                                //if send other SPI data continued
                        {
                                temp = UARTReceiveByte();                //get uart data
                                SPITransmitByte(temp);                        //send to SPI buffer

                        //        UARTTransmitByte(temp);                        //test SPI send
                        }
                }
        }
}

//end of program

mljda 发表于 2008-5-7 14:08:40

程序很漂亮。谢谢

zhuzi1441 发表于 2008-5-7 16:05:40

很好,记个号

yibin818 发表于 2008-5-7 18:33:14

记号

mtheory 发表于 2008-5-7 21:18:24

学习一下!!!

pansheng0251 发表于 2009-8-3 15:52:44

zsmbj朋友,你的代码我移植到atmega16上用,出现个问题,现在SPI接收,UART发送正常,UART接收也正常,但是SPI发送有问题
比如说,一个帧16个字节,我只发出去2个字节,其他的全都丢了,没发出去,uart的速度是115200,spi的速度是500k左右,虽然spi快,但是按照你的程序,至少会发0出去,spi这我能看到0,但是我看不到,我看到的是他自己返回的数据,比如说SPI发11 22 33 44 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0 f0过来,我要他在发f0的时候返数据给他,我返回的数据是11 22 33 44 00 00 00 00 00 00 00 00 01 00 00 00,但是我SPI打印出来看到的是11 22 f0 f0 f0 f0 f0 f0 00 f0 f0 f0 f0 80这种样子,33 44 01 这些数据都丢了,不知道是什么问题。

ylzouzhenyu 发表于 2011-7-3 20:43:03

很好,收藏了。

tthappy2008 发表于 2011-7-4 10:11:01

学习了。。先占座。。。等有时间了再来研究。。。

ysu533 发表于 2011-10-21 20:19:25

mark spi uart

gao_hailong 发表于 2011-10-23 11:09:45

MARK

nbmsse 发表于 2014-6-26 20:34:49

要看看是如何用的.

rockyyangyang 发表于 2014-6-29 11:01:31

4楼写的不错啊                  

xranger 发表于 2014-8-6 10:22:34

分享的代码不错
页: [1]
查看完整版本: 请问:串口和SPI怎么转换?使用ATmega8