问题描述:我在做一个高速采集的实验:can数据和串口数据帧周期都是10ms,问题描述有点多,我怕我说不清,可以直接看加粗的地方。
1、目前无法实现两个同时采集。
2、就拿一个来说,can。我的思路是,建立两个线程(1)CAN读取线程,(2)SD写入线程。线程运行简图如上
顺序是这样的,CAN读取线程优先级高于SD写入线程。
系统启动,CAN线程运行,1.互斥上锁、2.信号量未来临,被挂起。执行SD写入线程,由于CAN线程互斥量已经上锁,被挂起。
CAN中断来临,CAN线程被释放,1.把数据写入环形缓冲区,释放互斥信号,2.进入SD线程,我疑惑的地方就在SD线程,它不是运行完然后切换其他程序,它是一直在和空闲线程切换,切换好几次才会执行完,但是我检查代码发现,SD线程中没有引起线程切换的函数,这里疑惑,SD写入函数每次只写入环形缓冲区读取出来的8字节,希望大佬有空指点一下,感谢
下面是我调用钩子函数的情况:SD写入线程执行过程中会和空闲线程切换几次,我想知道为什么会切换。数据采集乱码概率是万分之1.
SD写入线程代码:
void Sd_WriteCan_Data(void* parameter)
{
//SD卡的写入,测试的时候先按照一帧数据,8字节写入,先打印出来。
uint8_t data[8] = {0};
char SDformat[100] = {0};
char buffer[20];
buffer[0] = '\0';
time_t now;
while(1)
{
// rt_kprintf("CAN SD startup\r\n");
rt_mutex_take(dynamic_mutex, RT_WAITING_FOREVER);//获取信号互斥信号量。
// rt_kprintf("CAN SD dynamic_mutex\r\n");
rt_size_t recv =rt_ringbuffer_get(RWSd, (rt_uint8_t *)data, sizeof(uint8_t)*8);//一直报错环形缓冲区的指针为空
RT_ASSERT(recv == sizeof(data));
//数据不再打印出来
// for (uint8_t i = 0; i < 8; i++)
// {
// rt_kprintf("0x%2x ", data[i]);
// }
for(uint8_t i = 0;i<8;i++)
{
sprintf(buffer,"%x,",data[i]);
strcat(SDformat,buffer);
}
now = time(RT_NULL);//获取实时时间,
strcat(SDformat,ctime(&now));//加了时间之后不需要空格换行了。
Write2SD(SDformat);
//rt_thread_mdelay(100);
memset(SDformat,'\0',strlen(SDformat));//把缓存清零了。
// rt_kprintf("CAN SD ending\r\n");
rt_mutex_release(dynamic_mutex);//释放信号量。
}
}
SD写入函数:
int Write2SD(char *C_data)
{
static int can_filecount = 00000001;//定义一个静态变量用来新建存储can数据的文件。
static int can_datacount = 0;//用来记录一个文件里面的帧数
static uint8_t Creatfile= 1;//用来表示是否需要创建文件
static uint8_t Creatdir = 1;//用来表示是否需要创建文件夹
static int fd = 0;
static DIR dirp;
int res_sync;
int res_write;
int res_close;
//这个函数只负责新建文件夹和新建文件存储数据。
//创建文件夹
if(Creatdir == 1)
{
int res_mk;
res_mk = mkdir("/can_data01",0x777);//创建了can_data01文件夹
if (res_mk < 0)
{
/ 创建目录失败 */
rt_kprintf("dir error!\n");
}
else {
//创建成功,下次进来之后就不再创建;
Creatdir = 0;
}
}
if(Creatfile == 1)
{
char name[50] = "/can_data01/can";
char file_type[] = ".csv";
char count2char[10];
count2char[0] = '\0';
sprintf(count2char,"%d",can_filecount);
strcat(name,count2char);
strcat(name,file_type);
dirp = opendir("/can_data01");
fd = open(name, O_CREAT|O_WRONLY);//如果文件不存在则创建一个文件
if(fd>0)
{
Creatfile = 0;//创建成功以后,再次进入函数不再创建文件。
}
else {
rt_kprintf("create file failed\r\n");
}
}
if(fd>0)
{
// rt_kprintf("C_data:%s\r\n",C_data);
res_write = write(fd, C_data, strlen(C_data));
if(res_write >0)
{
;
//rt_kprintf("res_write = %d\r\n",res_write);
}
else
{
rt_kprintf("write error%d \r\n",strlen(C_data));
rt_kprintf("write error \r\n");
}
lseek(fd,0, SEEK_CUR);
res_sync = fsync(fd);//同步,将缓存写到SD卡里面。
can_datacount++;
if(can_datacount>19999)
{
can_datacount = 0;//清零计数器
Creatfile = 1;//下次进入函数要创建新文件
can_filecount++;//新建文件的编号
// close(fd);
res_close = close(fd);//写完一个文件一定要关闭;
if(res_close == 0)
{
rt_kprintf("close successed:%d\r\n",res_close);
}
else {
rt_kprintf("close failed:%d\r\n",res_close);
}
closedir(dirp);//因为打开了目录,所以把目录也关闭一下。
rt_kprintf("file count:%d,fd = %d\r\n",can_filecount-1,fd);
}
if(res_sync == 0)
{
;
}
else {
rt_kprintf("res_sync failed:%d",res_sync);
}
}
}