📄 at45db_for_msp430.c
字号:
page = page_temp;
addr = addr_temp;
//return page2;
//注意,只有1, 21+1,21*2+1,..., 21*11+1=232为起始地址
//1-21; 22-42;43-63;64-84;85-105;106-126;127-147;148-168;169-189;190-210;211-231;232-252;
}
/*******************************************************************************
* name: At45_read_Flash_module(unsigned char *w_data)
* description: 模块内部自行维护flash的地址指针,能够实现自动时间数据的查询
flash第0页已占用,本模块不得对第0页做写操作。
数据包长度定义为全局变量 const uchar flash_data_len=21。
需要定义全局变量:unsigned int page=1,addr=1;
* input parameter: 时间值,6字节BCD。
方向,1=大于给定时间值,0=小于给定时间值。
* output parameter: 标志+离给定时间值最近的一条记录
其中标志=EB90表示数据有效,标志=0000表示无符合条件数据
********************************************************************************/
void At45_read_Flash_module(unsigned char *give_time, unsigned char direction, unsigned char *data)
{
unsigned int i=0, j=0, count=0, num_addr=0, max_addr_flag=0, page45_flag=0;
unsigned int beg_addr, second1, second2; //max_page=1023
unsigned int min_page=1, max_page=1023, min_addr=1, max_addr=252,min_j,max_j;
unsigned int page1 = 1, page2, page3 = 1023, page4=1, page5=1;
unsigned char r_data[21], r_data4[21], r_data5[21]; //21*12=252; 264-252=12;
unsigned char page_p[2];
At45_read_Flash(0, 262, page_p, 2);
page2=page_p[0]*256+page_p[1];
if (page_rebegin_flag == 0)//在1023页没有写完的情况下,只写了一部分页
{
min_page = page1;
max_page = page2;
page = (min_page+max_page)/2;
addr = 1;
At45_read_Flash(page, addr, r_data, flash_data_len);//读取中间页的时间值
for (i=0; i<=5; i++) //年月日时分秒的比较:年--秒,先确定页
{
count = 0;
while(*(give_time+i) != r_data[4+i]) //年--秒的比较
{ //第5个数据为年
// WDTCTL = WDTPW + WDTCNTCL + 0x04;
if (*(give_time+i) < r_data[4+i])
{//如果给定的数据<读出的数据值,则页应该在前面较小页数的地方
max_page = page;
page = (min_page + page)/2;
}
else if (*(give_time+i) > r_data[4+i])
{//如果给定的数据>读出的数据值,则页应该在后面较大页数的地方
min_page = page;
page = (max_page + page)/2;
}
At45_read_Flash(page, addr, r_data, flash_data_len);
count = count+1;
if (count > 12) break;
}
}
}
else if (page_rebegin_flag == 1)//在1023页写完的情况下,重新从头开始写了一部分页
{
// 计算在page1和page2之间的最优值page4
min_page = page1;
max_page = page2;
page = (min_page+max_page)/2;
addr = 1;
At45_read_Flash(page, addr, r_data, flash_data_len);//读取中间页的时间值
for (i=0; i<=5; i++) //年月日时分秒的比较:年--秒,先确定页
{
count = 0;
while(*(give_time+i) != r_data[4+i]) //年--秒的比较
{ //第5个数据为年
// WDTCTL = WDTPW + WDTCNTCL + 0x04;
if (*(give_time+i) < r_data[4+i])
{//如果给定的数据<读出的数据值,则页应该在前面较小页数的地方
max_page = page;
page = (min_page + page)/2;
}
else if (*(give_time+i) > r_data[4+i])
{//如果给定的数据>读出的数据值,则页应该在后面较大页数的地方
min_page = page;
page = (max_page + page)/2;
}
At45_read_Flash(page, addr, r_data, flash_data_len);
count = count+1;
if (count > 12) break;
}
}
page4 = page;
// 计算在page2和page3之间的最优值page5
min_page = page2;
max_page = page3;
page = (min_page+max_page)/2;
addr = 1;
At45_read_Flash(page, addr, r_data, flash_data_len);//读取中间页的时间值
for (i=0; i<=5; i++) //年月日时分秒的比较:年--秒,先确定页
{
count = 0;
while(*(give_time+i) != r_data[4+i]) //年--秒的比较
{ //第5个数据为年
// WDTCTL = WDTPW + WDTCNTCL + 0x04;
if (*(give_time+i) < r_data[4+i])
{//如果给定的数据<读出的数据值,则页应该在前面较小页数的地方
max_page = page;
page = (min_page + page)/2;
}
else if (*(give_time+i) > r_data[4+i])
{//如果给定的数据>读出的数据值,则页应该在后面较大页数的地方
min_page = page;
page = (max_page + page)/2;
}
At45_read_Flash(page, addr, r_data, flash_data_len);
count = count+1;
if (count > 12) break;
}
}
page5 = page;
// 对page4和page5与给定的时间值作比较,得到最优值
page45_flag=0;
At45_read_Flash(page4, addr, r_data4, flash_data_len);//读取中间页的时间值
At45_read_Flash(page5, addr, r_data5, flash_data_len);//读取中间页的时间值
for (i=0; i<=5; i++) //年月日时分秒的比较:年--秒,先确定页
{
if(abs(*(give_time+i) - r_data4[4+i])!=abs(*(give_time+i) - r_data5[4+i])&&page45_flag==0)
{
if (abs(*(give_time+i) - r_data4[4+i])<abs(*(give_time+i) - r_data5[4+i]))
{
page = page4;
page45_flag=1;
}
else if (abs(*(give_time+i) - r_data4[4+i])>abs(*(give_time+i) - r_data5[4+i]))
{
page = page5;
page45_flag=1;
}
else //在绝对值相等的情况下,则需要进行下一步计算
{
page45_flag=0;
}
}
}
}
//再确定页内地址:注意,只有1, 21*1+1,21*2+1,..., 21*11+1=232为起始地址
//1-21; 22-42;43-63;64-84;85-105;106-126;127-147;148-168;169-189;190-210;211-231;232-252;
num_addr = 264/flash_data_len; //=12
beg_addr = (num_addr/2)*flash_data_len+1; //=127
At45_read_Flash(page, beg_addr, r_data, flash_data_len);//读取页内中间起始地址的时间值
min_j = 0;
max_j = num_addr-1;
count = 0;
for (i=0; i<=5; i++) //年月日时分秒的比较:年--秒,再确定页内地址
{
max_addr_flag = 0; //地址最大标志
for (j=min_j; j<=max_j; j++)//每次都是在上一次时间数据基础上的范围内进行比较
{
beg_addr = j*flash_data_len+1; //得到页内的起始地址
At45_read_Flash(page, beg_addr, r_data, flash_data_len);
if (*(give_time+i) < r_data[4+i] && max_addr_flag ==0)
{//如果给定的数据<读出的数据值,则地址应该在前面较小地址的地方
max_j = j;// 得到最小的大于给定时间数据的位置P1,其它的大于P1的值就不能考虑,
max_addr_flag = 1; //这样就找到了最小的大于给定时间数据的位置
}
else if (*(give_time+i) > r_data[4+i])
{//如果给定的数据>读出的数据值,则地址应该在后面较大地址的地方
min_j = j;//找到了最大的小于给定时间数据的位置
}
}
}//得到了j的数据区间:min_j和max_j
beg_addr = min_j*flash_data_len+1;//得到页内最小的的起始地址
At45_read_Flash(page, beg_addr, r_data, flash_data_len);
second1 = r_data[9];//得到最小的的起始地址上时间秒的数据
beg_addr = max_j*flash_data_len+1;//得到页内最大的的起始地址
At45_read_Flash(page, beg_addr, r_data, flash_data_len);
second2 = r_data[9];//得到最大的的起始地址上时间秒的数据
// 判断最后的时间数据是离min_j近还是离max_j近
/**/ if (abs(*(give_time+5)-second1) < abs(*(give_time+5)-second2))
{
j = min_j;
}
else if (abs(*(give_time+5)-second1) > abs(*(give_time+5)-second2))
{
j = max_j;
}
else
{
j = (min_j + max_j)/2;
}
min_j = j;
max_j = j;
if (direction==1)// 1为大于给定数据的最接近数据
{
if (*(give_time+5) > second2)
{
j = max_j;
}
else
{
if (j<num_addr-1) //j<11
{
j = max_j+1;
}
else //j=11
{
j = 0;
if (page<1023)
{
page=page+1;
}
else
{
page=1;
}
}
}
}
if (direction==0)// 0为小于给定数据的最接近数据
{
if (*(give_time+5) < second1)
{
j = min_j;
}
else
{
if (j>0) //j>0
{
j = min_j-1;
}
else //j=0
{
j = num_addr-1;
if (page>1)
{
page=page-1;
}
else
{
page=1023;
}
}
}
}
beg_addr = j*flash_data_len+1;
At45_read_Flash(page, beg_addr, data, flash_data_len);
//读出来的r_data的内容即为与给定时间最为接近的数据值
for (i=flash_data_len-1; i>0; i--) //lhy
{
*(data+2+i)=*(data+i);
}
*(data)=0xeb;
*(data+1)=0x90;
}
/*******************************************************************************
* name: At45_write_Buffer()
* description: 该函数向指定的地址连续写入指定个数的数据。
* input parameter: page------目的页。有效范围:0~2047;
* addr------页内地址。有效范围:0~263;
* data------操作数据指针;
* num-------数据个数。
* output parameter: NULL
********************************************************************************/
void At45_write_Buffer(unsigned int addr,unsigned char *data,unsigned int num)
{
unsigned char cmd1;
unsigned int i;
if (addr>263) return; // 超出 at45 寻址范围,函数返回
CS_low();
cmd1 = 0x84;// 写Buffer1,命令码为0x84
at45_hdr(cmd1,0x00,addr);
at45_write_hdr(); // 发送命令和地址
for(i=0;i<num;i++) // 发送 num 个数据
{
SPIDataWrite(*(data+i));
//while(CheckStatus()==0); // 等待数据发送完毕
//delay(10);
}
CS_high();
}
/*******************************************************************************
* name: At45_read_Buffer()
* description: 该函数从 at45db041b 的指定地址连续读出指定个数的数据
* input parameter: page------目的页。有效范围:0~1023。
* addr------页内地址。有效范围:0~263。
* data------数据存放的首地址。
* num-------数据个数。
* output parameter: NULL
********************************************************************************/
void At45_read_Buffer(unsigned int addr,unsigned char *data,unsigned int num)
{
unsigned int i;
if(addr>263) return; // 超出 at45 的寻址范围,返回
CS_low(); // 选通 at45db041b
at45_hdr(0xD4,0x00,addr); // 读缓存的命令码为0xD4
at45_write_hdr(); // 发送读命令和地址
SPIDataWrite(0xE8); //8 don't care bits.
for(i=0;i<num;i++)
{
*(data+i) = SPIDataRead();
//while(CheckStatus()==0);
//delay(10);
}
CS_high();
}
//*******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -