本帖最后由 kevin0129 于 2015-1-11 14:14 编辑 4 E9 i7 W6 P. ~5 D
+ h% `/ G- l6 B; ?# B' K, e- I
最近看到沐紫老师手上有多余的nucleo stm32f072的板,果断以之前的活动价购买了一块,之前研究过stm32f103,当使用072的时候发现它的这个HAL库和标准库差别十分大,于是便研究了一下这个HAL库,之前使用了一点这个cube MX,发现这个配置软件非常好用,相对于103来说,我们不用再来自己动手配置外设了,直接设置几个参数就够了,今天来介绍下cube mx生成一个带I2C和SPI的工程的步骤(之前用103没怎么调通过I2C,一直软件模拟,这次尝试下,发现没有出现I2C bug,应该不是侥幸,毕竟测试了四天四夜.......)2 |9 v, V5 G$ v; N/ \- C% r' a
1.打开cubemx后选择nucleo f072的板子,这个很好找
/ G# F3 I/ l; X q0 z& N5 U& P9 O- @2.配置外设的引脚' `; |: X. ]0 ~1 |4 o' P2 e* \
7 s7 H& P M, k7 Q; w C
I2C就直接选择I2C模式7 m. {: E3 A2 B8 y& L5 ~
+ z m9 [$ G' f) ]
SPI设备我用的一块显示屏,没必要去读它,我就直接选择了主机只发送的模式,如果要读写的话就不要选择这个了
1 g; r/ }! Q% u- z3 |/ f
! S/ z+ G3 I2 b9 v- j6 {! |/ B
I2C的引脚更改,我看到板子上的SCL和SDA在PB8和PB9上果断把默认的引脚改成PB8和PB9(这个其实可以不用改的,我只是为了接线方便). |9 U* {' @7 d7 B! _( ~ Q, d3 L
g7 G- U. U" S$ @' K* O; z接下来配置几个I/O做显示屏的控制I/O,直接都设置为输出就够了!+ @" ]6 r: E; _+ n5 ~0 |
7 C+ L. W D9 c- ^+ U
接下来配置时钟,我自己焊了一个HSE晶振,所以选择了外部晶振,配置系统时钟为48M,还有设置I2C的时钟为系统时钟
# E5 S1 D" c$ z9 _
2 ]9 l8 i4 ^6 Z T5 L8 g- `2 M8 w
接下来是I2C的配置,设置为标准模式100k速度, 上升沿400ns下降沿100ns,这个地方的设置和f103的I2C配置有点不一样,我没有选择中断和DMA最后修改下I2C的GPIO配置就够了(和配置其他gpio一样)+ s: q' x: J: U: X! Z0 h* `
8 E# v7 u/ T9 ]% zSPI的设置更简单只需设置数据长度和速度就够了,同样没有用DMA和中断,只需配置I/O就够了4 q6 I2 B0 }8 d% L) r5 [1 ?5 z# q
最后去配置一下那几个控制I/O就够了,这样就可以生成工程了
8 _% W+ p1 g/ N& S8 `* k
0 |- r4 Q- ]9 H+ x/ X4 o4 `/ }; J生成工程的时候我选择了这个,我不喜欢把所有的代码都放到main.c文件里面,看起来很麻烦,这一项是单独生成对应的外设.c和.h文件,看起来比较舒服
& _( f, e5 _3 s& u4 h! S生成工程完毕后,外设都基本设置好了,主要配置下I2C的读写程序和SPI的写程序就够了2 d, k2 v. d! x3 n: r J, P/ C
- void Single_WriteI2C(uint8_t REG_Address,uint8_t REG_data)$ m, @4 I+ w' E' q& b% M. F# F
- {
& P7 W- v0 t, p! N" q - uint8_t TxData[2] = {REG_Address,REG_data};: ^! v2 h7 e; }5 S1 M. P1 a
- while(HAL_I2C_Master_Transmit(&hi2c1,I2C1_WRITE_ADDRESS,(uint8_t*)TxData,2,1000) != HAL_OK)
2 D: _2 i3 G" c# J$ e9 r" k - {1 j: v6 F0 c- m0 d( l
- if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
2 s6 o% s$ z6 P8 y6 g# g - {' E. F; s9 U; y5 s) d; g7 h, ?! I
- Error_Handler();6 N3 I$ b; }) c
- }% H3 F) Q1 e0 ?4 o3 h s
- }" Q+ Y6 s- R7 |/ q# ^
- }
复制代码 1 h; e$ ^7 O% d
3 B/ q2 C. e" a. ^8 l- e
这是I2C的写单个字节的程序
|6 r, s. b9 N5 t- uint8_t* Double_ReadI2C(uint8_t REG_Address)
2 h. ]- V. S$ I* H7 S: N) i - {
1 F) O1 z+ V' A: D# B -
- B" Z# i" j+ j" e. c% j0 @5 \" o$ S - while(HAL_I2C_Master_Transmit(&hi2c1,I2C1_WRITE_ADDRESS,®_Address,1,500) != HAL_OK). r+ H; h. Z' n6 [7 u. j; w
- {
% f3 S, E1 m; m9 A2 o Y, q/ [& z - if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF)
( M8 m: }7 G0 T. v7 b& ] - {! u9 i e a- i c" P, v s
- Error_Handler();$ l, k2 v' S9 T% Q, w9 ~% h
- }6 x( |% g/ U6 I, ~+ B
- }
) K p4 v, A: M4 a -
4 A9 Y! e- p6 a- P# k ?" t - if(HAL_I2C_Master_Receive(&hi2c1,I2C1_READ_ADDRESS,(uint8_t*)RxBuffer,2,1000) != HAL_OK)
: ~# O$ n5 y; U/ s7 X - {
( v# x% N4 _# A7 E7 H0 e9 g - if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF). P" H, Z3 i! [9 e3 b
- {
) H) ? X* c. L' D! ~ - Error_Handler();
|# \' G8 d( n" I6 z" e - }8 {8 V3 t- _1 \8 q4 m1 \
- }
. r( K, T- S* T: @) q7 k# @ v - return RxBuffer;# s7 |+ t$ l4 o: W, V: s
- }
复制代码
7 \( H3 f0 P" N3 W% @- f这是I2C读两个字节的 程序,主要写单个字节的时候需要取地址(®_Address),由于这个HAL_I2C_Master_Transmit()这个函数的输入参数,数据那一项是一个指针,所以如果传单个字节必须取地址,有一个PDF文件介绍了HAL库函数的使用,但是全英文的,可以看看提高自己的英文水平,主要的两个I2C函数都在这里,可以直接调用HAL 的API,用起来非常方便!2 E, S# J; n# {7 {* V, w
- void LCD_Send_Data(unsigned char Data)7 c/ |8 j! W% b \3 |" i0 L
- {0 F) B% \5 B4 |8 g& E2 i
- LCD_CS_L();) m* m! S7 s0 {% M8 k5 Q8 q# J- Q1 Y
- LCD_DC_H(); 0 E0 X: F- ]6 d$ I$ `% G+ ]0 E
- HAL_SPI_Transmit(&hspi1,&Data,1,100);. L8 H$ f( d% \) J
-
) ]7 I% N# l0 ^' ` - LCD_CS_H();, M2 u7 g% \9 c7 I7 B& y% w& U% R/ R" ^
- LCD_DC_H();
# i" y: F3 ^% G$ U1 Y9 Q% `. G( ` - }, C5 C+ o/ D! Q2 w
- void LCD_Send_CMD(unsigned char CommandByte)
1 a0 Q% D2 {& x9 t - {
+ ^1 {! u* I: O6 Q* T8 @! x - LCD_CS_L();
: L* c3 A* x V$ h L - LCD_DC_L(); + _8 y. R7 q7 x7 h
- HAL_SPI_Transmit(&hspi1,&CommandByte,1,100);
. N8 p0 g! |8 u2 }( u, x" W! G0 a. b - LCD_CS_H();
; V9 m! M/ j4 V/ ]! ]8 ? - LCD_DC_H(); 0 [: n' L6 \9 h6 z I' z C( l7 [
- }
复制代码 % ^7 D" e! ^; Q4 ^9 t
这是SPI的写函数,一个发命令,一个发数据,也是调用了HAL的API HAL_SPI_Transmit()这个函数,同样注意发一个字节的时候也要去地址
8 o* C8 _! P7 t5 `主要的东西都完成了,只要把对应的LCD驱动和I2C设备的驱动复制过来,然后把读写接口对上,工程就完成了。$ {4 R6 Q) g& P
本来自己的程序没有问题,但是调试的时候发现I2C一直卡死,还以为时出现了I2C,郁闷了一段时间,其实是自己没看电路图,造成视觉上的蒙蔽
; i$ h5 r7 [& i6 }
6 i' @; `# j, m+ e( t4 f1 F) W有没有人以为这里就是对应的SCL和SDA,我之前一直把SCL和SDA插在这里,结果I2C就一直卡死,表示自己给自己眼睛坑了,结果去查电路图才发现
- D$ Z5 F5 L( P( E6 M
4 K) C; {) b2 ]. M9 @. n6 dSCL和SDA分别是第二排和第三排靠内的那两个,换下接口后I2C就立马工作了,表示自己在这个上面把自己坑了半天........' H# z; C6 f$ p. v
STM32F0çHALåºç¨æ·æå_é¨å1.pdf
(6.34 MB, 下载次数: 1865)
|
我的IIC也显示为“FF”,原因是每次断电或复位产生的信号干扰被误读。
木有放弃啊,已经出来了,F7现在都支持了. h! d" P: f4 f4 c5 v* Y
http://www.st.com/web/en/catalog ... _searchtype=keyword
已解决,cube设置错误,把SPI定义成了单发。