久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1693|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

c語言實現(xiàn)SPI通信源程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1087508 發(fā)表于 2023-7-6 16:13 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
1.duio口初始化
2.初始化完成以下為spi程序:

/*************
***************/
void SPI_SendData(uint8_t data)
{
        uint8_t cnt;
        for(cnt=0;cnt<8;cnt++)
        {
                SPI_CLK_L;//拉低
          Delay1us(10);//這個延時時間任意,但要大于芯片數(shù)據(jù)手冊上的(納秒級的)
                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); //讀取狀態(tài)寄存器命令
  do
        {
                status = SPI_ReadData();
        }
        while((status&0x01) == 1);
        SPI_CS_H;
}

/************
扇區(qū)擦除
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();
}

/*****************
檢測設(shè)備是否正確
設(shè)備ID為ID=0XEF4017
正常才繼續(xù)后面的頁寫入和讀取數(shù)據(jù)
******************/
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;
}


/**************
讀取數(shù)據(jù)
readlen: 讀取長度
***************/
void SPI_BufferRead(uint8_t *pBuffer,uint32_t addr,uint32_t readlen)
{
        SPI_CLK_L;
        SPI_CS_L;
        SPI_SendData(0x03);//讀數(shù)據(jù)命令
        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;
}

/************
頁寫入---寫入字節(jié)數(shù)低于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字節(jié)\r\n");
                writelen = Page_Size ;
        }
        while(writelen--)
        {
                SPI_SendData(*pBuffer);
                pBuffer++;
        }
        SPI_CLK_L;//拉低
        SPI_CS_H;
        SPI_WaitErase();
}


/*************
寫入任意長度數(shù)據(jù)
*pBuffer :待寫入數(shù)據(jù)
addr                 :需寫入flash的地址
numToWrite :待寫入數(shù)據(jù)長度
***************/
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剩余字節(jié)數(shù)
        numPage = numToWrite/Page_Size;//待寫入的數(shù)據(jù)占用page數(shù)
        numSingle = numToWrite%Page_Size;//待寫入數(shù)據(jù)不夠一個page的字節(jié)數(shù)
        if(Addr == 0)//在某page 起始位置 1
        {
                if(numPage==0)//寫入字節(jié)數(shù)小于一個page
                {
                        SPI_PageWrite(pBuffer,addr,numToWrite);
                }
                else//寫入字節(jié)數(shù)大于等于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)//寫入字節(jié)數(shù)小于一個page
                {
                        if(numSingle>count)//剩余字節(jié)數(shù)>該page剩余位置
                        {
                                SPI_PageWrite(pBuffer,addr,count);//向該page的剩余位置寫入對應(yīng)字節(jié)
                                pBuffer+=count;
                                addr+=count;
                                SPI_PageWrite(pBuffer,addr,(numSingle-count));//其余的寫入下一個page
                        }
                        else
                        {
                                SPI_PageWrite(pBuffer,addr,numToWrite);
                        }
                }
                else//寫入字節(jié)數(shù)大于等于一個page
                {
                        numToWrite -= count;
                        numPage = numToWrite/Page_Size;
                        numSingle        =        numToWrite%Page_Size;
                        SPI_PageWrite(pBuffer,addr,count);//寫入該page還可寫入的字節(jié)數(shù)
                        addr+=count;
                        pBuffer+=count;
                        while(numPage--)//page個數(shù)
                        {
                                SPI_PageWrite(pBuffer,addr,Page_Size);
                                pBuffer+=Page_Size;
                                addr+=Page_Size;
                        }
                        if(numSingle!=0)//剩余字節(jié)數(shù)
                        {
                                SPI_PageWrite(pBuffer,addr,numSingle);
                        }
                }
        }
        SPI_WaitErase();
}


/************
數(shù)據(jù)比較
len :數(shù)據(jù)長度
不等: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設(shè)備正常!\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的讀寫數(shù)據(jù)一致!\r\n");
//                        DebgStr_FramProc("\r\n 讀出的數(shù)據(jù)為:%s \r\n", Read_pBuffer);
                }
                else
                {
                        if(comparm.DebugComm & F_DebugStart)
                                DebgStr_FramProc("軟件模擬SPI的讀寫數(shù)據(jù)不一致!\r\n");
                }
        }
        else
        {
                if(comparm.DebugComm & F_DebugStart)
                        DebgStr_FramProc("SPI FLASH設(shè)備異常!\r\n");
        }
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 精品一区二区久久 | 操人视频在线观看 | 天天干天天操 | 日本福利视频 | 亚洲一区导航 | 成人av大全 | 久久69精品久久久久久久电影好 | 精品国产一区二区三区免费 | 成人影院在线 | 亚洲高清网 | 亚洲国产欧美日韩 | 国产欧美三区 | 成人不卡 | 看一级毛片视频 | 久久99国产精一区二区三区 | 日本不卡视频 | 久久久久久久久久久丰满 | 欧美国产视频一区二区 | 狠狠操狠狠干 | 国产精品久久av | 国产一极毛片 | 成人一区在线观看 | 精品乱码一区二区 | 精品少妇一区二区三区在线播放 | 亚洲一区av在线 | 国产成人小视频 | 久久机热| 最新国产精品视频 | 日韩在线精品 | 美日韩精品| 国内精品久久影院 | 久久视频精品 | 亚洲国产精品99久久久久久久久 | 亚洲精品一区二区三区在线 | 99久久国产综合精品麻豆 | 日韩视频一区在线观看 | 国产婷婷色综合av蜜臀av | 国产一区二区三区四区在线观看 | 欧美啊v在线观看 | 最新中文字幕在线播放 | 欧美日韩在线一区二区 |