基于GCCAVR的模擬SPI程序
AVR的SPI接口很多只有一個(gè),如果驅(qū)動(dòng)較多的以SPI接口的外設(shè)時(shí)就必須通過(guò)IO來(lái)模擬,實(shí)際上對(duì)于低速外設(shè)來(lái)說(shuō)IO模擬的方式也很方便,網(wǎng)上關(guān)于模擬SPI的程序很多,我的程序是基于GCCAVR來(lái)寫(xiě)的,其他編譯器的都類(lèi)似,寫(xiě)的時(shí)候我盡量做到規(guī)范和方便后期使用時(shí)改動(dòng)調(diào)整。
使用時(shí)需要注意以下幾點(diǎn):
1、根據(jù)外設(shè)的時(shí)序要求,區(qū)分是在上升沿更新數(shù)據(jù)還是下降沿。
2、發(fā)送數(shù)據(jù)時(shí)高位在前還是地位在前。
3、外設(shè)對(duì)SPI通信有無(wú)速度要求,有些時(shí)候過(guò)快的通信速率可能無(wú)法讀取和寫(xiě)入數(shù)據(jù)
4、CLK,數(shù)據(jù)等引腳的平時(shí)電平
上面幾點(diǎn)只要對(duì)照著外設(shè)的時(shí)序圖一眼就能弄清楚,程序里面寫(xiě)的很清楚相應(yīng)的改動(dòng)一下就可以了。
程序如下:
/**************************(C) COPYRIGHT emouse 2011***************************
名稱(chēng):main.c
功能:模擬SPI程序測(cè)試
作者:emouse
時(shí)間:2011.1.11
版本:1.0
注意:無(wú)
*******************************************************************************/
#include"avr/io.h"
#include"avr/interrupt.h"
#include"util/delay.h"
#define SetBit(Port,N) (Port|=(1< #define ClrBit(Port,N) (Port&=~(1< #define ReverBit(Port,N) (Port^=(1< #define GetBit(Pin,N) ((Pin>>N)&0x01) //讀取IO某一位 /***************模擬SPI的相關(guān)宏定義********************/ #define SPI1_Port PORTC //設(shè)置使用的端口 #define SPI1_DDR DDRC #define SPI1_PIN PINC #define SPI1_CS 0 //設(shè)置每個(gè)信號(hào)對(duì)應(yīng)的引腳 #define SPI1_MISO 1 #define SPI1_MOSI 2 #define SPI1_CLK 3 #define SPI1_CS_H (SPI1_Port|=(1< #define SPI1_CS_L (SPI1_Port&=~(1< #define SPI1_GetMISO ((SPI1_PIN>>SPI1_MISO)&0x01) #define SPI1_MOSI_H (SPI1_Port|=(1< #define SPI1_MOSI_L (SPI1_Port&=~(1< #define SPI1_CLK_H (SPI1_Port|=(1< #define SPI1_CLK_L (SPI1_Port&=~(1< unsigned char spi_delay; //設(shè)置信號(hào)的持續(xù)時(shí)間,相當(dāng)于設(shè)置SPI的速度 /******************************************************************************* 名稱(chēng):void SPI1_Init() 功能:模擬SPI時(shí)序的端口初始化工作 參數(shù):無(wú) 時(shí)間:2011.1.11 版本:1.0 注意:無(wú) *******************************************************************************/ void SPI1_Init() { SPI1_Port|=((1< SPI1_DDR|=(((1< SPI1_CS_H; SPI1_CLK_L; spi_delay=5; } /******************************************************************************* 名稱(chēng):SPI1_Send(unsigned char data) 功能:發(fā)送SPI數(shù)據(jù) 參數(shù):unsigned char data 時(shí)間:2011.1.11 版本:1.0 注意:無(wú) *******************************************************************************/ void SPI1_Send(unsigned char data) { unsigned char i; SPI1_CS_L; //拉低片選信號(hào) SPI1_CLK_L; //時(shí)鐘空閑時(shí)為低電平 SPI1_MOSI_L; _delay_us(spi_delay); for(i=0;i<8;i++) { if(data&(0x80>>i))//高位在前,低位在前改為(0x01< SPI1_MOSI_H; else SPI1_MOSI_L; _delay_us(spi_delay); SPI1_CLK_H; //在上升沿更新數(shù)據(jù) _delay_us(spi_delay); SPI1_CLK_L; } _delay_us(spi_delay); SPI1_CS_H; //拉高片選,完成一次數(shù)據(jù)傳輸 } /******************************************************************************* 名稱(chēng):unsigned char SPI1_Get() 功能:接收SPI數(shù)據(jù) 參數(shù):返回data 時(shí)間:2011.1.11 版本:1.0 注意:無(wú) *******************************************************************************/ unsigned char SPI1_Get() { unsigned char i; unsigned char data=0x00; SPI1_CS_L; //拉低片選信號(hào) SPI1_CLK_L; //時(shí)鐘空閑時(shí)為低電平 SPI1_MOSI_L; _delay_us(spi_delay); for(i=0;i<8;i++) { if(SPI1_GetMISO) data|=(0x80>>i); _delay_us(spi_delay); SPI1_CLK_H; //在上升沿更新數(shù)據(jù) _delay_us(spi_delay); SPI1_CLK_L; } _delay_us(spi_delay); SPI1_CS_H; //拉高片選,完成一次數(shù)據(jù)傳輸 return data; } /******************************************************************************* 名稱(chēng):void USART0_Init(void) 功能:串口0初始化 參數(shù):無(wú) 時(shí)間:2011.1.11 版本:1.0 注意:無(wú) *******************************************************************************/ void USART0_Init(void) { UCSR0A=0x20; //波特率不加倍,單機(jī)通信模式 UCSR0B=0x18; //中斷不使能,允許發(fā)送和接收 UCSR0C=0x06;//異步模式,無(wú)校驗(yàn),8位數(shù)據(jù),1位停止位 UBRR0H=0x00; UBRR0L=51;//9600波特率 晶振8M } /******************************************************************************* 名稱(chēng):void USART0_Putc(unsigned char c) 功能:發(fā)送一個(gè)字符 參數(shù):unsigned char c 時(shí)間:2011.1.11 版本:1.0 注意:無(wú) *******************************************************************************/ void USART0_Putc(unsigned char c) { while(!(UCSR0A&(1< UDR0=c; //發(fā)送數(shù)據(jù) } /******************************************************************************* 名稱(chēng):void USART0_Puts(unsigned char * str) 功能:發(fā)送字符串 參數(shù):unsigned char * str 待發(fā)送的字符串 時(shí)間:2011.1.11 版本:1.0 注意:無(wú) *******************************************************************************/ void USART0_Puts(unsigned char * str) { while(*str) { USART0_Putc(*str++); } } int main(void) { unsigned char i=0; USART0_Init(); //初始化USART0接口 DDRA=0XFF; PORTA=0XFF; SPI1_Init(); USART0_Puts("SPI test"); while(1) { SPI1_Send(0x04); USART0_Putc(SPI1_Get()); ReverBit(PORTA,0); _delay_ms(500); } }