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

📄 at45db_for_msp430.c

📁 at45db_for_msp430.c,IAR2.31调试
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********************************Copyright (c)*********************************
 *										
 *					    西安.兰特水电测控技术有限责任公司
 *
 *							    	开发部
 *
 *----------------------------------文件信息-------------------------------------
 * 文件名称: at45db_for_msp430.c
 * 创 建 人: 李良福
 * 创建时间: 2006/03/08
 * 修改时间: 2006/03/08
 * 当前版本: v1.0: 针对于MSP430单片机的C语言(水情测量板:LT_V3RTU_2006_03_16)
 * 描    述:本模块定义了基于SPI总线读写Data Flash的相关函数。使用芯片为at45db021
 *            此Flash存储器共1024页,每页264字节。
 ********************************************************************************/
 #include <msp430x14x.h>
 #include "spi_for_msp430.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 
 //SDI: P3.1
 //SDO: P3.2
 //SCK: P3.3
 
 //端口数据输出电平高低控制
 //#define CS_high (P5OUT |= BIT4)
 //#define CS_low  (P5OUT &= ~BIT4)
 #define SCK_high (P3OUT |= BIT3)
 #define SCK_low  (P3OUT &= ~BIT3)
 #define SDI_high (P3OUT |= BIT1)
 #define SDI_low  (P3OUT &= ~BIT1)
 #define SDO_high (P3OUT |= BIT2)
 #define SDO_low  (P3OUT &= ~BIT2)
 
//端口方向控制 
 //#define CS_in  (P5DIR &= ~BIT4) 
 //#define CS_out (P5DIR |= BIT4)
 #define SCK_in  (P3DIR &= ~BIT3) //SCK输出, P3.3输入: P3DIR.3=0;
 #define SCK_out (P3DIR |= BIT3)  //SCK输入, P3.3输出: P3DIR.3=1;
 #define SDI_in  (P3DIR &= ~BIT1) //SDO输出, P3.1输入: P3DIR.1=0;
 #define SDI_out (P3DIR |= BIT1)  //SDO输入, P3.1输出: P3DIR.1=1;
 #define SDO_in  (P3DIR &= ~BIT2) //SDI输出, P3.2输入: P3DIR.2=0;
 #define SDO_out (P3DIR |= BIT2)  //SDI输入, P3.2输出: P3DIR.2=1;

 unsigned int page=1,addr=1;
 extern const unsigned char flash_data_len;
 unsigned int page_rebegin_flag = 0;

// 定义at45db021的信息头结构
 typedef struct
 {
 	unsigned char cmd;
  	unsigned char addr1;
 	unsigned char addr2;
 	unsigned char addr3;
 } AT45_HDR;
 
 AT45_HDR at45;

/*******************************************************************************
 * name: CS_low() 
 * description: 数据存储芯片的片选信号线为低
 * input parameter: 
 * output parameter: 
 ********************************************************************************/
 static void CS_low(void) 
 {
/*
 // 000 001 010 011; 100 101 110 111    //CS: P1.7 P1.6 P1.5  
 //  0   1   2   3    4   5   6   7 
   P1OUT |= BIT7;  //100
   P1OUT &= ~BIT6;
   P1OUT &= ~BIT5;
   */
    P3OUT &=~BIT0;          //lhy
 }
 
 /*******************************************************************************
 * name: CS_high() 
 * description: 数据存储芯片的片选信号线为高
 * input parameter: 
 * output parameter: 
 ********************************************************************************/
 static void CS_high(void) 
 {
/*
 // 000 001 010 011; 100 101 110 111    //CS: P1.7 P1.6 P1.5  
 //  0   1   2   3    4   5   6   7
   P1OUT |= BIT7; //111
   P1OUT |= BIT6;
   P1OUT |= BIT5;
   */
   P3OUT |=BIT0;            //lhy
 }

/*******************************************************************************
 * name: Init_at45db() 
 * description: 数据存储芯片的初始化
 * input parameter: 
 * output parameter: 
 ********************************************************************************/
 void Init_at45db(void) 
 {
   P1DIR |= BIT5;  // 74ls138--CS
   P1DIR |= BIT6;
   P1DIR |= BIT7;
   P1SEL &= ~BIT5;
   P1SEL &= ~BIT6;
   P1SEL &= ~BIT7;
   
   P3OUT = 0x00;  // SCK SO SI
   P3SEL = 0x00;
   P3DIR |= 0x0f; // 0000 1110;
   //lhy

 }
 
 /*******************************************************************************
 * name: CheckStatus()
 * description: 读状态寄存器内容
 * input parameter: Null.
 * output parameter: 0 or 1
 ********************************************************************************/
int CheckStatus(void)
{
	char status;
	SPIDataWrite(0xD7);
	
	status=SPIDataRead();
	if(status&0x80)	        
		return 1;//ready
	else
	        return 0;//busy
}

 /*******************************************************************************
 * name: at45_hdr()
 * description: 将提供的命令码和有效地址转换为便于处理的形式。
 * input parameter: cmd--------------8位操作命令码;                   
 *			 page-----11位页地址,有效页范围:0~2047; // PA10~PA7  // PA6~PA0,BA8
 *			 addr-----9位页内地址,有效氛围:0~263;   // BA7~BA0
 * output parameter: AT45_HDR 类型指针 at45 所指向的数据内容
 ********************************************************************************/
 static void at45_hdr(unsigned char cmd_op,unsigned int page,unsigned int addr)
 {
 	at45.cmd =cmd_op;
 	
 	at45.addr1 = 0x0f & (page>>7);		        // PA10~PA7
 	at45.addr2 = (page<<1) | (0x01 & (addr>>8));   // PA6~PA0,BA8
 	at45.addr3 = addr;				// BA7~BA0 	
 }
  
 /*******************************************************************************
 * name: at45_write_hdr()
 * description: 该函数用于写 at45db021b时发送命令字和地址。发送信息包含在数据结构at45中。
 * input parameter: NULL
 * output parameter: NULL
 ********************************************************************************/
 void at45_write_hdr(void)
 {
 	unsigned char i;
 	for(i=0;i<4;i++)
 	{
 	    SPIDataWrite(*(((unsigned char *)&at45)+i));// 发送命令码和地址码
 	  //delay(10);
 	  //  while(CheckStatus()==0);
	}
 }

/*******************************************************************************
 * name: At45_write_Flash()
 * description: 该函数向指定的地址连续写入指定个数的数据。
 * input parameter: page------目的页。有效范围:0~2047;
 *			 addr------页内地址。有效范围:0~263;
 *			 data------操作数据指针;
 *			 num-------数据个数。
 * output parameter: NULL
 ********************************************************************************/
 void At45_write_Flash(unsigned int page,unsigned int addr,unsigned char *data,unsigned int num)
 {
 	unsigned char cmd1, cmd2;
 	unsigned int i;
 	static unsigned char flag=0; 
 	
 	if((page>2047) || (addr>263)) return;	// 超出 at45 寻址范围,函数返回
 	
 	if(flag==0)
 	{
 		flag = 1;
 		cmd1 = 0x82;// 通过 Buffer1 写,命令码为0x82
 	}                   // Main memory page program through buffer1
 	else
 	{
 		cmd1 = 0x85;// 通过 Buffer2 写,命令码为0x85
 		flag = 0;
 	}
 	at45_hdr(cmd1,page,addr);
 	/**************************** 等待 at45 空闲 *******************************/
 	CS_low();	
	delay(100);
 	/************************** 将指定页的数据传入 Buffer **********************/
 	
 	if(at45.cmd == 0x82)
 		cmd2 = 0x53;   // 传入 Buffer1,命令码为0x53
 	else					
 		cmd2 = 0x55;   // 传入 Buffer2,命令码为0x55
 	
 	at45_hdr(cmd2,page,addr);// Main memory page to buffer 1 transfer
 	at45_write_hdr();	 // 主存储器和缓存之间数据的传递
 	SPIDataWrite(0x00);
        //while(CheckStatus()==0);  //等待 at45 数据传输完毕	
   /******************* Main Memorry Page write through Buffer *****************/	 	
 	CS_high();			// 选通 at45db041b
 	delay(100);
 	CS_low();                  
 	delay(100);
 	at45_hdr(cmd1,page,addr);// Main memory page program through buffer1
 	at45_write_hdr();	 // 通过 Buffer写入主存储器
 	//while(CheckStatus()==0);  //等待 at45 数据传输完毕
  	for(i=0;i<num;i++)			// 发送 num 个数据
 	{
 		SPIDataWrite(*(data+i));
 		//while(CheckStatus()==0);	// 等待数据发送完毕 		
 	}
 	delay(100);
 	CS_high(); 	
 }

 /*******************************************************************************
 * name: At45_read_Flash()
 * description: 该函数从 at45db041b 的指定地址连续读出指定个数的数据
 * input parameter: page------目的页。有效范围:0~1023。
 *			 addr------页内地址。有效范围:0~263。
 *			 data------数据存放的首地址。
 *			 num-------数据个数。
 * output parameter: NULL
 ********************************************************************************/
 void At45_read_Flash(unsigned int page,unsigned int addr,unsigned char *data,unsigned int num)
 {
 	unsigned int i;
 	
 	if((page>2047) || (addr>263)) return;	// 超出 at45 的寻址范围,返回
 	CS_low();   // 选通 at45db041b
 	delay(100);
 	                           // Main memory page read
 	at45_hdr(0xD2,page,addr);  // 读主存储器的命令码为0xD2
 	at45_write_hdr();	// 发送读命令和地址
 	
 /**************************** 等待 at45 空闲 *******************************/	
	SPIDataWrite(0xE8); //连续写32位don't care bits.
	SPIDataWrite(0xE8); //注意:不能在这条程序后面加while(CheckStatus()==0);
	SPIDataWrite(0xE8);
	SPIDataWrite(0xE8); //32位don't care bits
	//while(CheckStatus()==0);  //等待 at45 数据传输完毕
 	for(i=0;i<num;i++)
 	{
 		*(data+i) = SPIDataRead();
 		//while(CheckStatus()==0); //一定要加上,否则读出的数据出错 		
 	}
 	
 	delay(100);
 	CS_high();
 }
 
/*******************************************************************************
 * name: At45_write_Flash_module_init(void)
 * description: 需要在实现自动时间数据的查询之前对数据存储芯片AT45DB021进行初始化,
 *              全部写为方法0xff
 * input parameter: 数据包指针。
 * output parameter: NULL
 ********************************************************************************/
 void At45_write_Flash_module_init(void)
 {
        unsigned int min_page=1, max_page=1023, min_addr=1, max_addr=252;
        unsigned int page_temp=1,addr_temp=1, i=0, j=0;
        unsigned char init_data = 0xff, wdata[252];
        
        for (j=min_addr; j<=max_addr; j++)
        {
          wdata[j-1]=init_data;
        }
        
        for (i=min_page; i<=max_page; i++)
        {
          At45_write_Flash(i, min_addr, wdata, 252);//写数据存储芯片
          delay(100);
        }
 } 
 
/*******************************************************************************
 * name: At45_write_Flash_module(unsigned char *w_data)
 * description: 模块内部自行维护flash的地址指针,自动写Flash的代码,数据指针自动递增
                flash第0页已占用,本模块不得对第0页做写操作。
                数据包长度定义为全局变量 const uchar flash_data_len=21。
                需要定义全局变量:unsigned int page=1,addr=1;
 * input parameter: 数据包指针。
 * output parameter: null.
 ********************************************************************************/
void At45_write_Flash_module(unsigned char *wm_data)
 {
        unsigned int min_page=1, max_page=1023, min_addr=1, max_addr=252;
        unsigned int page_temp=1,addr_temp=1;
        unsigned char page_p[2];
        At45_write_Flash(page, addr, (unsigned char *)wm_data, flash_data_len); //写数据存储芯片缓存
        delay(1000);  //注意:这个延时不能少,否则下一个At45_write_Flash写不进去
        page_p[0]=page/256;
        page_p[1]=page-page_p[0]*256;
        At45_write_Flash(0, 262, page_p, 2);
        //delay(500);
        if (addr < max_addr-flash_data_len)//判断是否写到了页内最高地址处
        {
          page_temp = page; //页不变
          addr_temp = addr + flash_data_len; //地址增加数据包长度
        }
        else if(addr == max_addr-flash_data_len+1 && page < max_page)
        {//在页内最高地址处判断如果没有写到最大页
          page_temp = page+1;   //页加1
          addr_temp = min_addr; //地址重新开始计数
        }
        else if(addr == max_addr-flash_data_len+1 && page == max_page)
        {//在页内最高地址处判断如果写到了最大页
          page_temp = min_page;//页重新开始计数
          addr_temp = min_addr;//地址重新开始计数
          page_rebegin_flag = 1;
        }

⌨️ 快捷键说明

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