⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd.c

📁 AT45DB161串行flash全协议mega8程序
💻 C
📖 第 1 页 / 共 2 页
字号:

/*-----------------------------------------------------------
             SPI串行flash-at45db161d读写函数
 作者:zbw      日期:2007.10.25      版本:v1.0
 包含文件:SD.C   SD.H
 功能:运用AVR硬件SPI完成对芯片的不同方式的读写,各个函数的
       功能和参数参见函数体或头文件中的注释
 注意:本程序便于操作设置了一个528字节大小的缓存,由于芯片内
       部按页操作,每页528字节(可编程控制,但只能一次性更改
       故不做更改),因此此缓存大小不能随意改动!
-----------------------------------------------------------*/ 


#include <mega8.h>
#include "sd.h"

void SD_Port_Init(void)
{
   SD_CS_PIN=1;
}  

//-----------------------------------------------------------
//SPI Master初始化子程序
//-----------------------------------------------------------
void SPI_MasterInit(void)
{
   SD_Direction_REG = (1<<SPI_DO)|(1<<SPI_SS)|(1<<SPI_Clock);    /* 设置MOSI 和SCK 为输出,其他为输入 */
   SPCR = 0x50;                            /* 使能SPI 主机模式 */
   SPSR = 0x01;                            /* 倍速 */
}

//-----------------------------------------------------------
//SPI Master发送子程序
//-----------------------------------------------------------
void SPI_MasterTransmit(unsigned char cData)
{
   SPDR = cData;                          /* 启动数据传输 */
   while(!(SPSR & (1<<SPIF)));            /* 等待传输结束 */
}

//-----------------------------------------------------------
//SPI Master接收子程序
//-----------------------------------------------------------
unsigned char SPI_MasterReceive(void)
{
   SPDR = 0xFF;
   while(!(SPSR & (1<<SPIF)));            /* 等待接收结束 */
   return SPDR;                           /* 返回数据 */
}

void SDinit(void)
{
   SD_Direction_REG=0xff;
   DDRD=0xff;
   SD_Port_Init();
   SPI_MasterInit();
}

/*-----------------------------------------------------------
读状态寄存器      操作码0xD7
结束标志:CS管脚置高     该寄存器在忙状态下也可读取,便于判断状态
  Bit 7    Bit 6    Bit 5    Bit 4    Bit 3    Bit 2    Bit 1    Bit 0
RDY/BUSY   COMP       1        0        1        1     PROTECT  PAGE SIZE
-----------------------------------------------------------*/ 
unsigned char Status_Register_Read (void)
{
   unsigned char c;
   SD_CS_PIN=0;
   
   SPI_MasterTransmit(0xd7);//操作码
   c= SPI_MasterReceive();
  
   SD_CS_PIN=1;
   return c;
}

/*-----------------------------------------------------------
连续读模式1 最高66M    操作码0xE8
格式:操作码+3字节地址码(12页址+10页内地址(528byte))+4个空字节(延时启动内部读操作)
结束标志:CS管脚置高 注意该模式读期间页间转换无标志 无时差 完全连续直到读完这个存储器
由于不能建立太大的缓存,故该模式下,连续读的优势得到限制,可在主函数进行操作实现单字节传输
-----------------------------------------------------------*/ 
void Continuous_Array_Read_1 (unsigned char *p,unsigned int pageaddr,unsigned int byteaddr)   // 获取值放到缓存p,此处设置p为512字节
{
   unsigned int i;
   unsigned long j;
   
   j= ((((unsigned long)pageaddr)<<10)&0x3ffc00)|(((unsigned long)byteaddr)&0x3ff);
   
   SD_CS_PIN=0;
   SPI_MasterTransmit(0xe8);//操作码
   SPI_MasterTransmit((unsigned char)(j>>16));//地址
   SPI_MasterTransmit((unsigned char)(j>> 8));
   SPI_MasterTransmit((unsigned char) j);
   SPI_MasterTransmit(0x00);//无效字节
   SPI_MasterTransmit(0x00);
   SPI_MasterTransmit(0x00);
   SPI_MasterTransmit(0x00);
   for (i=0;i<528;i++)
   {
       p[i] = SPI_MasterReceive();
   }
   SD_CS_PIN=1;
   while(!(Status_Register_Read ()&0x80));//检测忙状态确保内部时序完成
}

/*-----------------------------------------------------------
连续读模式2 最高66M    操作码0x0B
格式:操作码+3字节地址码(12页址+10页内地址(528byte))+1个空字节(延时启动内部读操作)
结束标志:CS管脚置高 注意该模式读期间页间转换无标志 无时差 完全连续
由于不能建立太大的缓存,故该模式下,连续读的优势得到限制,可在主函数进行操作实现单字节传输
-----------------------------------------------------------*/ 
void Continuous_Array_Read_2 (unsigned char *p,unsigned int pageaddr,unsigned int byteaddr)   // 获取值放到缓存p,此处设置p为512字节
{
   unsigned int i;
   unsigned long j;
   
   j= ((((unsigned long)pageaddr)<<10)&0x3ffc00)|(((unsigned long)byteaddr)&0x3ff);
   
   SD_CS_PIN=0;
   SPI_MasterTransmit(0x0b);//操作码
   SPI_MasterTransmit((unsigned char)(j>>16));//地址
   SPI_MasterTransmit((unsigned char)(j>> 8));
   SPI_MasterTransmit((unsigned char) j);
   SPI_MasterTransmit(0x00);//无效字节

   for (i=0;i<528;i++)
   {
       p[i] = SPI_MasterReceive();
   }
   SD_CS_PIN=1;
   while(!(Status_Register_Read ()&0x80));//检测忙状态确保内部时序完成
}

/*-----------------------------------------------------------
连续读模式3 最高33M    操作码0x03
格式:操作码+3字节地址码(12页址+10页内地址(528byte))
结束标志:CS管脚置高 注意该模式读期间页间转换无标志 无时差 完全连续
由于不能建立太大的缓存,故该模式下,连续读的优势得到限制,可在主函数进行操作实现单字节传输
-----------------------------------------------------------*/ 
void Continuous_Array_Read_3 (unsigned char *p,unsigned int pageaddr,unsigned int byteaddr)   // 获取值放到缓存p,此处设置p为512字节
{
   unsigned int i;
   unsigned long j;
   
   j= ((((unsigned long)pageaddr)<<10)&0x3ffc00)|(((unsigned long)byteaddr)&0x3ff);
   
   SD_CS_PIN=0;
   SPI_MasterTransmit(0x03);//操作码
   SPI_MasterTransmit((unsigned char)(j>>16));//地址
   SPI_MasterTransmit((unsigned char)(j>> 8));
   SPI_MasterTransmit((unsigned char) j);

   for (i=0;i<528;i++)
   {
       p[i] = SPI_MasterReceive();
   }
   SD_CS_PIN=1;
   while(!(Status_Register_Read ()&0x80));//检测忙状态确保内部时序完成
}

/*-----------------------------------------------------------
数据读函数     操作码0xD2
格式:操作码+3字节地址码(12页址+10页内地址(528byte))+4个空字节(延时启动内部读操作)
结束标志:CS管脚置高    注意该方式读完一页返回从同一页开始读
缓存大小设置为512字节即工作于每页528字节模式
-----------------------------------------------------------*/ 
void Main_Memory_Page_Read (unsigned char *p,unsigned int pageaddr,unsigned int byteaddr)   // 获取值放到缓存p,此处设置p为512字节
{
   unsigned int i;
   unsigned long j;
   
   j= ((((unsigned long)pageaddr)<<10)&0x3ffc00)|(((unsigned long)byteaddr)&0x3ff);
   
   SD_CS_PIN=0;
   SPI_MasterTransmit(0xd2);//操作码
   SPI_MasterTransmit((unsigned char)(j>>16));//地址
   SPI_MasterTransmit((unsigned char)(j>> 8));
   SPI_MasterTransmit((unsigned char) j);
   SPI_MasterTransmit(0x00);//无效字节
   SPI_MasterTransmit(0x00);
   SPI_MasterTransmit(0x00);
   SPI_MasterTransmit(0x00);
   
   for (i=0;i<528;i++)
   {
       p[i] = SPI_MasterReceive();
   }
   SD_CS_PIN=1;
   while(!(Status_Register_Read ()&0x80));//检测忙状态确保内部时序完成
}

/*-----------------------------------------------------------
缓存数据读函数     操作码0xD6 0xD4 0xD3 0xD1
格式:操作码+3字节地址码(15无效位+10地址(528byte))
结束标志:CS管脚置高    
-----------------------------------------------------------*/ 
void Buffer_Read (unsigned char *p,unsigned int byteaddr,unsigned char rate,unsigned char buffer)   // 获取值放到缓存p,此处设置p为512字节
{    // 获取值放到缓存p,此处设置p为528字节   byteaddr 为地址,rate为读速度设定1为高速66M,0为低速33M
     //buffer为buffer选择,1为buffer1,同理
   unsigned int i;
   unsigned long j;
   
   j=((unsigned long)byteaddr)&0x03ff;
   
   SD_CS_PIN=0;
   
   if (rate)
   {
        if (buffer == 1)
            SPI_MasterTransmit(0xd4);//操作码
        else
            SPI_MasterTransmit(0xd6);//操作码
   }
   else 
   {
        if (buffer == 1)
            SPI_MasterTransmit(0xd1);//操作码
        else
            SPI_MasterTransmit(0xd3);//操作码
   }
   
   SPI_MasterTransmit((unsigned char)(j>>16));//地址
   SPI_MasterTransmit((unsigned char)(j>> 8));
   SPI_MasterTransmit((unsigned char) j);
   
   if (rate)
        SPI_MasterTransmit(0x00);//无效字节 仅高速模式下有效
   
   for (i=0;i<528;i++)
   {
       p[i] = SPI_MasterReceive();
   }
   SD_CS_PIN=1;
   while(!(Status_Register_Read ()&0x80));//检测忙状态确保内部时序完成
}

/*-----------------------------------------------------------
缓存数据写函数     操作码0x84 0x87
格式:操作码+3字节地址码(15无效位+10地址(528byte))
结束标志:CS管脚置高    
-----------------------------------------------------------*/ 
void Buffer_write (unsigned char *p,unsigned int byteaddr,unsigned char buffer) 
{    // 将缓存p写入buffer,此处设置p为528字节   byteaddr 为地址,buffer为buffer选择,1为buffer1,同理
   unsigned int i;
   unsigned long j;
   
   j= ((unsigned long)byteaddr)&0x03ff;
   
   SD_CS_PIN=0;
   
   if (buffer == 1)
       SPI_MasterTransmit(0x84);//操作码
   else
       SPI_MasterTransmit(0x87);//操作码
   
   SPI_MasterTransmit((unsigned char)(j>>16));//地址
   SPI_MasterTransmit((unsigned char)(j>> 8));
   SPI_MasterTransmit((unsigned char) j);
  
   for (i=0;i<528;i++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -