码迷,mamicode.com
首页 > 其他好文 > 详细

IIC、SPI小记

时间:2017-09-02 12:59:10      阅读:317      评论:0      收藏:0      [点我收藏+]

标签:简介   需要   技术   ack   flash   coff   i++   包括   spi_flash   

  • IIC
    • 简介
      • 该总线半双工,速度慢,多用于芯片之间通信。由数据线SDA和时钟SCL构成,可发送和接收数据。
      • 有三种类型信号:开始信号、结束信号和应答信号。
        • 开始信号:SCL为高电平时,SDA由高电平跳变为低电平,开始传送数据;
        • 结束信号:SCL为高电平时,SDA由低电平跳变为高电平,结束传送数据;
        • 应答信号:接收方收到8位数据后,向发送端发出低电平,表示数据收到。
    • 时序
      • 技术分享技术分享
    • 软件模拟IIC与24C02之间的通信
      • 写过程
        • 技术分享
        • 起始地址》》要写入的设备在吗》》要写入的数据地址在吗》》写入》》停止信号
      • 读过程
        • 技术分享
        • 起始信号》》要读的设备在吗》》要读的地址在吗》》要读的设备在吗》》读取数据》》停止信号
          • 注:这里要写两个设备地址,此两个地址只有前7bit真正表示地址,最后一位0表示写,1表示读,故设备地址不一样。
  • SPI
    • 简介
      • 高速、全双工同步总线,占用四根引脚
      • 技术分享
      • 若主机需读取数据,需要向从机发送空字节(0xff),与从机移位寄存器的数据进行交换。
    • 时序
      • 技术分享
      • 主从的时钟相位和极性应一致:CPOL=1,则空闲为高电平,CPPL=0,则空闲为低;CPHA=0,第一个边沿采集,CPHA=1,第二个边沿采集。
  • 软件模拟
    • IIC
      • void 24C02_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
        {                                                                                                  
            IIC_Start();  
            IIC_Send_Byte(0XA0);   //0XA0包括设备地址和写命令
            IIC_Wait_Ack();       
            IIC_Send_Byte(WriteAddr);   //WriteAddr为写入数据的目的地址
            IIC_Wait_Ack();              //                                             
            IIC_Send_Byte(DataToWrite);     //   DataToWrite写入的数据
            IIC_Wait_Ack();                     
            IIC_Stop();
            delay_ms(10);     
        }
        u8 24C02_ReadOneByte(u16 ReadAddr)
        {                  
            u8 temp=0;                                                                                   
            IIC_Start();  
            IIC_Send_Byte(0XA0);   //写入要读的设备地址
            IIC_Wait_Ack(); //
            IIC_Send_Byte(ReadAddr);   //
            IIC_Wait_Ack();        //
            IIC_Start();              
            IIC_Send_Byte(0XA1);    //真正的读
            IIC_Wait_Ack();     
            temp=IIC_Read_Byte(0);           
            IIC_Stop();    
            return temp;
        }
        void IIC_Send_Byte(u8 txd)//txd为待发送的数据
        {                        
            u8 t;   
            SDA_OUT();         
            IIC_SCL=0;//等待发送
            for(t=0;t<8;t++)
            {              
                IIC_SDA=(txd&0x80)>>7;//取最高位开始发送
                txd<<=1;       //将已发送的移走,次高位变成最高位
                delay_us(2);   //
                IIC_SCL=1;
                delay_us(2); 
                IIC_SCL=0;    
                delay_us(2);
            }     
        }
    • SPI
      • u8 SPI1_ReadWriteByte(u8 TxData)//TxData为要写入的命令或数据,写入命令,则一般返回值不采用,写入空字节,则为读取字节
        {        
            u8 retry=0;                     
            while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //RESET为0,表示发送缓冲区非空,待发送数据无法写入
                {
                retry++;
                if(retry>200)return 0;
                }              
            SPI_I2S_SendData(SPI1, TxData); //向SPI1写入命令或数据,在写之前要要保证发送缓冲区为空;
            retry=0;
            while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//RESET表示接收缓冲区无有效数据
                {
                retry++;
                if(retry>200)return 0;
                }                                  
            return SPI_I2S_ReceiveData(SPI1); //    通过SPI1接收最近的数据,在接收之前要保证接收缓冲去包含有效数据                
        }
        
        //读取SPI FLASH
        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));  //· 
            SPI1_ReadWriteByte((u8)((ReadAddr)>>8));   
            SPI1_ReadWriteByte((u8)ReadAddr);   
            for(i=0;i<NumByteToRead;i++)
            { 
                pBuffer[i]=SPI1_ReadWriteByte(0XFF);   //循环读数
            }
            SPI_FLASH_CS=1;                            //      取消片选
        }  
        void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   
        { 
            u32 secpos;
            u16 secoff;
            u16 secremain;       
             u16 i;    
        
            secpos=WriteAddr/4096;//一个扇区4096个地址,表示扇区地址
            secoff=WriteAddr%4096;//在扇区内偏移
            secremain=4096-secoff;//扇区剩余空间大小   
            if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//如果无跨区
            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;//
                    secpos++;//
                    secoff=0;//     
                       pBuffer+=secremain;  //
                    WriteAddr+=secremain;//
                       NumByteToWrite-=secremain;                //
                    if(NumByteToWrite>4096)secremain=4096;    //
                    else secremain=NumByteToWrite;            //
                }     
            };          
        }

         



         

IIC、SPI小记

标签:简介   需要   技术   ack   flash   coff   i++   包括   spi_flash   

原文地址:http://www.cnblogs.com/zdddd/p/7466221.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!