单片机
返回首页

STM32CubeMX----杂记

2018-07-01 来源:eefocus

(1)在使用FSMC作为LCD接口时,同时ENABLE了FreeRTOS,发现生成的工程文件,编译之后会出问题。


        


         研究后发现问题出在“FreeRTOSConfig.h”这段代码:


/* Cortex-M specific definitions. */

#ifdef __NVIC_PRIO_BITS

 /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */

 #define configPRIO_BITS         __NVIC_PRIO_BITS

#else

 #define configPRIO_BITS         4

#endif

   当我使用了FSMC并且ENABLE 了FreeRTOS,“__NVIC_PRIO_BITS”这个宏就会被定义,此时RTOS的宏


“configPRIO_BITS”会被定义为“__NVIC_PRIO_BITS”,这个宏在“stm32f205xx.h”里面:


#define __NVIC_PRIO_BITS          4U       /*!< STM32F2XX uses 4 Bits for the Priority Levels */

也就是说“configPRIO_BITS”这个宏被定义为“4U”也就是类型为“unsigned int”的4。


我尝试在汇编函数里,直接将:


mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY

改为:


mov r0, #4U

编译出错,但如果将“4U”改为“4”是没问题的。


后记:在韦东山第一期加强版视频编写LED程序的视频有讲到,在汇编里面指令需要占据一定的位数,例如:



mov r0, #0x12345678

是不行的,因为“MOV”这个指令本身占据了一定的位数。而“4U“本身为32位,stm32为32位系统,所以”MOV“这个指令码被清零了。具体可以了解下机器码跟汇编。


(2)ADC采集一次信号后不再采集


        问题可以参考这个链接:http://www.ing10bbs.com/forum.php?mod=viewthread&tid=194&extra=


        除了RCC、SYS,只配置了ADC2的IN8,NVIC Settings打开ADC全局中断:


  生成工程的改动很小,增加了一个ADC值获取的回调函数以及一个ADC启动的函数:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

{

   ADC_VAL = ADC2->DR;

}

ADC初始化里面添加了IT启动:


HAL_ADC_Start_IT(&hadc2);

然后进入仿真发现,ADC采样一次信号后,ADC2->DR寄存器里面的值不变了。研究了老半天,看了几遍参考手册中ADC寄存器的描述,怀疑是EOCS寄存器的问题。所以将:


hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

改为:


hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;

很好,ADC连续采样了。但又产生一个新的问题,程序一直重复进入ADC中断,不进入while(1);大循环了。


由此猜测,是不是因为ADC采样转化太快了,导致未处理完一次中断又产生新的中断?


又进行修改:


sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

改为:


sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;

这次可以正常运行了。其实,最好在启动ADC之后,关闭不必要的中断源,例如只需要看门狗中断:


__HAL_ADC_DISABLE_IT(&hadc2, ADC_IT_EOC|ADC_IT_JEOC|ADC_IT_OVR);

后记:在MDK仿真下观察寄存器,发现关闭中断的指令,关闭的是”ADC_IT_OVR“这个中断源。


这个是”溢出中断“的中断源。当ADC以”ADC_SAMPLETIME_3CYCLES“进行转换时,当前中断尚未处理完便再次触发中断


就会造成中断溢出。所以将ADC转换速率降低,或者关闭”ADC_IT_OVR“程序可以正常运行。


(3)内部FLASH的操作


MCU是F205VCT6


1、写


//STM FLASH写函数

void STMFLASH_Write_NoCheck ( uint32_t WriteAddr, uint16_t * pBuffer, uint16_t NumToWrite )   

{

        uint16_t i;        

 

     HAL_FLASH_Unlock();

     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR|FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);

        for(i=0;i

        {

          HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,WriteAddr,pBuffer[i]);

          WriteAddr+=2;                                    //地址增加2.

        }  

HAL_FLASH_Lock();

}


写之前要去除FLASH的写保护,然后就是写函数中的清楚标志位问题。如执行了


HAL_FLASH_Unlock();

然后立即执行写函数,会发现第一个数据写不进FLASH,但是后续的数据是正常的。试过增加几十毫秒的延时,但是结果依旧错误。如果在写之前先清除错误标志位,则可以正常写入。


2、擦除


//STM FLASH擦除函数

void SectorErase(u32 SectorNum )  

{  

    FLASH_EraseInitTypeDef  eraseInit;  

    u32         error;  

 

 HAL_FLASH_Unlock();

 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR|FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);

 eraseInit.Sector = SectorNum;

    eraseInit.TypeErase = FLASH_TYPEERASE_SECTORS;   

    eraseInit.NbSectors   = 1;  

    eraseInit.VoltageRange   = FLASH_VOLTAGE_RANGE_3;

  

    if ( HAL_FLASHEx_Erase( &eraseInit, &error ) == HAL_OK )  

    {  

    }  

HAL_FLASH_Lock();

}  


跟写函数一样,解锁FLASH后立即擦除,需要先清除错误标志位。


另外,执行擦除函数,如果是擦除0~3扇区,则可以正常进入仿真(代码在扇区0,擦除扇区0会出现异常,但确实能进入仿真的)界面。


如果擦除4~5扇区,则出现以下问题


不能进入仿真,但是扇区擦除却是成功的。解决办法,暂时未找到


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 光控音效发生器电路

  • 非常简单的150W功放电路图

  • 优化电路板布局的简单方法

  • 如何使用LED驱动器LM3915制作振动计

  • 电谐波图形均衡器示意图

  • 一种构建12V和230V双直流电源的简单方法

    相关电子头条文章