OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7582|回复: 8

stm32开发问题集锦

[复制链接]

38

主题

292

帖子

1

精华

高级会员

Rank: 4

积分
614
金钱
614
注册时间
2012-7-6
在线时间
0 小时
发表于 2013-1-10 09:43:42 | 显示全部楼层 |阅读模式

1 在flash中跑程序时,能进入中断,但在ram中跑时,进不了中断的原因。
看以下的中断配置函数可以知道,要在ram中调试程序,需要定义VECT_TAB_RAM。
定义方法a:在Project\Options for taget 'xxx' 的对话框的c/c++中定义宏VECT_TAB_RAM
定义方法b:在程序中直接定义

void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif

/* Configure and enable ADC interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

2 SysTickHandler 函数不能进入。
原先初始化的语句为
SysTick_Config();
修改为以下时可以进入
SysTick_Config();
SysTick_CounterCmd(SysTick_Counter_Enable);

3 如何解决链接时错误"..\obj\LowCostDA.axf: Error: L6218E: Undefined symbol assert_failed (referred from stm32f10x_flash.o)."?
如果所加入的库是STM32F10xD.LIB(即调试模式库),则需要在无论什么得放添加函数定义
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */
while (1)
{
}
}

如果所加入的库是STM32F10xR.LIB(即发布模式库),则不会报错。

4 打开中断的时机不正确,导致无法进行任务切换。
由于我过早地打开了 SysTick 中断,而我在SysTickHandler 中有如下语句:
{
...
OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
    OSIntNesting++;
    OS_EXIT_CRITICAL();

    OSTimeTick();        /* Call uC/OS-II's OSTimeTick()               */

    OSIntExit();
...
}
因为打开过早,因此 OSIntNesting++ 能够执行,而OSIntExit函数却没有把OSIntNesting减1.因此,导致了无法进行任务切换。

注意2点可以避免该情况:
a 同时使用 OSIntExit(); 和OSIntEnter(); 而不是像我这样使用OSIntNesting++ 和OSIntExit()。
b 开中断要在操作系统初始化后完成,即在OSStart之后。
5 程序中只要使用了printf函数,就会执行到BKTP语句挂掉。
解决方法:Project\Options Target选项页中选中 Use MicroLIB
关于 MicroLIB的详细说明见网友文章
http://hi.baidu.com/tt_gt/blog/item/8320b3dd7b3da2d38c1029e8.html

6 参考99的rtc时钟的使用方法,出现问题并顺利解决。
在程序中我修改当前时间是调用的以下函数
void Time_SetUnixTime(time_t t)
{
   RTC_WaitForLastTask();
   RTC_SetCounter((u32)t);
  
   RTC_WaitForLastTask();
   return;
}
但是程序会一直运行在 RTC_WaitForLastTask 中无法出来。
最终顺利解决。
99所介绍的程序启动是配置rtc的函数如下:
void RTC_Config(void)
{
   //我们在BKP的后备寄存器1中,存了一个特殊字符0xA5A5
   //第一次上电或后备电源掉电后,该寄存器数据丢失,
   //表明RTC数据丢失,需要重新配置
   if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
   {
       //重新配置RTC
       RTC_Configuration();
       //配置完成后,向后备寄存器中写特殊字符0xA5A5
       BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
   }
   else
   {
       //若后备寄存器没有掉电,则无需重新配置RTC
       //这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型
       if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
       {
           //这是上电复位
       }
       else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
       {
           //这是外部RST管脚复位
       }
       //清除RCC中复位标志
       RCC_ClearFlag();

       //虽然RTC模块不需要重新配置,且掉电后依靠后备电池依然运行
       //但是每次上电后,还是要使能RTCCLK???????
       //RCC_RTCCLKCmd(ENABLE);
       //等待RTC时钟与APB1时钟同步
       //RTC_WaitForSynchro();

       //使能秒中断
       RTC_ITConfig(RTC_IT_SEC, ENABLE);
       //等待操作完成
       RTC_WaitForLastTask();
   }

#ifdef RTCClockOutput_Enable
   /* Enable PWR and BKP clocks */
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

   /* Allow access to BKP Domain */
   PWR_BackupAccessCmd(ENABLE);

   /* Disable the Tamper Pin */
   BKP_TamperPinCmd(DISABLE); /* To output RTCCLK/64 on Tamper pin, the tamper
                               functionality must be disabled */

   /* Enable RTC Clock Output on Tamper Pin */
   BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
#endif

   return;
}

要调用Time_SetUnixTime设置时间 应该在if分支里边。
而不是在else分支里边。
我正好是犯了这样的错误。

7 关于堆栈对齐的问题
程序中出现了一个奇怪的问题
char g_cpTask2Buffer[200];
void Task2(void *arg)
{
...
sprintf(g_cpTask2Buffer,"%.3f", ADCInfoArray[0].m_fVolt);
...
}
ADCInfoArray[0].m_fVolt是一个float值。
在执行完 sprintf 后,无论m_fVolt是多少,始终得到的g_cpTask2Buffer的内容都是"0.000"。
调试了好几天的汇编终于解决了问题,根源竟然是ucos的堆栈需要以8字节对齐。
Task2是一个ucos的任务,Stack2 是Task2的任务堆栈。
如果是以下形式则出错:
Stack2                                   0x200084ac   Data         804 main.o(.bss)
Stack3                                   0x200087d0   Data         800 main.o(.bss)
如果是以下形式则不出错:
Stack2                                   0x200084ac   Data         800 main.o(.bss)
Stack3                                   0x200087cc   Data         800 main.o(.bss)

为什么 sprintf在Task2 的中,但是执行结果的正确与否却看起来似乎与Task3的任务堆栈Stack3相关?
原因是,任务 Task2 的堆栈顶实际上位于Stack2 + (Stack2STKSIZE - 1),该值正好与Stack3
相连。

为什么堆栈必须要8字节对齐?
因为在汇编中有这样的语句:
BIC      r0,r2,#0x07  
该句得到double型值(在处理过程中,m_fVolt先从float被转换为double型) 的存储地址。
该汇编的意思是把r2的最低一个字节的二进制最后3位清零,即把r2变为形如16进制xxxxxxx0或者xxxxxxx8,然后放入r0。
可以看到该地址必然是8字节对齐的。

最根本的原因我仍然没有找到,但算是解决了问题。
8 外部sram用作堆栈的一个问题
系统中使用了ucos,由于任务堆栈的空间需要的比较多,因此把其放到了外部sram中,使用这样的语句:
OS_STK Stack1[STKSIZE] __at (Bank1_SRAM3_ADDR) ;
但是没有想到的是,在使用sdio方式操作sd卡时,总是出现SDIO_IT_TXUNDERR 中断。
没有好的解决办法,只能老老实实地把任务堆栈放入片内的sram。
想来,恐怕原因是系统在和SD卡交换数据时用到了任务堆栈区,而任务堆栈区所在的片外的sram速度不够快导致的问题。
虽然问题凑合解决了,但是问题仍然存在:
外部sram到底能怎么用? 如果外部sram能和片内的sram一样方便地使用就好了。
看到这篇博客的朋友,有没有什么好的解决办法?

9 闹钟中断的问题(RTCAlarm)
打算在standby模式下使用闹钟中断,但由于standby模式调试不方便 ,因此在正常运行状态下先测试闹钟中断。
没想到遇到了问题:
关掉了RTC_IRQHandler,只打开RTCAlarm_IRQHandler。但是依然能进入RTC_IRQHandler中断函数,但不是正常状态下的进,而是不停地进中断,
而且RTC_GetITStatus(RTC_IT_SEC)得到状态也确实不是秒中断发生。
同时,也会进RTCAlarm_IRQHandler中断,也不是正常状态下的进,而是不停地进中断,而且RTC_GetITStatus(RTC_IT_ALR)得到状态也确实不是闹钟中断发生。
最终找到了问题所在:
一定要在RTCAlarm_IRQHandler函数中有这句:EXTI_ClearITPendingBit(EXTI_Line17);
stm32f0  f1  f3  f2  f4 等系列相关型号产品资料下载:http://www.y-ec.com/down/class/

STM32F3系列公司现有货供应!STM32F0,STM32F2,STM32F3,STM32F4 银洋电子专业一级代理http://www.y-ec.com 联系电话:021-53086303  淘宝网:http://y-ec.taobao.com
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

51

主题

214

帖子

0

精华

高级会员

Rank: 4

积分
561
金钱
561
注册时间
2011-4-11
在线时间
43 小时
发表于 2013-1-10 18:43:42 | 显示全部楼层
回复 支持 反对

使用道具 举报

38

主题

292

帖子

1

精华

高级会员

Rank: 4

积分
614
金钱
614
注册时间
2012-7-6
在线时间
0 小时
 楼主| 发表于 2013-1-11 09:50:23 | 显示全部楼层
ding
回复 支持 反对

使用道具 举报

46

主题

333

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
357
金钱
357
注册时间
2013-12-12
在线时间
63 小时
发表于 2014-1-11 10:13:44 | 显示全部楼层
回复【3楼】shyinyang:
---------------------------------
老大,小弟愚钝,解决不了这么高深的问题。。。但是能否给小弟解决下这个。。。
现在我的驱动板上有四个电机,然后我用CAN发送数据,我想要实现的是先给每一个电机口都附上一个地址,然后再附上数据,这样就可以保证数据不会“走”错。。。。
或是一个数据一个+一个地址作为一组。。。。
我对CAN的认识还是很肤浅的,希望大神可以给我一点启发~~
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2014-1-11 19:36:37 | 显示全部楼层
cool
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2014-1-11 19:38:35 | 显示全部楼层
希望其他坛友,也能有楼主这份心。
将自己开发过程中遇到的一些问题,总结起来,这样,大家都能少走弯路,共同提高。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
11
金钱
11
注册时间
2016-6-8
在线时间
0 小时
发表于 2016-6-11 22:15:55 | 显示全部楼层
收藏了,顶一下~~~
回复 支持 反对

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1823
金钱
1823
注册时间
2014-8-5
在线时间
211 小时
发表于 2016-6-11 22:46:56 | 显示全部楼层
谢谢楼主的指导
回复 支持 反对

使用道具 举报

5

主题

305

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1690
金钱
1690
注册时间
2018-11-28
在线时间
214 小时
发表于 2023-10-11 14:14:15 | 显示全部楼层
学习一下,谢谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 19:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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