1.duio口初始化
2.初始化完成以下為spi程序:
/*************
***************/
void SPI_SendData(uint8_t data)
{
uint8_t cnt;
for(cnt=0;cnt<8;cnt++)
{
SPI_CLK_L;//拉低
Delay1us(10);//這個延時時間任意,但要大于芯片數據手冊上的(納秒級的)
if(data &0x80)
{
SPI_MOSI_H;
}
else
{
SPI_MOSI_L;
}
data <<= 1;//
Delay1us(10);
SPI_CLK_H;//拉高
Delay1us(10);
}
}
/*****************************************/
uint8_t SPI_ReadData(void)
{
uint8_t i = 0;
uint8_t value=0;
SPI_CLK_H;
Delay1us(2);
for(i=0;i<8;i++)
{
SPI_CLK_L;
value<<=1;
if(SPI_MISO_READ())
{
value |= 0x01;
}
Delay1us(2);
SPI_CLK_H;
Delay1us(2);
}
return value;
}
/*************
等待擦除完成
**************/
void SPI_WaitErase(void)
{
uint8_t status = 0x01;
SPI_CS_L;
SPI_SendData(0x05); //讀取狀態寄存器命令
do
{
status = SPI_ReadData();
}
while((status&0x01) == 1);
SPI_CS_H;
}
/************
扇區擦除
4k
**************/
void SPI_EraseSector(uint32_t addr)
{
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0x06);
SPI_CLK_L;
SPI_CS_H;
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0x20);
SPI_SendData((uint8_t)(addr&0xFF0000)>>16);
SPI_SendData((addr&0xFF00)>>8);
SPI_SendData((addr&0xFF));
SPI_CLK_L;
SPI_CS_H;
SPI_WaitErase();
}
/************
塊擦除
32k
**************/
void SPI_EraseBlock(uint32_t addr)
{
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0x06);
SPI_CLK_L;
SPI_CS_H;
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0x52);
SPI_SendData((uint8_t)(addr&0xFF0000)>>16);
SPI_SendData((addr&0xFF00)>>8);
SPI_SendData((addr&0xFF));
SPI_CLK_L;
SPI_CS_H;
SPI_WaitErase();
}
/************
塊擦除
64k
**************/
void SPI_Erase64kBlock(uint32_t addr)
{
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0x06);
SPI_CLK_L;
SPI_CS_H;
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0xd8);
SPI_SendData((uint8_t)(addr&0xFF0000)>>16);
SPI_SendData((addr&0xFF00)>>8);
SPI_SendData((addr&0xFF));
SPI_CLK_L;
SPI_CS_H;
SPI_WaitErase();
}
/*****************
檢測設備是否正確
設備ID為ID=0XEF4017
正常才繼續后面的頁寫入和讀取數據
******************/
uint32_t SPI_CheckDevice(void)
{
uint8_t temp0,temp1,temp2;
uint32_t Device_ID=0;
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0x9F);
temp0 = SPI_ReadData();
temp1 = SPI_ReadData();
temp2 = SPI_ReadData();
SPI_CLK_L;
SPI_CS_H;
Device_ID = (temp0<<16) | (temp1<<8) | (temp2);
return Device_ID;
}
/**************
讀取數據
readlen: 讀取長度
***************/
void SPI_BufferRead(uint8_t *pBuffer,uint32_t addr,uint32_t readlen)
{
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0x03);//讀數據命令
SPI_SendData((uint8_t)(addr&0xFF0000)>>16);
SPI_SendData((addr&0xFF00)>>8);
SPI_SendData((addr&0xFF));
while(readlen--)
{
*pBuffer = SPI_ReadData();
pBuffer++;
}
SPI_CLK_L;
SPI_CS_H;
}
/************
頁寫入---寫入字節數低于256可用頁編程
**************/
void SPI_PageWrite(uint8_t *pBuffer,uint32_t addr,uint16_t writelen)
{
SPI_CLK_L;
SPI_CS_L;
SPI_SendData(0x06);
SPI_CLK_L
SPI_CS_H;
SPI_CLK_L;//拉低
SPI_CS_L;
SPI_SendData(0x02);
SPI_SendData((addr&0xFF0000)>>16);
SPI_SendData((addr&0xFF00)>>8);
SPI_SendData((addr&0xFF));
if(writelen>Page_Size)
{
// printf("\r\n頁寫入最大為256字節\r\n");
writelen = Page_Size ;
}
while(writelen--)
{
SPI_SendData(*pBuffer);
pBuffer++;
}
SPI_CLK_L;//拉低
SPI_CS_H;
SPI_WaitErase();
}
/*************
寫入任意長度數據
*pBuffer :待寫入數據
addr :需寫入flash的地址
numToWrite :待寫入數據長度
***************/
void SPI_BufferWrite(uint8_t *pBuffer,uint32_t addr,uint32_t numToWrite)
{
uint32_t count=0,numPage=0,numSingle=0,Addr=0;
Addr = addr%Page_Size;//某個page的地址
count = Page_Size - Addr;//某page剩余字節數
numPage = numToWrite/Page_Size;//待寫入的數據占用page數
numSingle = numToWrite%Page_Size;//待寫入數據不夠一個page的字節數
if(Addr == 0)//在某page 起始位置 1
{
if(numPage==0)//寫入字節數小于一個page
{
SPI_PageWrite(pBuffer,addr,numToWrite);
}
else//寫入字節數大于等于1個page
{
while(numPage--)
{
SPI_PageWrite(pBuffer,addr,Page_Size);
pBuffer+=Page_Size;
addr+=Page_Size;
}
SPI_PageWrite(pBuffer,addr,numSingle);
}
}
else //在某page的2~256位置
{
if(numPage==0)//寫入字節數小于一個page
{
if(numSingle>count)//剩余字節數>該page剩余位置
{
SPI_PageWrite(pBuffer,addr,count);//向該page的剩余位置寫入對應字節
pBuffer+=count;
addr+=count;
SPI_PageWrite(pBuffer,addr,(numSingle-count));//其余的寫入下一個page
}
else
{
SPI_PageWrite(pBuffer,addr,numToWrite);
}
}
else//寫入字節數大于等于一個page
{
numToWrite -= count;
numPage = numToWrite/Page_Size;
numSingle = numToWrite%Page_Size;
SPI_PageWrite(pBuffer,addr,count);//寫入該page還可寫入的字節數
addr+=count;
pBuffer+=count;
while(numPage--)//page個數
{
SPI_PageWrite(pBuffer,addr,Page_Size);
pBuffer+=Page_Size;
addr+=Page_Size;
}
if(numSingle!=0)//剩余字節數
{
SPI_PageWrite(pBuffer,addr,numSingle);
}
}
}
SPI_WaitErase();
}
/************
數據比較
len :數據長度
不等:0
相等:1
************/
uint8_t pBuffer_Cmp(uint8_t *buffer1,uint8_t *buffer2,uint32_t len)
{
while(len--)
{
if(*buffer1!=*buffer2)
{
return 0;
}
buffer1++;
buffer2++;
}
return 1;
}
uint8_t Write_pBuffer[]={"軟件模擬SPI成功!"};
uint8_t Read_pBuffer[3500]={0};
/***********
讀寫測試,驗證是否正常
***********/
void SPI_Test(void)
{
uint32_t Device_ID = 0;
Device_ID = SPI_CheckDevice();
// printf("ID=0x%x \r\n", Device_ID);
if(Device_ID == 0xEF4016)
{
if(comparm.DebugComm & F_DebugStart)
DebgStr_FramProc("SPI FLASH設備正常!\r\n");
SPI_EraseSector(0x001000);//sector1
SPI_BufferWrite(Write_pBuffer,0x001000,(sizeof(Write_pBuffer)/sizeof(*(Write_pBuffer))-1));
SPI_BufferRead(Read_pBuffer,0x001000,(sizeof(Write_pBuffer)/sizeof(*(Write_pBuffer))-1));
if(pBuffer_Cmp(Write_pBuffer,Read_pBuffer,(sizeof(Write_pBuffer)/sizeof(*(Write_pBuffer))-1)) == 1)
{
if(comparm.DebugComm & F_DebugStart)
DebgStr_FramProc("軟件模擬SPI的讀寫數據一致!\r\n");
// DebgStr_FramProc("\r\n 讀出的數據為:%s \r\n", Read_pBuffer);
}
else
{
if(comparm.DebugComm & F_DebugStart)
DebgStr_FramProc("軟件模擬SPI的讀寫數據不一致!\r\n");
}
}
else
{
if(comparm.DebugComm & F_DebugStart)
DebgStr_FramProc("SPI FLASH設備異常!\r\n");
}
}
|