📄 sd.c
字号:
/*-----------------------------------------------------------
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 + -