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