?? main.c
字號(hào):
/***********************************************
**** AVR SPI接口使用范例 ***
**** ***
**** 作者: HJJourAVR ***
**** 編譯器:WINAVR20050214 ***
**** ***
**** www.OurAVR.com 2005.9.26 ***
***********************************************/
/*
本程序簡(jiǎn)單的示范了如何使用AVR ATMEGA16的SPI接口來(lái)訪問(wèn)DS1302 RTC實(shí)時(shí)時(shí)鐘芯片
串行外設(shè)接口-SPI
DS1302的讀寫控制
USART跟PC連接,實(shí)現(xiàn)顯示和控制
*/
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
//時(shí)鐘定為外部晶振 7.3728MHz,F_CPU=7372800
#include "main.h"
unsigned char DS1302_EXIST;
unsigned char INITDATE[8]={0x50, //59秒
0x59, //59分
0x23, //23時(shí) 24小時(shí)制
0x06, //06日
0x10, //10月
0x04, //星期四
0x05, //2005年
0x80 //寫保護(hù)
};
unsigned char CURDATE[7];
unsigned char sCURDATE[]="20xx年xx月xx日xx時(shí)xx分xx秒 星期xx";
unsigned char sWEEK[]="錯(cuò)一二三四五六日";
//注意 漢字要占用2個(gè)字節(jié)的空間
int main(void)
{
//上電默認(rèn)DDRx=0x00,PORTx=0x00 輸入,無(wú)上拉電阻
PORTA=0xFF; //不用的管腳使能內(nèi)部上拉電阻。
PORTC=0xFF;
PORTD=0xFF;
DDRD=(1<<PIN_TXD); //串口的輸出
PORTB=~((1<<DS1302_CE)|(1<<DS1302_MOSI)|(1<<DS1302_MISO)|(1<<DS1302_SCK));
//DS1302帶內(nèi)部下拉電阻
DDRB =(1<<DS1302_CE)|(1<<DS1302_SCK)|(1<<DS1302_MOSI);
//設(shè)定SPI接口
init_USART();
init_SPI();
put_s("這是個(gè)簡(jiǎn)單的SPI接口訪問(wèn)DS1302實(shí)時(shí)時(shí)鐘(RTC)的程序");
DS1302_EXIST=check_RTC(); //檢測(cè)DS1302的存在
if(DS1302_EXIST)
{
put_s("按下[I]鍵可以初始化RTC時(shí)間,默認(rèn)為2005年10月06日23時(shí)59分50秒 星期四");
put_s("按下[R]鍵可以讀取當(dāng)前時(shí)間");
put_s("用戶可以自行開(kāi)發(fā)其他功能");
put_s(" www.ouravr.com");
}
else
put_s("RTC找不到!");
sei(); //使能全局中斷
while(1);
}
/*
串行外設(shè)接口-SPI
SPI接口可以令A(yù)Tmega16 和外設(shè)或其他AVR器件進(jìn)行高速的同步數(shù)據(jù)傳輸
ATmega16的SPI接口同時(shí)還用來(lái)實(shí)現(xiàn)程序和EEPROM的下載和上載。請(qǐng)參見(jiàn)[SPI串行編程和校驗(yàn)]。
SPI系統(tǒng)包括兩個(gè)移位寄存器和一個(gè)主機(jī)時(shí)鐘發(fā)生器。
主機(jī)和從機(jī)將需要發(fā)送的數(shù)據(jù)放入相應(yīng)的移位寄存器。
主機(jī)在SCK 引腳上產(chǎn)生時(shí)鐘脈沖以交換數(shù)據(jù)。
主機(jī)的數(shù)據(jù)從主機(jī)的MOSI 移出,從從機(jī)的MOSI 移入;從機(jī)的數(shù)據(jù)從從機(jī)的MISO 移出,從主機(jī)的MISO 移入
(其實(shí)就是由主機(jī)和從機(jī)構(gòu)成一個(gè)16位的循環(huán)移位寄存器,所以收發(fā)數(shù)據(jù)是同時(shí)的,收發(fā)函數(shù)可以寫成一條函數(shù))
SPI系統(tǒng)的發(fā)送方向只有一個(gè)緩沖器,而在接收方向有兩個(gè)緩沖器。
也就是說(shuō),在發(fā)送時(shí)一定要等到移位過(guò)程全部結(jié)束后才能對(duì)SPI 數(shù)據(jù)寄存器執(zhí)行寫操作。
而在接收數(shù)據(jù)時(shí),需要在下一個(gè)字符移位過(guò)程結(jié)束之前通過(guò)訪問(wèn)SPI 數(shù)據(jù)寄存器讀取當(dāng)前接收到的字符。
否則第一個(gè)字節(jié)將丟失。
SS引腳的功能
1從機(jī)模式
從機(jī)模式當(dāng)SPI配置為從機(jī)時(shí),從機(jī)選擇引腳SS總是為輸入。
SS 為低將激活SPI 接口, MISO成為輸出( 用戶必須進(jìn)行相應(yīng)的端口配置) 引腳,其他引腳成為輸入引腳。
當(dāng)SS 為高時(shí)所有的引腳成為輸入, SPI 邏輯復(fù)位,不再接收數(shù)據(jù)。
SS引腳對(duì)于數(shù)據(jù)包/字節(jié)的同步非常有用,可以使從機(jī)的位計(jì)數(shù)器與主機(jī)的時(shí)鐘發(fā)生器同步。
當(dāng)SS 拉高時(shí)SPI從機(jī)立即復(fù)位接收和發(fā)送邏輯,并丟棄移位寄存器里不完整的數(shù)據(jù)。
2主機(jī)模式
當(dāng)SPI 配置為主機(jī)時(shí)(MSTR 的SPCR 置位),用戶可以決定SS 引腳的方向。
若SS 配置為輸出,則此引腳可以用作普通的I/O 口而不影響SPI 系統(tǒng)。典型應(yīng)用是用來(lái)驅(qū)動(dòng)從機(jī)的SS 引腳。
(單主機(jī)系統(tǒng),SS引腳最好設(shè)成輸出)
如果SS 配置為輸入,必須保持為高以保證SPI 的正常工作。
若系統(tǒng)配置為主機(jī), SS 為輸入,但被外設(shè)拉低,則SPI 系統(tǒng)會(huì)將此低電平解釋為有一個(gè)外部主機(jī)將自己選擇為從機(jī)。
為了防止總線沖突, SPI 系統(tǒng)將實(shí)現(xiàn)如下動(dòng)作:
1. 清零SPCR 的MSTR 位,使SPI 成為從機(jī),從而MOSI 和SCK 變?yōu)檩斎搿? 2. SPSR 的SPIF 置位。若SPI 中斷和全局中斷開(kāi)放,則中斷服務(wù)程序?qū)⒌玫綀?zhí)行。
因此,使用中斷方式處理SPI 主機(jī)的數(shù)據(jù)傳輸,并且存在SS 被拉低的可能性時(shí),中斷服務(wù)程序應(yīng)該檢查MSTR 是否為"1”。
若被清零,用戶必須將其置位,以重新使能SPI 主機(jī)模式。
數(shù)據(jù)模式(中文手冊(cè)有點(diǎn)混亂,請(qǐng)參考英文原版)
相對(duì)于串行數(shù)據(jù), SCK的相位和極性有4種組合,由CPHA和CPOL控制組合的方式。
SPI模式 CPOL CPHA 起始沿 結(jié)束沿
0 0 0 采樣(上升沿) 設(shè)置(下降沿)
1 0 1 設(shè)置(上升沿) 采樣(下降沿)
2 1 0 采樣(下降沿) 設(shè)置(上升沿)
3 1 1 設(shè)置(下降沿) 采樣(上升沿)
SPI控制寄存器-SPCR
Bit 7 – SPIE: 使能SPI 中斷
置位后,只要SPSR 寄存器的SPIF 和SREG 寄存器的全局中斷使能位置位,就會(huì)引發(fā)SPI 中斷。
Bit 6 – SPE: 使能SPI
SPE 置位將使能SPI。進(jìn)行任何SPI 操作之前必須置位SPE。
Bit 5 – DORD: 數(shù)據(jù)次序
DORD 置位時(shí)數(shù)據(jù)的LSB 首先發(fā)送;否則數(shù)據(jù)的MSB 首先發(fā)送。
Bit 4 – MSTR: 主/ 從選擇
MSTR置位時(shí)選擇主機(jī)模式,否則為從機(jī)。
如果MSTR為"1”,SS配置為輸入,但被拉低,則MSTR 被清零,寄存器SPSR 的SPIF 置位。
用戶必須重新設(shè)置MSTR 進(jìn)入主機(jī)模式
Bit 3 – CPOL: 時(shí)鐘極性
CPOL 置位表示空閑時(shí)SCK 為高電平;否則空閑時(shí)SCK 為低電平。
Bit 2 – CPHA: 時(shí)鐘相位
CPHA 決定數(shù)據(jù)是在SCK 的起始沿采樣還是在SCK 的結(jié)束沿采樣。
Bits 1, 0 – SPR1, SPR0: SPI 時(shí)鐘速率選擇1 與0
確定主機(jī)的SCK 速率。
SPR1 和SPR0 對(duì)從機(jī)沒(méi)有影響。
SCK 和振蕩器的時(shí)鐘頻率fosc關(guān)系如下表所示:
SPI2X SPR1 SPR0 SCK 頻率
0 0 0 fosc/4
0 0 1 fosc/16
0 1 0 fosc/64
0 1 1 fosc/128
1 0 0 fosc/2
1 0 1 fosc/8
1 1 0 fosc/32
1 1 1 fosc/64
SPI狀態(tài)寄存器-SPSR
Bit 7 – SPIF: SPI 中斷標(biāo)志
串行發(fā)送結(jié)束后,SPIF 置位。
若此時(shí)寄存器SPCR 的SPIE 和全局中斷使能位置位,SPI中斷即產(chǎn)生。
如果SPI 為主機(jī), SS 配置為輸入,且被拉低, SPIF 也將置位。
進(jìn)入中斷服務(wù)程序后SPIF自動(dòng)清零。
或者可以通過(guò)先讀SPSR,緊接著訪問(wèn)SPDR來(lái)對(duì)SPIF清零。
Bit 6 – WCOL: 寫碰撞標(biāo)志
在發(fā)送當(dāng)中對(duì)SPI 數(shù)據(jù)寄存器SPDR寫數(shù)據(jù)將置位WCOL。
WCOL可以通過(guò)先讀SPSR,緊接著訪問(wèn)SPDR 來(lái)清零。
Bit 0 – SPI2X: SPI 倍速
置位后SPI 的速度加倍。
若為主機(jī),則SCK 頻率可達(dá)CPU 頻率的一半。
若為從機(jī),只能保證fosc /4。
SPI數(shù)據(jù)寄存器-SPDR
SPI數(shù)據(jù)寄存器為讀/寫寄存器,用來(lái)在寄存器文件和SPI移位寄存器之間傳輸數(shù)據(jù)。
寫寄存器將啟動(dòng)數(shù)據(jù)傳輸,
讀寄存器將讀取寄存器的接收緩沖器。
*/
/*
DS1302的SPI接口特點(diǎn):
1 I/O共用一個(gè)引腳,故M16的MOSI要串10K電阻到MISO,然后把MISO跟DS1302_IO腳短接在一起的
2 低位在先
3 SPI模式0 CPOL = 0, CPHA = 0,空閑時(shí)SCK為低電平,上升沿采樣,下降沿設(shè)置
4 CE引腳為使能端,高電平使能SPI口
5 最高時(shí)鐘速度 2MHz@Vcc=5V 500KHz@Vcc=2V
6 SCK/IO/CE都帶有40K內(nèi)部下拉電阻。
7 有寫保護(hù),寫入數(shù)據(jù)前需要先去掉寫保護(hù)。
8 BURST模式下對(duì)CLOCK進(jìn)行寫操作,必須一次寫完8字節(jié)。
9 0x80地址的秒寄存器的第7位(CH)需要置0,震蕩器才能起振.
*/
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -