基于Atmega128单片机SD卡读写程序(免费分享)

合集下载

SD卡内部构造与工作原理(免费分享).doc

SD卡内部构造与工作原理(免费分享).doc

SD卡内部构造与工作原理(附加基于Atmega128单片机SD卡读写程序)1、简介:SD卡(Secure Digital Memory Card)是一种为满足安全性、容量、性能和使用环境等各方面的需求而设计的一种新型存储器件,SD卡允许在两种模式下工作,即SD模式和SPI模式,本系统采用SPI模式。

本小节仅简要介绍在SPI模式下,STM32处理器如何读写SD卡,女口果读者如希望详细了解SD卡,可以参考相关资料。

SD卡内部结构及引脚如下图所示:/[ /1 1 1 M N 1 H,I T 1 FDAT2CMD CLK DATOCD/DAT3Inierface driver DAT1OCR£3l:01I 01X127:0]K RCA(15:0]o DSR[15:0]* CSD[12":O]* SCRK551O1*interfacecon^iollerre:eruoipot^Memor,1' core interface re^etSD卡内部图JPG2、SD卡管脚图:1 iMIN门2禹卞I-■■■- -II15 6250 9MRJFy工<D2™5>DD CLL VSS DATJ&ATilock Ros11iOOtn n?D IDw r i- f eSD卡图JPG3、SPI模式下SD各管脚名称为: sd卡:SPI模式下SD各管脚名称为JPG注般SD有两种模式:SD模式和SPI模式,管脚定义如下:(A)、SD MODE 1、CD/DATA3 2、CMD 3、VSS1 4、VDD 5、CLK6、VSS27、DATA08、DATA19、DATA22、DI3、VSS4、VDD5、(B)、SPI MODE 1、CSSCLK 6、VSS2 7、DO 8、RSV 9、RSVSD 卡主要引脚和功能为:CLK :时钟信号,每个时钟周期传输一个命令或数据位,频率可在0〜25MHz之间变化,SD卡的总线管理器可以不受任何限制的自由产生0〜25MHz的频率;CMD :双向命令和回复线,命令是一次主机到从卡操作的开始,命令可以是从主机到单卡寻址,也可以是到所有卡;回复是对之前命令的回答,回复可以来自单卡或所有卡;DAT0〜3:数据线,数据可以从卡传向主机也可以从主机传向卡。

基于ATmega128的闪存数据记录器的设计

基于ATmega128的闪存数据记录器的设计

基于ATmega128的闪存数据记录器的设计王龙;聂强广【摘要】设计采用SPI通信控制闪存芯片W25Q128BV,将接收到的数据暂时存储到闪存中,然后在USART通信模式下控制USB接口芯片CH376将数据传输到U 盘,最后实现外部的快速存储数据到U盘.【期刊名称】《湘南学院学报》【年(卷),期】2019(040)002【总页数】5页(P9-13)【关键词】ATmega128;CH376;flash;数据存储【作者】王龙;聂强广【作者单位】湘南学院电子信息与电气工程学院,湖南郴州 423000;湘南学院电子信息与电气工程学院,湖南郴州 423000【正文语种】中文【中图分类】TP333.91面对科学技术的进步,工业应用中数据采集的需求不断增加,数据采集技术的标准也在不断提高.因此,必须进一步提高数据存储设备的存储容量、速度、质量、便携性和工业应用环境.由U盘组成的数据存储记录仪可用于海量数据采集和存储、设备黑匣子、考勤机数据记录、水文监测、无纸记录仪和自动生产线.在中国最早使用磁带录制技术打开数字时代,高数字录制(HDDR)的特点是动态范围广.随着半导体技术的飞速发展,EPROM,EEPROM,SDRAM,FLASH等半导体存储芯片逐渐诞生.与磁带存储相比,上述数据存储芯片具有空间小,耐高温,存储速度极快,容量大,稳定性高的特点.中国科学院(CAS)开发的高速固态数据记录仪是早期的数据记录仪,以Flash作为中国的存储介质.其存储容量已超过120 GByte[1].它主要围绕CAN、USB2.0、PXIE等接口进行设计.1990年前后开始,在国外开发的数据记录器已经用于许多需要数据存储的领域.例如,SEAKR Engineering MMUR系列数据记录仪具有28 bit输出接口,数据记录速度为3.6 Gbps,容量为768 Gbit[2].代表性的研发公司是美国的 VCI和欧洲的 ATRIUM[3].随着USB总线的快速发展,采用USB接口技术实现数据记录具有传输速度快,即插即用的优点,因此USB接口技术在高速数据传输领域得到了推广和普及[4].ATmega128主控芯片将外部接收数据缓存到大容量闪存中,从闪存中读出缓存数据,并在U盘控制芯片CH376的帮助下将数据存储到U盘中.一方面,U盘高速数据记录器采用U盘,可靠性高,操作简单,成本低,避免了操作系统奔溃的问题.另一方面,使用闪存作为主数据高速缓存的目的是使数据写入速率与闪存存储速率相匹配.因此数据不受U盘存储数据采集速度的限制,达到数据采集和存储的最佳效果.具体构成如图1所示.图1 整体框架图1 CH376电路设计CH376是一个文件管理控制芯片,用于读写U盘或SD卡中的文件.CH376支持三种通信接口:8位并行端口、SPI接口和异步串行端口,支持普通USB存储设备和SD卡.CH376支持USB设备模式和USB主机模式,并且内置SD卡通信接口固件,内置USB通信协议的基本固件,内置处理Mass-Storage大容量存储设备专用通信协议固件,内置FAT16、FAT32和FAT12文件系统管理固件.MCU、DSP、MCU、MPU等控制器可以通过上述任何通信接口控制CH376芯片,访问U盘或SD卡中的文件,与计算机进行通信.1.1 文件应用基础U盘提供了几个用于数据存储的物理扇区,每个扇区的大小通常为512字节[5].因为计算机通常将U盘的物理扇区组织成FAT文件系统,以方便MCU通过U盘或SD卡在计算机之间交换,单片机也应该按照FAT规范以文件形式访问U盘中的数据.U盘可以有多个文件,每个文件是一组数据,由文件名区分和标识.实际文件数据的存储可能不是连续的,而是由一组“指针”(即,分配单元或集群)链接的多个块,从而可以根据需要增加文件长度以容纳更多数据.目录(文件夹)旨在促进分类管理.在FAT文件系统中,磁盘容量以簇的形式分配,这些簇总是扇区的倍数,因此文件占用的空间始终是集群的倍数和扇区的倍数.FAT_DIR_INFO记录当前文件中有效数据的长度,即有效数据的字节数.在信息中记录文件的长度,FAT文件系统会认为数据长度超过文件的长度是无效的.一般情况下,虽然数据确实存在,但无法读取文件长度的数据.如果数据很小或不连续,可以在每次添加数据后立即更新文件目录信息中的文件长度.但是,如果数据量很大并且需要连续写入数据,则更新文件目录信息会立即降低效率并经常修改文件目录信息,缩短了U盘上闪存的使用寿命(因为闪存只能被擦除有限次数),所以在这种情况下,在连续写入多组数据之后,或者在文件关闭之前,应再次更新文件目录信息中文件的长度.CMD_FILE_CLOSE命令将内存中文件的长度刷新为U盘文件的文件目录信息.虽然CH376支持最大1 GB的单个文件,但建议单个文件的长度不应超过100 MB以提高效率.1.2 存取模式CH376可以通过两种方式读写U盘文件:扇区模式和字节模式.在字节模式下,读写U盘文件的字节数小于1个字节,超过65535个字节,读写速度稍慢,但不需要额外的文件数据缓冲区,易于使用,适合较少的 RAM单片机系统,字节读写子程序主要是字节读取CH376ByteRead、字节写入CH376ByteWrite和移动文件指针CH376ByteLocate.在扇区模式下,可以在扇区中读取和写入U盘文件(通常每个扇区512个字节),因此读写速度稍快一些,但通常需要额外的文件数据缓冲区,并且额外的文件数据缓冲区必须是扇区512的整个长度.因此适用于具有大量RAM,大量数据和频繁读写数据的单片机系统.扇区读写子程序主要是扇区读取CH376SecRead和扇区写入CH376SecWrite.1.3 CH376模块电路设计CH376的通讯方式为异步串行通讯,R XD为串行数据输入,TXD为数据输出.使用这种通信方法的优点是减少连接.通信中CH376的数据格式属于标准字节传输模式:一个起始位,八个数据位和一个停止位.CH376可以适应硬件设置串口通讯的波特率,当然也可以按照单片机修改CMD_SET_BAUDRATE的功能.每次通电后,CH376的波特率由三个引脚(BZ、SCK和SDI)组合决定.CH376与MCU的连接见图2.2 Flash电路设计串行闪存W25Q128BV为那些对空间大小、引脚数和功耗有严格限制的系统提供一种存储解决方案.25Q系列比普通Flash设备具有更高的灵活性和性能.串行Flash代码可以映射到RAM并直接通过DUAL/QUAD SPI执行,以存储声音、文本和数据.W25Q128BV的供电范围为2.7~3.6 V,功耗在有效状态下低至4 MA,在睡眠状态下低至1 UA.W25Q128BV由65536个可编程页面组成,每页256字节,一次最多可以写入256个字节,可以擦除16页(4 KB扇区擦除)、128页(32 KB扇区擦除)、256页(64 KB扇区擦除),或一次擦除整个部分.W25Q128BV具有4096个可擦除扇区和256个可擦除块.4 KB的扇区对于数据和参数存储更加灵活.图2 CH376模块电路图W25Q128BV支持标准SPI接口和更高性能的DUAL/QUAD SPI,有时钟、片选、I/O0(DI)、I/O1(DO)、I/O2(/WP)和I/O3(/HOLD)几个引脚.SPI时钟可以达到104 MHz.这种传输速率比一般8位异步、16位并行FLASH存储器更快.连续读取模式在访问存储器方面非常有效,它可以读取具有8个时钟指令开销的24位地址数据,因此可以实现XIP.2.1 引脚说明2.1.1 片选信号(/CS)SPI的片选信号可以启动或禁止芯片操作.当/CS引脚为高电平时,芯片处于未选择状态,串行数据输出引脚处于高电阻状态.当芯片处于未检查状态时,芯片的功耗将处于待机状态,除非内部擦除、编程、写寄存器周期仍在进行中.当/CS为低电平时,选择芯片,功耗处于激活状态,则可以进行相应的读写和擦除.上电后,/CS必须在接受指令之前从高到低.上电后,/CS引脚必须跟踪VCC,因此最好在/CS引脚上添加一个上拉电阻.2.1.2 串口数据输入/输出(I/O口)W25Q128BV支持标准SPI,DUAL SPI,QUAD SPI操作.标准SPI指令使用单向DI引脚,在时钟的上升沿进行串行写入指令、地址和数据传输,还可以使用单向DO引脚在时钟下降沿读取芯片数据并读取寄存器值.DUAL和QUAD SPI指令使用双向IO引脚在时钟上升时向芯片写入指令、地址和数据,在时钟下降时从芯片读取数据和寄存器值.使用QUAD SPI指令必须把状态寄存器2中的非易失性QUAD使能位置位.当QE=1时,/WP和/HOLD引脚分别变为IO2和IO3.2.1.3 写保护(/WP)将SRBP和SRP的两个寄存器组合在一起,小至4 KB,这样整个芯片就可以被硬件保护./WP处于低位运行状态.当寄存器SR2中的QE位设置为1时,/WP功能无效,此时/WP已用作IO2.2.1.4 HOLD(/HOLD)选择芯片时,/HOLD引脚可以暂停芯片.当芯片/HOLD为低电平且/CS为低电平时,DO引脚为高阻态,DI和时钟引脚上的信号将被忽略.当/HOLD为高电平时,芯片恢复正常工作.当SPI总线上有多个器件时,/HOLD脚非常有用.放置QE时,/HOLD引脚为IO3,此时/HOLD功能无效.2.2 读取Flash电路的设计端口定义:CLK=PB5,/CS=PB4,DO=PB6,DI=PB7,程序配置过程,配置引脚使能,SPI时钟,系统IO端口初始化,进入SPI初始化,确定是否已设置指定的SPI标志位,进一步读取空标志位发送缓存,判断是否配置了SPI缓存标志.单片机与Flash的连接见图3所示,Atmega128分别使用了 PB4、PB5、PB6、PB7这几个I/O口.其中PB5输出CLK时钟信号,PB4输出/CS片选信号,PB6接输出,PB7接输入.图3 单片机与Flash连接3 软件设计3.1 主程序流程图主程序的主要功能是对定时器、I/O口资源、WRD128FLASH、CH376、串口通信等所用到的资源进行初始化.主程序流程见图4所示.3.2 CH376程序结构分析主程序除了对所用到的外设资源进行初始化之外还调用了3个子程序,分别是模拟数据传感器的读写程序、Flash暂存程序、对CH376s数据处理程序,单片机将数据存入U盘中是以文本文档形式存储的.CH376工作流程见图5.图4 主程序流程图图5 CH376工作流程图4 评价设计结果U盘高速数据记录器采用U盘,可靠性高,操作简单,成本低,避免了操作系统奔溃的问题.使用FLASH作为前级数据缓存的目的是在数据写入速率与采集/存储中的闪存速率之间实现有效匹配,不会因为采集和存储中的数据受U盘存储数据速率的限制,实现了数据采集和存储的最佳效果.表1是几种存取方式对比情况,可以看出这种U盘+FLASH方式有极大的优势.表1 几种存取方式对比存取方式存取特性存取容量存取速度使用方便度U盘连接不稳定,容易掉数据较小较慢即插即用FLASH 连接稳定较大较快不方便U 盘+FLASH 连接稳定较大较快即插即用这种记录仪使用环境灵活,功耗低,便于森林生态数据记录和水文观测点的数据记录,不通电的情况下可以采用电池或者太阳能供电来解决.操作简单,对于户外记录数据非常有帮助,当然如果工业实际应用,需要大量调试和各种环境测试、数据论证,从而进一步提高其性能.参考文献:【相关文献】[1]薛园园.USB应用开发宝典[M].北京:人民邮电出版社,2011.[2]周立功.PDIUSBD12/USB/固件编程与驱动开发[M].北京:北京航空航天大学出版社,2003.[3]邓剑,杨晓非,廖俊卿.FAT文件系统原理及实现[J].计算机与数字工程,2005(9):105-108.[4]张延园,焦磊.一种闪存文件系统的数据恢复机制[J].计算机工程,2008(14):283-285.[5]刘卫.Nand Flash控制器的设计与验证[M].长沙:国防科技大学,2008.。

atmega8L读写SD卡

atmega8L读写SD卡
return 1;
}
}
SD_Disable();
return 0;
}
9.write 512 bytes to a given sector from a Byte_byte_long Buffer
unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer,unsigned int Bytes)
temp=SD_READ;
temp&=0x10;//to maintain the pb.4 bit(data_in)
WDR();//feed the dog
if(temp)
{
data|=0x01;
}
if(b<7)
{
data=data<<1;//
}
delay_4ms();//4ms
//delay_1ms();
return(tmp);//the respone of the byte_write_operation
}
7.初始化
unsigned char SDInit(void)
{
unsigned char a,b,retry,erroetoken;
unsigned char CMD[]={0x40,0x00,0x00,0x00,0x00,0x95};//cmd0
if(num>0x01)
num=num>>1;
}
}
2.io口模拟spi,实现数据读取,在初始化时使用
unsigned char iodataread(void)

姚磊-基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序

姚磊-基于AVR的atmega128单片机读取DS1307数据在LCD12864上显示程序

//////////以下是DS1307头文件/////////////////////////////#include <avr/io.h>#include <util/delay.h>#define uchar unsigned char#define uint unsignedint#define IIC_PORT PORTF //定义是使用PROTF口,定义scl连接的是PF1,定义sda连接的是PF0 #define IIC_DDR DDRF//IIC_DDR&=SSDA;-设置SDA为输入口//IIC_DDR|=SDA;-设置SDA为输出口#define SCL 0X02 // IIC_PORT|=SCL; -scl置1#define SDA 0X01 // IIC_PORT|=SDA; -sda置1#define SSCL 0XFD // IIC_PORT&=SSCL; -scl置0#define SSDA 0XFE // IIC_PORT&=SSDA; -sda置0uintaa[7]; //定义一个数组以便接受数据void delay(unsigned int us){while(us--);}void Start_I2C(void){IIC_PORT|=SDA; //sdaIIC_PORT|=SCL; //sclasm("nop");IIC_PORT&=~SDA;asm("nop");IIC_PORT&=~SCL;}/********************************************内部函数,I2C结束********************************************/void Stop_I2C(void){IIC_PORT&=~SDA;IIC_PORT&=~SCL;asm("nop");IIC_PORT|=SCL;asm("nop");IIC_PORT|=SDA;asm("nop");}/********************************************内部函数,等待ACK********************************************/void Ack_I2C(void){unsigned char errtime=20;IIC_PORT|=SDA; //上拉IIC_DDR&=~SDA; //设置为输入口IIC_PORT|=SCL;asm("nop");while(PIND&SDA){errtime--;if(!errtime){Stop_I2C();IIC_PORT&=~SDA; //超时,给他个离开的理由}}IIC_PORT&=~SCL;asm("nop");IIC_DDR|=SDA; //设置为输出口}/********************************************内部函数,I2C发送ACK********************************************/void SendAck_I2C(){IIC_PORT &= ~SDA; //数据线保持拉低,时钟线发生一次从高低的跳变发送一个应答信号asm("nop");IIC_PORT |= SCL;asm("nop");IIC_PORT &= ~SCL;}/********************************************内部函数,向总线传送非响应********************************************/void SendNotAck_I2C(){IIC_PORT |= SDA; //数据线保持高,时钟线发生一次从高低的跳变没有应答asm("nop");IIC_PORT |= SCL;asm("nop");IIC_PORT &= ~SCL;}/********************************************内部函数,向总线传送字节@ch数据********************************************/void Send_I2C (intch){inti,a;for (i=1;i<=8;i++) //发送八位{IIC_PORT &= ~SCL; //总线放空delay(1);a = (ch&0x80); //根据给定数据,又高位到低位逐步提出字节位,发送到总线上if(a){IIC_PORT |= SDA;}else{IIC_PORT &= ~SDA;}ch<<= 1; //左循环以便输出下一位delay(1);IIC_PORT |= SCL; //总线使能,发送总线数据delay(1);}IIC_PORT &= ~SCL; //总线8位传送完成,总线放空}/********************************************内部函数,向总线传送字********************************************/unsignedint Receive_I2C(){unsigned char i,a;IIC_DDR &= ~SDA; //设置为输入口IIC_PORT |= SDA; //不知道为啥,1的时候读入正确0的时候读入全部为0;for(i=1;i<=8;i++) //读入八个位{a<<=1; // 读入数据左循环IIC_PORT &= ~SCL; //总线放空delay(1);IIC_PORT |= SCL; //时钟做一次从低到高的跳变可以接收一位数据delay(1);if(PINF&SDA)////////////////////////此处特别注意,变更SDA引脚时这个一定要跟着变{a |= 1;}else{a |= 0;} // 将数据编入变量a}IIC_PORT &= ~SCL; //总线放空IIC_DDR |= SDA; //io变成输出return a; //反馈接收到的信息}/********************************************外部函数向芯片D1307 之中地址为address的寄存器写入数据date 仅为八位字节@addtess要写数据的地址@date 要写的数据********************************************/voidwrite_time(intaddress,int date){Start_I2C(); //启动总线Send_I2C (0xD0); //呼叫芯片D1307,并定义为写动作Ack_I2C(); //等待响应信号Send_I2C (address); //发送地址Ack_I2C(); //等待响应信号Send_I2C (date); //发送数据Ack_I2C(); //等待响应信号Stop_I2C (); //停止总线}/********************************************外部函数从芯片D1307读出10为字节地址1:秒2:分3:时4:星期5:号6:月7:年8 控制字@addtess要读数据的地址********************************************/intread_time(){int i=0;Start_I2C(); //启动传送Send_I2C (0xD0); //呼叫芯片D1307,并定义为写动作Ack_I2C(); //等待响应信号Send_I2C (0x00); //发送起始地址Ack_I2C(); //等待响应信号Stop_I2C (); //关闭总线Start_I2C(); //启动总线Send_I2C (0xD1); //呼叫芯片D1307,并定义为读动作Ack_I2C();for(i=0;i<7;i++){ aa[i]=Receive_I2C(); //接受自初始地址开始的10个字节地址1:秒2:分3:时4:星期5:号6:月7:年8 控制字if(i<6)SendAck_I2C(); //每成功接受一位发送一个响应信号以便接受下一位if(i==6)SendNotAck_I2C();}Stop_I2C (); //接受完成停止}void ds1307init(){write_time(0x00,0x40);write_time(0x01,0x32);write_time(0x02,0x10);write_time(0x03,0x01);write_time(0x04,0x30);write_time(0x05,0x10);write_time(0x06,0x17);}//////////以下是LCD12864头文件//////////////////////////////**============================================================================== ==========================** File : ws_lcd_st7920.h* Hardware Environment:* Build Environment : AVR Studio 4.16 + Winavr 20090313* Version : V1.0* By : Wu Ze** (c) Copyright 2005-2009, WaveShare* * All Rights Reserved**============================================================================== ==========================*/#include <util/delay.h>#include <string.h>#include <stdarg.h>#include <avr/io.h>#define LCD_DELAY() _delay_us(75)unsignedintlcd_buffer[64];/**-------------------------------------------------------------------------------------------------------** 从SPI接口发送1byte的数据**-------------------------------------------------------------------------------------------------------*/voidspiSendChar(uint8_t send_char){SPDR = send_char;while (!(SPSR & (1<<SPIF)));}/**-------------------------------------------------------------------------------------------------------** 给LCD控制芯片ST7920发送指令的函数**-------------------------------------------------------------------------------------------------------*/void sendCodeST7920(uint8_t code){spiSendChar(0xF8);spiSendChar(code & 0xF0);spiSendChar((code<<4));LCD_DELAY();}/**------------------------------------------------------------------------------------------------------- ** 给LCD控制芯片ST7920发送数据的函数**------------------------------------------------------------------------------------------------------- */void sendDataST7920(uint8_t data){spiSendChar(0xFA);spiSendChar(data & 0xF0);spiSendChar((data<<4));LCD_DELAY();}/**------------------------------------------------------------------------------------------------------- ** 读取数据栈内容刷新LCD函数* *lcd_stack指向用于刷新LCD的数据栈,需64byte容量**------------------------------------------------------------------------------------------------------- */voidrefreshLCD(const uint8_t *lcd_stack){uint8_taddr;sendCodeST7920(0x02); /*地址归位*/for(addr=0;addr < 16;addr++){sendDataST7920(*(lcd_stack + addr));}for(addr=32;addr < 48;addr++){sendDataST7920(*(lcd_stack + addr));}for(addr=16;addr < 32;addr++){sendDataST7920(*(lcd_stack + addr));}for(addr=48;addr < 64;addr++){sendDataST7920(*(lcd_stack + addr));}}/**------------------------------------------------------------------------------------------------------- ** 将十进制数据转换成ASCII字符的函数* *str是转换ASCII后存放用的栈* dec是需要转换的十进制数据* width是转换成ASCII后的宽度(高位填充'0')**------------------------------------------------------------------------------------------------------- */voiddecToAscii(uint8_t* str,uint16_t dec,uint8_t width){while(width){switch(width){case 5:{*str = (dec/10000+'0');dec%=10000;break;}case 4:{*str = (dec/1000+'0');dec%=1000;break;}case 3:{*str = (dec/100+'0');dec%=100;break;}case 2:{*str = (dec/10+'0');dec%=10;break;case 1:{*str = (dec+'0');break;}default: *str = '0';}width--;str++;}}/**------------------------------------------------------------------------------------------------------- ** 将十六进制数据转换成ASCII字符的函数* *str是转换ASCII后存放用的栈* hex是需要转换的十六进制数据* width是转换成ASCII后的宽度(高位填充'0')**------------------------------------------------------------------------------------------------------- */voidhexToAscii(uint8_t* str,uint16_t hex,uint8_t width){uint16_ttmp;while(width){switch(width){case 4:{tmp=(hex>>12);if(tmp>9) *str = tmp+('A'-10);else *str = tmp+'0';break;}case 3:{tmp=(hex>>8)&0x000F;if(tmp>9) *str = tmp+('A'-10);else *str = tmp+'0';break;case 2:{tmp=(hex>>4)&0x000F;if(tmp>9) *str = tmp+('A'-10);else *str = tmp+'0';break;}case 1:{tmp=hex&0x000F;if(tmp>9) *str = tmp+('A'-10);else *str = tmp+'0';break;}default: *str = '0';}width--;str++;}}/**-------------------------------------------------------------------------------------------------------** showLine是用于编辑LCD数据栈的函数* showLine的使用方法与功能类似于ANSI C的printf函数* 例子:showLine(0,0,lcd_buffer,"My name is %c%c.%d3...",'W','s',12);* 上面的例子通过refreshLCD函数刷新后,在带有ST7920控制芯片的LCD上显示的效果为"My name is Ws.012..."* x对应LCD的横坐标* y对应LCD的纵坐标* *lcd_stack指向用于刷新LCD的数据栈* *str指向用于将要显示的内容**-------------------------------------------------------------------------------------------------------*/voidshowLine(const uint8_t x,const uint8_t y,uint8_t* lcd_stack,char * str,...){uint8_t coordinate = 16*y + x;va_list marker;va_start(marker,str); /* Initialize variable arguments. */while(*str!='\0'){if(coordinate>64) break; /*防止堆栈溢出*/if(*str == '\\'){str++;lcd_stack[coordinate] = *str;}else if(*str == '%'){str++;if (*str=='d'||*str=='D'){str++;decToAscii(&lcd_stack[coordinate],va_arg(marker,uint16_t),(*str-'0'));coordinate+=(*str-'0'-1);}else if(*str=='c'||*str=='C'){lcd_stack[coordinate] = va_arg(marker,uint16_t);}else if(*str=='x'||*str=='X'){str++;hexToAscii(&lcd_stack[coordinate],va_arg(marker,uint16_t),(*str-'0'));coordinate+=(*str-'0'-1);}}/*如有新的转义符指令请添加在这里*/else{lcd_stack[coordinate] = *str;}str++;coordinate++;}va_end( marker ); /* Reset variable arguments. */}void st7920LcdInit(void)// SPI initialization// SPI Type: Master// SPI Clock Rate: 2*1843.200 kHz// SPI Clock Phase: Cycle Half// SPI Clock Polarity: Low// SPI Data Order: MSB First{ DDRB|=0x87;PORTB|=0xF8;SPCR=0x50;SPSR=0x01;sendCodeST7920(0x0C);//整体显示sendCodeST7920(0x01);//清屏_delay_ms(2);memset(lcd_buffer,' ',sizeof(lcd_buffer));}//////////以下是主函数/////////////////////////////#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>#include "ws_lcd_st7920.h"#include"ds1307.h"#define uchar unsigned char#define uint unsignedintexternuintlcd_buffer[64];externuintaa[7];void main(void){ uchar a1,a2,b1,b2,c1,c2,d1,d2,e1,e2,f1,f2,g1,g2,h1,h2,key=0;st7920LcdInit(); /*LCD init*/IIC_DDR|=SCL;IIC_DDR|=SDA;//设置SCL,SDA为输出口ds1307init();///不可每次都初始化while (1){ read_time();a1=aa[0]>>4; a2=aa[0]&0x0F;//秒b1=aa[1]>>4; b2=aa[1]&0x0F;//分c1=aa[2]>>4; c2=aa[2]&0x0F;//时d1=aa[3]>>4; d2=aa[3]&0x0F;//星期e1=aa[4]>>4; e2=aa[4]&0x0F;//号f1=aa[5]>>4; f2=aa[5]&0x0F;//月g1=aa[6]>>4; g2=aa[6]&0x0F;//年showLine(3,1,lcd_buffer,"time is:");showLine(2,2,lcd_buffer,"20%d1%d1-%d1%d1-%d1%d1-%d1%d1",g1,g2,f1,f2,e1,e2,d1,d2);showLine(2,3,lcd_buffer,"%d1%d1:%d1%d1:%d1%d1",c1,c2,b1,b2,a1,a2); refreshLCD(lcd_buffer); /*刷新LCD*/}}。

基于ATmega128单片机的图像采集硬件系统

基于ATmega128单片机的图像采集硬件系统

基于ATmega128单片机的图像采集硬件系统丁曼;张代远【摘要】ATmega128系列单片机具有处理速度快,内部功能模块丰富等优点,其数据吞吐率可高达1MIPS/MHz,能够很好地缓解系统在功耗与处理速度上的矛盾.而OV6620作为一种数字摄像头,避免了传统模拟摄像头的消耗MCU资源、功耗大等缺点.文中正是基于这些特点,采用ATmega128单片机,将软件程序通过ISP下载到AVR单片机后,按照原理图连接好电路板及实物,通过OV6620摄像头采集一幅图像,传输到AVR单片机,再对图形进行一定的处理.实验证明所设计的硬件系统能够实现图像的采集、处理以及通信的功能,提高了图像采集与通信的速率,并保持了较好的图像稳定度.%Considering ATmegal28 MCU has advantages of good processing speed and rich internal function, and its data throughput rates can be as high as lMlPS/MHz.it can alleviate the contradiction of system's power consumption and processing speed well. OV6620, as a digital camera, can avoid the shortcomings of traditional analog camera such as MCU resource consumption needing large power. It is based on these characteristics, uses the ATmegal28 MCU, after downloads the software program to the AYR via ISP, connects the physical circuit board following the schematic to capture an image by OV6620 camera and transmit to the AVR microcontroller, and then does a certain treatment to the graphics. Experiments show that die design of the hardware systems can realize the image acquisition , processing and communications. This method improves die rates of image acquisition and communication as much as possible, and has a better image stability.【期刊名称】《计算机技术与发展》【年(卷),期】2012(022)007【总页数】4页(P215-218)【关键词】AVR单片机;图像采集;OV6620;Protel99SE;PCB电路图【作者】丁曼;张代远【作者单位】南京邮电大学计算机学院,江苏南京210003;南京邮电大学计算机学院,江苏南京210003;江苏省无线传感网高技术研究重点实验室,江苏南京210003;南京邮电大学计算机技术研究所,江苏南京210003【正文语种】中文【中图分类】TP390 引言AVR 单片机是RISC 精简指令集的高速8 位单片机,具有I/O 口和A/D 转换功能,高速、低耗、保密性,并且有功能强大的定时器/计数器及通讯接口[1]。

单片机读取SD卡程序

单片机读取SD卡程序
uint count; printf("SD_read_block"); SD_CS=0; SdCommand(0x11,address,0xff); if(SdResponse()==00) { while(SdRead()!=0xfe);
for(count=0;count<len;count++) *Block++=SdRead(); for(;count<512;count++) SdRead(); SdRead(); SdRead(); SD_CS=1; SdRead(); printf(" Read Data as Follows\n");
buf1[i]=0;
}
SdReadBlock (buf1,0x00,512); //读地址为0x00的存储块, 大小为512字节
for(i=0;i<0x20;i++) {
//读取的数据通过串行口输出
for(j=0; j<0x10; j++){
printf("%4bX",buf1[(i<<4)+j]);
return 1; } printf("Command 0x11 (Read) was not received by the SD.\n"); return 0; }
/******************************* 主函数 *******************************/
uchar xdata buf1[512]; uchar xdata buf2[30];
/********************** *****************************/ void SdWrite(uchar n){

ATmega128L单片机的MicroSD卡读写

ATmega128L单片机的MicroSD卡读写

T ECH N OLOGYRE VI E W技术纵横ATmega128L单片机的Micro SD卡读写u西安工程大学朱大锐张团善高文摘要针对电脑横机控制系统对花型文件数据存储的要求,在ATmega128L单片机基础上采用Micro SD卡实现嵌入式文件系统。

文章介绍了Micro SD卡的特点、FAT文件系统、SPI模式协议以及硬件接口的实现。

通过ATmega128L的SPI模式与Micro SD卡进行同步数据传输,实现Micro SD卡的读写,以FAT32文件格式建立相应的文件系统,把数据以文件方式写入Micro SD卡。

通过单片机向Micro SD卡发送读写扇区命令,完成文件的创建、打开、读写、删除等操作。

关键词ATmega128L Micro SD卡串行外设协议文件分配表引言随着工业控制系统功能的增强,系统对于存储介质的安全、容量、性能的要求越来越高。

Micro SD卡是在SD卡和Mini SD卡基础上发展起来的一种多功能存储卡,具备串行和随机存取能力,可以通过专用优化速度的串行接口访问,数据传输可靠,安全性好,传输速度快,存储容量大,体积小,被列为目前全球最小的迷你存储卡。

Micro SD卡支持SD模式和SPI模式。

随着高性能单片机的性能不断提高,利用高性能、低功耗的AVR8位ATmega128L单片机的串行外设接口SPI与Micro SD卡之间进行高速同步数据传输,设计开发了一种嵌入式文件系统。

1硬件电路设计Micro SD卡的接口可以支持两种操作模式:SD模式和SPI模式。

主机系统可以选择其中任一模式。

SD卡模式允许4线的高速数据传输,传输速率高,但是大部分单片机无此接口,使用软件模拟协议复杂。

SPI模式使用简单通用的SPI通道接口就可实现数据传输,目前大多数单片机提供SPI接口。

SPI模式的优势在于可以使用标准主机,从而把外设减少到最低。

SPI模式相对于SD模式的缺点是损失了传输速度;但是目前的微处理器的处理速度越来越高,利用SPI模式大都能满足工程需要。

单片机读写SD卡API模式读写

单片机读写SD卡API模式读写

单片机读写SD卡最简单最根本的程序处理器:s3c44b0 〔arm7〕SD卡与处理器的引脚连接:MISO -->SIORxD MOSI -->SIOTxD CLK -->SCLK CS-->PE5四个文件:sd_drive.c :用户API函数,移植时不需修改sd_cmd.c:中间层函数,移植时不需修改sd_hard.c:硬件层函数,移植时需修改sd_config.h:一些功能的宏定义,移植时需修改第一次读写SD卡时,需调用SD_Init(void),然后就可以条用Read_Single_Block或者Write_Single_Block进展读写操作注意:进展写操作时,最好不要写前700个扇区,应为这些扇区都是FAT文件系统的重要扇区,一旦误写那么可能会导致SD无法被电脑识别,需格式化。

/*******************************************************文件名:sd_drive.c作用:用户API函数,包括四个函数,读取一块扇区〔512字节〕U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf)写一个扇区〔512字节〕U8 Write_Single_Block(U32 blk_addr, U8 *tx_buf)获取SD卡根本信息,即读CSD存放器信息〔16字节〕:void SD_info()SD卡初始化:U8 SD_Init(void)********************************************************//********************************************功能:读取一个block输入:blk_addr为第几个block,rx_buf为数据缓存区首地址输出:返回NO_ERR那么成功,其它那么读取失败********************************************/U8 Read_Single_Block(U32 blk_addr, U8 *rx_buf){U16 rsp = 1;U8 i = 0;SD_sel(); //使能SD卡while(rsp && (i < 100)){write_cmd(CMD17, blk_addr << 9); //写命令CMD17 rsp = Get_rsp(R1); //获取容许send_clk();}if(i > 99) //如果命令超时,那么执行超时处理{SD_desel();Uart_Printf("fail in writing CMD17\n");return WR_SGL_BLK_ERR;}spi_ro_mode();send_clk(); //发送8个clkread_data(rx_buf); //读取512字节SD_desel();Uart_Printf("succeed in reading the %dst block!!!\n", blk_addr); return NO_ERR;}/********************************************功能:写一个block输入:blk_addr为要写第几个block,tx_buf为数据区输出:返回NO_ERR那么成功,其它那么读取失败********************************************/U8 Write_Single_Block(U32 blk_addr, U8 *tx_buf){U16 rsp = 1;U8 i = 0;SD_sel(); //使能SD卡while(rsp && (i < 100)){write_cmd(CMD24, blk_addr << 9); //写命令CMD24 rsp = Get_rsp(R1); //获取容许send_clk();}if(i > 99) //如果命令超时,那么执行超时处理{SD_desel();Uart_Printf("fail in writing CMD17\n");return WR_SGL_BLK_ERR;}spi_ro_mode();send_clk(); //发送8个clkwrite_data(tx_buf); //读取512字节SD_desel();Uart_Printf("succeed in writing a block!!!\n");return NO_ERR;}/********************************************功能:SD卡初始化输入:无输出:返回NO_ERR那么成功,其它那么读取失败********************************************/U8 SD_Init(void){U16 rsp = 1;U8 i = 0;spi_port_init(); //初始化spi端口spi_low_speed(); //初始化时SPI的速度必须低于400khzspi_ro_mode(); //只读模式SD_sel(); //选择SD卡for (i = 0;i < 10; i++) //发送至少75个clksend_clk();while(rsp && (i++ < 100)){write_cmd(CMD0, 0); //写命令CMD0rsp = Get_rsp(R1); //获取容许if (rsp == 1) //rsp为0那么初始化成功,为1那么继续写CMD0 break;send_clk();}SD_desel();if (i > 99) //初始化超时处理{Uart_Printf("fail in writing CMD0!!!\n");return INIT_FAIL;}i=0;SD_sel();while(rsp && (i++ < 100)){write_cmd(CMD1, 0); //写CMD1rsp = Get_rsp(R1); //获取容许send_clk();}SD_desel();if (i > 99){Uart_Printf("fail in writing CMD1!!!\n");return INIT_FAIL;}Uart_Printf("SD card init OK!!!\n");spi_high_speed(); //初始化工作全部完毕,SPI进入模式模式spi_rt_mode();return NO_ERR;}/********************************************功能:获取SD卡信息输入:输出:********************************************/void SD_info(){U8 rsp=0;U8 csd[16];SD_sel();write_cmd(CMD9, 0);rsp = Get_rsp(R1);if (rsp != 0){SD_desel();Uart_Printf("error in getting SD info!!!\n");return ;//GET_INFO_ERR;}if (read_register(16, csd) != NO_ERR){SD_desel();return ;}SD_desel();Uart_Printf("SD information :\n");if (csd[0] & 0x40 ==0x40){Uart_Printf("version 2.0\n");Uart_Printf("size is : %d\n",1024 * (csd[8]<<8 + csd[9]));}else{Uart_Printf("version 1.x \n");Uart_Printf("size is : %d MByte\n", ((((csd[6]&0x03)<<10) | (csd[7]<<2) | ((csd[8]&0xC0)>>6) + 1) * (1 << ((((csd[9]&0x03)<<1) | ((csd[10]&0x80)>>7)) + 2)))>>11);}Uart_Printf("max block lenght is : %d\n",1<<(csd[5]&0x0f));}/****************************************************************************文件名:sd_cmd.c作用:中间层函数****************************************************************************//********************************************功能:向SD写入一个命令输入:cmd为命令,addr为SD卡片内地址输出:无********************************************/void write_cmd(U8 cmd, U32 addr){U8 i = 0;U8 temp[4];spi_rt_mode(); //spi发送与接收模式if (cmd <= 13) //前13个命令与地址无关{spi_write_byte((cmd & 0x3F) | 0x40); //命令最高两位必须是01for(i = 0; i < 4; i++) //发送4个0,协议规定的spi_write_byte(0);if (cmd == 0)spi_write_byte(0x95); //如果是CMD0,那么要发送CRC校正else spi_write_byte(0xff); //非CMD0,那么无需CRC校正,默认为0xFF}else{for(i = 0; i < 4; i++) //将32位的地址分割成4个字节,准备发送temp[i]=(char)(addr >> (24 - 8 * i));spi_write_byte((cmd & 0x3F) | 0x40); //命令最高两位必须是01for(i =0; i < 4; i++)spi_write_byte(temp[i]); //发送地址,共4个字节spi_write_byte(0xff); //非CMD0,那么无需CRC校正,默认为0xFF}}/********************************************功能:获取SD卡的容许字节,可能是一个或者两个字节输入:type为容许类型输出:容许字节,个数有容许类型而定********************************************/U16 Get_rsp(U8 type){U16 rsp, temp;spi_ro_mode(); //spi只读模式send_clk(); //先发送8个clkrsp = spi_read_byte(); //用spi读取容许字节if (rsp & 0x8)rsp = spi_read_byte();if (type == R2) //如果是R2类型,那么容许为两个字节,须再次读取{temp = rsp << 8;rsp = spi_read_byte();rsp = temp | rsp;}return rsp;}/********************************************功能:读取SD的一个block的内容,一般为512字节输入:buffer为数据缓存区头地址输出:无********************************************/void read_data(U8 *buffer){U32 i;U8 rsp = 0;while(!(rsp == 0xfe)) //容许字节的最低为0那么代表起始位rsp = spi_read_byte();for(i = 0;i < BLOCK_LEN; i++) //读一个block的内容,一般为512字节buffer[i] = spi_read_byte();for(i = 0; i < 2; i++) //读两个CRC校正码send_clk();send_clk(); //读完毕字节}/********************************************功能:写入SD的一个block的内容,一般为512字节输入:buffer为数据缓存区头地址输出:********************************************/U8 write_data(U8 *buffer){U16 rsp = 0, tmp = 0, busy = 0, i = 6;spi_rt_mode();spi_write_byte(0xfe); //起始位for(i = 0; i < 512; i++) //发送512个字节spi_write_byte(buffer[i]);for(i = 0; i < 2; i++) //发送16位的CRC校正spi_write_byte(0xff);spi_ro_mode(); //等待容许while(!(rsp == 0x1)){rsp =(U16)spi_read_byte();tmp = rsp;rsp &= 0x11;}while(!(busy == 0xff)) //判忙{busy = spi_read_byte();}tmp &= 0xe;if (tmp == 4)return NO_ERR;else{Uart_Printf("writing error!!!\n");return WR_SGL_BLK_ERR;}}/******************************************** 功能:输入:输出:********************************************/ U8 read_register(U8 len, U8 *buffer){U8 rsp = 0xff, i = 0;spi_ro_mode();while((rsp == 0xff) && (i < 100)){rsp=spi_read_byte();}if (i > 99){Uart_Printf("ERR in readding register!!!\n");return rsp;}if (rsp != 0xfe){buffer[0] = rsp;i = 1;}elsei = 0;for( ; i < len; i++)buffer[i] = spi_read_byte();for(i = 0; i < 2; i++ )send_clk();send_clk();return NO_ERR;}/*******************************************************************文件名:sd_hard.c作用:硬件层函数,移植时需根据处理器或者硬件构造的不同,对该文件的函数进展修改********************************************************************//********************************************功能:使能SPI,发送CLK输入:无输出:无********************************************/void send_clk(){rSIOCON |= (1 << 3); //使能SPIwhile (!(rINTPND & BIT_SIO)); //等待发送完毕rI_ISPC|=BIT_SIO; //去除中断标志}/********************************************功能:用SPI发送一个字节输入:dat为要发送的字节输出:无********************************************/void spi_write_byte(U8 dat){rSIODAT = dat;send_clk(); //SPI发送}/********************************************功能:用SPI读取外设一个字节输入:无输出:读到的一个字节********************************************/U8 spi_read_byte(void){send_clk(); //SPI发送return rSIODAT;}/********************************************功能:初始化SPI的端口输入:无输出:无********************************************/void spi_port_init(){rIVTT = 0;rPCONF = (rPCONF & 0xe3ff) | 0x1B0C00; //除了CLK,MISO,MOSI外,不改变其他位rPUPF |= 0x160; //使能MISO的上拉电阻}/***************************************************************文件名:sd_config.h作用:相关功能的宏定义,以便被以上三个文件调用,便于移植移植时需修改***************************************************************/#ifndef _SD_CONG#define _SD_CONG#define BLOCK_LEN (512) //一个block的长度#define CMD0 0#define CMD1 1 // 读OCR存放器#define CMD9 9 // 读CSD存放器#define CMD10 10 // 读CID存放器#define CMD12 12 // 停顿读多块时的数据传输#define CMD13 13 // 读Card_Status 存放器#define CMD16 16 // 设置块的长度#define CMD17 17 // 读单块#define CMD18 18 // 读多块,直至主机发送CMD12#define CMD24 24 // 写单块#define CMD25 25 // 写多块#define CMD27 27 // 写CSD存放器#define CMD28 28 // Set the write protection bit of the addressed group#define CMD29 29 // Clear the write protection bit of the addressed group#define CMD30 30 // Ask the card for the status of the write protection bits#define CMD32 32 // 设置擦除块的起始地址#define CMD33 33 // 设置擦除块的终止地址#define CMD38 38 //擦除所选择的块#define CMD42 42 // 设置/复位密码或上锁/解锁卡#define CMD55 55 // 制止下一个命令为应用命令#define CMD56 56 // 应用命令的通用I/O#define CMD58 58 // 读OCR存放器#define CMD59 59 // 使能或制止//错误返回#define INIT_FAIL 0#define NO_ERR 1#define WR_SGL_BLK_ERR 2#define GET_INFO_ERR 3#define R1 1 //SD卡容许类型,表示一个字节#define R2 2 //SD卡容许类型,表示两个字节//一下是移植时需修改的内容#define SD_desel() rPDATE=0x20; //使能SD卡#define SD_sel() rPDATE=0x00; //放开SD卡#define spi_high_speed() rSBRDR = 5; //spi高速模式#define spi_low_speed() rSBRDR = 99; //spi低速模式#define spi_ro_mode() rSIOCON = (0x0 << 7) | (0x0 << 6) | (0x0 << 5) | (0x0 << 4) | (0x0<< 3) | (0x0 << 2) | 0x1 //只读模式#define spi_rt_mode() rSIOCON = (0x0 << 7) | (0x0 << 6) | (0x1 << 5) | (0x0 << 4) | (0x0 << 3) | (0x0 << 2) | 0x1 //读写模式#endif。

单片机读写SD卡教程

单片机读写SD卡教程

郑重声明:本实验并不是对所有SD卡都能成功运行第一步:打开win hex软件,用读卡器读SD卡,在win hex中查看SD卡FPrlrj 旧nmg *御日・曲日尺 立件(日轄:号iifllPI 讥吵:当Tfllll 春罰;〔I SW (£)旨口凹帶此|;也S X电a► O C3 * -0 畫・■€■*电bld! IbiljUA ] 初1 悶「1|馆口曲佃 AgraaSBJLXsta InAEiqptetEJ' 03839535 16BH(*J-): 0曲* ?;第詞 EKt £i2f UrEiib&d MT 1 SOB 66.5 K0 1.2 MB Famof 跆hl 色 TipHium 1 Offset 0 1 2 3 4 5 6 7 3 9 A B c n E F /1 ModSfA'v wC Cans Ae^defDOOOOOD Ec 00 00 OD 00 00 DO aa 00 00 00 00 DO ao DO oo fc 1j uFirmwlrf Atv.. 1.D0 OCIIDOOOI 00 00 00 00 oo 00 00 OiO 00 no 00 00 GO no no 00..DUS : USB D000002D 00 00 00 00 00 00 DO 00 :ir 00 00 00 DO 00 DO ao I! ■DerauitEdnDD00003D 00 00 00 00 00 ao DO aa 00 00 00 00 DO a)a DO aa ■i ■ j 4Sl5te: original oomoQQin 00 00 00 00 00 on on OQ 00 no 00 00 00 Qi Q 00 00. .Undo lewef: 0 00000050 oa 00 00 00 00 00 DO OQ 00 00 00 00 m 00 DO QO r i ■, f Undo rsverses: Ma D000006D 00 OD 00 00 00 ao DO aa 00 00 00 ao DO o)a DO aa -・ --oonoau70 on 00 00 OQ 00 00 DO oa oa OQ 00 QO 00 ao DO 00. ■1.^7,1126.576 诩跆 DOOaOOBD oa 00 00 00 00 00 DO OQ 00 00 00 00 m 00 DO 00 r ・ ■■ 1D000009D 00 OD 00 00 00 ao DO aa 00 00 00 ao DO a)a DO oaii i J 4 Siapkis seclorfi 创 entE51 3 DOOQOaM) 00 00 00 OQ 00 00 no a>a 00 00 00 00 do00 DO-”4 4OOOOOOB oa 00 00 00 00 00 DO OU 00 00 00 00 DO 00 DO 00 r i■1 f Psritllfln: -:1 DOOOOOC D 00 00 00 aa 00 ao DO aa 00 00 00 ao DO a)o DO oa h ij 4R C ISW B S-BCbO r Ho Na OOOOOOD 00 QO m 00 00 00 00 no 00 00 GO 00 DO 00 00 ao MDC J B : hiBoodewnalOOOOOOE D 00 00 00 00 00 00 DO ao 00 00 00 00 00 00 DO 00, ,Cuaiader 虻I ANSI ASCIIoooaaoFD 00 OD 0000 DO ao DO aa 00 00 00 00 DO a)a DO aoOR 曲: hexadecwnaloomoaioo 00 00 00OQ oo 00 no aa 00 OQ 00 00 lOO Qi O 00 DOoooaoiiD 00 00 00 00 00 00 DO □ Q 00 00 00 00 m00DO 00 r ilnllnuiiw *. 1No ofwIridcrBVK' ID000012D 00 OD 00 00 00 ao DO aa 00 00 00 ao DO a)a DO oa ii iJ 4D000013Q oo 00 oo00 oo 00 oo ao oo no do Qfl oo oo 00 so加 Aab 用 00000140 DU 00 00 00 00 00 DO QO 00 00 00 00 DO ao DO 00 ,, ,.TEMPltilifer 1.2GBffee D000015D 00 OD 00 OQ 00 ao DO aa 00 00 00 ao DO a)a DO aa B1J 4 ^D MINI -IIL OC AL S'1 打 amp QOOOQ1B O 00 QO 00 QO oo 00 DO aa 00 00 00 00 lOO Qi O 00 DO..tJ 00000170 00 00 0000 00 00 DO 00 00 00 00 00 uo 00DO 00 r i■1 1J4D00001BD 00 00 00OQ 00 aoDO aa0000 00ao DO a)o DO oa “.J-SedamoT 胡4■加轴 0tT9«l:a=D Blatk-^ParHion 1Siad BecWrsUnp3it(jon^b*5 阿苗点击查找(ctrl+F ) Find Text 3 3 J J J J J J J J 3 ] ] ] ] ]The folouing text string wil be searched: FAT| caseASCII/Code page vUse this as a wildcardI I Whole wo(d^ odjjSearch:□ Cond.: offset mod =I_ Search in plgk only]Search in dll open windows |—| List search hits, 14)to 1Cancel输入FAT (找到 DBR 处)发现DBR 起始于0x11200扇区地址,它必是512整数倍,因为一个扇区含 512BYTE ,所以 在程序中读一个扇区时一定要是 512整数倍,否则会出错。

Almel ATmega128 ATmega128L 可编程 Flash 说明书

Almel ATmega128 ATmega128L 可编程 Flash 说明书

产品特点•高性能、低功耗的 AVR® 8位微处理器•先进的 RISC 结构–133条指令 – 大多数可以在一个时钟周期内完成–32 x 8 通用工作寄存器 + 外设控制寄存器–全静态工作–工作于16 MHz时性能高达16 MIPS–只需两个时钟周期的硬件乘法器•非易失性的程序和数据存储器–128K 字节的系统内可编程Flash寿命: 10,000次写/擦除周期–具有独立锁定位、可选择的启动代码区通过片内的启动程序实现系统内编程真正的读-修改-写操作–4K字节的EEPROM寿命: 100,000次写/擦除周期–4K 字节的内部SRAM–多达64K字节的优化的外部存储器空间–可以对锁定位进行编程以实现软件加密–可以通过SPI实现系统内编程•JTAG接口(与IEEE 1149.1标准兼容)–遵循JTAG标准的边界扫描功能–支持扩展的片内调试–通过JTAG接口实现对Flash, EEPROM, 熔丝位和锁定位的编程•外设特点–两个具有独立的预分频器和比较器功能的8位定时器/计数器–两个具有预分频器、比较功能和捕捉功能的16位定时器/计数器–具有独立预分频器的实时时钟计数器–两路8位PWM–6路分辨率可编程(2到16位)的PWM–输出比较调制器–8路10位ADC8个单端通道7个差分通道2个具有可编程增益(1x, 10x, 或200x)的差分通道–面向字节的两线接口–两个可编程的串行USART–可工作于主机/从机模式的SPI串行接口–具有独立片内振荡器的可编程看门狗定时器–片内模拟比较器•特殊的处理器特点–上电复位以及可编程的掉电检测–片内经过标定的RC振荡器–片内/片外中断源–6种睡眠模式: 空闲模式、ADC噪声抑制模式、省电模式、掉电模式、Standby模式以及扩展的Standby模式–可以通过软件进行选择的时钟频率–通过熔丝位可以选择ATmega103兼容模式–全局上拉禁止功能•I/O和封装–53个可编程I/O口线–64引脚TQFP与 64引脚 MLF封装•工作电压–2.7 - 5.5V ATmega128L–4.5 - 5.5V ATmega128•速度等级–0 - 8 MHz ATmega128L–0 - 16 MHz ATmega128微处理器,具有128K字节的系统BDTIC /ATMEL2ATmega1282467L–AVR–05/04引脚配置Figure 1. ATmega128的引脚综述ATmega128为基于AVR RISC 结构的8位低功耗CMOS 微处理器。

单片机读写SD卡教程

单片机读写SD卡教程

单片机读写SD卡教程引言:SD卡(Secure Digital Card)是广泛应用于各类数字设备上的一种存储介质。

它小巧轻便,可靠性高,容量大,因此在各种嵌入式系统中都广泛使用。

本教程将介绍如何使用单片机读写SD卡,包括初始化SD卡、读写数据等基本操作。

一、硬件准备在开始之前,我们需要准备以下硬件设备:1.一个支持SPI协议的单片机开发板(例如STC89C51、STM32等);2.一个SD卡插槽,或者是一个带有SD卡插槽的扩展板;3.杜邦线、面包板等连接器。

二、软件准备除了硬件设备,我们还需要准备以下软件工具:1. Keil C51、IAR、Keil MDK等单片机编译工具;2. SD卡相关的库文件,例如FatFs;3.一个用于测试的程序(可以是一个简单的读写数据的程序)。

三、连接SD卡插槽将SD卡插入到对应的插槽中,并将插槽与单片机的硬件SPI接口连接。

根据不同的开发板,连接方式可能有所不同,一般SPI接口包括SCK(时钟线)、MOSI(主机输出从机输入线)、MISO(主机输入从机输出线)和CS(片选线)等。

四、编写读写SD卡的程序在开始编写程序之前,我们需要先了解SD卡的工作原理。

SD卡通过SPI总线与单片机进行通信,通过发送特定的命令和参数实现读写操作。

以下是一个简单的读写SD卡的流程:1.初始化SD卡a.发送CMD0命令,将SD卡设置为SPI模式;b.发送CMD8命令,验证SD卡是否支持高速SPI模式;c.发送ACMD41命令,等待SD卡初始化完成。

2.读写数据a.发送CMD17命令,指定要读取的扇区地址;b.等待SD卡回应,确认读取命令执行成功;c.读取数据;d.发送CMD18命令,继续读取下一个扇区;e.重复步骤c和d,直到读取完所有数据;f.发送CMD12命令,停止读取。

g.发送CMD24命令,指定要写入的扇区地址;h.等待SD卡回应,确认写入命令执行成功;i.写入数据;j.发送CMD25命令,继续写入下一个扇区;k.重复步骤i和j,直到写入完所有数据;l.发送CMD12命令,停止写入。

atMega128的bootloader例程

atMega128的bootloader例程
//读取校验
char CheckFlash(void)
{
unsigned int i;
unsigned int TempInt;
unsigned int TempInt2;
for (i=0;i<ageByte;i+=2)
{
TempInt = read_program_memory(PageAddress + i,0x00);
//大于64K控制
if (PageAddressHigh) RAMPZ = 1;
else RAMPZ = 0;
}
/*****************************************************************************/
char GetPage(void)
TxChar(BootSize);
TxChar(BootVer);
break;
case 'L': //写配置信息
break;
case 'R': //读配置信息
break;
case 'I': //读信息
break;
default :
break;
}
//
void FlashLoad(void)
{
TxChar('O')
TxChar('K'); //发送OK
while (1)
{
GetPageNumber();
if (RealPageAddress == 0xffff) return;

AVR ATMEGA128 串口简单好使程序

AVR ATMEGA128 串口简单好使程序
}
//以上是串口发送接收函数
int main(void)
{
//PORTE=0B01000011;//调整让单片机的发送和接收直接连到MAX3232上
//DDRE =0B11100110;
PORTE=0B01110011;//针对本电路中的相关设置RS485通信
DDRE =0B11110110;
unsigned char temp;
Usart0_init();
while(1)
{
temp=Usart0_receive();
Usart0_transmit(temp);
//Usart0_transmit(0x5f);
}
//return 0;
}
#include <avr/io.h>
#include <avr/interrupt.h>
#include<util/delay.h>
#define UDRE0 5
#define RXC0 7
void Usart0_init(void) ;
//设置波特率9.6k,8位数据位,无校验,接收发送使能,1位停止位
UCSR0B=(1<<RXEN0)|(1<<TXEN0); //发送接收使能,使用查询方式,故没有使能中断
}
void Usart0_transmit(unsigned char c) //查询方式发送接收字符函数
{
while( !(UCSR0A&(1<<UDRE0)));//等待发送缓冲区为空
UDR0=c;
void Usart0_transmit(unsigned char c);

基于ATmega8的SD卡读写程序

基于ATmega8的SD卡读写程序
for(i=0;i<512;i++)//将缓冲区中要写入的512个字节写入SD卡
{
SD_spi_write(buffer[i]);
}
SD_spi_write(0xff);
SD_spi_write(0xff);//两个字节的CRC校验码,不用关心
temp=SD_spi_read();//读取返回值0x05,说明已写入数据
{
//SPCR &=~(1<<SPR0);
//SPCR |=(1<<SPR1);
//SPCR=~(1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);
SPSR &=~(1<<SPI2X);
}
void Spi_Init(void)
{
DDRB=0x2c; //0b0010 1100
return (temp);
}
/*复位SD卡*/
uchar SD_Reset(void)
{
uchar time,temp,i;
uchar pcmd[]={0x40,0x00,0x00,0x00,0x00,0x95};
is_init=1;
//Spi_low();
SS_set;//关闭片选
for(i=0;i<0x0f;i++)//至少74个时钟信号
SID_set;
else
SID_clr;
SCLK_clr;
SCLK_set;
Order<<=1;
}
Order=Data;
Order<<=4;
for(i=0;i<8;i++)

ATMEGA128单片机读写倾角传感器ADXL345及所有I2C器件读写通用程序程序

ATMEGA128单片机读写倾角传感器ADXL345及所有I2C器件读写通用程序程序

}
uchar shin() {
uchar i,read_data; DDRD&=0XFD;//输入 for(i=0;i<8;i++)
{ PORTD|=0X01;//SCL=1 read_data<<=1; read_data|=(uchar)((PIND&0X02)>>1);//SDA PORTD&=0XFE; Delayuslcd(5);
temp1=((float)y_data*3.9); display(0,1,temp1);//显示 Y 方向加速度值 temp2=((float)z_data*3.9); display(0,9, temp2);//显示 Z 方向加速度值 delaylcd(1000); angle=(((atan2f(temp,temp1)*180)/3.14159265)+180);//算出倾角值 writeonechar(12,angle);//显示角度 }
void AX353_INIT()//倾角传感器初始化 {
write_byte(0x31,0x0B); //测量范围,正负 16g,13 位模式 write_byte(0x2C,0x08); //速率设定为 12.5 参考 pdf13 页 write_byte(0x2D,0x08); //选择电源模式 参考 pdf24 页 write_byte(0x2E,0x80); //使能 DATA_READY 中断 write_byte(0x1E,0x00); //X 偏移量 根据测试传感器的状态写入 pdf29 页 write_byte(0x1F,0x00); //Y 偏移量 根据测试传感器的状态写入 pdf29 页 write_byte(0x20,0x05); //Z 偏移量 根据测试传感器的状态写入 pdf29 页 }

ATmega128并行控制带字库的12864程序

ATmega128并行控制带字库的12864程序

ATmega128并行控制带字库的12864程序m128的特点是io口很多,所以我们可以用并行的方式来驱动此液晶屏,增加总线的速度,此程序是是网上整理收集而来,但已经通过本人验证可以使用,故在此发表.大家在应用的时候只需更改相应的io就行了. 软件:GCC V4.20---------------------------------------------------------------实验内容:写Lcd12864_ST7920。

---------------------------------------------------------------硬件连接:LCD12864_ST7920 ATmega1281.GND -------- GND2.VCC -------- VCC3.V0 -------- NC4.RS(CS) -------- PD75.R/W(SID) -------- PG06.E(SCLK) -------- PG17.D0 -------- PC08.D1 -------- PC19.D2 -------- PC210.D3 -------- PC311.D4 -------- PC412.D5 -------- PC513.D6 -------- PC614.D7 -------- PC715.PSB -------- VCC16.NC -------- NC17.RST -------- VCC18.NC -------- NC19.LED+ -------- VCC20.LED- -------- GND以下是程序源代码:---------------------------------------------------------------*/#include ;#include;#include ;#define E_set PORTG|=_BV(PG1) //液晶使能#define E_clear PORTG&=~_BV(PG1)#define RW_set PORTG|=_BV(PG0) //液晶读写#define RW_clear PORTG&=~_BV(PG0)#define RS_set PORTD|=_BV(PD7) //液晶数据#define RS_clear PORTD&=~_BV(PD7) //液晶指令unsigned char j=0;unsigned char yb=0x80;unsigned char name00[] PROGMEM={&quot;飞射白鹿雪连天,&quot;};unsigned char name01[] PROGMEM={&quot;笑书神侠倚碧鸳。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

基于Atmega128单片机SD卡读写程序实物图对照接线图以下是一个简单的测试SD卡读写的程序,程序是基于Atmega128单片机编写的,对于Atmega的其他单片机仅需要做管脚改动就可以使用,其他单片机更改要更大。

sd.h//********************************************************** ********//SPI各线所占用的端口#define SD_SS PB6#define SD_SCK PB1#define SD_MOSI PB2#define SD_MISO PB3//********************************************************** ********#define SD_DDR DDRB#define SD_PORT PORTB#define SD_PIN PINB#define SD_SS_H SD_PORT |= (1<#define SDSS_L SD_PORT &= ~(1<#define SD_SCK_H SD_PORT |= (1<#define SD_SCK_L SD_PORT &= ~(1<#define SD_MOSI_H SD_PORT |= (1<#define SD_MOSI_L SD_PORT&= ~(1<#defineSD_MISO_IN (SD_PIN&(1<//-------------------------------------------------------------// 错误号//-------------------------------------------------------------#define INIT_CMD0_ERROR 0xFF#define INIT_CMD1_ERROR 0xFE#define WRITE_BLOCK_ERROR 0xFD#define READ_BLOCK_ERROR 0xFC#define TRUE 0x01//-------------------------------------------------------------// MMC/SD 命令(命令号从40开始,只列出基本命令,并没有都使用) //-------------------------------------------------------------#define SD_RESET 0x40 + 0#define SD_INIT 0x40 + 1#define SD_READ_CSD 0x40 + 9#define SD_READ_CID 0x40 + 10#define SD_STOP_TRANSMISSION 0x40 + 12#define SD_SEND_STATUS 0x40 + 13#define SD_SET_BLOCKLEN 0x40 + 16#define SD_READ_BLOCK 0x40 + 17#define SD_READ_MULTI_BLOCK 0x40 + 18#define SD_WRITE_BLOCK 0x40 + 24#define SD_WRITE_MULTI_BLOCK 0x40 + 25//片选关(MMC/SD-Card Invalid)#define SD_Disable() SD_SS_H//片选开(MMC/SD-Card Active)#define SD_Enable() SD_SS_LSD_TEST.C//********************************************************** ******************************///ICC-A VR application builder : 03-5-20 8:39:11// Target : M128// Crystal: 3.6864Mhz#include#include#include 'sd.h'void uart0_init(void);void putchar(unsigned char content);void putstr(unsigned char *s);void SD_Port_Init(void);unsigned char SD_Init(void);unsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer);unsigned char SD_read_sector(unsigned long addr,unsigned char *Buffer);unsigned char SPI_TransferByte(unsigned char byte);unsigned char Write_Command_SD(unsigned char cmd,unsigned long address);unsigned long SD_find(void);//********************************************************** ****************//串口调试程序//********************************************************** ****************void uart0_init(void){UCSR0B = 0x00; //disable while setting baud rateUCSR0A = 0x00;UCSR0C = 0x06; // 00000110 UART0设置为异步模式、无奇偶校验、1位停止位、8位数据位UBRR0L = 0x17; //set baud rate loUBRR0H = 0x00; //set baud rate hi 设置UART0口通信速率9600 UCSR0B = 0x18;}void putchar(unsigned char content){while(!(UCSR0A & (1 << UDRE0))); /* 判断上次发送有没有完成*/UDR0 = content; /* 发送数据*/}void putstr(unsigned char *s){while(*s){putchar(*s);s++;}}//********************************************************** ******************//端口初始化void SD_Port_Init(void)//********************************************************** ******************{SD_PORT |= (1< SD_DDR |= (1< SD_ DDR &= ~(1<}//********************************************************** ******************//初始化MMC/SD 卡为SPI模式unsigned char SD_Init(void)//********************************************************** ******************{unsigned char retry,temp;unsigned char i;SPCR=0x53; //设定SPI为128分频,慢速进行初始化SPSR=0x00;for (i=0;i<0x0f;i++){SPI_TransferByte(0xff); //延迟74个以上的时钟}SD_Enable(); //开片选SPI_TransferByte(SD_RESET); //发送复位命令SPI_TransferByte(0x00);SPI_TransferByte(0x00);SPI_TransferByte(0x00);SPI_TransferByte(0x00);SPI_TransferByte(0x95);SPI_TransferByte(0xff);SPI_TransferByte(0xff);retry=0;do{temp="Write"_Command_SD(SD_INIT,0); //发送初始化命令retry++;if(retry==100) //重试100次{SD_Disable(); //关片选return(INIT_CMD1_ERROR); //如果重试100次失败返回错误号}}while(temp!=0);MSD_Disable(); //关片选SPCR=0x50; //设置SPI为2分频。

进行高速读写SPSR=0x01;return(TRUE); //返回成功}//********************************************************** ******************//发送命令给MMC/SD卡//Return: 返回MMC/SD卡对命令响应的第2字节,作为命令成功判断unsigned char Write_Command_SD(unsigned char cmd,unsigned long address)//********************************************************** ******************{unsigned char tmp;unsigned char retry="0";SD_Disable();SPI_TransferByte(0xFF);SD_Enable();SPI_TransferByte(cmd); //将32位地址进行移位作为地址字节SPI_TransferByte(address>>24);SPI_TransferByte(address>>16);SPI_TransferByte(address>>8);SPI_TransferByte(address);SPI_TransferByte(0xFF);SPI_TransferByte(0xFF);do{tmp = SPI_TransferByte(0xFF); //发送8个时钟接受最后一个字节retry++;}while((tmp==0xff)&&(retry<8));return(tmp);}//********************************************************** ******************//写一个扇区(512Byte) to MMC/SD-Card//如果写完成返回TRUEunsigned char SD_write_sector(unsigned long addr,unsigned char *Buffer)//********************************************************** ******************{unsigned char temp;unsigned int i;SPI_TransferByte(0xFF); //延迟8个时钟SD_Enable(); //开片选temp = Write_Command_MMC(MMC_WRITE_BLOCK,addr<<9); //发送写扇区命令if(temp != 0x00){SD_Disable();return(temp);}SPI_TransferByte(0xFF);SPI_TransferByte(0xFF);SPI_TransferByte(0xFE);for (i=0;i<512;i++){SPI_TransferByte(*Buffer++); //发送512字节数据}//CRC-ByteSPI_TransferByte(0xFF); //Dummy CRCSPI_TransferByte(0xFF); //CRC Codetemp = SPI_TransferByte(0xFF); //读SD卡运行响应if((temp & 0x1F)!=0x05) //如果最后4位为0101,为操作成功。

相关文档
最新文档