搜索
bottom↓
回复: 15

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

[复制链接]

出0入0汤圆

发表于 2008-5-7 09:42:56 | 显示全部楼层 |阅读模式
使用ATmega8,

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2008-5-7 09:53:23 | 显示全部楼层
请问:SPI从机查询方式发送数据后,怎么清除SPIF位??

出0入0汤圆

发表于 2008-5-7 12:50:51 | 显示全部楼层
可以通过先读SPSR,紧接着访问SPDR来对SPIF清零

出0入0汤圆

发表于 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[UART_RX_BUFFER_SIZE];
volatile        unsigned char UART_RxHead;
volatile        unsigned char UART_RxTail;

unsigned char        UART_TxBuf[UART_TX_BUFFER_SIZE];
volatile        unsigned char UART_TxHead;
volatile        unsigned char UART_TxTail;

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

unsigned char        SPI_TxBuf[SPI_TX_BUFFER_SIZE];
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[tmphead] = 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[tmptail]; /* 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[tmptail]; /* 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[tmphead] = 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[tmphead] = 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[tmptail]; /* 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[tmptail]; /* 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[tmphead] = 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

出0入0汤圆

发表于 2008-5-7 14:08:40 | 显示全部楼层
程序很漂亮。谢谢

出0入0汤圆

发表于 2008-5-7 16:05:40 | 显示全部楼层
很好,记个号

出0入0汤圆

发表于 2008-5-7 18:33:14 | 显示全部楼层
记号

出0入0汤圆

发表于 2008-5-7 21:18:24 | 显示全部楼层
学习一下!!!

出0入0汤圆

发表于 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 这些数据都丢了,不知道是什么问题。

出0入0汤圆

发表于 2011-7-3 20:43:03 | 显示全部楼层
很好,收藏了。

出0入0汤圆

发表于 2011-7-4 10:11:01 | 显示全部楼层
学习了。。先占座。。。等有时间了再来研究。。。

出0入0汤圆

发表于 2011-10-21 20:19:25 | 显示全部楼层
mark spi uart

出0入0汤圆

发表于 2011-10-23 11:09:45 | 显示全部楼层
MARK

出0入0汤圆

发表于 2014-6-26 20:34:49 | 显示全部楼层
要看看是如何用的.

出0入0汤圆

发表于 2014-6-29 11:01:31 | 显示全部楼层
4楼写的不错啊                  

出0入0汤圆

发表于 2014-8-6 10:22:34 | 显示全部楼层
分享的代码不错
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 09:49

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表