使用SPI接口控制74HC595 LED顯示
SPI接口的全稱是"Serial Peripheral Interface",意為串行外圍接口。SPI接口主要應(yīng)用在EEPROM,F(xiàn)LASH,實(shí)時(shí)時(shí)鐘,AD轉(zhuǎn)換器,還有數(shù)字信號處理器和數(shù)字信號解碼器之間。
SPI接口是在CPU和外圍低速器件之間進(jìn)行同步串行數(shù)據(jù)傳輸,在主器件的移位脈沖下,數(shù)據(jù)按位傳輸,為全雙工通信,數(shù)據(jù)傳輸速度總體來說比I2C總線要快,速度可達(dá)到幾Mbps。
SPI接口是以主從方式工作的,這種模式通常有一個(gè)主器件和一個(gè)或多個(gè)從器件,其接口包括以下四種信號:
(1)MOSI – 主器件數(shù)據(jù)輸出,從器件數(shù)據(jù)輸入
(2)MISO – 主器件數(shù)據(jù)輸入,從器件數(shù)據(jù)輸出
(3)SCLK – 時(shí)鐘信號,由主器件產(chǎn)生
(4)/SS – 從器件使能信號,由主器件控制
在BASCOM中,提供了軟件實(shí)現(xiàn)的SPI接口的語句,同樣BASCOM也有支持硬件SPI的語句。
下面將使用三個(gè)例子來說明如何在BASCOM中使用SPI接口。
在介紹例子之前,我們先了解一下硬件連接圖,連接如圖1所示。
圖中共使用三片74HC595芯片,分別控制三個(gè)數(shù)碼管,三片74HC595通過Q7’引腳進(jìn)行級聯(lián)。第一片74HC595的DS引腳連接到了ATmega88的MOSI引腳,而SH_CP引腳連接到了ATmega88的SCK引腳,ST_CP引腳連接到了ATmega88的PB1引腳。
一、使用硬件SPI接口控制74HC595 '------------------------------------------------------------------------ '使用芯片: ATmega88, '晶振: 內(nèi)部8MHz晶振 'email: support@avrbascom.com '軟件版本: Bascom-AVR 1.11.8.3 Full version '------------------------------------------------------------------------ $regfile = "m88def.dat" '芯片為ATmega88 $crystal = 8000000 '8M晶振頻率 $hwstack = 32 '設(shè)置堆棧大小 $swstack = 10 $framesize = 40 Dim I As Byte Dim A(3) As Byte Latch Alias Portb.1 Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 0 '定義使用單片機(jī)自帶的硬件SPI,SPI中斷未使能,數(shù)據(jù)發(fā)送時(shí),高位先發(fā)送。 '設(shè)為SPI主設(shè)備,時(shí)鐘4分頻 Spiinit 'SPI初始化 Restore Segtab '獲取要顯示數(shù)據(jù)的內(nèi)容 For I = 1 To 3 Read A(i) Next I Spiout A(1) , 3 '輸出要顯示的內(nèi)容給74HC595,分別輸出A(1),A(2),A(3) Latch = 1? '使能顯示 Waitus 10 Latch = 0 Do Loop End '******************************************************************************* '--------------------------專用字形表------------------------------------------ Segtab: Data &H77 , &H14 , &HE6 , &HB6 , &H95 , &HB3 , &HF3 , &H16 , &HF7 , &HB7 '0 1 2 3 4 5 6 7 8 9 二、使用軟件SPI接口控制74HC595 '------------------------------------------------------------------------ '使用芯片: ATmega88, '晶振: 內(nèi)部8MHz晶振 'email: support@avrbascom.com '軟件版本: Bascom-AVR 1.11.8.3 Full version '------------------------------------------------------------------------ $regfile = "m88def.dat" '芯片為ATmega88 $crystal = 8000000 '8M晶振頻率 $hwstack = 32 '設(shè)置堆棧大小 $swstack = 10 $framesize = 40 Const On = 1 Const Off = 0 Dim I As Byte Dim A(3) As Byte Latch Alias Portb.1 Config Spi = Soft , Dout = Portb.3 , Ss = None , Clock = Portb.5 '定義使用軟件SPI,pb3作為數(shù)據(jù)輸出口,pb5作為時(shí)鐘引腳 Spiinit 'SPI初始化 Restore Segtab '獲取要顯示數(shù)據(jù)的內(nèi)容 For I = 1 To 3 Read A(i) Next I Spiout A(1) ,3 '輸出要顯示的內(nèi)容給74HC595,分別輸出A(1),A(2),A(3) Latch = Off '使能顯示 Waitus 10 Latch = On Do Loop End '******************************************************************** '--------------------------專用字形表------------------------------------------ Segtab: Data &H77 , &H14 , &HE6 , &HB6 , &H95 , &HB3 , &HF3 , &H16 , &HF7 , &HB7 '0 1 2 3 4 5 6 7 8 9 三、使用軟件SPI接口控制74HC595 '------------------------------------------------------------------------ '使用芯片: ATmega88, '晶振: 內(nèi)部8MHz晶振 'email: support@avrbascom.com '軟件版本: Bascom-AVR 1.11.8.3 Full version '------------------------------------------------------------------------ $regfile = "m88def.dat" '芯片為ATmega88 $crystal = 8000000 '8M晶振頻率 $hwstack = 32 '設(shè)置堆棧大小 $swstack = 10 $framesize = 40 Const On = 1 Const Off = 0 Ledata Alias Portb.3 '數(shù)據(jù)輸出口 Ledclk Alias Portb.5 '時(shí)鐘輸出口 Latch Alias Portb.1 Dim I As Byte Dim A(3) As Byte Restore Segtab '獲取要顯示數(shù)據(jù)的內(nèi)容 For I = 1 To 3 Read A(i) Next I For I = 3 To 1 Step -1 Shiftout Ledata , Ledclk , A(i) , 1 '輸出要顯示的內(nèi)容給74HC595 Next I Latch = Off '使能顯示 Waitus 10 Latch = On Do Loop End '******************************************************************** '--------------------------專用字形表------------------------------------------ Segtab: Data &H77 , &H14 , &HE6 , &HB6 , &H95 , &HB3 , &HF3 , &H16 , &HF7 , &HB7 '0 1 2 3 4 5 6 7 8 9
//******************************************* // 74HC595/165驅(qū)動程序 // (165,595均為兩片) //******************************************* unsigned int LED; unsigned int KEY_DATA; void Driver_595(unsigned char Bit,unsigned char State) { if(State) LED|=(0x00001<<Bit); else LED&=~(0x00001<<Bit); SPI_W_R((int)(LED>>8)); set_bit(1,0); clr_bit(1,0); SPI_W_R((int)LED); set_bit(1,0); clr_bit(1,0); } void Port_Init(void) { DDRB=0xff; PORTB=0x00; } //**************************************************************** void Driver_165(void) //Bite所取位0~15,State為改位的狀態(tài)0,1 { unsigned char a1; unsigned char a2; clr_bit(1,3); set_bit(1,3); a1=SPI_W_R(0x00); //74HC165輸入使能 a2=SPI_W_R(0x00); //讀出鍵值 KEY_DATA=a1; KEY_DATA<<=8; KEY_DATA+=a2; return; } //******************************************************************* void set_bit(unsigned char port,unsigned char n)//port為端口號分別用0~3表示A~D,n該端口的引腳號0~7 { switch(port) { case 0x00: PORTA|=(0x01<<n); break; case 0x01: PORTB|=(0x01<<n); break; case 0x02: PORTC|=(0x01<<n); break; case 0x03: PORTD|=(0x01<<n); break; } } //****************OK********************** //************************************** void clr_bit(unsigned char port,unsigned char n)//port為端口號分別用0~3表示A~D,n該端口的引腳號0~7 { switch(port) { case 0x00: PORTA&=~(0x01<<n); break; case 0x01: PORTB&=~(0x01<<n); break; case 0x02: PORTC&=~(0x01<<n); break; case 0x03: PORTD&=~(0x01<<n); break; } } //***************OK*********************************************** unsigned char SPI_W_R(unsigned char data) { SPCR=0x50; //SPI為查詢方式,系統(tǒng)時(shí)鐘四分頻 SPDR=data; //寫入數(shù)據(jù) while((SPSR>>7)==0x00); //等待數(shù)據(jù)發(fā)送完畢 return SPDR; //返回收到的數(shù)據(jù) } //*********************OK*****************************************
總結(jié):以上是AVR單片機(jī)使用SPI接口控制74HC595的例子,這些例子經(jīng)過簡單的修改就可以應(yīng)用到其它具有SPI即可的芯片上,如SPI接口的Flash存儲芯片AT45DB系列、SPI接口的時(shí)鐘芯片DS1302、SPI接口的AD或DA芯片等等。
對于AVR mega系列單片機(jī)一般都具有硬件SPI接口,建議客戶使用硬件SPI接口,這樣可以占用更少的硬件和軟件資源。但軟件實(shí)現(xiàn)SPI接口,也有一定的優(yōu)勢,如它使用的IO口不是固定的,可以根據(jù)需要來指定,它一次發(fā)送的數(shù)據(jù)可以不是8位,而是可以根據(jù)需要來指定。
Shiftout VS Spiout
這兩個(gè)語句都是SPI輸出語句,與它們對應(yīng)的分別是shiftin和spiin
shiftout語句可以使用在硬件spi或軟件spi接口,通過config語句來確定:
Config Spi = Hard/soft
Shiftout語句使用在軟件spi接口。