?? spi_2dpj_slave.c
字號(hào):
/*****************************************************
**** AVR SPI總線使用范例(兩個(gè)mega16) ***
**** 作者: liugangdi ***
**** 編譯器:WINAVR20050214 ***
**** 日期:2005.11.15 ***
***********************************************/
/*
從機(jī)功能簡(jiǎn)介:通過SPI實(shí)現(xiàn)兩機(jī)通訊, 采用中斷方式實(shí)現(xiàn)雙全工通訊。
本例用兩MEGA16實(shí)現(xiàn),連接為:
MISO----MISO
MOSI----MOSI
SCK ----SCK
/SS ----/SS
將要發(fā)送的數(shù)據(jù)加載到發(fā)送緩沖區(qū)的函數(shù)fill_tx_buffer()
和從接收緩沖區(qū)讀出數(shù)據(jù)的函數(shù)read_rx_buffer()
注意:從機(jī)程序和主機(jī)程序基本相同,只是將該單片機(jī)該為從同步方式即可,2機(jī)運(yùn)行時(shí),從機(jī)先開機(jī)等待甲機(jī)SPI發(fā)送*/
//注: 內(nèi)部函數(shù)_delay_ms() 最高延時(shí) 262.144mS@1MHz
// ffor()/while()語句計(jì)算延時(shí)時(shí)間較麻煩。
// 為了使 _delay_ms()函數(shù)的延時(shí)正確,須在makefile中設(shè)定F_CPU為實(shí)際的系統(tǒng)時(shí)鐘頻
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#define uint unsigned int
#define uchar unsigned char
#define SPI_RX_BUFFER_SIZE 11
#define SPI_RX_BUFFER_MASK SPI_RX_BUFFER_SIZE - 1
#define SPI_TX_BUFFER_SIZE 11
#define SPI_TX_BUFFER_MASK SPI_TX_BUFFER_SIZE - 1
unsigned char SPI_RxBuf[SPI_RX_BUFFER_SIZE];
volatile unsigned char SPI_RxHead;
unsigned char SPI_TxBuf[SPI_TX_BUFFER_MASK];
volatile unsigned char SPI_TxHead;
uchar Tx_counter,spi_trans_com;
//***************************************************
//七段數(shù)碼管顯示函數(shù)
//***************************************************
void disp(unsigned char data)
{ DDRB=0xFF;
DDRA=0xFF;
PORTA&=~(1<<6);
PORTB=data;
}
//***************************************************
// 要發(fā)送的數(shù)據(jù)加載到發(fā)送緩沖區(qū)的函數(shù)fill_tx_buffer()
//***************************************************
void fill_tx_buffer(void)
{
uchar SPI_TxBuf[SPI_TX_BUFFER_MASK]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
}
//***************************************************
// 從接收緩沖區(qū)讀出數(shù)據(jù)的函數(shù)read_rx_buffer()
//***************************************************
void read_rx_buffer(void)
{
/*for(uint i=1;i<SPI_TX_BUFFER_SIZE;i++)
{disp(SPI_RxBuf[i]);
for (uint k=0;k<50 ;k++) _delay_ms(20) ; //延時(shí)
}*/
if(SPI_RxBuf[1]==0xc0&&SPI_RxBuf[2]==0xf9&&SPI_RxBuf[3]==0xa4&&SPI_RxBuf[4]==0xb0&&SPI_RxBuf[5]==0x99
&&SPI_RxBuf[6]==0x92&&SPI_RxBuf[7]==0x82&&SPI_RxBuf[8]==0xf8&&SPI_RxBuf[9]==0x80&&SPI_RxBuf[10]==0x90)
PORTC&=~(1<<5); //如果接收的都正確則燈點(diǎn)亮
}
//******************************************
// SPI 中斷服務(wù)程序 interrupt [SPI_STC]:11
//******************************************
SIGNAL(SIG_SPI)
{
SPI_RxBuf[SPI_RxHead] = SPDR; //從ISP口讀出收到的字節(jié)
if (SPI_RxHead == SPI_RX_BUFFER_MASK) //如果是接收幀的最后一個(gè)數(shù)據(jù)
{
SPI_RxHead = 0; //已接收數(shù)據(jù)還原
spi_trans_com=1; //置接收完成標(biāo)志
}
else
{
SPI_RxHead++; //已接收數(shù)據(jù)計(jì)數(shù)器加1
}
if (Tx_counter) //如果發(fā)送緩沖區(qū)中有待發(fā)的數(shù)據(jù)
{
--Tx_counter;
SPDR=SPI_TxBuf[SPI_TxHead]; //發(fā)送一個(gè)字節(jié)數(shù)據(jù),并調(diào)整指針
if (++SPI_TxHead ==SPI_TX_BUFFER_MASK)
{SPI_TxHead = 0;
Tx_counter=SPI_TX_BUFFER_MASK;
}
}
}
//**************************************************************
// SPI 初始化 (MEGA16 PB4——/SS,PB5——MOSI,PB6——MISO,PB7——SCK)
//**************************************************************
void spi_init(void)
{
unsigned char temp;
DDRB = 0xB0; //MISO=input and MOSI,SCK,SS = output
PORTB = 0x40; //MISO上拉電阻有效
SPCR = 0xC5; //SPI允許,從機(jī)模式,MSB,允許SPI中斷,極性方式01,1/16系統(tǒng)時(shí)鐘速率
SPSR = 0x00;
temp = SPSR;
temp = SPDR; //清空SPI,和中斷標(biāo)志,使SPI空閑
}
//***************************************************************
//將數(shù)據(jù)0XFF送給SPDR,等待主機(jī)發(fā)送,(接收方接收到的第一個(gè)數(shù)據(jù)為0xFF應(yīng)忽略 )
//***************************************************************
void spi_send(void)
{
fill_tx_buffer(); //調(diào)用fill_tx_buffer函數(shù),將要發(fā)送的數(shù)據(jù)加載到發(fā)送緩沖區(qū)
spi_init(); //初始化spi為從方式
SPDR=0xFF; //開始發(fā)送,接收方接收到的第一個(gè)數(shù)據(jù)為0xFF應(yīng)忽略
sei(); //開總中斷
SPCR|=(1<<SPIE)|(1<<SPE); //使能SPI,開SPI中斷
SPI_TxHead = 0; //已發(fā)送數(shù)據(jù)計(jì)數(shù)器清0
}
int main(void)
{
PORTC=0xFF;
DDRC=0xFF; //PC口設(shè)為輸出高電平,燈滅
SPI_RxHead=0;
SPI_TxHead=0;
Tx_counter=SPI_TX_BUFFER_MASK;
spi_send();
while(1)
{
if(spi_trans_com==1) //如果接收完成標(biāo)志為1,表明有所數(shù)據(jù)已接收
{
read_rx_buffer(); //調(diào)用read_rx_buffer函數(shù),將接收到的數(shù)據(jù)從接收緩沖區(qū)讀出
spi_trans_com=0; //讀完清除接收完成標(biāo)志
}
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -