📄 spi.c
字号:
//********************************************************************************************
//
// Title : MP3测试 - SPI驱动程序
// Author : Pascal Stang - Copyright (C) 2000-2002
// Created : 2005/02/16
// Revised : 2005/02/19
// Version : 0.1
// Target MCU : MEGA16
// Editor Tabs : 4
//
// 本文件来自"Procyon AVRlib".
//
// 注: 本代码用于测试STA013硬件及其驱动程序, 并非一个完整的MP3播放器程序.
// 上电后,会循环不停播放一段约2秒的MP3音乐.
// 硬件没有连接RAM缓冲及储存MP3文件的设备, MP3数据是保存在AVR的FLASH中.
// 本代码经测试, 但可能存有Bugs, 若你发现有任何Bug或有任何建议,
// 请来信告知: gz_ant@126.com
//// 本代码部分来自"Procyon AVRlib": http://hubbard.engr.scu.edu/embedded/avr/avrlib/release_notes.html
// 特此感谢它的创始人: Pascal Stang !
//
// 感谢在www.21icbbs.com帮助过winsu的朋友, 希望使用者能发扬网络的 "自由,开放" 精神.
//********************************************************************************************
/*! \file spi.c \brief SPI interface driver. */
//*****************************************************************************
//
// File Name : 'spi.c'
// Title : SPI interface driver
// Author : Pascal Stang - Copyright (C) 2000-2002
// Created : 11/22/2000
// Revised : 06/06/2002
// Version : 0.6
// Target MCU : Atmel AVR series
// Editor Tabs : 4
//
// NOTE: This code is currently below version 1.0, and therefore is considered
// to be lacking in some functionality or documentation, or may not be fully
// tested. Nonetheless, you can expect most functions to work.
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include "type.h"
#include "main.h"
#include "spi.h"
// Define the SPI_USEINT key if you want SPI bus operation to be
// interrupt-driven. The primary reason for not using SPI in
// interrupt-driven mode is if the SPI send/transfer commands
// will be used from within some other interrupt service routine
// or if interrupts might be globally turned off due to of other
// aspects of your program
//
// Comment-out or uncomment this line as necessary
#define SPI_USEINT
// global variables
volatile u8 spiTransferComplete;
// SPI interrupt service handler
#ifdef SPI_USEINT
SIGNAL(SIG_SPI)
{
spiTransferComplete = TRUE;
}
#endif
// access routines
void spiInit()
{
#ifdef __AVR_ATmega128__
// setup SPI I/O pins
sbi(PORTB, 1); // set SCK hi
sbi(DDRB, 1); // set SCK as output
cbi(DDRB, 3); // set MISO as input
sbi(DDRB, 2); // set MOSI as output
sbi(DDRB, 0); // SS must be output for Master mode to work
#else
// setup SPI I/O pins
sbi(PORTB, 7); // set SCK hi
sbi(DDRB, 7); // set SCK as output
cbi(DDRB, 6); // set MISO as input
sbi(DDRB, 5); // set MOSI as output
sbi(DDRB, 4); // SS must be output for Master mode to work
#endif
// setup SPI interface :
// master mode
sbi(SPCR, MSTR);
// clock = f/4
// cbi(SPCR, SPR0);
// cbi(SPCR, SPR1);
// clock = f/16
cbi(SPCR, SPR0);
sbi(SPCR, SPR1);
// select clock phase positive-going in middle of data
cbi(SPCR, CPOL);
// Data order MSB first
cbi(SPCR,DORD);
// enable SPI
sbi(SPCR, SPE);
// some other possible configs
//outp((1<<MSTR)|(1<<SPE)|(1<<SPR0), SPCR );
//outp((1<<CPHA)|(1<<CPOL)|(1<<MSTR)|(1<<SPE)|(1<<SPR0)|(1<<SPR1), SPCR );
//outp((1<<CPHA)|(1<<MSTR)|(1<<SPE)|(1<<SPR0), SPCR );
// clear status
inp(SPSR);
spiTransferComplete = TRUE;
// enable SPI interrupt
#ifdef SPI_USEINT
sbi(SPCR, SPIE);
#endif
}
/*
void spiSetBitrate(u8 spr)
{
outb(SPCR, (inb(SPCR) & ((1<<SPR0)|(1<<SPR1))) | (spr&((1<<SPR0)|(1<<SPR1)))));
}
*/
void spiSendByte(u8 data)
{
// send a byte over SPI and ignore reply
#ifdef SPI_USEINT
while(!spiTransferComplete);
#else
while(!(inp(SPSR) & (1<<SPIF)));
#endif
spiTransferComplete = FALSE;
outp(data, SPDR);
}
u8 spiTransferByte(u8 data)
{
// make sure interface is idle
#ifdef SPI_USEINT
while(!spiTransferComplete);
#else
while(!(inp(SPSR) & (1<<SPIF)));
#endif
// send the given data
spiTransferComplete = FALSE;
outp(data, SPDR);
// wait for transfer to complete
#ifdef SPI_USEINT
while(!spiTransferComplete);
#else
while(!(inp(SPSR) & (1<<SPIF)));
// *** reading of the SPSR and SPDR are crucial
// *** to the clearing of the SPIF flag
// *** in non-interrupt mode
//inp(SPDR);
// set flag
spiTransferComplete = TRUE;
#endif
// return the received data
return inp(SPDR);
}
u16 spiTransferWord(u16 data)
{
u16 rxData = 0;
// send MS byte of given data
rxData = (spiTransferByte((data>>8) & 0x00FF))<<8;
// send LS byte of given data
rxData |= (spiTransferByte(data & 0x00FF));
// return the received data
return rxData;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -