cortex_m3_stm32嵌入式學習筆記(二十一):SPI實驗(通信總線)

ARM 500瀏覽

SPI 是英語 Serial Peripheral interface 的縮寫,顧名思義就是串行外圍設備接口。是 Motorola首先在其 MC68HCXX 系列處理器上定義的。 SPI 接口主要應用在 EEPROM, FLASH,實時時鐘, AD 轉換器,還有數字信號處理器和數字信號解碼器之間。
SPI,是一種高速的,全雙工,同步的通信總線
,并且在芯片的管腳上只占用四根線,節約了芯片的管腳,同時為 PCB 的布局上節省空間,提供方便,正是出于這種簡單易用的特性,現在越來越多的芯片集成了這種通信協議, STM32 也有 SPI 接口。

功能類似于上節的I2C,都屬于傳輸數據的用途。。找到一篇I2C VS SPI的文章:點擊打開鏈接

SPI 接口一般使用 4 條線通信:
MISO 主設備數據輸入,從設備數據輸出。
MOSI 主設備數據輸出,從設備數據輸入。
SCLK 時鐘信號,由主設備產生。
CS 從設備片選信號,由主設備控制。

SPI 主要特點有: 可以同時發出和接收串行數據; 可以當作主機或從機工作; 提供頻率可編程時鐘; 發送結束中斷標志; 寫沖突保護; 總線競爭保護等。

本章,我們將使用STM32的SPI來讀取外部 SPI FLASH 芯片( W25Q64),實現類似上節的功能。
W25Q64 是華邦公司推出的大容量SPI FLASH 產品, W25Q64 的容量為 64Mb, 該系列還有 W25Q80/16/32 等。 MiniSTM32 V3.0開發板所選擇的 W25Q64 容量為 64Mb,也就是 8M 字節。

連接圖如下:

? ? ? ? ? ? ? ??

也就說外設我們需要初始化PA5 6 7

配置SPI 和 flash的文件很長。。

spi.c

#include "spi.h"
//以下是SPI模塊的初始化代碼,配置成主機模式,訪問SD Card/W25X16/24L01/JF24C							  
//SPI口初始化
//這里針是對SPI1的初始化

SPI_InitTypeDef  SPI_InitStructure;

void SPI1_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
  
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );	
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //復用推挽輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

 	GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //設置SPI單向或者雙向的數據模式:SPI設置為雙線雙向全雙工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//設置SPI工作模式:設置為主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//設置SPI的數據大小:SPI發送接收8位幀結構
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;		//選擇了串行時鐘的穩態:時鐘懸空高
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	//數據捕獲于第二個時鐘沿
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信號由硬件(NSS管腳)還是軟件(使用SSI位)管理:內部NSS信號有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;		//定義波特率預分頻的值:波特率預分頻值為256
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定數據傳輸從MSB位還是LSB位開始:數據傳輸從MSB位開始
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值計算的多項式
	SPI_Init(SPI1, &SPI_InitStructure);  //根據SPI_InitStruct中指定的參數初始化外設SPIx寄存器
 
	SPI_Cmd(SPI1, ENABLE); //使能SPI外設
	
	SPI1_ReadWriteByte(0xff);//啟動傳輸		 
}   
//SPI 速度設置函數
//SpeedSet:
//SPI_BaudRatePrescaler_2   2分頻   (SPI [email protected] 72M)
//SPI_BaudRatePrescaler_8   8分頻   (SPI [email protected] 72M)
//SPI_BaudRatePrescaler_16  16分頻  (SPI [email protected] 72M)
//SPI_BaudRatePrescaler_256 256分頻 (SPI [email protected] 72M)
  
void SPI1_SetSpeed(u8 SpeedSet)
{
	SPI_InitStructure.SPI_BaudRatePrescaler = SpeedSet ;
  	SPI_Init(SPI1, &SPI_InitStructure);
	SPI_Cmd(SPI1,ENABLE);
} 

//SPIx 讀寫一個字節
//TxData:要寫入的字節
//返回值:讀取到的字節
u8 SPI1_ReadWriteByte(u8 TxData)
{		
	u8 retry=0;				 	
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //檢查指定的SPI標志位設置與否:發送緩存空標志位
		{
		retry++;
		if(retry>200)return 0;
		}			  
	SPI_I2S_SendData(SPI1, TxData); //通過外設SPIx發送一個數據
	retry=0;

	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//檢查指定的SPI標志位設置與否:接受緩存非空標志位
		{
		retry++;
		if(retry>200)return 0;
		}	  						    
	return SPI_I2S_ReceiveData(SPI1); //返回通過SPIx最近接收的數據					    
}

spi.h

#ifndef __SPI_H
#define __SPI_H
#include "sys.h" 				  	    													  
void SPI1_Init(void);			 //初始化SPI口
void SPI1_SetSpeed(u8 SpeedSet); //設置SPI速度   
u8 SPI1_ReadWriteByte(u8 TxData);//SPI總線讀寫一個字節 
#endif

flash.c

#include "flash.h" 
#include "spi.h"
#include "delay.h"   
u16 SPI_FLASH_TYPE=W25Q64;//默認就是25Q64
//4Kbytes為一個Sector
//16個扇區為1個Block
//W25X16
//容量為2M字節,共有32個Block,512個Sector 

//初始化SPI FLASH的IO口
void SPI_Flash_Init(void)
{

	GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOA, ENABLE );

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;  //SPI CS
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //復用推挽輸出
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
 	GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);
	SPI1_Init();		   //初始化SPI
	SPI1_SetSpeed(SPI_BaudRatePrescaler_4);	//設置為18M時鐘,高速模式
	SPI_FLASH_TYPE=SPI_Flash_ReadID();//讀取FLASH ID.
}  

//讀取SPI_FLASH的狀態寄存器
//BIT7  6   5   4   3   2   1   0
//SPR   RV  TB BP2 BP1 BP0 WEL BUSY
//SPR:默認0,狀態寄存器保護位,配合WP使用
//TB,BP2,BP1,BP0:FLASH區域寫保護設置
//WEL:寫使能鎖定
//BUSY:忙標記位(1,忙;0,空閑)
//默認:0x00
u8 SPI_Flash_ReadSR(void)   
{  
	u8 byte=0;   
	SPI_FLASH_CS=0;                            //使能器件   
	SPI1_ReadWriteByte(W25X_ReadStatusReg);    //發送讀取狀態寄存器命令    
	byte=SPI1_ReadWriteByte(0Xff);             //讀取一個字節  
	SPI_FLASH_CS=1;                            //取消片選     
	return byte;   
} 
//寫SPI_FLASH狀態寄存器
//只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以寫!!!
void SPI_FLASH_Write_SR(u8 sr)   
{   
	SPI_FLASH_CS=0;                            //使能器件   
	SPI1_ReadWriteByte(W25X_WriteStatusReg);   //發送寫取狀態寄存器命令    
	SPI1_ReadWriteByte(sr);               //寫入一個字節  
	SPI_FLASH_CS=1;                            //取消片選     	      
}   
//SPI_FLASH寫使能	
//將WEL置位   
void SPI_FLASH_Write_Enable(void)   
{
	SPI_FLASH_CS=0;                            //使能器件   
    SPI1_ReadWriteByte(W25X_WriteEnable);      //發送寫使能  
	SPI_FLASH_CS=1;                            //取消片選     	      
} 
//SPI_FLASH寫禁止	
//將WEL清零  
void SPI_FLASH_Write_Disable(void)   
{  
	SPI_FLASH_CS=0;                            //使能器件   
    SPI1_ReadWriteByte(W25X_WriteDisable);     //發送寫禁止指令    
	SPI_FLASH_CS=1;                            //取消片選     	      
} 			    
//讀取芯片ID W25X16的ID:0XEF14
u16 SPI_Flash_ReadID(void)
{
	u16 Temp = 0;	  
	SPI_FLASH_CS=0;				    
	SPI1_ReadWriteByte(0x90);//發送讀取ID命令	    
	SPI1_ReadWriteByte(0x00); 	    
	SPI1_ReadWriteByte(0x00); 	    
	SPI1_ReadWriteByte(0x00); 	 			   
	Temp|=SPI1_ReadWriteByte(0xFF)<<8;  
	Temp|=SPI1_ReadWriteByte(0xFF);	 
	SPI_FLASH_CS=1;				    
	return Temp;
}   		    
//讀取SPI FLASH  
//在指定地址開始讀取指定長度的數據
//pBuffer:數據存儲區
//ReadAddr:開始讀取的地址(24bit)
//NumByteToRead:要讀取的字節數(最大65535)
void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)   
{ 
 	u16 i;    												    
	SPI_FLASH_CS=0;                            //使能器件   
    SPI1_ReadWriteByte(W25X_ReadData);         //發送讀取命令   
    SPI1_ReadWriteByte((u8)((ReadAddr)>>16));  //發送24bit地址    
    SPI1_ReadWriteByte((u8)((ReadAddr)>>8));   
    SPI1_ReadWriteByte((u8)ReadAddr);   
    for(i=0;i<NumByteToRead;i++)
	{ 
        pBuffer[i]=SPI1_ReadWriteByte(0XFF);   //循環讀數  
    }
	SPI_FLASH_CS=1;                            //取消片選     	      
}  
//SPI在一頁(0~65535)內寫入少于256個字節的數據
//在指定地址開始寫入最大256字節的數據
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大256),該數不應該超過該頁的剩余字節數!!!	 
void SPI_Flash_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
 	u16 i;  
    SPI_FLASH_Write_Enable();                  //SET WEL 
	SPI_FLASH_CS=0;                            //使能器件   
    SPI1_ReadWriteByte(W25X_PageProgram);      //發送寫頁命令   
    SPI1_ReadWriteByte((u8)((WriteAddr)>>16)); //發送24bit地址    
    SPI1_ReadWriteByte((u8)((WriteAddr)>>8));   
    SPI1_ReadWriteByte((u8)WriteAddr);   
    for(i=0;i<NumByteToWrite;i++)SPI1_ReadWriteByte(pBuffer[i]);//循環寫數  
	SPI_FLASH_CS=1;                            //取消片選 
	SPI_Flash_Wait_Busy();					   //等待寫入結束
} 
//無檢驗寫SPI FLASH 
//必須確保所寫的地址范圍內的數據全部為0XFF,否則在非0XFF處寫入的數據將失敗!
//具有自動換頁功能 
//在指定地址開始寫入指定長度的數據,但是要確保地址不越界!
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大65535)
//CHECK OK
void SPI_Flash_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   
{ 			 		 
	u16 pageremain;	   
	pageremain=256-WriteAddr%256; //單頁剩余的字節數		 	    
	if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256個字節
	while(1)
	{	   
		SPI_Flash_Write_Page(pBuffer,WriteAddr,pageremain);
		if(NumByteToWrite==pageremain)break;//寫入結束了
	 	else //NumByteToWrite>pageremain
		{
			pBuffer+=pageremain;
			WriteAddr+=pageremain;	

			NumByteToWrite-=pageremain;			  //減去已經寫入了的字節數
			if(NumByteToWrite>256)pageremain=256; //一次可以寫入256個字節
			else pageremain=NumByteToWrite; 	  //不夠256個字節了
		}
	};	    
} 
//寫SPI FLASH  
//在指定地址開始寫入指定長度的數據
//該函數帶擦除操作!
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大65535)  		   
u8 SPI_FLASH_BUF[4096];
void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   
{ 
	u32 secpos;
	u16 secoff;
	u16 secremain;	   
 	u16 i;    

	secpos=WriteAddr/4096;//扇區地址 0~511 for w25x16
	secoff=WriteAddr%4096;//在扇區內的偏移
	secremain=4096-secoff;//扇區剩余空間大小   

	if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096個字節
	while(1) 
	{	
		SPI_Flash_Read(SPI_FLASH_BUF,secpos*4096,4096);//讀出整個扇區的內容
		for(i=0;i<secremain;i++)//校驗數據
		{
			if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除  	  
		}
		if(i<secremain)//需要擦除
		{
			SPI_Flash_Erase_Sector(secpos);//擦除這個扇區
			for(i=0;i<secremain;i++)	   //復制
			{
				SPI_FLASH_BUF[i+secoff]=pBuffer[i];	  
			}
			SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096);//寫入整個扇區  

		}else SPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain);//寫已經擦除了的,直接寫入扇區剩余區間. 				   
		if(NumByteToWrite==secremain)break;//寫入結束了
		else//寫入未結束
		{
			secpos++;//扇區地址增1
			secoff=0;//偏移位置為0 	 

		   	pBuffer+=secremain;  //指針偏移
			WriteAddr+=secremain;//寫地址偏移	   
		   	NumByteToWrite-=secremain;				//字節數遞減
			if(NumByteToWrite>4096)secremain=4096;	//下一個扇區還是寫不完
			else secremain=NumByteToWrite;			//下一個扇區可以寫完了
		}	 
	};	 	 
}
//擦除整個芯片
//整片擦除時間:
//W25X16:25s 
//W25X32:40s 
//W25X64:40s 
//等待時間超長...
void SPI_Flash_Erase_Chip(void)   
{                                             
    SPI_FLASH_Write_Enable();                  //SET WEL 
    SPI_Flash_Wait_Busy();   
  	SPI_FLASH_CS=0;                            //使能器件   
    SPI1_ReadWriteByte(W25X_ChipErase);        //發送片擦除命令  
	SPI_FLASH_CS=1;                            //取消片選     	      
	SPI_Flash_Wait_Busy();   				   //等待芯片擦除結束
}   
//擦除一個扇區
//Dst_Addr:扇區地址 0~511 for w25x16
//擦除一個山區的最少時間:150ms
void SPI_Flash_Erase_Sector(u32 Dst_Addr)   
{   
	Dst_Addr*=4096;
    SPI_FLASH_Write_Enable();                  //SET WEL 	 
    SPI_Flash_Wait_Busy();   
  	SPI_FLASH_CS=0;                            //使能器件   
    SPI1_ReadWriteByte(W25X_SectorErase);      //發送扇區擦除指令 
    SPI1_ReadWriteByte((u8)((Dst_Addr)>>16));  //發送24bit地址    
    SPI1_ReadWriteByte((u8)((Dst_Addr)>>8));   
    SPI1_ReadWriteByte((u8)Dst_Addr);  
	SPI_FLASH_CS=1;                            //取消片選     	      
    SPI_Flash_Wait_Busy();   				   //等待擦除完成
}  
//等待空閑
void SPI_Flash_Wait_Busy(void)   
{   
	while ((SPI_Flash_ReadSR()&0x01)==0x01);   // 等待BUSY位清空
}  
//進入掉電模式
void SPI_Flash_PowerDown(void)   
{ 
  	SPI_FLASH_CS=0;                            //使能器件   
    SPI1_ReadWriteByte(W25X_PowerDown);        //發送掉電命令  
	SPI_FLASH_CS=1;                            //取消片選     	      
    delay_us(3);                               //等待TPD  
}   
//喚醒
void SPI_Flash_WAKEUP(void)   
{  
  	SPI_FLASH_CS=0;                            //使能器件   
    SPI1_ReadWriteByte(W25X_ReleasePowerDown);   //  send W25X_PowerDown command 0xAB    
	  SPI_FLASH_CS=1;                            //取消片選     	      
    delay_us(3);                               //等待TRES1
}   

flash.h

#ifndef __FLASH_H
#define __FLASH_H			    
#include "sys.h" 
#define W25Q80 	0XEF13 	
#define W25Q16 	0XEF14
#define W25Q32 	0XEF15
#define W25Q64 	0XEF16
extern u16 SPI_FLASH_TYPE;//定義我們使用的flash芯片型號		
#define	SPI_FLASH_CS PAout(2)  //選中FLASH					 
extern u8 SPI_FLASH_BUF[4096];
//W25X16讀寫
#define FLASH_ID 0XEF14
//指令表
#define W25X_WriteEnable		0x06 
#define W25X_WriteDisable		0x04 
#define W25X_ReadStatusReg		0x05 
#define W25X_WriteStatusReg		0x01 
#define W25X_ReadData			0x03 
#define W25X_FastReadData		0x0B 
#define W25X_FastReadDual		0x3B 
#define W25X_PageProgram		0x02 
#define W25X_BlockErase			0xD8 
#define W25X_SectorErase		0x20 
#define W25X_ChipErase			0xC7 
#define W25X_PowerDown			0xB9 
#define W25X_ReleasePowerDown	0xAB 
#define W25X_DeviceID			0xAB 
#define W25X_ManufactDeviceID	0x90 
#define W25X_JedecDeviceID		0x9F 

void SPI_Flash_Init(void);
u16  SPI_Flash_ReadID(void);  	    //讀取FLASH ID
u8	 SPI_Flash_ReadSR(void);        //讀取狀態寄存器 
void SPI_FLASH_Write_SR(u8 sr);  	//寫狀態寄存器
void SPI_FLASH_Write_Enable(void);  //寫使能 
void SPI_FLASH_Write_Disable(void);	//寫保護
void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead);   //讀取flash
void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite);//寫入flash
void SPI_Flash_Erase_Chip(void);    	  //整片擦除
void SPI_Flash_Erase_Sector(u32 Dst_Addr);//扇區擦除
void SPI_Flash_Wait_Busy(void);           //等待空閑
void SPI_Flash_PowerDown(void);           //進入掉電模式
void SPI_Flash_WAKEUP(void);			  //喚醒
#endif

函數雖多。。其實用到一般也只有讀和寫

寫:

/寫SPI FLASH  
//在指定地址開始寫入指定長度的數據
//該函數帶擦除操作!
//pBuffer:數據存儲區
//WriteAddr:開始寫入的地址(24bit)
//NumByteToWrite:要寫入的字節數(最大65535)  		   
u8 SPI_FLASH_BUF[4096];
void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) 

//讀取SPI FLASH  
//在指定地址開始讀取指定長度的數據
//pBuffer:數據存儲區
//ReadAddr:開始讀取的地址(24bit)
//NumByteToRead:要讀取的字節數(最大65535)
void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)

主函數實現的功能跟I2C類似。。

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "lcd.h"
#include "key.h"
#include "spi.h"
#include "flash.h"   	
//要寫入到W25Q64的字符串數組
const u8 TEXT_Buffer[]={"MY SPI TEST"};
u32 FLASH_SIZE;
#define SIZE sizeof(TEXT_Buffer)	
void init(void)
{
	delay_init();	    	 //延時函數初始化	  
	uart_init(9600);	 	//串口初始化為9600
	LED_Init();		  		//初始化與LED連接的硬件接口
 	LCD_Init();
	KEY_Init();				//按鍵初始化		 	
	SPI_Flash_Init();  		//SPI FLASH 初始化 	 
 	POINT_COLOR=RED;//設置字體為紅色 
	LCD_ShowString(60,50,200,16,16,"Mini STM32");	
	LCD_ShowString(60,70,200,16,16,"SPI TEST");	
	LCD_ShowString(60,90,200,16,16,"[email protected]");
	LCD_ShowString(60,110,200,16,16,"2015/1/26");	
	LCD_ShowString(60,130,200,16,16,"WK_UP:Write  KEY0:Read");	//顯示提示信息		
	while(SPI_Flash_ReadID()!=W25Q64)							//檢測不到W25Q64
	{
		LCD_ShowString(60,150,200,16,16,"25Q64 Check Failed!");
		delay_ms(500);
		LCD_ShowString(60,150,200,16,16,"Please Check!      ");
		delay_ms(500);
		LED0=!LED0;//DS0閃爍
	}
	LCD_ShowString(60,150,200,16,16,"25Q64 Ready!");
	FLASH_SIZE=8*1024*1024;	//FLASH 大小為8M字節
  POINT_COLOR=BLUE;		//設置字體為藍色	  
}
 int main(void)
 { 
	u8 key;
	u16 i=0;
	u8 datatemp[SIZE];
	
	init();
	while(1)
	{
		key=KEY_Scan(0);
		if(key==WKUP_PRES)	//WK_UP 按下,寫入W25Q64
		{
			LCD_Fill(0,170,239,319,WHITE);//清除半屏    
 			LCD_ShowString(60,170,200,16,16,"Start Write W25Q64....");
			SPI_Flash_Write((u8*)TEXT_Buffer,FLASH_SIZE-100,SIZE);		//從倒數第100個地址處開始,寫入SIZE長度的數據
			LCD_ShowString(60,170,200,16,16,"W25Q64 Write Finished!");	//提示傳送完成
		}
		if(key==KEY0_PRES)	//KEY0 按下,讀取字符串并顯示
		{
 			LCD_ShowString(60,170,200,16,16,"Start Read W25Q64.... ");
			SPI_Flash_Read(datatemp,FLASH_SIZE-100,SIZE);				//從倒數第100個地址處開始,讀出SIZE個字節
			LCD_ShowString(60,170,200,16,16,"The Data Readed Is:  ");	//提示傳送完成
			LCD_ShowString(60,190,200,16,16,datatemp);					//顯示讀到的字符串
		}
		i++;
		delay_ms(10);
		if(i==20)
		{
			LED0=!LED0;//提示系統正在運行	
			i=0;
		}		   
	}
}

七星彩走势图2元网官网