搜索
bottom↓
回复: 33

把Kalman移植到单片机上,编译错误-缺少浮点元算库(用的 试用版keil编译器)

[复制链接]

出0入0汤圆

发表于 2008-7-26 10:04:44 | 显示全部楼层 |阅读模式
C51FPS.LIB  C51FPC.LIB  C51FPL.LIB

谁有这几个库?  借来用用,谢谢了!

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2008-7-26 11:17:08 | 显示全部楼层
点击此处下载 ourdev_358772.rar(文件大小:33K) (原文件名:LIB.rar)

出0入0汤圆

 楼主| 发表于 2008-7-26 14:05:33 | 显示全部楼层
谢谢了!

出0入0汤圆

发表于 2008-7-26 14:49:23 | 显示全部楼层
Kalman的源码可以共享吗?谢谢。我的邮件:redrain@sjtu.edu.cn

出0入0汤圆

 楼主| 发表于 2008-7-26 16:12:09 | 显示全部楼层
试验中。。。

出0入0汤圆

发表于 2008-7-26 16:22:29 | 显示全部楼层
51算浮点吃力,可以借鉴DSP的Q格式做定点运算

出0入0汤圆

 楼主| 发表于 2008-7-28 14:08:30 | 显示全部楼层
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    SEGMENT: ?PR?_INIT_MEMPOOL?INIT_MEM

请教 这个警告是什么原因?
导致 我的定式时中断里面a/d采样出现错误!

出0入0汤圆

发表于 2008-7-28 18:15:24 | 显示全部楼层
是说有段没有被调用。

出0入0汤圆

发表于 2008-7-28 20:40:17 | 显示全部楼层
我现正将kalman应用于IMU,有类似应用的朋友可以一起讨论.
MCU:mega168.硬件资源是够用了.

出0入0汤圆

发表于 2008-7-28 23:48:27 | 显示全部楼层
这个警告没关系,一般不会出错,提示的函数没有被调用

出0入0汤圆

 楼主| 发表于 2008-7-29 08:03:59 | 显示全部楼层
【8楼】 coolhe
我用的51  硬件资源不够用!
【9楼】 xiaoqun
我根本就没有定义这个函数?(_INIT_MEMPOOL)!  现在定时中断里面a/d采样寄存器出现错误,而且会有死机现象!

出0入0汤圆

发表于 2008-7-29 08:22:02 | 显示全部楼层
init_mempool是stdlib里的函数,用来初始化堆的。extern void init_mempool (void _MALLOC_MEM_ *p, unsigned int size);这个是原形

出0入0汤圆

 楼主| 发表于 2008-7-29 08:34:06 | 显示全部楼层
【11楼】 xiaoqun  谢谢 !

不知什么原因把  a/d采样寄存器  冲乱了!

出0入0汤圆

 楼主| 发表于 2008-7-29 08:34:28 | 显示全部楼层
【11楼】 xiaoqun  谢谢 !

不知什么原因把  a/d采样寄存器  冲乱了!

出0入0汤圆

发表于 2008-7-29 08:47:07 | 显示全部楼层
不知道你程序里是否用malloc这个函数,这个函数如果要用必须先调用init_mempool这个函数初始化,并且必须是xdata就是扩展RAM,51里尽量少用这个函数,我估计你在做KALMAN的矩阵时可能初始化几个堆了,我觉得你可以定义全局的静态数组,虽然占更多资源,但是还是比较稳定。

出0入0汤圆

 楼主| 发表于 2008-7-29 08:59:00 | 显示全部楼层
用过 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.
    int  xdata i, j, iPass, imx, icol, irow;
    float  xdata 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[n*i+j] = 0;
            ac[n*i+j] = A[n*i+j];
        }
        AInverse[n*i+i] = 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[n*irow+iPass]) > fabs(A[n*imx+iPass])) 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[n*iPass+icol];
                AInverse[n*iPass+icol] = AInverse[n*imx+icol];
                AInverse[n*imx+icol] = temp;
                if (icol >= iPass)
                {
                    temp = A[n*iPass+icol];
                    A[n*iPass+icol] = A[n*imx+icol];
                    A[n*imx+icol] = temp;
                }
            }
        }

        // The current pivot is now A[iPass][iPass].
        // The determinant is the product of the pivot elements.
        pivot = A[n*iPass+iPass];
        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[n*iPass+icol] = AInverse[n*iPass+icol] / pivot;
            if (icol >= iPass) A[n*iPass+icol] = A[n*iPass+icol] / 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[n*irow+iPass];
            for (icol = 0; icol < n; icol++)
            {
                if (irow != iPass)
                {
                    AInverse[n*irow+icol] -= factor * AInverse[n*iPass+icol];
                    A[n*irow+icol] -= factor * A[n*iPass+icol];
                }
            }
        }
    }

    free(ac);
    return 1;
}

出0入0汤圆

 楼主| 发表于 2008-7-29 09:01:10 | 显示全部楼层
float   * ac = (float *)calloc(n*n, sizeof(float));  
改成静态数组 试试吧,

xiaoqun  高手! 谢谢指点!

出0入0汤圆

 楼主| 发表于 2008-7-29 09:09:14 | 显示全部楼层
改成静态数组  不成!
调用init_mempool这个函数初始化  试试!

出0入0汤圆

 楼主| 发表于 2008-7-29 09:38:27 | 显示全部楼层
警告消除,还是存在 a/d采样  问题(把a/d采样 放在定时中断中采样错误,放在外面采样没有问题。)

看样子不是这个警告的问题。!

出0入0汤圆

 楼主| 发表于 2008-7-29 09:40:26 | 显示全部楼层
编译信息:

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).

出0入0汤圆

发表于 2008-7-29 10:44:14 | 显示全部楼层
你可能还有一个问题,就是用了递归调用,这样你需要定义为重入函数,要用到reentrant这个关键词比如说int f(int x) reentrant,必须注意这个问题,或者都用指针,这样函数就可以有可重入性了,C51给的库文件大部分有重入性

出0入0汤圆

 楼主| 发表于 2008-7-29 11:35:02 | 显示全部楼层
没有  递归调用  。

出0入0汤圆

发表于 2008-7-29 11:48:49 | 显示全部楼层
中断里调用的函数也需要注意。好多时候用到中断嵌套的,假如说同一个函数可能在同一时间调用的话,那么必须是再入的。往往数据发生错误大部分是在中断中发生的,因为没有做好保护现场,或者中断中更改了别的函数的数据,用仿真器可以跟踪到。还有一个问题,你的优化级别不要太高,我觉得6级就可以了,太高可能出现意想不到的错误。

出0入0汤圆

 楼主| 发表于 2008-7-29 12:01:29 | 显示全部楼层
谢谢老大指点! 可能找到问题所在了,下午再 确定一下!!

出0入0汤圆

 楼主| 发表于 2008-7-29 16:01:24 | 显示全部楼层
问题 定位在 上面的函数上!   
float   * ac = (float *)calloc(n*n, sizeof(float));

出0入0汤圆

发表于 2008-7-29 16:36:52 | 显示全部楼层
#include <stdlib.h>

unsigned char xdata malloc_mempool [0x1000];

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的例子程序,你可以参考一下,可能是你的堆没有初始化好

出0入0汤圆

 楼主| 发表于 2008-7-30 08:21:54 | 显示全部楼层
问题原因定位在单片机ram资源不够用!
谢谢xiaoqun。

出0入0汤圆

发表于 2008-7-30 08:37:48 | 显示全部楼层
Program Size: data=73.0 xdata=502 code=6943 你用的是片上集成的XRAM,512byte?那你应该把一些变量定义在data或idata里,还有那么大的地方。

出0入0汤圆

 楼主| 发表于 2008-7-30 09:19:26 | 显示全部楼层

(原文件名:q.JPG)

xdata 是1024byte  , 编译的时候显示“data=73.0 xdata=502 code=6943” 我怀疑编译信息有问题。

我做过这个一个试验: kalman子程序我不在主程序里面调用,ad采样后通过串口 上传到pc,数据无误!!然后再多 定义一个全局变量unsigned char xdata calloc_mempool [100];  编译后试验,结果上传到pc,数据是乱的!  所以我推断是ram问题。

“data=73.0 xdata=502 code=6943”这只是一kalman处理程序,还没有加上角速度和加速度的角度计算还有pid,和后来的gps....这样算来最终还得换单片机。

不过为了试验 kalman 的正确与否,还会继续用51试下去。同时做换单片机的准备!

出0入0汤圆

发表于 2008-7-30 09:29:48 | 显示全部楼层
你可以试一下小模式编译。把数组之类的定义在XDATA,程序自己的临时变量自动会在data中生成。小模式相对速度也要快些。因为大模式编译的时候要注意startup的设置。因为默认keil不会初始化XDATA

出0入0汤圆

 楼主| 发表于 2008-7-30 09:55:30 | 显示全部楼层
小模式编译  :

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

出0入0汤圆

发表于 2010-8-3 11:16:35 | 显示全部楼层
zhcool_521 我最近也在学习单片机处理角速度 加速度的卡尔曼滤波 可是数学功底太差了  能不能帮帮我 我的Mail 是kaesi0@qq.com

出0入0汤圆

发表于 2011-9-16 14:46:02 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-25 11:27:25 | 显示全部楼层
编程很痛苦   但为了我的飞行器那就不一样了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 06:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表