zoukankan      html  css  js  c++  java
  • stm32开发问题集锦

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

    郁闷啊,小小的问题,找了一下午。

  • 相关阅读:
    Struts2 MVC基础介绍
    【转载】Linux下安装、配置、启动Apache
    网易校招编程题
    libevent中evmap实现(哈希表)
    libevent源码阅读笔记(一):libevent对epoll的封装
    Linux进程间通信总结
    【转载】Ubuntu 12.04 LTS 中文输入法的安装
    转载 正则表达式30分钟入门教程
    简明Vim练级攻略
    【转载】C++基本功和 Design Pattern系列 ctor & dtor
  • 原文地址:https://www.cnblogs.com/gaotaozhaolei/p/1613187.html
Copyright © 2011-2022 走看看