请问:串口和SPI怎么转换?使用ATmega8
使用ATmega8,半双工,MCU如果从串口接收数据,就把数据从SPI发送出去,
如果SPI收到数据,就把数据从串口发送出去,怎么实现? 请问:SPI从机查询方式发送数据后,怎么清除SPIF位?? 可以通过先读SPSR,紧接着访问SPDR来对SPIF清零 我以前写的一个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 程序很漂亮。谢谢 很好,记个号 记号 学习一下!!! 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 这些数据都丢了,不知道是什么问题。 很好,收藏了。 学习了。。先占座。。。等有时间了再来研究。。。 mark spi uart MARK 要看看是如何用的. 4楼写的不错啊 分享的代码不错
页:
[1]