把Kalman移植到单片机上,编译错误-缺少浮点元算库(用的 试用版keil编译器)
C51FPS.LIBC51FPC.LIBC51FPL.LIB谁有这几个库?借来用用,谢谢了! 点击此处下载 ourdev_358772.rar(文件大小:33K) (原文件名:LIB.rar) 谢谢了! Kalman的源码可以共享吗?谢谢。我的邮件:redrain@sjtu.edu.cn 试验中。。。 51算浮点吃力,可以借鉴DSP的Q格式做定点运算 *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
SEGMENT: ?PR?_INIT_MEMPOOL?INIT_MEM
请教 这个警告是什么原因?
导致 我的定式时中断里面a/d采样出现错误! 是说有段没有被调用。 我现正将kalman应用于IMU,有类似应用的朋友可以一起讨论.
MCU:mega168.硬件资源是够用了. 这个警告没关系,一般不会出错,提示的函数没有被调用 【8楼】 coolhe
我用的51硬件资源不够用!
【9楼】 xiaoqun
我根本就没有定义这个函数?(_INIT_MEMPOOL)!现在定时中断里面a/d采样寄存器出现错误,而且会有死机现象! init_mempool是stdlib里的函数,用来初始化堆的。extern void init_mempool (void _MALLOC_MEM_ *p, unsigned int size);这个是原形 【11楼】 xiaoqun谢谢 !
不知什么原因把a/d采样寄存器冲乱了! 【11楼】 xiaoqun谢谢 !
不知什么原因把a/d采样寄存器冲乱了! 不知道你程序里是否用malloc这个函数,这个函数如果要用必须先调用init_mempool这个函数初始化,并且必须是xdata就是扩展RAM,51里尽量少用这个函数,我估计你在做KALMAN的矩阵时可能初始化几个堆了,我觉得你可以定义全局的静态数组,虽然占更多资源,但是还是比较稳定。 用过 calloc 这个函数
//-------------------------------------------------------------------------------------------------
//矩阵倒置,A为倒置前矩阵,AInverse为结果矩阵;
//矩阵均为n行,n列
//-------------------------------------------------------------------------------------------------
static int matrix_inversion(float xdata * A, int n, float xdata * AInverse)
// Matrix Inversion Routine
{
// A = input matrix (n x n)
// n = dimension of A
// AInverse = inverted matrix (n x n)
// This function inverts a matrix based on the Gauss Jordan method.
// The function returns 1 on success, 0 on failure.
intxdata i, j, iPass, imx, icol, irow;
floatxdata det, temp, pivot, factor;
float * ac = (float *)calloc(n*n, sizeof(float));
det = 1;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
AInverse = 0;
ac = A;
}
AInverse = 1;
}
// The current pivot row is iPass.
// For each pass, first find the maximum element in the pivot column.
for (iPass = 0; iPass < n; iPass++)
{
imx = iPass;
for (irow = iPass; irow < n; irow++)
{
if (fabs(A) > fabs(A)) imx = irow;
}
// Interchange the elements of row iPass and row imx in both A and AInverse.
if (imx != iPass)
{
for (icol = 0; icol < n; icol++)
{
temp = AInverse;
AInverse = AInverse;
AInverse = temp;
if (icol >= iPass)
{
temp = A;
A = A;
A = temp;
}
}
}
// The current pivot is now A.
// The determinant is the product of the pivot elements.
pivot = A;
det = det * pivot;
if (det == 0)
{
free(ac);
return 0;
}
for (icol = 0; icol < n; icol++)
{
// Normalize the pivot row by dividing by the pivot element.
AInverse = AInverse / pivot;
if (icol >= iPass) A = A / pivot;
}
for (irow = 0; irow < n; irow++)
{
// Add a multiple of the pivot row to each row.The multiple factor
// is chosen so that the element of A on the pivot column is 0.
if (irow != iPass) factor = A;
for (icol = 0; icol < n; icol++)
{
if (irow != iPass)
{
AInverse -= factor * AInverse;
A -= factor * A;
}
}
}
}
free(ac);
return 1;
} float * ac = (float *)calloc(n*n, sizeof(float));
改成静态数组 试试吧,
xiaoqun高手! 谢谢指点! 改成静态数组不成!
调用init_mempool这个函数初始化试试! 警告消除,还是存在 a/d采样问题(把a/d采样 放在定时中断中采样错误,放在外面采样没有问题。)
看样子不是这个警告的问题。! 编译信息:
Build target 'Main_mcu'
compiling mainloop.c...
linking...
Program Size: data=73.0 xdata=502 code=6943
creating hex file from "Main_mcu"...
"Main_mcu" - 0 Error(s), 0 Warning(s). 你可能还有一个问题,就是用了递归调用,这样你需要定义为重入函数,要用到reentrant这个关键词比如说int f(int x) reentrant,必须注意这个问题,或者都用指针,这样函数就可以有可重入性了,C51给的库文件大部分有重入性 没有递归调用。 中断里调用的函数也需要注意。好多时候用到中断嵌套的,假如说同一个函数可能在同一时间调用的话,那么必须是再入的。往往数据发生错误大部分是在中断中发生的,因为没有做好保护现场,或者中断中更改了别的函数的数据,用仿真器可以跟踪到。还有一个问题,你的优化级别不要太高,我觉得6级就可以了,太高可能出现意想不到的错误。 谢谢老大指点! 可能找到问题所在了,下午再 确定一下!! 问题 定位在 上面的函数上!
float * ac = (float *)calloc(n*n, sizeof(float)); #include <stdlib.h>
unsigned char xdata malloc_mempool ;
void tst_init_mempool (void) {
int i;
xdata void *p;
init_mempool (&malloc_mempool, sizeof(malloc_mempool));
p = malloc (100);
for (i = 0; i < 100; i++)
((char *) p) = i;
free (p);
}
这个是keil的例子程序,你可以参考一下,可能是你的堆没有初始化好 问题原因定位在单片机ram资源不够用!
谢谢xiaoqun。 Program Size: data=73.0 xdata=502 code=6943 你用的是片上集成的XRAM,512byte?那你应该把一些变量定义在data或idata里,还有那么大的地方。 http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_362432.JPG
(原文件名:q.JPG)
xdata 是1024byte, 编译的时候显示“data=73.0 xdata=502 code=6943” 我怀疑编译信息有问题。
我做过这个一个试验: kalman子程序我不在主程序里面调用,ad采样后通过串口 上传到pc,数据无误!!然后再多 定义一个全局变量unsigned char xdata calloc_mempool ;编译后试验,结果上传到pc,数据是乱的!所以我推断是ram问题。
“data=73.0 xdata=502 code=6943”这只是一kalman处理程序,还没有加上角速度和加速度的角度计算还有pid,和后来的gps....这样算来最终还得换单片机。
不过为了试验 kalman 的正确与否,还会继续用51试下去。同时做换单片机的准备! 你可以试一下小模式编译。把数组之类的定义在XDATA,程序自己的临时变量自动会在data中生成。小模式相对速度也要快些。因为大模式编译的时候要注意startup的设置。因为默认keil不会初始化XDATA 小模式编译:
Build target 'Main_mcu'
compiling mainloop.c...
MAINLOOP.C(375): error C241: '_kalman_update': auto segment too large
MAINLOOP.C(553): error C193: '>>': bad operand type
MAINLOOP.C(555): error C193: '>>': bad operand type
MAINLOOP.C(557): error C193: '>>': bad operand type
MAINLOOP.C(559): error C193: '>>': bad operand type
Target not created zhcool_521 我最近也在学习单片机处理角速度 加速度的卡尔曼滤波 可是数学功底太差了能不能帮帮我 我的Mail 是kaesi0@qq.com mark 编程很痛苦 但为了我的飞行器那就不一样了
页:
[1]