这段时间在公司里做了一个移植的项目,是stm32f103c8t6——>stm32f070cbt6,管脚基本上一样,移植一下库就行了,大概是为了节省成本吧。一开始是懵逼的,以前从来没有移植过stm32,都是想用哪个功能,发现一个是F1一个是F4,就耍小聪明,把其中没有用到库函数的部分复制到另一个上,然后开始编啊编啊……现在遇到项目要做了没办法,网上也找不到资料(我是小白),只能自己硬着头皮改啦!9 p7 [" P6 d6 q2 I1 O# c" |
6 @& ~ X6 I/ u$ D 想想想,想到后来就是先创建一个工程再说吧!
9 }, e3 k B) {1 j( z
8 C8 ^& @. T* Q$ \ 于是乎,第一步来了:创建一个STM32F0的工程。* F. @; G; I: k6 J! b) F' E
2 K7 ^7 O! C/ n2 _ 如果你在选择芯片的时候没有你想要的F0芯片,说明你没有那个pack,得下载一个,具体步骤不详细说了。
3 t, V4 ^8 d3 o) h# K" o# T# y3 U& O+ H$ s* r+ D1 q5 F( m# I
你需要用到的文件有:F0的库、F0的启动文件、F0的各种头文件、CORTEX-M0、系统文件……详细的不说了,对照图中的文件放就行了
* e, _3 F: H+ R2 h6 e( J% u8 T9 L( I/ ~2 L$ _; N9 b5 ~
# ]: p' v- J' X6 s
/ L3 b) n3 u! ]7 u 图中没有红线的不用管,其他都必须有,还有一些头文件没在上面,记得在设置——>C/C++里面引用一下,这些文件基本上在官网例程里都能下到。, O, w( n9 Y0 u2 J: w3 Q7 R. K4 b
9 u7 q0 g$ y' Y! c
同时要在C/C++一栏里加这么一行字:USE_STDPERIPH_DRIVER,STM32F0XX_MD
! M5 K# X6 ] C' ?5 a
2 d: F- G% G$ `/ W5 G) ?
8 y r8 `8 H ^1 o8 s0 i+ ]
) X6 w9 z: T. |$ o) f1 w& B2 h 然后再把你自己的程序贴上去,一编译,肯定不会通过的拉,哈哈哈,但是会把你程序中F1用到的库函数和F0库中相冲突的地方显示出来,这时候你就只需要一个个改就成了。
1 \! G8 b. t4 s. `' Q2 \
4 n( Z5 n+ L% ] E1 \6 H7 l9 G" }/ | 1.GPIO.c方面4 J" m# Z% g1 ?. i8 \; O9 k
gpio这方面比较简单,错误大部分都是引脚时钟设置、引脚的模式设置方面会出错误。/ n$ N) r; k7 `( H9 L/ ~2 k
3 I) p4 G1 `7 P8 s3 ?! \0 z 1.时钟的话由于F0库中没有使用PCLK作为GPIO时钟源的命令,所以一般都使用HCLK来作为GPIO的时钟源;
: ^' B9 m; Q2 o6 X3 P% L8 a3 Z' q$ i7 U3 o$ ~* H! q5 b7 q" |. N
2.引脚的模式设置方面你可以右键“GPIO_InitTypeDef”——>go to Definition看一下这个结构体里面的定义,比较一下F1和F0的设置的不同。$ [, m; @* v0 m0 m
+ Z! B' e$ j% P* w1 |# G 这里放两种图,一张是F1的,一张是F0的GPIO设置,大家可以对比一下. S, c* J- S# P, g3 U) ]
# ^* e. x, a+ S/ e" ^7 k
1 Q6 K8 _0 a# |. |6 Q0 e
: Q- x6 W0 v# E4 M+ y, o. f, s7 b( pF1 GPIO设置F0 GPIO设置
, _" ~+ N9 \7 v, K: F% A* C2 R( P9 V. W, b9 ~4 n
3 J3 ?! h( L, z4 \5 q) ]
$ d% S$ ?6 b; V2 V; e 另外,如果引脚模式为AF_PP,复用输出模式时需要用函数配置一下复用的用途:
8 A. D7 Q9 `- g9 T3 R
) t; K; k8 u( O0 c* L6 ~0 _ GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);GPIO_AF_1对应一些外设,比如说我这里用到了USART1,故要用GPIO_AF_1,你可以右键Definition看一下各个模式的定义。" B; p! ]$ t- |# m( G
9 @: }, E% \; L# N- |+ Q3 y
是不是感觉F0的设置很啰嗦,呵呵。; f( N* q4 u0 Z W* F- y
( Y( \# d" F% `7 C4 c
2.MISC.c(NVIC,即中断)、EXTI.C(外部中断)/ K4 a! q* x* s: C6 U
1.模式设置
2 x- x7 B+ ]- G# y% a) y7 ]( A9 q0 |
与GPIO模式配置差不多,修改方式大同小异。右键Definition一下“NVIC_InitTypeDef”、“EXTI_InitTypeDef”查看异同,相同不用改,不同就改,多删少补。
& f4 [) h9 {. O* z
( m* ~& R/ F) C# ]( K$ Q! q 还有在配置外部中断源时注意F1和F0是不同的,F1配得外部中断源在哪个通道范围,F0也得相应换:
& Z- c' u1 K% g E! i4 l; j! k+ p! N; W1 c
F1的中断源有:EXTI15_10_IRQn(10-15)、EXTI9_5_IRQn(5-9)、EXTI1_IRQn、EXTI2_IRQn……(1、2、3、4、5)
5 s) j4 }+ v8 @- `* \: Z
- ~( U3 J: B7 p F0的中断源有:EXTI0_1_IRQn(0-1)、EXTI2_3_IRQn(2-3)、EXTI4_15_IRQn(4-15)
4 q* s% b+ ^$ v; S' k1 ^6 w: H9 K7 H4 d* y
F1的中断源比如说是EXTI15_10_IRQn,那在F0中就得配EXTI4_15_IRQn,如果不在范围中,就得看你外部中断的引脚了,中断源和你引脚号相同% x2 ?2 @- x. q) p" P2 g
B4 E" P1 w$ x/ P9 b5 \ 3.定时器方面
% [2 o2 _ ^$ E7 U2 y 这部分由于项目中没有用到,我这里也不敢乱贴以致误导。相信小伙伴们上面的会改了,这个也不是难事,大部分都是修改模式配置的问题。
# ^5 I9 K" l7 u/ g& m" w2 @# S8 k; S- @. D% e
4.USART.c方面8 o1 u5 ~" x# Q, a) L, K& q, n7 b
串口配置首先是GPIO的配置和中断方面的配置,上面已经有方法了。这里的模式配置MS是不需要改的:
$ @; R1 ]* w* B" t
9 V% s- J# [6 v5 G7 U% |4 x F0:
/ E e/ J: G8 Z7 O; g+ V2 J4 @! L9 r4 s# [
- /* USART1 mode config */6 j8 g( {# Y5 Z2 V) K& f
- USART_InitStructure.USART_BaudRate = bps;: u' v7 e8 ]7 j% D& D( _/ V) u
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
! [7 [' h- [8 E% b8 c - USART_InitStructure.USART_StopBits = USART_StopBits_1;
& \6 f" E/ o& A. j; i% z9 M - USART_InitStructure.USART_Parity = USART_Parity_No ;- N( E% E) l' E( {: l
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
2 h b" t4 ^0 h$ N# A# | - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;$ l- m& T+ a. j$ r9 l
- USART_Init(RS485_UART, &USART_InitStructure);
3 u. S U G2 N( N* d - USART_ITConfig(RS485_UART, USART_IT_RXNE, ENABLE); ^. K3 q4 R/ F+ W
! @; P3 v" z4 v- c- USART_Cmd(RS485_UART, ENABLE);
复制代码 2 V, n; |+ q" }( r" t
F1:1 O4 S3 I' r- k& a6 l
) G4 H* ?# R" } H8 i- }- /* USART1 mode config */8 c/ T5 j5 `- ]1 t
- USART_InitStructure.USART_BaudRate = bps;
$ Q5 A4 H% D9 x7 }) G - USART_InitStructure.USART_WordLength = USART_WordLength_8b;$ f) A8 d) O) _0 {; v
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
2 G. ?8 N- n5 y7 W. e7 _ - USART_InitStructure.USART_Parity = USART_Parity_No ;
4 Q1 h5 @3 R; d* ?- C2 r1 b P - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;5 }+ r) l$ m6 B2 `: X# ^% K* {
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
! k/ F5 b2 |. t, B6 ^" K- t6 @ - USART_Init(RS485_UART, &USART_InitStructure);$ D- g0 {% z! J2 {; i& v. `8 }7 ^
- USART_ITConfig(RS485_UART, USART_IT_RXNE, ENABLE);
1 w# a o- b# d$ j$ Y$ `4 q4 K
* c V- S* U' Y( Y- G0 r- USART_Cmd(RS485_UART, ENABLE);
复制代码 嗯....一样一样的。注意这里有个寄存器是不一样的:
; a4 @3 { j, h1 ]6 Q7 R& R7 w# I; J% z# t8 P2 p8 M( N2 z# c, _
就是在接收中断中,有些项目可能需要将这个寄存器重置一下:
7 X( Q8 y( } ]& ?4 @" _
! q/ Z$ v; n, v# R' G: _F1中为“RS485_UART->SR=0x00;”,SR寄存器,只有16位
' W' B( b% h* {' y+ A" N' n: W& `: `% @' g& ^% s9 U
而F0中则为“RS485_UART->ISR=0x00C0; ”,ISR寄存器,有32位, B: S; O+ i0 Y6 v( j+ A2 d% t
% G3 r& m6 ^: x* v这些好像不是必要的,具体的功能可以看一下数据手册里怎么介绍的...似乎是中断接收标志位?9 p) ~7 q* F8 x1 R* z# Y8 o' d8 f6 n
% V0 |& `8 }8 l6 [. y 5.中断向量表的重映射8 w) X" q8 M9 L' O" Q; U1 b
如果你的项目用到了软件bootloader,中断向量表就得重映射,而F1中有函数可以直接用,然后你会发现F0中没有) N4 a6 o& I. r
+ L+ \: `; L9 E# I3 t F1中的函数:
* z0 N4 I0 x7 `; w
' E7 ~8 b- E1 r* r" ~) `( N NVIC_SetVectorTable(NVIC_VectTab_FLASH, BSP_ADDR_Boot);
6 o8 ~0 U, R% @7 k$ I' l
6 s, |/ y) E1 F. r" g9 C! T/ t. ]
+ _- @1 o2 n) z0 z 通过查资料得知我们可以用memcpy,将中断向量表拷贝到ram下(F0的中断向量表可以放在RAM中),然后保证存储中断向量表的这部分不会被修改就行了,方法在上面这个网址中。
* |7 d, V! f1 T1 |6 W
- a }" K4 |. z F0中的函数:
0 E6 M- V/ m2 i2 j9 |/ I3 Q3 O) v5 x i
memcpy((void*)0x20000000, (void*)0x08000000, VECTOR_SIZE);
- D. y+ H4 ~- p SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
# p8 b5 K8 @( Z: Z7 N: q8 n/ m2 ]
, F) T5 p* D& R 至于JTAG口的复用问题,STM32F0并不存在,可以将相应的函数删掉即可。
) B# F0 f5 F. a& h
+ Y5 m7 `% @: N, a# u1 ?1 M0 D- f. P( \0 V
) F/ t9 O! u8 D* w! Y! k" E$ V* y
/ k$ ]+ h/ _$ O
( q5 I% d: q/ f* ^ |