以前一直使用STM32F1系列的MCU做产品,去年参加了ST无锡研讨会,了解到STM32cubeMX,回来后就下载了,发现功能还是比较强大。正好一款产品需要改版,所以就选择了STM32F030,正好也偿试一下STM32cubeMX的强大功能。& p/ |# ^9 E/ I 打开软件,选择MCU,配置IO,配置外设,配置时钟,配置功能,一气呵成。不得不说,图形化的界面真的很直观,每个IO的复用功能,每个外设的时钟频率,等等一目了然。最后,可以直接生成IAR工程文件(当然也可以生成其他工程文件),再也不要为建工程而烦恼了。。。 # N! [" Y) |: n6 f5 b接着,打开IAR,打开刚刚生成的工程文件,开始写应用程序(此过程省略)。5 ^, h/ t- R, S1 a0 Y& u5 Z 由于有标定值需要储存,没几个字节,就打算存在内部FLASH中,因为之前也是这样做的。等到调试的时候,发现每次读出的值都是0xff,很明显是没有写进FLASH,于是就开始找原因( H6 o4 l Y1 f- L x4 U void WriteRevise(void)9 Q3 T8 C/ o- { { s6 x% f, ~9 @$ x HAL_FLASH_Unlock();7 E5 t9 O' k# d s FLASH_PageErase(0x8003c00);& g; X6 i9 W r- x: J HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, 0x8003c00, RealFlow);% ^0 J2 b I c1 s9 f+ A8 a HAL_FLASH_Lock();9 Q( N9 P9 r7 a3 I. H1 S8 }! K } # ]4 n" a6 E5 j! J1 Z8 _- s x; s3 ^0 w5 J( C5 ~7 o+ e void GetRevise(void) , `: [: \& K3 e" w3 Z4 B0 a" |) y{ 2 s! U' F$ Y! t7 v/ k+ i RealFlow = *(__IO uint32_t*)(0x8003c00);, M5 { w# L/ a6 u9 Q" j- q% `, d9 ~9 X 5 J* V+ _/ }. l/ {" }1 X" G if(RealFlow == 0xffff)// > 8000 || RealFlow < 500)& x6 i# h" r7 ?8 f {4 S, e: o" o, a: R7 S RealFlow = 2060;3 Z! u9 P v9 b7 x: c8 u9 q8 v+ Z WriteRevise(); 3 E0 ^! Q9 Q: P& X4 V3 D T8 j4 i } - [( K% L* p; F& c/ t h}0 e6 v) C; r& [0 y; \3 r* w / G L# t, V/ K5 i$ M9 w读写函数都很简单,看不出问题。 " l1 B. w$ r, o% ?$ O1 a于是重写测试程序,单步跟踪,先来 读-加1-写-再读 操作,发现结果正确,接着,再来 读-加1-写-再读-擦除-再读 操作,发现结果也正确;这时候我有郁闷了,读,写,擦除操作都没问题,为什么程序里有不行呢? 5 C& @5 X: o# c9 F 没找到根本原因,就在原写函数中,每一步操作后加了一个读操作,也就是,解锁-读-擦除-读-写-读……发现写完之后再读就是0xff了,中间各种测试,延时、去掉擦除操作等等,最终,单独的写操作或者是擦除操作都是没有问题的,连起来就是不行。' q1 ?2 ^* S5 ?7 H( ~9 c+ _ 在无技可施的时候,就去看看库函数里的实现方法,在看到擦除函数的时候发现: ' \. }" T% L! ~/**2 ?) g, j3 x. S( w- }; V * @brief Erase the specified FLASH memory page ! H+ T) z& o7 t( k * @param PageAddress: FLASH page to erase, D0 _+ { {# K3 v * The value of this parameter depend on device used within the same series . [+ b s: n/ m( e- Y5 w * 6 Y* }! o. z' ^7 A( Q * @retval None0 c, p1 ?# F0 j7 K */ $ _ f w) F$ Ivoid FLASH_PageErase(uint32_t PageAddress) 0 m, s# T: i" p) D! j9 t{ ) z- `4 _( B& j) R% \ /* Clear pending flags (if any) */ 4 |8 ? l% s7 M8 h& J. P6 Y; j __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR); + [- M( j0 e. }- d( b) R- ^ 9 P* k& u" _/ O /* Proceed to erase the page */ : W# [6 K3 o) R3 i SET_BIT(FLASH->CR, FLASH_CR_PER);( R" z+ }/ ]) T6 m7 z' b& s& Q WRITE_REG(FLASH->AR, PageAddress);$ T! w1 [3 R; y( Z' w SET_BIT(FLASH->CR, FLASH_CR_STRT);5 v* S- ^ K: I" z0 o0 w6 X }3 ^5 m1 r; _ N( W o ! T+ }& [/ j. U% Y该函数中,只是置位了FLASH_CR_PER,然后写地址,开始擦除,而完成之后并没有清除该位。问题就出现在这儿,只要调用了擦除函数后,该位就一直为高,所以导致数据无法写入,而不调用擦除函数时,写正常。于是对该函数修改,如下: : {4 o8 ]) C: T2 t, W# {: U# lvoid FLASH_PageErase(uint32_t PageAddress) 7 {" X: N, e7 E. n H I{ , E/ {$ I6 u0 e! T /* Clear pending flags (if any) */ , p/ ]' Y, q" U% d __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR); 2 {- R3 e3 }4 S U3 Q4 {. _ X c: q* C' S3 y- |% l /* Proceed to erase the page */+ k, A. R5 G; d# p SET_BIT(FLASH->CR, FLASH_CR_PER); % `6 B/ ~8 j8 S WRITE_REG(FLASH->AR, PageAddress);' S: v# E6 a) k9 U SET_BIT(FLASH->CR, FLASH_CR_STRT); ; t2 _! W: q, w2 n* _# ]& p) X$ l FLASH_WaitForLastOperation((uint32_t)HAL_FLASH_TIMEOUT_VALUE); , l+ y$ k {; p. @: ], U4 | CLEAR_BIT(FLASH->CR, FLASH_CR_PER); & v! m; H: `6 A}0 |1 g. D9 y) {8 J4 ] / j; e G* Z: b9 } 增加等待操作完成,清除FLASH_CR_PER,至此,读写FLASH正常。 2 `+ H! r) D6 z; x 7 ]! u: H+ s3 H" M$ y! q+ e) R : D) z) g4 [2 V# N. d========================================================================================2 Y- _, u8 t% m& }1 F% M$ Q! A 以上是我在第一次使用STM32cubeMX中遇到的一点问题,应该是ST在设计过程中出现的BUG,我也看了之前的F1库函数,在擦除后是需要清的。, B3 R x2 {2 t# L) P v 希望ST的工作人员看到之后能对此优化,也希望各位工程师能避免此问题。1 F! x2 n ?4 w) l, Z" A 7 m9 D" B8 Y6 K2 O- o, S0 Z STM32cubeMX也刚出来不久,使用确实比较方便,但也难免有些BUG,不知道现在有多少人在用,什么地方可以交流? $ Y; x$ i8 @2 y& _
cubeMX确实好,特别是配IO脚、外设、时钟、中断,生成的项目模板也好用。