你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

sprintf函数和STemwin 里的GUI_TOUCH_Exec()函数起冲突,什么原...

[复制链接]
xuyejin 提问时间:2017-7-28 12:11 /
各位大侠您们好

           有个新问题请教,我要是用 sprintf显示字符,为什么%d,%s都可以,而%f一直都是0.000000?
后来发现是调用stemwin里的GUI_TOUCH_Exec()函数有冲突,当不调用GUI_TOUCH_Exec()函数时,sprintf函数的使用就正常,如果一调用,就会出现上面的问题,还有大侠指教下啊?谢谢




        for( ; ; )
        {
                GUI_TOUCH_Exec();

                GUI_Exec();

                GUI_Delay(10);       
        }       

收藏 1 评论10 发布时间:2017-7-28 12:11

举报

10个回答
moyanming2013 回答时间:2017-7-28 13:58:04

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

xuyejin 回答时间:2017-7-28 21:34:42
moyanming2013 发表于 2017-7-28 13:58
参考问题:
https://www.stmcu.org.cn/module/forum/thread-612727-1-1.html
增加栈和堆。

我试了下,还是不行,真是奇了怪了
xuyejin 回答时间:2017-7-28 21:37:13
在startup_stm32f2xx.s中 原来  
Stack_Size      EQU     0x00000400
Heap_Size       EQU     0x00000200

我给改成
Stack_Size      EQU     0x00001000
Heap_Size       EQU     0x00000800

扩大了4倍,还是不行啊
kylongmu 回答时间:2017-7-29 00:06:20
uint32_t Msg_Size = 0; char P_msg1[]="Err\n\r";
char testc[100];
     Msg_Size=sprintf(testc,"Any your message %d\n\r",i);
    if (Msg_Size>100)
    {
      printf(P_msg1);
    }
给你个思路,以上代码仅是示例,看懂意思自己实现,每次sprintf会返回实际打印字符数,你在每个打印语句后都用这个返回值与你实际申请的空间做一次越界判断。
------------------------------------
如果你调整堆栈尺寸不能解决问题,说明不是多层次调用后溢出引起的,你需要先排除sprintf的打印溢出潜在错误。



评分

参与人数 1ST金币 +3 收起 理由
zero99 + 3

查看全部评分

kylongmu 回答时间:2017-7-29 00:19:44
sprintf是一个潜藏风险的函数,调用它如果参数多(打印格式复杂)或者调用层次深,而你默认堆栈太小,则会有堆栈溢出风险。
另外它不检查是否打印超过了你申请空间的尺寸。
----------------------------------------------------------
以上两个问题,如果是现在的GCC编译器是可以帮你检查出来的,但是keil的编译器,起码现在5.0的是不会帮你检查出来的。目前keil 5.24版本里有了6.7版编译器,可惜CubeMX生成的工程不支持,坐等ST啥时候发福利。
xuyejin 回答时间:2017-7-29 08:55:32
kylongmu 发表于 2017-7-29 00:06
uint32_t Msg_Size = 0; char P_msg1[]="Err\n\r";
char testc[100];
     Msg_Size=sprintf(testc,"Any ...

e:\q.png
谢谢你的指点,我按照你说的方法试了,显示没有超出我设置12的长度,真是邪门了
xuyejin 回答时间:2017-7-29 08:57:29
char bStr[12];
        float  temp;
        int msize;

        for(i=0; i<nCH; i++)
        {
                LISTVIEW_SetItemText(hDlgListView, 1,  i, TRAINSTATUS[StateUn.Current.CH_Para[i].TrainState]);

                //temp = StateUn.Current.CH_Para[i].TrainDura/1000.0;
                //temp =1000.0;
                msize = sprintf(bStr, "%.3f", 1000.0);
                if(msize < 12)
                LISTVIEW_SetItemText(hDlgListView, 2,  i, bStr);
                else
                LISTVIEW_SetItemText(hDlgListView, 2,  i, "Error");       
       
靠,图片怎么显示不出来? 运行后msize = 5, 显示0.000
               
xuyejin 回答时间:2017-7-29 09:10:30
xuyejin 发表于 2017-7-29 08:57
char bStr[12];
        float  temp;
        int msize;

还有个关键,为什么不调用GUI_TOUCH_Exec(); 就是好的,而一调用就不对?缓冲区,堆栈我都加大了,把sprintf的第一个参数的长度定义为256,%.3f   改为%7.3f还是不行
kylongmu 回答时间:2017-7-29 12:07:59
MDK下有两种方式给函数定位(均在代码中控制):
1. 给函数声明 __attribute__
比如声明函数:
void task(void) __attribute((section(".ARM.__at_0x8100000")));
这样函数 task 会被连接到 0x8100000 地址处.
不同的函数可以使用同一个地址,链接的时候会自动处理.
每个函数都需要声明一次.
2. 使用#pagaram 控制
如下定义:
#pragma arm section code=".ARM.__at_0x8100000"
void task(void)
{
}
#pragma arm section
这样函数 task 会被链接到 0x8100000 地址.
这样做的优点是声明区内的函数都会包含在指定的地址范围内.
-------------------------------------------------------------------------------
把你的GUI_TOUCH_Exec()函数独立指定链接地址,你可以先看一下你编译后代码尺寸,然后把这个函数放在你总尺寸以后,如果你这个函数立即又调用别的函数,这个方法就不好使了。
与你怀疑有问题的大块内存变量,可以用类似:TempBuf [1024] __attribute__((at(0X20002000)))
指定内存分配地址。
这样可以把问题函数,变量孤立出来,可以排除编译链接问题。
zero99 回答时间:2017-9-29 16:04:57
xuyejin 发表于 2017-7-29 08:57
char bStr[12];
        float  temp;
        int msize;

楼主上传方法不对吧,看这里

https://www.stmcu.org.cn/module/forum/thread-612788-1-1.html
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版