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扇区,则出现以下问题 不能进入仿真,但是扇区擦除却是成功的。解决办法,暂时未找到