在做一个单片机监测项目时,项目要求能够将一些报警以及状态信息作为2或者4字节的LOG存到EE2PROM中,供客户随时导出查看。
要求和实现过程都比较简单,但是在测试过程中发现有一个小问题:由于EE2PROM的存储过程相较于单片机运行速度来说还是比较慢的,存储数据时会有5ms左右的不响应,所以在同时有多个LOG出现时,会有漏存的情况发生,虽然存储指针正常增加,但实际未存储,EE2PROM内容仍为FF。
所以考虑开辟一个100或200字节左右的缓冲数组,LOG先存在这个数组中,待系统有空闲再依次写入。这就要求该数组能够循环存取。
在付诸行动之前,先写一个小程序测试可行性:
预期实现的功能是每隔1s将输入的数字或字母按照输入顺序输出,即使不再按键,也会将数组中保存的输出。暂定义缓冲的数组大小为10,所以如果按的太快,超出的部分丢弃。
首先编写存储和取出的子程序:
定义需要使用的变量:
static unsigned short logdata_storage[N] = {0}; //定义存储数组
static unsigned short logdata_Put_in= 0; //存储地址
static unsigned short logdata_Take_out= 0; //取出地址
当空闲时,如果存储和取出地址不同,则表示仍有数据待输出,需要注意到达数组边界时要转到头部:
if(logdata_Take_out != logdata_Put_in)
{
printf("%c %d %d\n",logdata_storage[logdata_Take_out],logdata_Put_in,logdata_Take_out);
logdata_Take_out++;
if(logdata_Take_out >= N) logdata_Take_out = 0;
}
else
{
ret = 1;
return ret;
}
存入数据时,只要保证存入地址最多到达取出地址减一的位置即可,因为如果相等了,即适用上面数据输出完毕的情况,这显然是不合适的。
logdata_storage[logdata_Put_in] = logdata;
if (logdata_Put_in != logdata_Take_out - 1)
{
logdata_Put_in++;
if(logdata_Put_in >= logdata_Take_out)
if(logdata_Put_in >= N) logdata_Put_in = 0;
}
主程序方面,由于是在windows环境下,所以还需要包含如下头文件:
#include <time.h>
#include <windows.h>
#include <conio.h>
这样就可以使用kbhit()与time()函数,kbhit()可以非阻塞地响应键盘输入。
完整程序如下:
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <conio.h>
#define N 10
unsigned char save_log(unsigned short logdata);
int main(){
unsigned char i,j = 0;
time_t start, current = 0; //在windows下获取时间,以用来实现1S间隔
while(j != 27) //判断是否按下ESC键
{
if(kbhit()) //判断是否有按键内容
{
j = getch();
save_log(j); //有则存储
}
time(&start); //获取当前时间
if((current - start) != 0) //1S间隔
{
current = start;
save_log(0); //0为显示参数
}
}
return 0;
}
unsigned char save_log(unsigned short logdata)
{
unsigned char i = 0;
unsigned char ret = 0;
static unsigned short logdata_storage[N] = {0}; //定义存储数组
static unsigned short logdata_Put_in= 0; //存储地址
static unsigned short logdata_Take_out= 0; //取出地址
if(logdata == 0)
{
if(logdata_Take_out != logdata_Put_in)
{
printf("%c %d %d\n",logdata_storage[logdata_Take_out],logdata_Put_in,logdata_Take_out);
logdata_Take_out++;
if(logdata_Take_out >= N) logdata_Take_out = 0;
}
else
{
ret = 1;
return ret;
}
}
else
{
logdata_storage[logdata_Put_in] = logdata;
if (logdata_Put_in != logdata_Take_out - 1)
{
logdata_Put_in++;
if(logdata_Put_in >= logdata_Take_out)
if(logdata_Put_in >= N) logdata_Put_in = 0;
}
}
return ret;
}