你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F7 硬件IIC驱动

[复制链接]
STMCU小助手 发布时间:2021-12-11 12:00
目前只实现了主设备模式,一般也只用到主设备模式,IIC如果不能使用硬件方式,读取大量数据的时候效率很大,由于只有1个字节的缓冲区,根本不能使用中断模式(实际使用过程中,IIC会造成100us以内间隔的中断,单片机根本扛不住的),所以建议数据少就直接阻塞,1个字节也就几十us,数据多直接用DMA,将线程阻塞,等待DMA传输完成,而不会阻塞CPU(上传的代码没有实现DMA部分,便于理解)。
, F# s& C4 L, _% h" P0 |' i. q* @2 C( g) w; q
目前已经做了完善的错误处理,读写操作前都会清除中断,遇到错误会软复位,所有位置均做了超时处理,防止程序卡死,目前只测试了几个字节的读写,大量的,长时间的读写均表现稳定,目前手上开发板没有eeprom,无法做大数据的连续读写,如果你在使用过程中遇到问题,欢迎指正。
% A/ y8 l/ k1 q3 j! q  r' B" j2 v% u- O$ M- {" U
下面是IIC读写的时序例子,可以先熟悉一下,这样比较容易上手,哪一个环节出了问题也要调试。
% c  i- f/ q* Z- K1 ^' c, H" \7 d/ L# P- g, x; Z1 }) @
20200216194202434.png
" `* Q; X9 @7 R, d+ F3 p4 f. {
4 K  S2 w# O6 a
20200216194219185.png

' C/ Z# J2 ^# r4 |
1 P* D! z: I4 P) h8 O4 s: T/ ~6 y
20200216194234908.png
7 C* E+ y. C; T
! g" \8 N$ J& d" Z
/ A% u: _" E, o8 B. C( r- K4 ?
下面简要说明一下STM32F7硬件IIC的驱动设计方式(建议先百度学习一下IIC的时序要求):
/ t9 c3 _8 R% e' X9 d
; L+ N0 f1 r9 @* |' l, T[基本的初始化]& E: ]; E( n% G8 A, R/ j* e

  P/ h  p) b) Y- }1.初始化IIC时钟,IO(IIC IO必须设置为复用开漏输出,这个很重要)。
8 f3 h! Q; `) E8 x1 U  _% P
) H5 x5 ]; B! W. g$ c9 R, T9 b2.CR1先赋值为0,复位IIC.
% W) p1 {! x6 ^* H& @# Z$ p8 j% Z  H9 r4 `. l3 W- [
3.除了TIMINGR寄存器需要自己计算设置好,其余寄存器全部复位为0! S4 v- L( V2 ~: w7 y- T

% _) @* o& }8 e4.设置CR1使能IIC。/ M* h6 T: a4 Y

! O1 W5 ~  N( w注意:上面说到,IIC的IO必须初始化为复用开漏输出,我之前初始化为复用推挽输出,测试很久,只要一启动传输,就会立马收到NACK,然后是STOP中断,数据根本没法发送,弄了好久才发现是这个IO初始化的问题。
9 y. J" X7 j5 n' L4 C+ Y! z+ z
3 G" e& q! f" a) W2 d% g5 T3 ~0 C! Y

; J: V+ R8 V( Z; m[读取]- d# _9 ?, I! U+ U1 h

' F% V' Y% V$ N1.检查总线是否忙,如果忙的话可以根据你的需要时推出还是直接复位总线,清除中断状态。1 `; Q# m; i" q' ^

1 b8 v: v% b/ C2.设置CR2寄存器,从机地址,待写入数据长度(就是后面要发送的寄存器地址长度,通常1-2字节)软件STOP,写模式,启动传输。
. u; d" |. U  k& u  j! o' m3 t% S! B7 X. D0 F2 h% t1 w$ I+ n
3.等待TXIS置位,然后写入1字节的寄存器地址,如果寄存器地址有2个字节,重复上面过程。4 b+ K$ |/ p# y( d' |

2 w5 d4 Y: m' ^$ Q0 |4.等待TC置位,意味着上面的1-2字节的寄存器地址以及写完成了。/ D( {! d) F6 o  G0 v0 m% r
6 L8 O- t/ h# P/ ]" ]
5.根据要读取的数据长度,去设置CR2寄存器,由于一次最大只能读取255字节(计数器只有8位),如果超出了就要分多次,这里有2种情况,如果当前是最后一包,则将自动STOP使能,RELOAD禁止;如果后面还有数据要发送,则将RELOAD使能自动STOP禁止;这2个是二选一的,而且RELOAD优先级高一些。* s& u4 h) \+ ]

! i9 s6 Z- g( y6 j1 P6.设置了从机地址,要读取的数据长度,之后设置方向为读取,然后启动START(从写切换到读要重新发送START,这个跟软件模拟是一模一样的)。
. `: L/ V" W3 f& F  P3 ~2 j1 C: n+ l* X% C* L0 L
7.循环一个字节一个字节的读取数据,字节读取需要等待RXNE有效,只有读取RXDN寄存器,直到所有数据读取完成。
6 j( K0 l6 _; k* }0 U7 A; |# f! \5 S: U8 I0 ^; [3 z2 _
8.读取完成后等待STOP有效,因为前面在最后一包数据读取的时候使能了自动STOP,这个时候检查STOP是否生成。- a, ^2 ~: k$ q8 |
/ e5 ]0 ?: E8 u; m3 B
9.需要注意的是,所有的操作都要给超时,并且是自己可控的,绝对不要有死循环,之所以一直说STM32的IIC死机很大程度上都是由于这个地方没有涉及好,我的程序设计方法是:一旦出现了异常,就复位IIC,如果不复位就会导致下次进去的时候IIC一直忙,因为还处于上一个通讯过程。  T- X5 \% t9 o. b+ r7 V
+ C' i( w4 M; m: V$ K8 a

5 y% B& Q/ F( ?( f0 o/ W; _9 @& N1 `' G
[写入]! j1 B# }# a. K0 A" J, ~: W* S

+ ^5 o* h3 g8 v! w/ }, u5 w1.检查总线是否忙,如果忙的话可以根据你的需要时推出还是直接复位总线,清除中断状态。
* p9 N" S  F1 [3 J) q) Q6 v1 X; M& {; b' W/ e
2.设置CR2寄存器,从机地址,待写入数据长度(就是后面要发送的寄存器地址长度,通常1-2字节)自动重载,写模式,启动传输。
0 F, C, N/ [( t5 E5 _/ R. ^6 V+ U& ^. X+ b$ j
3.等待TXIS置位,然后写入1字节的寄存器地址,如果寄存器地址有2个字节,重复上面过程。
7 J; L$ ?) k$ `$ [+ f% {( \
2 q, X  l9 z% n! S+ R4.等待TCR置位,意味着上面的1-2字节的寄存器地址以及写完成了,已经发生重载了,后续可以继续写入数据了。8 d" o3 y4 f9 y6 C: L& `
8 F# e0 r, r9 x0 I: W  V. v% j" b
5.根据要写入的数据长度,去设置CR2寄存器,由于一次最大只能读取255字节(计数器只有8位),如果超出了就要分多次,这里有2种情况,如果当前是最后一包,则将自动STOP使能,RELOAD禁止;如果后面还有数据要发送,则将RELOAD使能自动STOP禁止;这2个是二选一的,而且RELOAD优先级高一些。2 |% x/ }) F8 e

0 T& n3 \' i' g- ?2 J6.设置了从机地址,要写入的数据长度,之后不用切换方向,不用启动START(都是写,不用重复发送START,这个与读取有区别)。
2 Q3 ~/ a* _2 X" Y9 Z& Q, q- i+ P0 \+ ?  F  `. w6 e3 u7 s( M
7.循环一个字节一个字节的写入,字节写入与步骤3一样,等待TXIS置位,就可以写入数据到TXDR。( h! R+ W; p# L4 v$ C7 S) E

. F, |; O; j2 F, E, v& @0 o8.等待STOP有效,因为前面在最后一包数据写入的时候使能了自动STOP,这个时候检查STOP是否生成。3 a4 M6 R, X3 ^: P
9 e' @8 u9 }( k" R  y* L) X
9.需要注意的是,所有的操作都要给超时,跟读取一样。
! W' F3 O2 h( o6 R* [: A3 h" T6 ]8 N! ]" |4 p" @% ^) T

1 d( p( q( c  e6 C& X
. N; R1 {9 Y6 z注意:IIC的读取实际很短,超时也不用给很长,以标准的100KHz通讯时钟速度,一个字节大概在90us左右,超时可以给个5-10B时间,也就是450-900us左右。
; U$ W, m  ^( t: P/ k
+ n. ^/ ~4 T2 H2 M3 X& g1 y3 v# U+ K! c* H! b. h

9 [, ]* z* ]3 \# ]好了说了这么多,具体的看代码中的注释,直接上代码(我只测试过I2C3,其余的理论上都是一样的,就是IO初始化部分有区别,别的通道没有硬件进行测试)- v6 m& d5 _& i; @: u

% k. H- J/ T3 Q' |# @
  1. /*************************************************************************************************************
    8 R: i( R1 s7 Z1 P
  2. * 文件名                :        stm32f7_iic.c
    # U; r- k& J- B* W& `! @
  3. * 功能                        :        STM32F7 IIC接口驱动) l  `$ U/ O5 Q! S1 u# v4 @: P
  4. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>5 O, \, L; C6 e9 z  E# F9 L1 K
  5. * 创建时间                :        2020-02-09
    7 k3 Q, ^- ]# ?9 f* M8 }% R
  6. * 最后修改时间        :        2020-02-093 y$ }% e* I6 @/ r) @% T) E
  7. * 详细:                        只支持主机模式,7bit地址,默认APB1为IIC提供时钟# t7 v" y% L, ^+ x; X7 w' T
  8.                                         涉及到读写1字节的超时时间是us,其余的是ms
    - o7 O; N$ R0 F5 U
  9.                                         注意:IIC的IO必须初始化为复用开漏输出。& y# D% X" l" l! \8 D
  10. *************************************************************************************************************/        
    ! f5 H) V, C6 X& H: J! j" u
  11. #include "stm32f7_iic.h"- _7 A# v; m9 `, v! }/ C
  12. #include "system.h"
    5 a: h/ B# B& ^7 G2 O4 y; E
  13. #include "dma.h"
    ' h+ W& h) b& `; e5 Q' f

  14. 1 _9 k3 v8 z) P' S: Y$ X# D" Z
  15. #define IIC_FLAG_MASK  ((uint32_t)0x0001FFFF)        //中断标志掩码
    ! V1 P& R1 c2 r7 ]" L
  16. . B% v- r. j* Q, M( T4 u$ j1 B. z
  17. //自动结束或自动重载设置(重载与自动结束只能二选一,或者都不选)
    % a4 e, H6 R2 i; S$ W! y
  18. typedef enum
    " d: ?! Z0 [, C
  19. {! k4 s/ h) `) z# {8 {9 U6 P
  20.         IIC_SOFTEND_MODE                =        0,        //手动结束,并不开启重载7 i. y" T$ i) V0 d( v7 W) I* v
  21.         IIC_AUTOEND_MODE                =        1,        //自动结束,用于最后一次通讯完成后自动发送STOP结束通讯
    1 r0 e7 e4 B  U5 l
  22.         IIC_RELOAD_MODE                        =        2,        //后续还有数据,本次通讯后自动重载,重新设置后继续通讯
    ( A2 \% k2 m& V; c! [
  23. }IIC_RELOAD_END_MODE;$ f( ?6 [- k' s+ u1 ^/ t# s
  24. % s6 Z2 ~# A* h+ E$ Y
  25. //读写与开始模式控制
    ' R* v% [5 i4 a3 l" O* @% R
  26. typedef enum
    9 r2 B: ]- Z; Y7 Z, \7 H
  27. {; L. V" H+ y6 o% c  ~
  28.         IIC_NOSTART_WRITE                =        0,        //没有开始的写-用于后续数据的写入$ h4 ?2 x' J5 [  [) A: _# k
  29.         IIC_NOSTART_READ                =        1,        //没有开始的读-用于后续数据读取
    % e4 [1 y! S7 \- ]# O
  30.         IIC_START_WRITE                        =        2,        //生成开始写-用于通讯开始时,写地址或数据. l2 R( |6 x$ i8 \; q. S0 W' Z$ ^( a
  31.         IIC_START_READ                =        3,        //生成开始读-用于读取数据时切换到读取方向,并读取后续数据
    & D* E$ _8 t/ X9 z* S- t
  32. }IIC_START_WR_MODE;4 d. Y; q# m  y, H1 g
  33. 3 T# x* Z+ d* V0 e2 ^* T# I4 E
  34. //IIC句柄
      n- U8 w5 D8 I# O4 J0 A3 x7 S
  35. typedef struct6 m8 \+ s+ Y( L2 t& d( p2 G8 d
  36. {: S$ u0 F) j8 f) F- e
  37.         IIC_CH_Type ch;                        //当前通道( Z& D/ g6 m4 {; s1 _9 P. ^
  38.         I2C_TypeDef *I2Cx;                //当前通道外设结构体7 `# N) ?9 |* z; E/ [0 D6 Z
  39.         u32 TimeOutUs;                        //操作超时,单位us: U( G4 T3 ^* b/ C
  40.         u16 Speed_KHz;                        //通讯速度,单位KHz
    0 C4 _% J$ x9 R# H+ V/ F
  41.         bool isMasterMode;                //是否为主设备模式-目前只支持主设备模式* N0 e2 W" F: Q1 p- Y. p( y. u
  42. }IIC_HANDLE;' a. |" H4 Q% |' u" _
  43. & x! y) v$ Z; }1 O; n
  44. //IIC外设结构指针" a. x: E, s+ z/ p7 I+ s
  45. static const  I2C_TypeDef * const I2C_TYPE_BUFF[IIC_CH_COUNT] = {I2C1,I2C2,I2C3,I2C4};; q$ f1 j2 w9 k2 ]$ x4 j
  46. //IIC通道句柄定义
    ( D' c5 u$ z" J
  47. static IIC_HANDLE sg_IIC_Handle[IIC_CH_COUNT];
    * a; _3 D$ a) S% Y/ Z1 X0 P5 N

  48. 7 B' D/ T, @+ R& ~: ]6 o+ D7 e
  49. //发送NAK& s7 o# Y! b$ A7 Q5 B
  50. //static __inline void IIC_SendNAK(IIC_HANDLE *pHandle) {pHandle->I2Cx->CR2 |= BIT15;}
    8 ~4 F+ Q- _* ~' m( I; J
  51. //发送STOP
    3 j% T( A  n5 d0 _, ~. v
  52. static __inline void IIC_SendStop(IIC_HANDLE *pHandle) {pHandle->I2Cx->CR2 |= BIT14;}3 o6 d. u+ m8 A0 ^  t# M
  53. //发送START- u% e1 q0 e( h. a9 Q* E
  54. //static __inline void IIC_SendStart(IIC_HANDLE *pHandle) {pHandle->I2Cx->CR2 |= I2C_CR2_START;}/ n" S* T( e, h* G4 C* Y% ?' B
  55. //获取中断状态2 w6 c2 B" _! g
  56. static __inline u32 IIC_GetISR(IIC_HANDLE *pHandle) {return pHandle->I2Cx->ISR & IIC_FLAG_MASK;}$ A5 n8 c' t4 ~; [/ a  d
  57. //清除中断状态
    $ V! i; G6 r9 Q
  58. static __inline void IIC_ClearISR(IIC_HANDLE *pHandle, u32 IsrFlag) {pHandle->I2Cx->ICR = IsrFlag & IIC_FLAG_MASK;}
    & j$ T  F) b+ e* C
  59. //复位CR2寄存器7 c& j, O* ^9 @( D& D9 R
  60. static __inline void IIC_ClearCR2(IIC_HANDLE *pHandle) {pHandle->I2Cx->CR2 = 0;}+ E& ~+ i  C& X+ m2 V5 D% A9 V- a
  61. 2 g/ X! g0 p: X& ^. u- U$ O
  62. static void IIC_SoftReset(IIC_HANDLE *pHandle);//硬件IIC软复位(会使能IIC)
    ( }% X. b* S" E5 a- ]+ l& M# U
  63. static u32 IIC_CalculationTiming(u16 Speed_KHz);//硬件IIC时序计算- x' ]- w. R/ v3 \7 P
  64. ! \$ Q3 f2 X, }. B) [

  65. ; ?6 u. [* m- u. n
  66. /*************************************************************************************************************************) ^3 k, \. P0 u5 s( r
  67. * 函数        :                        bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs)2 @4 J* n+ E3 g. u
  68. * 功能        :                        硬件IIC初始化7 p, d) e2 I8 a, z4 y
  69. * 参数        :                        ch:IIC通道;Speed_KHz:速度10-1000(如果速度是100,则按照SMBUS时序);TimeOutUs:操作超时us(0:自定计算超时)
    6 F# P# J% c+ y6 w
  70. * 返回        :                        IIC_ERROR
    2 S. E/ ^% F3 j7 R9 x* Q. P
  71. * 依赖        :                        底层宏定义& E& }) O4 A/ X
  72. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    5 q1 _. I' y. v2 g! W+ f/ q: E
  73. * 时间        :                        2020-02-15
    + a5 z8 D1 L9 h1 o
  74. * 最后修改时间 :         2020-02-15
    9 p8 s3 ^4 |7 G8 Q
  75. * 说明        :                         速度只是个大概的计算值,设置为100KHz时会严格的按照SMBUS时序,其余的不保证SMBUS兼容,正常情况下只要时钟速度符合要求,3 i9 w# ]. |: @* h& b* q, y+ Q/ h+ J
  76.                                         时钟上升沿到来前数据以及稳定的切换了即可保证通讯稳定性
    & x8 x4 U& O0 \
  77. *************************************************************************************************************************/
    , I$ G. e3 g# Y' a
  78. bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs)
    * z1 q# U9 @) a- Q1 Y
  79. {! W3 N0 y4 Q/ T
  80.         SYS_DEV_CLOCK DevClock;  q6 V7 r; U9 g4 g! M) |: [1 n
  81.         IIC_HANDLE *pHandle;
    $ w  r! ^  S0 y+ j' T2 o
  82.         
    2 q) |( x7 l" [3 w: X: D; W/ W) {1 Y# X
  83.         switch(ch)
    * D# v3 A& d. N7 J% X7 A
  84.         {
    ! ~" A, {$ V+ C# ?
  85.                 case IIC_CH1        :        //IIC1
    - V% c' T! [* H; I2 R4 `
  86.                 {
    * p; l9 W( O+ G, M- L
  87.                         RCC->DCKCFGR2 &= ~(0x3 << 16);        //清除设置,使用APB1作为时钟源
    # O6 g! E4 @' R. J% J+ v% }
  88.                         DevClock = DEV_I2C1;
    ' O$ N2 G! |. M% M+ `$ ]
  89.                         //初始化I2C IO; `" D. y( K( B7 a
  90. #if(IIC_CH1_IO_SELECT==IIC_CH1_PB6_7)        //I2C1        使用PB6/7  T, m  }4 z; M7 k! }$ M  c
  91.                         SYS_DeviceClockEnable(DEV_GPIOB, TRUE);                                //使能GPIOB时钟
    " @, y4 R6 i/ I4 z$ q% L
  92.                         SYS_GPIOx_OneInit(GPIOB, 6, AF_OD, SPEED_25M);                //PB6
    % ^$ {4 z; e' h4 g; j
  93.                         SYS_GPIOx_OneInit(GPIOB, 7, AF_OD, SPEED_25M);                //PB7
    " B+ |  B" O! y0 B" z
  94.                         SYS_GPIOx_SetAF(GPIOB, 6, AF4_I2C1);                                //AF4# d* L  g) J! V& E
  95.                         SYS_GPIOx_SetAF(GPIOB, 7, AF4_I2C1);                                //AF4: g& R+ K+ u: @( E, U
  96. #elif(IIC_CH1_IO_SELECT==IIC_CH1_PB8_9)        //I2C1        使用PB8/9
    0 \5 L0 o3 E; S3 j
  97.                         SYS_DeviceClockEnable(DEV_GPIOB, TRUE);                                //使能GPIOB时钟, S0 x4 p- Z2 o1 d' H4 V" J: W
  98.                         SYS_GPIOx_OneInit(GPIOB, 8, AF_OD, SPEED_25M);                //PB8$ c; ?3 E% t& s7 s# A
  99.                         SYS_GPIOx_OneInit(GPIOB, 9, AF_OD, SPEED_25M);                //PB9
    0 `& l! L# G! ~' s% B
  100.                         SYS_GPIOx_SetAF(GPIOB, 8, AF4_I2C1);                                //AF4* G! R: H$ Q1 I7 K
  101.                         SYS_GPIOx_SetAF(GPIOB, 9, AF4_I2C1);                                //AF4- H) L/ a% F6 R3 i2 O+ N
  102. #else8 R; b) O/ A9 W9 ^2 c6 q
  103.                         #error("无效的I2C1 IO选择");, ]  F* N! F( y# B
  104. #endif //IIC_CH1_IO_SELECT3 G" R3 d+ R, w5 [% b9 k  K
  105.                 }break;
      W1 p% f- \9 ^' q0 p' z$ v
  106.                 case IIC_CH2        :        //IIC2+ l% d" \& {2 P5 a3 ]/ z7 X
  107.                 {
    3 ?2 W0 f/ ^) ]/ ^1 c
  108.                         RCC->DCKCFGR2 &= ~(0x3 << 18);        //清除设置,使用APB1作为时钟源
    + I" J" t, r1 r
  109.                         DevClock = DEV_I2C2;
    # d  @) X: `$ w4 g
  110.                         //初始化I2C IO
    : [% c9 H2 w. ^: ?
  111. #if(IIC_CH2_IO_SELECT==IIC_CH2_PB10_11)        //使用PB10,PB11
    ; o& M% z! t+ s) ~! K. j
  112.                         SYS_DeviceClockEnable(DEV_GPIOB, TRUE);                                //使能GPIOB时钟/ @: n, M+ {6 R3 W! c$ [
  113.                         SYS_GPIOx_OneInit(GPIOB, 10, AF_OD, SPEED_25M);                //PB108 U- c. T$ U# j0 U5 \+ o/ a
  114.                         SYS_GPIOx_OneInit(GPIOB, 11, AF_OD, SPEED_25M);                //PB11
    1 O+ P! X2 a8 Q, h
  115.                         SYS_GPIOx_SetAF(GPIOB, 10, AF4_I2C2);                                //AF4( R8 {; D( ?  w1 q  K
  116.                         SYS_GPIOx_SetAF(GPIOB, 11, AF4_I2C2);                                //AF4
    2 ]6 G8 E& E8 V- O; r; z3 S
  117. #elif(IIC_CH2_IO_SELECT==IIC_CH2_PF0_1)        //PF0,PF1
    / h( ]0 Z$ o4 ~5 m
  118.                         SYS_DeviceClockEnable(DEV_GPIOF, TRUE);                                //使能GPIOF时钟( s8 |: c& m1 @7 l1 K' y
  119.                         SYS_GPIOx_OneInit(GPIOF, 0, AF_OD, SPEED_25M);                //PF0
    2 c0 y$ n2 p0 I7 [
  120.                         SYS_GPIOx_OneInit(GPIOF, 1, AF_OD, SPEED_25M);                //PF1" P' t! S& ^8 k% ~1 x3 ]4 W
  121.                         SYS_GPIOx_SetAF(GPIOF, 0, AF4_I2C2);                                //AF4
    2 p; y  b: u* Y+ `; b+ R6 U9 V
  122.                         SYS_GPIOx_SetAF(GPIOF, 1, AF4_I2C2);                                //AF4
    , K( ^8 g  I" @0 C8 c3 B% w
  123. #elif(IIC_CH2_IO_SELECT==IIC_CH2_PH4_5)        //PH4,PH5
    " N2 \$ g) X: c
  124.                         SYS_DeviceClockEnable(DEV_GPIOH, TRUE);                                //使能GPIOH时钟
      k6 M, ^, M: W; G/ A; K* C# ~4 b
  125.                         SYS_GPIOx_OneInit(GPIOH, 4, AF_OD, SPEED_25M);                //PH4
    / m$ i9 d3 N! P2 a& w
  126.                         SYS_GPIOx_OneInit(GPIOH, 5, AF_OD, SPEED_25M);                //PH5& M" g% A& @7 j% b" @
  127.                         SYS_GPIOx_SetAF(GPIOH, 4, AF4_I2C2);                                //AF4
    ; W1 p% p2 ?( v9 Y
  128.                         SYS_GPIOx_SetAF(GPIOH, 5, AF4_I2C2);                                //AF4                        
    % z2 _) O" |) f" P7 s4 y
  129. #else
    3 e5 Y0 N" D" X, S: }
  130.                         #error("无效的I2C2 IO选择");& a" Y0 |# l$ J1 q7 S8 m- U- K
  131. #endif //IIC_CH2_IO_SELECT) ?/ h& W* ~/ |& f/ M
  132.                 }break;                        ) ~( _. ?* S: R# A1 ~
  133.                 case IIC_CH3        :        //IIC3
    - e/ w) D& f' l3 _  b
  134.                 {7 O  G3 w2 a9 r
  135.                         RCC->DCKCFGR2 &= ~(0x3 << 20);        //清除设置,使用APB1作为时钟源( z7 z  ?: m( ^" l) g$ V" ~9 U* m
  136.                         DevClock = DEV_I2C3;
    + X! v9 g7 m  u2 l$ o  T% [& N
  137.                         //初始化I2C IO
    2 e9 ~+ }0 j4 b  @0 L
  138. #if(IIC_CH3_IO_SELECT==IIC_CH3_PH7_8)                //PH7,PH8' w8 h, K/ b7 x: j7 j
  139.                         SYS_DeviceClockEnable(DEV_GPIOH, TRUE);                                //使能GPIOH时钟
    ; X  U6 \* t5 o7 j
  140.                         SYS_GPIOx_OneInit(GPIOH, 7, AF_OD, SPEED_25M);                //PH7) r$ V* {% a* q4 W5 w; H
  141.                         SYS_GPIOx_OneInit(GPIOH, 8, AF_OD, SPEED_25M);                //PH8
    - c1 Y2 z& L# r/ \8 X; }
  142.                         SYS_GPIOx_SetAF(GPIOH, 7, AF4_I2C3);                                //AF4
    ( z$ D' n9 s1 Q
  143.                         SYS_GPIOx_SetAF(GPIOH, 8, AF4_I2C3);                                //AF4
    + r+ E7 C& j, N3 `# o: `/ c
  144. #elif(IIC_CH3_IO_SELECT==IIC_CH3_PA8_PC9)        //PA8,PC9
    ) W) N8 k/ z; {6 Q
  145.                         SYS_DeviceClockEnable(DEV_GPIOA, TRUE);                                //使能GPIOA时钟. Z) {/ g# R6 R. ?5 g
  146.                         SYS_DeviceClockEnable(DEV_GPIOC, TRUE);                                //使能GPIOC时钟# L  c! H9 r9 y% d. F2 K1 B
  147.                         SYS_GPIOx_OneInit(GPIOA, 8, AF_OD, SPEED_25M);                //PA8
    * g3 U7 S% z/ n6 r3 A. E
  148.                         SYS_GPIOx_OneInit(GPIOC, 9, AF_OD, SPEED_25M);                //PC9
    % [  |3 L$ e' F$ K7 O
  149.                         SYS_GPIOx_SetAF(GPIOA, 8, AF4_I2C3);                                //AF46 c. l$ R  O; j) F0 ^* d
  150.                         SYS_GPIOx_SetAF(GPIOC, 9, AF4_I2C3);                                //AF4                  n0 }6 |) V- G4 C, G2 X
  151. #else4 I) w  K( c$ t7 \$ p/ e
  152.                         #error("无效的I2C3 IO选择");
    ( |# E. n1 y( z; t5 f3 D2 t) F. O
  153. #endif //IIC_CH3_IO_SELECT                        
    4 w1 N2 g' ^$ w8 b: `
  154.                 }break;                        8 d1 e7 r, _' V: X' N4 O
  155.                 case IIC_CH4        :        //IIC4
    1 r) I, l) ?3 H+ d  j* {6 C
  156.                 {5 U$ \% M$ S- {1 x9 I% L6 `7 M$ q
  157.                         RCC->DCKCFGR2 &= ~(0x3 << 22);        //清除设置,使用APB1作为时钟源1 P) n# F. p% F+ Q
  158.                         DevClock = DEV_I2C4;# v) ]& b9 c) v9 J9 F* X! p
  159.                         //初始化I2C IO
    2 [4 o  F- B5 R1 o- U, q! l& b8 F
  160. #if(IIC_CH4_IO_SELECT==IIC_CH4_PD12_13)                //PD12,PD13
    + m6 E/ i$ ~( k% v
  161.                         SYS_DeviceClockEnable(DEV_GPIOD, TRUE);                                //使能GPIOD时钟6 ~* w  y# j6 y2 p2 Q7 _, V
  162.                         SYS_GPIOx_OneInit(GPIOD, 12, AF_OD, SPEED_25M);                //PD12
    # E, Y2 r3 |, r
  163.                         SYS_GPIOx_OneInit(GPIOD, 13, AF_OD, SPEED_25M);                //PD13
    ( l, f$ G% @8 t& C( ?( {
  164.                         SYS_GPIOx_SetAF(GPIOD, 12, AF4_I2C4);                                //AF4% D7 x) P1 ]  R9 J2 ?
  165.                         SYS_GPIOx_SetAF(GPIOD, 13, AF4_I2C4);                                //AF4
    ! I; J8 h4 {3 w0 Y) s% P
  166. #elif(IIC_CH4_IO_SELECT==IIC_CH4_PF14_15)        //PF14,PF15
    * E1 `6 E7 T& m7 u  w/ b+ N0 n
  167.                         SYS_DeviceClockEnable(DEV_GPIOF, TRUE);                                //使能GPIOF时钟
    7 x* o  x6 `: I
  168.                         SYS_GPIOx_OneInit(GPIOF, 14, AF_OD, SPEED_25M);                //PF14. d0 K/ e2 T# X" B/ l% p  [
  169.                         SYS_GPIOx_OneInit(GPIOF, 15, AF_OD, SPEED_25M);                //PF15' g; u3 W# ]4 U9 l+ d* \
  170.                         SYS_GPIOx_SetAF(GPIOF, 14, AF4_I2C4);                                //AF4
    % Q6 O* E1 o+ N% r9 Z
  171.                         SYS_GPIOx_SetAF(GPIOF, 15, AF4_I2C4);                                //AF4$ @. @7 s+ ^7 i' c0 X, T
  172. #elif(IIC_CH4_IO_SELECT==IIC_CH4_PH11_12)        //PH11,PH12
    ; L" u- o. V6 O$ M
  173.                         SYS_DeviceClockEnable(DEV_GPIOH, TRUE);                                //使能GPIOH时钟7 A7 o5 u3 N; K& `" X, W+ k
  174.                         SYS_GPIOx_OneInit(GPIOH, 11, AF_OD, SPEED_25M);                //PH11' v! F1 P, j' m3 b3 i) @9 K  N
  175.                         SYS_GPIOx_OneInit(GPIOH, 12, AF_OD, SPEED_25M);                //PH12
    1 E, S. H, J3 x  e# H4 D2 B
  176.                         SYS_GPIOx_SetAF(GPIOH, 11, AF4_I2C4);                                //AF4& b: r: E6 ]! n6 a- D
  177.                         SYS_GPIOx_SetAF(GPIOH, 12, AF4_I2C4);                                //AF4                        
    8 U9 q+ a7 `( m7 L
  178. #else: ~' t1 n8 T5 w- l+ m
  179.                         #error("无效的I2C4 IO选择");
    9 E& d+ l( ]& j8 m* Q" N. J, m
  180. #endif //IIC_CH4_IO_SELECT                        
    - P; ]2 R) B, M5 f
  181.                 }break;( Q% f/ r- N, p+ x6 Q8 B
  182.                 default:
    ( Z+ T5 K  I$ h; \9 u( R+ K
  183.                 {& O6 g! N3 Z( S" g  M" O! }
  184.                         DEBUG("初始化IIC失败:无效的IIC通道%d\r\n", ch);
    ; t5 }( o1 s( b/ J
  185.                         return FALSE;
    # X4 A. C# t* e% S: K
  186.                 }% a4 Z, h/ g& Z( d/ r/ e
  187.         }- _" G: Q- s7 d$ x
  188.         pHandle = &sg_IIC_Handle[ch];                                                        //获取相关通道的句柄0 n  Z9 c( v& o" Q1 }' P
  189.         if(pHandle == NULL)& s- M- H/ D% \
  190.         {4 ]  b& J# m: E/ t2 ?+ [/ D
  191.                 DEBUG("初始化IIC失败:无效的IIC句柄\r\n");
      o! ^: D+ R. M4 z2 V3 n
  192.                 return FALSE;
    / ?+ G& N) F; b
  193.         }
    ; U, X8 Y0 V$ S
  194.         
    7 d9 ~5 G( d2 L
  195.         SYS_DeviceClockEnable(DevClock, TRUE);                                        //使能时钟
    ; V5 F! N& b) x9 |+ H6 ^& v. _
  196.         SYS_DeviceReset(DevClock);                                                                //外设复位
    ' v( ~" {' R; @8 Y4 v8 _
  197.         pHandle->I2Cx = (I2C_TypeDef *)I2C_TYPE_BUFF[ch];                //外设指针: g9 w1 F0 y% O; F8 A
  198.         pHandle->I2Cx->CR1 = 0;
    7 d" q! d% v( z) V
  199.         Delay_US(1);                                                
      W: [. ~' {7 P, P/ Q
  200.         pHandle->I2Cx->CR1 |= 2<<8;                                                                //设置噪声滤波器,关闭所有中断
    5 t% k! \# p/ |& @3 C
  201.         pHandle->I2Cx->CR2 = 0;% P2 T' U" k& B
  202.         pHandle->I2Cx->OAR1 = 0;0 K7 J' w) {3 a$ V3 U' c
  203.         pHandle->I2Cx->OAR2 = 0;
    * |- V! U5 [6 o7 @8 V2 C0 y6 M
  204.         if(Speed_KHz > 1000) Speed_KHz = 1000;
    - K0 B% Q) Y. c
  205.         if(Speed_KHz < 10) Speed_KHz = 10;
    5 P+ E0 c3 g, q9 S( _' A
  206.         pHandle->Speed_KHz = Speed_KHz;                                                        //记录速度# Y5 \  j; c0 u2 x  A. b
  207.         if(TimeOutUs == 0)                                                                                //需要自动计算超时时间,时钟周期*10*10
    0 b. ^( g0 f9 I% Y) M
  208.         {
    3 y, @; K8 E" `0 G- \, [
  209.                 TimeOutUs = 1000/Speed_KHz;                                                        //时钟周期
    ' U: {4 Y1 t: ~
  210.                 TimeOutUs *= 10;                                                                        //字节周期7 |! J/ S" @' C
  211.                 TimeOutUs *= 10;                                                                        //超时时间为10个字节时间
    * e. Y* D/ ~3 [5 Z* n3 j
  212.         }
    8 t& C$ g9 S0 y; s+ b" N6 P
  213.         if(TimeOutUs < 3) TimeOutUs = 3;
    ' b; g; F3 e/ a& d) i
  214.         pHandle->TimeOutUs = TimeOutUs;                                                        //记录通讯超时时间$ c- M2 _6 e5 U, O: m+ X- V
  215.         uart_printf("IIC超时时间:%dus\r\n", pHandle->TimeOutUs);
    ) G$ j2 Z: |7 v5 \# p
  216.         pHandle->I2Cx->TIMINGR = IIC_CalculationTiming(pHandle->Speed_KHz);//0x40912732;                                        //时序, W1 M6 _: f$ V, X! t
  217.         pHandle->I2Cx->CR1 |= BIT0;                                                                //使能IIC  D' l& X% s' l  r4 h# f! o3 {
  218.         pHandle->isMasterMode = TRUE;                                                        //主设备模式8 E2 ]% _, A  ^9 v
  219.         Delay_US(1);
    + x6 l6 r5 I" I2 J. ~
  220. " ]! n1 B3 F0 j$ }
  221.         return TRUE;5 j) ], i7 Q4 }/ y
  222. }
    - Y; Z' H3 |( U+ V

  223. # \( n6 s7 J) u0 k$ |& @

  224. . J2 o/ u/ \0 ^3 i2 Y2 D
  225. /*************************************************************************************************************************& Z+ }, T  \3 }7 F0 _7 ?
  226. * 函数        :                        static IIC_ERROR IIC_isCheckNackFlag(IIC_HANDLE *pHandle, u32 TimeOutUs)
    ) z# Q7 `/ W3 Y+ O2 x9 |- f7 a1 y
  227. * 功能        :                        检查是否有NACK中断状态,如果有则清除掉1 x  Z, u! \  i5 z& \
  228. * 参数        :                        pHandle:句柄;TimeOutUs:超时时间,单位us
    ' P, {" G1 \( G, K! w' C: M
  229. * 返回        :                        IIC_ERROR7 h" ?9 |4 c" I
  230. * 依赖        :                        底层宏定义
    ; i3 c) A* k* ?4 G4 Y5 p- k
  231. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    6 [2 N: S. v) [( b1 q
  232. * 时间        :                        2020-02-15
    , j8 Z9 @2 X1 O7 J
  233. * 最后修改时间 :         2020-02-15
    9 C& V4 d; d, w' y& m# m4 {* n
  234. * 说明        :                         如果有NACK中断,则先产生停止位,然后清清除掉所有的中断,并复位IIC,然后返回错误2 F" x, e) e( b2 h# P7 @- w
  235. *************************************************************************************************************************/  
    ( Z& c2 S4 m  x
  236. static IIC_ERROR IIC_isCheckNackFlag(IIC_HANDLE *pHandle, u32 TimeOutUs)
    . q8 X+ ?1 V' b6 o2 `
  237. {
    . k  h% s' |1 u6 B1 M1 m
  238.         IIC_ERROR Error = IIC_OK;! r* J6 z; A" G" Y* o1 S% N7 F
  239.         ! }1 n5 n( E  g
  240.         if(IIC_GetISR(pHandle) & IIC_FLAG_NACKF)        //接收到否定应答标志& G7 A$ c8 d/ n/ E: J! `% @
  241.         {
    1 o5 V& q% E4 `& K7 j+ c
  242.                 uart_printf("NACK : IIC_isWaitTXIS:CR1=0x%X\t", pHandle->I2Cx->CR1);
    6 o' }. x9 ]% B. }. j0 d. U
  243.                 uart_printf("CR2=0x%X\t", pHandle->I2Cx->CR2);
    / I! F3 G+ d1 X' E) Z
  244.                 uart_printf("ISR=0x%X\r\n", IIC_GetISR(pHandle));7 Z  Y9 Y; S3 A; w1 x* u4 @  g9 U
  245.                 //主设备下,如果没有开启自动产生停止位,则手动产生停止位2 W; N3 q; h( W) l: {
  246.                 if(pHandle->isMasterMode && ((pHandle->I2Cx->CR2 & I2C_CR2_AUTOEND) == 0))
    , N9 b! s  f. o$ u) h, O+ R
  247.                 {
    . G' o2 A( h7 @
  248.                         IIC_SendStop(pHandle);                        //send stop
    9 v( d4 J. K. a# Y; b) A
  249.                 }
    # O3 ]; r. L+ A- u  U
  250.                 //等待STOP标志有效
    1 a# N1 `1 p2 C# q
  251.                 while((IIC_GetISR(pHandle) & IIC_FLAG_STOPF) == 0)1 x. U% U9 y) r6 h
  252.                 {
    ' }4 q2 k/ H' T( U6 w
  253.                         if(TimeOutUs == 0)                                //检查是否超时了* f2 D* o- C) w# J& h
  254.                         {
    " @+ u. [# _1 P! t( \  m' t: D" o
  255.                                 break;
    - d+ N9 c8 v& f1 }- T
  256.                         }                        ( {) x8 e0 U& \5 G
  257.                         TimeOutUs --;
    . R0 u: B) ]: H, w% [
  258.                         Delay_US(1);                                                //延时# [8 N) E4 s! ~2 T' Q
  259.                 }* j$ a: A* F" w; K# |6 m; t
  260.                 //清除相关的中断标志
    # y- k$ `2 e, T
  261.                 IIC_ClearISR(pHandle, IIC_FLAG_NACKF | IIC_FLAG_STOPF);        //清除NACK,STOP标志  x# e. Y" D: ]7 a* c. n1 `
  262.                 pHandle->I2Cx->CR2 = 0;                                                                                //清除CR2寄存器
    ( ~9 k" X! d6 b( F9 g
  263.                 IIC_SoftReset(pHandle);                                                                        //执行软复位
    * T5 F! P8 Y1 l/ k: z0 ]
  264.                 if(TimeOutUs == 0)                                                //没有超时,就是硬件通讯出错了5 w+ r9 ?; p6 l3 {' w; j
  265.                 {
    , ^, i2 J3 y- t: r7 O
  266.                         DEBUG("IIC发送stop超时\r\n");
    % d! \- |  N, T: Q& r+ T7 M7 J
  267.                         Error = IIC_TIMEOUT;                                //超时
    - i# j+ j1 s! f, |4 O( I
  268.                 }# U1 T* u+ e0 b( Y
  269.                 else
    + o" _8 G) t- R8 s. {
  270.                 {/ S  t1 P9 {; n  ~- C
  271.                         Error = IIC_HAL_ERROR;                                //底层错误
    8 z- J# X$ U  C$ m% P/ O; M
  272.                 }
    * }: C  i5 G; Z. _6 ^. a
  273.         }3 }# i) a# s7 J8 }9 H  t
  274.         
    / ~5 B' ~4 G4 c
  275.         return Error;
    ; Y1 m4 x% v6 F7 G% U4 |
  276. }! Q% R- q" r" D3 V0 t
  277. & m* A" D- F# B4 E5 ^
  278. ; e! v3 L7 y3 Q: _" Y
  279. 2 U: o7 |8 z2 Q9 i1 z# W
  280. /*************************************************************************************************************************
    ) `$ x( g2 B  |( U/ [( L
  281. * 函数        :                        static IIC_ERROR IIC_isWaitTXIS(IIC_HANDLE *pHandle, u32 TimeOutUs)
    " g5 {# o; E" Q8 W0 N9 n
  282. * 功能        :                        等待TXIS中断有效(等待 I2C_TXDR 发送寄存器为空)
    ' y! C' m! X1 a2 ^; Z9 a
  283. * 参数        :                        pHandle:句柄;TimeOutUs:超时时间,单位us
    5 F2 g3 n7 M, q( o
  284. * 返回        :                        IIC_ERROR% N1 W6 q% L" f' `# R( b! e: `4 Z
  285. * 依赖        :                        底层宏定义
    - ?  V( @7 e  p4 z6 ^- D4 F5 t/ K* ~
  286. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>, [) Q/ Z* s3 T$ M1 [0 K4 B
  287. * 时间        :                        2020-02-15
    5 o; R! U4 L- }: {5 D; d% l
  288. * 最后修改时间 :         2020-02-15; y4 z" L% O6 g9 H5 E3 G& U
  289. * 说明        :                         会先检查NACK中断,如果有NACK会直接退出的3 R) F  l; R5 d% S" |, u- N6 i* \
  290. *************************************************************************************************************************/  
    ) L( n; X2 f& M+ J
  291. static IIC_ERROR IIC_isWaitTXIS(IIC_HANDLE *pHandle, u32 TimeOutUs)
    : `1 T& ?' k4 y) ~9 J6 f" g2 f2 G
  292. {" z9 A* x* T) N' ~, r
  293.         //等待TXIS中断有效
    7 P" u6 S8 ?4 k
  294.         while((IIC_GetISR(pHandle) & IIC_FLAG_TXIS) == 0)
    0 S# f; B+ q( K7 l; k/ A! D+ f
  295.         {
    8 l+ P2 P  R( ~5 [, r& @
  296.                 //有NACK中断,进行处理
    & P$ \% A6 e1 w' p0 g
  297.                 if(IIC_isCheckNackFlag(pHandle, TimeOutUs) != IIC_OK)        * ]2 X2 \! H' ?
  298.                 {' P  m4 g+ H* a+ A
  299.                         DEBUG("检测到NAK错误\r\n");3 J1 g9 g& Q3 x+ a
  300.                         return IIC_NACK;
    0 \6 ]; f+ W( q
  301.                 }0 F/ h, r* h! H% |% Q3 L( L. e6 Z
  302.                
    ' k( Y" O& c9 ^6 v
  303.                 if(TimeOutUs == 0)                                        //检查是否超时了* G; @/ N! V. Q" W) {- w
  304.                 {
    ! J! i. U' D7 I0 j* a3 {, m) }. c
  305.                         uart_printf("IIC_isWaitTXIS:CR1=0x%X\t", pHandle->I2Cx->CR1);
    ' U5 C3 [) y; S* l8 R
  306.                         uart_printf("CR2=0x%X\t", pHandle->I2Cx->CR2);
    - n: I7 w: w( K" h
  307.                         uart_printf("ISR=0x%X\r\n", IIC_GetISR(pHandle));' t- R. F5 h+ X0 I$ o/ D; A+ c+ [
  308.                         
    2 ?/ {; v7 |; T; i/ f" v4 k
  309.                         IIC_SoftReset(pHandle);                //执行软复位
    3 W% x* c2 Z' z0 e; G
  310.                         return IIC_TIMEOUT;                                //超时
    , I- j6 u5 v$ N* `
  311.                 }                        
    8 i- C9 w% z$ g
  312.                 TimeOutUs --;% Y+ H' c  H! }6 `5 E3 P: S3 D: ]
  313.                 Delay_US(1);                                                //延时$ e$ }$ E3 I2 A5 B% P. I$ R0 U) a
  314.         }
    ; ]3 t" X3 X+ j% b
  315.         
    2 m; _, O! ]- R3 q
  316.         return IIC_OK;
    + d4 ~8 v8 z  h- `$ O) p; i9 k
  317. }: R: J. Q8 P( G
  318. ) O( w/ _! Z# ]$ U2 ?1 k

  319. 1 R7 O7 X6 ?5 G1 k* V
  320. /*************************************************************************************************************************' ?/ T( Z- f0 z& g4 s
  321. * 函数        :                        static IIC_ERROR IIC_isWaitSTOPF(IIC_HANDLE *pHandle, u32 TimeOutUs)
    . ?7 x2 T( i, o* [
  322. * 功能        :                        等待STOP中断有效(等待 发送结束 )
    & Z* b. q& M1 I0 h- G. `& F
  323. * 参数        :                        pHandle:句柄;TimeOutUs:超时时间,单位us5 u! I+ f' q1 ~; m8 e/ D
  324. * 返回        :                        IIC_ERROR
    1 D4 ^0 j2 {- |8 b, H+ ^; `# K
  325. * 依赖        :                        底层宏定义3 g3 O( s# ?: w  r. f6 k
  326. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>* H" l5 M$ Y: n: q
  327. * 时间        :                        2020-02-15
    : @0 n$ P9 m" x3 u1 O# q
  328. * 最后修改时间 :         2020-02-15
    % X1 ]# v9 p" }& p( A/ b
  329. * 说明        :                         会先检查NACK中断,如果有NACK会直接退出的$ y$ H7 e- s8 `' i! F/ @
  330. *************************************************************************************************************************/  
    * _' ^& u0 _8 q
  331. static IIC_ERROR IIC_isWaitSTOPF(IIC_HANDLE *pHandle, u32 TimeOutUs); J  }2 L0 k. g. Z+ x
  332. {  ]- b; i9 i! M. C  K5 `
  333.         //等待STOPF中断有效
    : o. O$ H# |2 B8 k; |; ?/ x: v
  334.         while((IIC_GetISR(pHandle) & IIC_FLAG_STOPF) == 0)
    % ?, x0 R3 `% m& U  S5 v' d
  335.         {
    " W# L. }# |4 `1 O
  336.                 //有NACK中断,进行处理
    ( @" L) j1 x/ I* N4 H( r; S+ x
  337.                 if(IIC_isCheckNackFlag(pHandle, 5) != IIC_OK)        0 f) @2 Y# S  r8 ?; m1 D
  338.                 {0 Y& K" a0 h7 ?, h( V4 |8 l! f/ E" Z
  339.                         return IIC_HAL_ERROR;
    + G/ I! ]# Y5 R! \
  340.                 }6 }1 l- A2 R' t
  341.                   e" |" o& a" p8 d( ~
  342.                 if(TimeOutUs == 0)                                        //检查是否超时了
    ( L; N3 _) U0 |) A8 f
  343.                 {  H% K' F3 N+ q7 s3 u$ i
  344.                         IIC_SoftReset(pHandle);                //执行软复位
    ' A% I; Z0 ]1 J
  345.                         DEBUG("IIC等待结束超时\r\n");$ \+ @" G7 L& N, X8 [& S
  346.                         return IIC_TIMEOUT;                                //超时
    " C. a+ G1 C# @, I. z
  347.                 }                        
    1 L  o) W, k& Q' j8 ?$ f$ k
  348.                 TimeOutUs --;
    : e3 V$ |7 d  w5 y" ^. E
  349.                 Delay_US(1);                                                //延时
    + r, K- m% h; L- L: r. f
  350.         }: r& O9 g  [  Q& ^6 Q5 \
  351.         2 T# r* J" N! f, M1 o
  352.         return IIC_OK;- O8 B5 h! k6 O2 Y, w
  353. }( J9 R. I  b) N" m' |1 J: k
  354. $ _9 i% _' |" l* [
  355. : `4 r- f* v4 u4 c  O5 o& T
  356. /*************************************************************************************************************************1 U, c- j2 p5 |9 @6 `: K2 l& _  O7 f& b
  357. * 函数        :                        static IIC_ERROR IIC_isWaitFlag(IIC_HANDLE *pHandle,u32 Flag,bool isWaitFlagSet, u32 TimeOutUs)3 G( v. v! ~+ x( C* d
  358. * 功能        :                        等待中断有效
    7 v8 I9 t- f# }% j" z& c6 H, R# F
  359. * 参数        :                        pHandle:句柄;Flag:需要等待的flag,见IIC_FLAG_xxx;isWaitFlagSet:TRUE:等待标志有效,FALSE:等待标志复位;TimeOutUs:超时时间,单位Us; ], V" a  p4 l& ~
  360. * 返回        :                        IIC_ERROR% B" _' A' y* R: }6 H$ T9 A- T5 s
  361. * 依赖        :                        底层宏定义
    4 U0 N6 s0 t! e' T$ X, c. S6 b
  362. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>  m. g7 b  _& B- B6 B0 i& L) y$ ?
  363. * 时间        :                        2020-02-15
    2 S2 P. r& F* V5 Y  C* H
  364. * 最后修改时间 :         2020-02-15
    ! i3 G( Y0 t' S; C' e% t" d9 S
  365. * 说明        :                        
    3 B  Q& z. N0 F: a. ?$ [- N8 C
  366. *************************************************************************************************************************/  % _. i$ A9 ~/ P5 n# x: ^
  367. static IIC_ERROR IIC_isWaitFlag(IIC_HANDLE *pHandle,u32 Flag,bool isWaitFlagSet, u32 TimeOutUs)
    9 A1 Q4 g6 o0 Z0 H6 g. m) w" \
  368. {
    ' G+ k* r( c9 P7 K7 [
  369.         if(isWaitFlagSet)        //需要等待标志有效
    1 a$ d* A. t: L% R, T5 \- j0 L- ^
  370.         {/ X) G9 I2 A) Y  v" Q# {3 C. S
  371.                 while((IIC_GetISR(pHandle) & Flag) == 0)
    ; r  B% ], c3 z- p2 N  k/ b
  372.                 {. m) F! U7 l5 Y$ x
  373.                         if(TimeOutUs == 0)                                        //检查是否超时了
    + l3 _4 |9 U$ y5 U$ l" F
  374.                         {
    3 d: N; y0 @2 A( ~% W
  375.                                 return IIC_TIMEOUT;                                //超时
    + l2 h9 D, F5 y+ p! M& Y
  376.                         }                        
    8 ?+ e3 R: u" a$ R  G
  377.                         TimeOutUs --;
    " F* v% \  l, I+ c" T9 A' }
  378.                         Delay_US(1);                                                //延时
    + {5 d% I: B0 Y# [5 n
  379.                 }
      ~* P) n% V2 Q! c$ t
  380.         }
    - Y* \. o0 u  u+ M* ?1 T  O
  381.         else                                //需要等待标志复位- C" P0 m. [3 f1 d. C! }# v+ K
  382.         {$ T! O7 x  j0 \; u: S$ X' {
  383.                 while((IIC_GetISR(pHandle) & Flag) != 0); {0 I8 T" v- x6 X
  384.                 {
    # L% M$ G: D* p
  385.                         if(TimeOutUs == 0)                                        //检查是否超时了
    + c( y( |" y# D9 b) V
  386.                         {# e0 r( h0 Y# }- ^; ~, E
  387.                                 return IIC_TIMEOUT;                                //超时, n! h* }! ^  O. k. {6 f# I) Z
  388.                         }                        
    3 r' y; i7 O! t& m& R( C
  389.                         TimeOutUs --;5 s- x% p7 \. K* R/ d
  390.                         Delay_US(1);                                                //延时% M- u! P. K! t4 m; `; i' {# b
  391.                 }4 K7 C# r, W: V( N" C0 n
  392.         }; l4 B( Z' ?4 x4 x! m
  393. / o- i. Z, D! N/ V( a/ Q2 ]
  394.         return IIC_OK;/ a: L- R' E3 `% w6 s& S
  395. }6 ]2 f' @/ F1 N( W- ]
  396. 8 Z* g( J3 v- [/ V( w" a

  397. : @( e2 d4 }: q. B8 V

  398. 3 P2 B, Z2 a: I1 C- |  |
  399. / p5 O: b+ b3 ^5 m+ y
  400. /*************************************************************************************************************************, \& c" V7 Q9 W9 r9 J% k2 O
  401. * 函数        :                        static void IIC_MasterTransConfig(IIC_HANDLE *pHandle, u16 SlaveAddr, u8 TransByteCount, IIC_RELOAD_END_MODE EndorReload, IIC_START_WR_MODE StartAndWR)( c$ c* h* f: _; G/ d% [
  402. * 功能        :                        主设备传输配置(配置CR2寄存器)4 r! c5 W% {- u1 J$ ~
  403. * 参数        :                        pHandle:句柄;SlaveAddr:从机地址;TransByteCount:需要传输的数据长度;EndorReload:自动结束还是重载设置,见IIC_RELOAD_END_MODE;StartAndWR:开始读写控制,见StartAndWR4 Z  ^* L& [; K
  404. * 返回        :                        无$ f7 ^. M* p6 I7 j+ j6 I3 d% [
  405. * 依赖        :                        底层宏定义* `( G% _6 g  x" p
  406. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>! p; |. E4 ^: ?
  407. * 时间        :                        2020-02-15
    8 C% A8 v8 Q& G. Y5 P( H+ a9 o! g- x8 `- l
  408. * 最后修改时间 :         2020-02-16
    9 y. }' R# G" S# c
  409. * 说明        :                         在往 NBYTE 中设置最后一次传输的字节数前,必须把 RELOAD 位清零便于后续自动发送STOP。- {. o/ `) l1 u: r1 J
  410.                                         当 RELOAD 位置 1 时,AUTOEND 位将不起作用;$ a; _2 ?% N3 Z) _3 R9 I# E
  411. *************************************************************************************************************************/  
    ! ~" v8 ^% N) z" p$ C2 a& N; u) K
  412. static void IIC_MasterTransConfig(IIC_HANDLE *pHandle, u16 SlaveAddr, u8 TransByteCount, IIC_RELOAD_END_MODE EndorReload, IIC_START_WR_MODE StartAndWR)
    + K- {' ~: K& k8 ~( J
  413. {+ X; X: w3 e* ]! W* v; q
  414.         u32 temp = 0;- U4 |6 z, w: ]4 B
  415.         7 r: `1 J& x5 I) I' X) }$ \
  416.         //先读取CR2寄存器的值# [4 r$ a3 b2 m0 }2 h. S6 v: J2 Y
  417.         temp = pHandle->I2Cx->CR2;2 ]5 K  ^; v( h; {% n1 o
  418.         //清除掉相关的字节
    . Z! r& F  K) h9 R  v" O  S
  419.         temp &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND |I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
    2 s) b) y  z" q' r) B8 D, ~4 J1 x' Z
  420.         //生成配置数据( ^. D+ X! V* v+ T' q$ }
  421.         temp |= (u32)(((u32)SlaveAddr & I2C_CR2_SADD) | (((u32)TransByteCount << 16 ) & I2C_CR2_NBYTES));! e: W% I  U) `$ f- h6 S
  422.         //重载与自动结束只能二选一) ]. l1 ~+ H# [6 x5 D9 X% D
  423.         if(EndorReload == IIC_AUTOEND_MODE)         
    2 N' D: y' a3 N) m/ m7 O
  424.         {
    ; |9 s: q& v  l0 Y3 z7 ]
  425.                 temp |= I2C_CR2_AUTOEND;        //自动结束模式
    , w' i; D9 t, Q
  426.         }5 ]+ c! F( ~3 i; L1 S
  427.         else if(EndorReload == IIC_RELOAD_MODE)5 }% z7 g" t- R5 F2 I" z
  428.         {) U1 b, z# ?; M9 }+ s
  429.                 temp |= I2C_CR2_RELOAD;                //NBYTES 重载模式
    & f: u+ ]% y6 U: A
  430.         }+ S. M. J: V' Q
  431.         4 x& z* _- j5 Z- l$ y3 h4 q
  432.         switch(StartAndWR), d; Q8 |; ?$ D* n/ ?* k+ b! q
  433.         {
    ' m+ j8 a6 H% m. C) n. _
  434.                 case IIC_NOSTART_WRITE        :        break;        //没有开始的写-默认就是这样的5 \# K: F) T& C3 L, @' X
  435.                 case IIC_NOSTART_READ        :                        //没有开始的读-用于后续数据读取# j+ S" i  h: V9 g  J" S
  436.                 {
    & I' n( w* ~, ?/ C+ s; X2 m2 m
  437.                         temp |= I2C_CR2_RD_WRN;                        //读取
    2 n$ C, Q+ j" ]& g6 ?6 K% z
  438.                 }break;8 y/ E. K! m8 y! v( I- P
  439.                 case IIC_START_WRITE        :                        //生成开始写
    8 _, p& C' N! @  a
  440.                 {; f! C7 G$ N. m+ X2 t$ i7 f+ }
  441.                         temp |= I2C_CR2_START;                        //启动传输& ~8 ~: L* [5 S) t+ n
  442.                 }break;
    5 U! y2 M" w7 V5 h: s
  443.                 case IIC_START_READ                :                        //生成开始读        & i0 ^1 k- J( Q- L
  444.                 {
    6 Q. b1 h8 |8 O$ S  `; n8 F
  445.                         temp |= I2C_CR2_RD_WRN;                        //读取6 l- M/ y: V; q* }- p1 J
  446.                         temp |= I2C_CR2_START;                        //启动传输
    ( ?! C* k* F( ^& j7 {. J8 i$ W  `
  447.                 }break;, \9 L# Y* v: C& F1 x
  448.                 default:break;8 V' U2 ^- v+ \4 _
  449.         }
    . o3 {- {. }, X( a3 G' h- H7 q
  450.         ! Q# v! z3 |& z6 {; T
  451.         //uart_printf("准备写入CR2=0x%X\t", temp);8 x0 M" e/ a9 }. M9 [9 M" W3 G0 t
  452.         //更新到寄存器
    ; ]" D+ R  c" o
  453.         pHandle->I2Cx->CR2 = temp;  //测试$ s. S: d9 O. {7 \
  454.         //uart_printf("ISR=0x%X\r\n", pHandle->I2Cx->ISR);
    + p2 p. P# {8 s5 p( d, j4 F! D3 k
  455.         Delay_US(100);
    : A8 H3 \$ x- e( \# F: H+ H6 b6 I
  456. }
    " G* A5 ^; `& G" j7 \+ s

  457. / z$ H1 s/ ]  ]- q/ |9 r+ x# d4 G# e

  458. , A8 W. y0 Z! g  t& F, N
  459. /*************************************************************************************************************************: f7 {& O, E6 j: d) K6 L
  460. * 函数        :                        static IIC_ERROR IIC_SendByte(IIC_HANDLE *pHandle, u8 data, u32 TimeOutUs)
    + ^) `' n* d" a7 q% r
  461. * 功能        :                        IIC发送一字节
    5 V7 p) W0 b; ^0 M
  462. * 参数        :                        pHandle:句柄;data:待发送数据;TimeOutUs:超时时间,单位us/ Q' [; r. j2 p
  463. * 返回        :                        IIC_ERROR1 l" D9 O# a" a  E/ J+ A3 {& L
  464. * 依赖        :                        底层宏定义
    $ C1 S4 @/ ?* L' z1 ?3 Z
  465. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    9 n2 U/ A* d  u) r1 V
  466. * 时间        :                        2020-02-15% i; X" q% w' t% R. s" f
  467. * 最后修改时间 :         2020-02-16/ B* E; w0 g! U( X0 M
  468. * 说明        :                         TXIS有效后才会进行数据发送,不会检查数据发送是否完成。7 ~" F1 Z, o7 c1 [8 X
  469.                                         如果最后一个字节发送完成后不会再触发TXIS中断,只会触发TC中断8 L' c( n4 m, s
  470. *************************************************************************************************************************/  8 f5 Z  f2 x+ p+ }8 L
  471. static IIC_ERROR IIC_SendByte(IIC_HANDLE *pHandle, u8 data, u32 TimeOutUs)) B: s7 b1 Z! |' F
  472. {
    8 g; f( [1 t7 _/ G, e
  473.         IIC_ERROR Error = IIC_isWaitTXIS(pHandle, TimeOutUs);                                //先等待可以发数据
    0 S5 i; k" Y5 D
  474.         if(Error != IIC_OK) return Error;
    * I7 I& m+ x2 l$ B/ G
  475.         pHandle->I2Cx->TXDR = data;                                                                                        //写数据到发送寄存器-不会等待数据发送完成        6 M5 z1 A! m; v& a

  476. 3 r" e  e6 `: k* F
  477.         return IIC_OK;
    % L( F7 C! v, v% s  t9 j6 }0 {. ?9 T- d
  478. }
    9 [% U9 W* Y$ f2 n
  479. " v9 W! l; b# e7 \) K+ T; r
  480. /*************************************************************************************************************************
    4 z, b  C9 T, s! ~
  481. * 函数        :                        static IIC_ERROR IIC_MasterRequestWriteAddr(IIC_HANDLE *pHandle, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,
    2 O& a1 I7 |* ]" \! C2 p3 o! B
  482.                                                 bool isRead,u32 TimeOutUs)
    4 @7 n( F1 F  Y( O5 G1 U: }& f
  483. * 功能        :                        主设备请求发送从机地址与目标寄存器地址
    1 T- g0 Q) U. y! ^8 y
  484. * 参数        :                        pHandle:句柄;SlaveAddr:从机地址;RegAddr:寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,
    % z# u, G0 E& y0 g0 Q; Q# t( |
  485.                                                 FALSE:16bit寄存器地址;isRead:TRUE:这个操作是读取寄存器;否则是写入寄存器;TimeOutUs:超时时间,单位us  i5 f: }8 ?, H9 `  v7 \( F6 ~- ]
  486. * 返回        :                        IIC_ERROR
    # T! j# _1 l* Z8 H: E* V1 t* d4 d
  487. * 依赖        :                        底层宏定义3 D* c: f* C2 t$ }- q$ `
  488. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>$ ?  I4 }, q- b: W8 h/ C- P
  489. * 时间        :                        2020-02-15# {5 u' z$ C6 r; ^) {  M: A- F# w
  490. * 最后修改时间 :         2020-02-16
    % K8 o$ q3 K7 q6 h- [
  491. * 说明        :                         % k# g3 c8 M  K) r2 e" }
  492. *************************************************************************************************************************/  
    / G! Q5 n8 {: P, E6 M
  493. static IIC_ERROR IIC_MasterRequestWriteAddr(IIC_HANDLE *pHandle, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,bool isRead, u32 TimeOutUs)
      l$ h7 K3 }$ J
  494. {        
    7 N6 I8 Z8 b/ g7 C
  495.         IIC_ERROR Error;& I: m; j) W* Y" F" |" s7 _3 T
  496.         7 {2 n1 g( v0 b  X3 w( C& h" S7 P
  497.         //uart_printf("WriteAddr1:CR1=0x%X\t", pHandle->I2Cx->CR1);
    ! l2 N# H- F' p/ g
  498.         //uart_printf("CR2=0x%X\t", pHandle->I2Cx->CR2);
    + h4 v3 _& F) F
  499.         //uart_printf("ISR=0x%X\r\n", pHandle->I2Cx->ISR);7 B8 m5 h/ A1 ~( a$ w" m5 j" X* P2 R
  500.         //传输配置,并启动传输,发送起始序列,开始IIC传输了
    / r6 d( K5 {5 i! i' ]4 z4 i
  501.         //如果是读取则使能软件结束,如果是写则是自动重载+ j3 W# J1 X) w7 O. B( _* l& |
  502.         IIC_MasterTransConfig(pHandle, SlaveAddr, (is8bitRegAddr==FALSE)?2:1, (isRead)?IIC_SOFTEND_MODE:IIC_RELOAD_MODE, IIC_START_WRITE);        //传输相关配置-写,并启动传输! F! d/ h" C6 v1 {; z
  503.         / w4 y- i- e  Q4 O; g
  504.         //开始发送寄存器地址
    % `- t  {- Z, B, L; C& [$ ^( s* m4 U* L
  505.         if(is8bitRegAddr==FALSE)                                                                                                //寄存器地址是16位的,IIC通常是MSB高位在前,需要进行高低位对调" N5 n9 z- b# F* N
  506.         {
    2 r5 X% [4 z% e" `& ~+ C
  507.                 Error = IIC_SendByte(pHandle, RegAddr>>8, TimeOutUs);        //先发送MSB-非最后一字节1 I% f% {: r  h
  508.                 if(Error != IIC_OK)$ s. p+ G( h$ ?6 Q
  509.                 {) {" V# Z% q3 E& c
  510.                         DEBUG("IIC发送寄存器地址MSB失败\r\n");$ ?9 @) [. N- C' U
  511.                         return Error;
    . @4 R0 Y  ^6 U: _# a
  512.                 }        
    1 y* V0 K! G. v
  513.         }- e# m* Z9 l! A2 S* d
  514.         Error = IIC_SendByte(pHandle, RegAddr & 0xFF, TimeOutUs);        //再发送LSB-最后一字节- r* |% x# g5 S6 K2 G! D# J  L1 V
  515.         if(Error != IIC_OK)8 `4 @$ p' }' ^: y  o% Q; \  ~- I* K
  516.         {, o1 B7 P9 R* Q3 F0 q
  517.                 DEBUG("IIC发送寄存器地址LSB失败\r\n");
    8 W$ M8 |8 |1 |0 K# ~
  518.                 return Error;
    . ^% G4 C6 H# @
  519.         }( a" G( e( Q9 q
  520.         //等待全部数据发送完成
    * J& I( o7 \# E, r8 H
  521.         if(isRead)        //读取方向-非重载,等待数据传输完成 当 RELOAD=0、AUTOEND=0 且 NBYTES 数据传输完成时,该标志由硬件置 1。
    . T; Q( W, W. r: W
  522.         {4 f& i9 v( B6 t9 v2 t
  523.                 if(IIC_isWaitFlag(pHandle, IIC_FLAG_TC, TRUE, TimeOutUs) != IIC_OK)" Y' y4 q& h1 ?( L5 c) i' N1 W5 O
  524.                 {
    1 [6 b6 H/ ]; L
  525.                         return IIC_TIMEOUT;
    8 [# @$ x) w, F
  526.                 }9 y3 h" R) z1 u3 h# _1 Y2 r
  527.         }        3 l  Y' K, s4 d5 J
  528.         else //写入方向,等待重载
    & Q% y8 j9 y% C
  529.         {7 e. u8 K: a1 o' l6 \# ^! J4 D0 O+ G& w
  530.                 if(IIC_isWaitFlag(pHandle, IIC_FLAG_TCR, TRUE, TimeOutUs) != IIC_OK)7 n* X0 f" |! d5 f# L. h8 ~
  531.                 {
    : I7 H5 M, Z+ \
  532.                         return IIC_TIMEOUT;' \+ Q9 d& m7 [' J
  533.                 }
    + c8 I5 r. b, W
  534.         }
    + c, z# t: H  E  w3 `; l' y* I: q5 X
  535.         % _2 a) c! D" u
  536.         return Error;
    0 K1 ~" v* p. x0 H8 S7 V, Q0 Z
  537. }
    % h$ ~9 W5 A! A8 g( q2 F
  538. , W0 z& k9 q& B
  539. & z& t$ }8 m0 P% O7 W5 r1 j4 w
  540. /*************************************************************************************************************************
    + @/ U- d- _, k/ _/ R' c
  541. * 函数        :                        static IIC_ERROR IIC_WaitRxOneByte(IIC_HANDLE *pHandle, u8 *pData, u32 TimeOutUs)! n4 I4 F3 a8 w, H0 }. B8 g$ ^
  542. * 功能        :                        等待接收一字节数据
      g7 L6 w% y* n
  543. * 参数        :                        pHandle:句柄;pData:接收的字节数据缓冲区;TimeOutUs:超时时间,单位ms& c0 X4 m7 x& t  T7 T4 a
  544. * 返回        :                        IIC_ERROR
    / t0 N( F  x; c- H* l) p8 R; q
  545. * 依赖        :                        底层宏定义
      a9 N: S- ~4 F
  546. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    2 ]8 q) G' f9 o1 ~: ~
  547. * 时间        :                        2020-02-15
    ! o9 e( T5 G; s2 M* j  w
  548. * 最后修改时间 :         2020-02-15
    % s- _* {% U0 O9 q0 z( b
  549. * 说明        :                         当RXNE有效后读取一条数据,否则可能会超时
    0 z) D  Q5 x  M( ~9 k0 q9 O+ ^5 d% s
  550. *************************************************************************************************************************/  
    % s1 d; a( y/ k+ O- J/ M
  551. static IIC_ERROR IIC_WaitRxOneByte(IIC_HANDLE *pHandle, u8 *pData, u32 TimeOutUs)
    3 d5 U. @) J* ]2 f0 N, r
  552. {
    9 A: f% q! [& \
  553.         while((IIC_GetISR(pHandle) & IIC_FLAG_RXNE) == 0)        //等待RXNE有效' K* `# \  p" x8 u4 P- ]5 F; M8 R
  554.         {3 o" i0 A( @3 h- n( Y. A
  555.                 if(TimeOutUs == 0)                                        //检查是否超时了/ S% K5 A( j' y, k
  556.                 {. Y( O: O/ P0 {5 Z$ I* _7 f
  557.                         DEBUG("IIC等待接收超时\r\n");
    6 |; V8 Q7 G5 e4 j. p
  558.                         return IIC_TIMEOUT;                                //超时! L1 a/ T# p! I- O3 x6 O7 O
  559.                 }                        % x6 B* A% s& M# ~3 _
  560.                 TimeOutUs --;
    1 L, j$ S- M1 K0 j) \0 n' D
  561.                 Delay_US(1);                                                //延时- E1 d- @' O/ I
  562.         }+ I3 l7 z8 h+ P/ S1 ~
  563.                
    2 K% [+ ]5 G2 O( u$ ]; l+ ^
  564.         *pData = pHandle->I2Cx->RXDR;                                                        //读取收到的数据
    0 S/ v* F0 X5 \4 w0 S! F6 f
  565.         return IIC_OK;7 W" N# T0 ]9 z  ?6 }+ o8 V
  566. }
    ( M( T" B& n* [! H  L% W

  567. , J. |" F5 k2 \/ _6 `

  568. ; [$ c: G0 L. P. y0 H  E% [) t" d
  569. /*************************************************************************************************************************( E3 l0 G+ b2 @; w! f2 }
  570. * 函数        :                        IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,   y1 |6 }' G" b; @6 I$ w7 [4 ~0 O
  571.                                                 u8 *pDataBuff, u16 ReadByteNum)
      `! g/ s1 ^/ g7 x; W. n/ N
  572. * 功能        :                        IIC读取寄存器(可以读取1个或者多个寄存器). S( p* u9 {0 ~8 ^7 ^
  573. * 参数        :                        ch:IIC通道,见IIC_CH_Type;SlaveAddr:从机地址;RegAddr:要读取的寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,FALSE:16bit寄存器地址;3 i1 g- U$ N' D1 ?. d: s1 o; ~9 L
  574.                                                 pDataBuff:接收的字节数据缓冲区;ReadByteNum:要读取的寄存器数量;
    0 s2 Z% u0 t4 I
  575. * 返回        :                        IIC_ERROR3 i1 r$ J0 s; m, D
  576. * 依赖        :                        底层宏定义# _7 {* [* _% c  D3 f
  577. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>8 `3 Y; n) j* T3 g) z  B
  578. * 时间        :                        2020-02-15* D/ {. }; U( Y' T2 d( o
  579. * 最后修改时间 :         2020-02-15$ p8 f/ Y, P4 {; O. z' y, F- j
  580. * 说明        :                         读取的数据都是小端模式,如果是16bit的寄存器,请读取偶数个数据,并且需要另外进行高低字节对调最后组成16bit数据
    " T1 b: p" N% M
  581.                                         可能的意外:比如一个异常的操作可能会导致IIC一直忙,此处检测到忙后会直接复位IIC,但是必须在应用层做好重入保护,比如. @# N& ]0 G& P$ `& \* g( w! E5 y$ t
  582.                                                 增加信号量$ T! l# Q% ]( _3 j2 e
  583.                                         通过测试发现:在函数进入的时候,清除掉中断状态,之后几乎检测不到IIC忙的情况,当然在结束的时候如果检测到忙会主动发送一个STOP,在& C+ Q1 O. K- f
  584.                                                 操作失败的情况下,会对IIC进行软复位,确保本次的错误不会影响下一次的IIC操作。' R, o; b$ b3 l0 }
  585. *************************************************************************************************************************/) l7 a8 v  \# L
  586. IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 ReadByteNum)
    * l& ^) N* }3 V+ W, x
  587. {
    1 m# c; O! M  O4 ?
  588.         IIC_ERROR Error = IIC_OK;7 j" l6 J" h* z! |
  589.         u16 ReadCount;, Q/ U! J) q7 ]/ `
  590.         IIC_HANDLE *pHandle;
    & f- ?0 n- T; P0 i4 L
  591.         
    4 m2 m+ X8 w8 W+ x& F
  592.         if(ch > (IIC_CH_COUNT-1) || pDataBuff == NULL || ReadByteNum == 0)
    9 @" w+ I8 t8 h2 `& _( r2 T4 x+ S
  593.         {
    / `& i7 {. H9 ^  \$ G1 d1 d
  594.                 DEBUG("IIC错误:无效的参数\r\n");
    2 E% G) ~. G+ ~1 x0 m/ C
  595.                 return IIC_PARAMETER_ERROR;+ Y/ F3 a/ Q; V+ d- S. A' j. M
  596.         }& b% ^8 t- `' B* B/ K
  597.         pHandle = &sg_IIC_Handle[ch];                                        //获取相关通道的句柄
    9 t% {! j4 z7 y  Q* ?; {
  598.         
    4 T! F, |$ ?: e7 m; T! q
  599.         if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                        //忙$ h' H' _0 b7 x2 h- k. x' M. U
  600.         {
    2 l# S2 s1 }+ s2 K* r4 u
  601.                 IIC_SoftReset(pHandle);! e9 f; l. N$ m. n" W
  602.                 DEBUG("IIC错误:总线忙,复位总线,可能直接打断别的地方IIC操作,做好保护措施\r\n");: ~# P# u' i2 K9 z/ Q& u' Q
  603.                 if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                //忙  w) i* S! Y7 r2 {* T
  604.                 {
    # \: y! y: _8 |- q: F( n& N
  605.                         DEBUG("IIC错误:总线忙,复位后未恢复\r\n");
    1 }: e! G! K' {+ [# e  V( U$ _: @
  606.                         Error = IIC_BUSY;
    & j% a- g; B- ~* R
  607.                         goto end_loop;
      u" A$ u5 g4 o% j6 ~8 N
  608.                 }& p7 B3 J8 f) h/ v  T* X; f
  609.         }. c, ^$ ^/ I, r9 \0 O0 T
  610.         IIC_ClearISR(pHandle, IIC_GetISR(pHandle));                //复位错误状态) N5 U- d% {+ k: P/ D+ ^5 |- B1 V
  611.         IIC_ClearCR2(pHandle);                                                        //复位CR2寄存器
    7 T$ C) I; o; ^' n  ~# e8 H' w
  612.         //主设备请求发送从机地址以及寄存器地址-会切换到写方向,并发送START
    7 c  _" {! K3 w( c
  613.         Error = IIC_MasterRequestWriteAddr(pHandle, SlaveAddr, RegAddr, is8bitRegAddr,TRUE, pHandle->TimeOutUs);: ^5 z2 `* Z# n/ h
  614.         if(Error != IIC_OK)
    & d' f! v$ y/ M- g
  615.         {: v8 F: J! n; x( W4 {$ `0 f- [+ B
  616.                 goto end_loop;9 i3 p, Q  Y9 w- ]$ D: c5 q
  617.         }
    7 C$ `0 F9 t6 t0 }9 H
  618.         //发送后续数据, q; I8 i8 [" g" R
  619.         if(ReadByteNum > 255)        //如果超过255字节,则需要分多次读取-后续还有数据,需要重载
    + w' j/ Q  R, p- {$ v" M
  620.         {
    # P2 B) h1 {/ |7 _: u
  621.                 ReadCount = 255;        //本次需要读取的数据长度2557 x' b8 m% V+ }# I* P
  622.                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_RELOAD_MODE, IIC_START_READ);        //传输相关配置-读取,并启动传输               
    4 E# V' @; ]6 [3 H
  623.         }% i3 V9 Q# m$ G7 }! Z* P
  624.         else
    ' Q% ^, }2 T4 e
  625.         {
      C  ~) p, i6 R! b) ]
  626.                 ReadCount = ReadByteNum;        //记录本次需要读取的数据长度-最后一次通讯后自动结束
    # ~" C9 o' N' @0 g: N$ n& W
  627.                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_AUTOEND_MODE, IIC_START_READ);        //传输相关配置-读取,并启动传输+ _, |) {3 s3 p) S
  628.         }
    / \+ Z5 M1 ?2 v0 F. F% G
  629.         / }# e" W9 ?* y" u/ g( V9 K% _
  630.         //循环等待接收数据完成
    . R# s+ M0 G; j; J6 ~  b% l
  631.         do6 s5 ~* A) I; P! b1 i
  632.         {
      [/ {* k$ ?1 g$ v9 s7 t: N6 i
  633.                 //uart_printf("读ISR=0x%X\r\n", pHandle->I2Cx->ISR);/ u: v7 Y) q: Q2 {" H1 g- I. C
  634.                 Error = IIC_WaitRxOneByte(pHandle, pDataBuff,  pHandle->TimeOutUs);                                        //接收1字节数据
    : i$ @9 A1 Q- _2 }. R
  635.                 if(Error != IIC_OK)
    4 B6 m. L. F! \3 e
  636.                 {
    9 D9 X) c! @4 D9 z$ A' ], v
  637.                         goto end_loop;
    . ^5 W* K) D5 B; ?5 B
  638.                 }
    0 w" k9 r& {3 M3 Q! W( B
  639.         
    ! d  f; g+ k" S7 }& C' e) b
  640.                 pDataBuff ++;
    ! S% T9 y' Z" M9 Y9 U
  641.                 ReadCount --;
    , i& R" E0 r7 D  f! [
  642.                 ReadByteNum --;/ T) w7 Y, o( y& u) c% n3 Z4 I
  643.                 if((ReadByteNum > 0) && (ReadCount == 0))        //还有数据要读取
    / f$ B' A+ s6 p; _- Z6 g
  644.                 {
    ) D7 H+ ^( e3 J* y9 X  Q5 \' }3 n0 U
  645.                         if(ReadByteNum > 255)        //如果超过255字节,则需要分多次读取& b# }; t0 L  B9 p( m& F6 T+ Z
  646.                         {. X6 F, ~2 `0 o& ?$ U# j
  647.                                 ReadCount = 255;        //本次需要读取的数据长度255-后续还有数据,需要重载3 L( G' m' X8 q; ^7 |
  648.                                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_RELOAD_MODE, IIC_NOSTART_READ);        //传输相关配置-读取,不启动传输                        
    5 s1 B* ?3 y$ H/ t
  649.                         }
    , b0 ^( F5 K+ V5 ~8 }7 g
  650.                         else
    + N- A3 S9 r! V6 k
  651.                         {, V" X6 a9 n( R
  652.                                 ReadCount = ReadByteNum;        //记录本次需要读取的数据长度-最后一次通讯,自动结束
    * a/ `  b7 s4 p- }% _5 |
  653.                                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_AUTOEND_MODE, IIC_NOSTART_READ);        //传输相关配置-读取,不启动传输                          m: s* X; a( Z; ?2 b; t9 J# B: I
  654.                         }8 F( H8 a( |* r# i+ c( D
  655.                 }2 B/ l9 R* T& i9 ^' ]5 F
  656.         }while(ReadByteNum);7 C! g8 q# J9 [: s4 m9 U& t# F
  657.         //读取完成了,等待STOP位有效: E* _- ^: G  U4 P
  658.         Error = IIC_isWaitSTOPF(pHandle, pHandle->TimeOutUs);; j( d3 x! r! k" n0 i- ^, B
  659.         if(Error != IIC_OK)
    , a" r2 S* m0 S
  660.         {! x3 [, u8 E- W( c8 L" D: C
  661.                 Error = IIC_STOP_ERROR;
    ) E4 L, u! c0 m  ^' `1 M9 q4 U
  662.                 goto end_loop;& _9 C" V: e' O' f) d$ o
  663.         }        ! d- B' N. K1 u: g5 [* x
  664.         IIC_ClearISR(pHandle, IIC_GetISR(pHandle));                //复位错误状态& k/ x4 g- T) p: P$ S
  665.         & V3 n7 c- E/ \% M9 m9 S
  666. end_loop:        
    ! T2 C! W$ U; `7 l; \7 r3 n
  667.         IIC_ClearCR2(pHandle);                                                        //复位CR2寄存器        
    ; I: R8 i0 `4 Y
  668.         if(Error != IIC_OK)# L. W' A+ y! B
  669.         {
    6 D/ |* r  b5 f/ ^
  670.                 IIC_SoftReset(pHandle);                                                //IIC软复位,清除掉错误9 W' {5 y: ^5 a' C
  671.                 DEBUG("[IIC R错误]:%d\r\n", Error);
    ' D: ~! b- e8 r: G' h7 z( e( t9 d; U1 \
  672.         }7 J- F7 L) N2 G
  673.         if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                        //忙,注:奇怪的是高速读取的时候,此处可能会检测到忙,TC标志有效,正常此处不应该有TC标志的
    , m5 c/ n* [8 `+ Q( B! Y' y
  674.         {  f) n5 Y& y  k7 B
  675.                 IIC_SendStop(pHandle);                                                //总线忙,发送一个STOP,释放掉总线
    % e: I5 U" {( k. @' x
  676.                 DEBUG("IIC R结束:总线忙 ISR=0x%X\r\n", pHandle->I2Cx->ISR);               
    # Z) _: o: ?7 D2 G. m1 {, B
  677.         }
    3 q6 w$ r' g: w1 G0 b0 B
  678.         
    : {  e7 @! W* U& G
  679.         return Error;6 \: @' w/ |) b* G8 N/ L
  680. }  S: H, G$ ~9 R) o3 c/ N5 q
  681. / n6 N$ D# i# ]+ c) [  o$ N
  682. 7 I- l0 E  q0 Q
  683. /*************************************************************************************************************************% |& x( |  L* Y6 j& z- X7 k8 E
  684. * 函数        :                        IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,
    . U6 v' s' e5 l$ x# B
  685.                                                 u8 *pDataBuff, u16 WriteByteNum)
    ! y7 ]+ h$ y5 {5 k
  686. * 功能        :                        IIC写寄存器(可以写1个或者多个寄存器)' Y3 U+ P5 s7 D0 q
  687. * 参数        :                        ch:IIC通道,见IIC_CH_Type;SlaveAddr:从机地址;RegAddr:要写入的寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,FALSE:16bit寄存器地址;  b% A  L5 X! L% w
  688.                                                 pDataBuff:写入的字节数据缓冲区;WriteByteNum:要写入的寄存器数量;
    2 v, S# S* c5 I3 j# X
  689. * 返回        :                        IIC_ERROR1 [8 a) U% f. z8 J/ O! M
  690. * 依赖        :                        底层宏定义
    ) s* F" j* x; z  Y: l
  691. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    ! B" i" H& q4 A. c- g8 T; \. f
  692. * 时间        :                        2020-02-16
    6 i/ F  X" m5 j0 _
  693. * 最后修改时间 :         2020-02-16
    6 t7 l+ [) Z5 ~
  694. * 说明        :                         写入的数据都是小端模式,如果是16bit的寄存器,请写入偶数个数据,并且需要提前进行高低字节对调最后组成高字节在前的数据buff
    ; w  B$ {) p7 g( D4 i
  695.                                         可能的意外:比如一个异常的操作可能会导致IIC一直忙,此处检测到忙后会直接复位IIC,但是必须在应用层做好重入保护,比如
    ' m  h3 ^( b# @9 [/ h
  696.                                                 增加信号量' I. v& E; S  Y% R
  697.                                         通过测试发现:在函数进入的时候,清除掉中断状态,之后几乎检测不到IIC忙的情况,当然在结束的时候如果检测到忙会主动发送一个STOP,在
    3 c, k5 L: {' W' T0 F
  698.                                                 操作失败的情况下,会对IIC进行软复位,确保本次的错误不会影响下一次的IIC操作。
    1 Z3 {' ~+ d! s
  699. *************************************************************************************************************************/% a1 p' i5 j, g/ B/ J" F
  700. IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 WriteByteNum)
    * R4 V, f6 t- i7 a2 n. G
  701. {# b7 o- S) B3 \! v4 l& R
  702.         IIC_ERROR Error = IIC_OK;( I# y2 ?9 b7 p8 R/ p; ^2 V
  703.         u16 ReadCount;0 j9 u/ p  J& m' U
  704.         IIC_HANDLE *pHandle;& O( B) M- q+ \
  705.         
    ) V' ^- t4 z' c! J
  706.         if(ch > (IIC_CH_COUNT-1) || pDataBuff == NULL || WriteByteNum == 0)0 R& ^6 w, P+ t9 A2 ?- \5 v
  707.         {  h& }7 r7 B4 I+ x* S+ [0 q
  708.                 DEBUG("IIC错误:无效的参数\r\n");
    ) s( t5 \. y$ F8 i6 n' N9 i& o
  709.                 return IIC_PARAMETER_ERROR;; t8 m# t  ~$ y
  710.         }
    & D  ], g! {% y5 T
  711.         pHandle = &sg_IIC_Handle[ch];                                        //获取相关通道的句柄
    3 o% \, U; e# v( E, c% [5 Z2 h
  712.         
    4 P( i2 R- a* [6 ^5 n
  713.         if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                //忙* k3 {; @2 Y8 {) q* n# Q) u. h
  714.         {# p$ M! {$ c( }( y5 n
  715.                 DEBUG("IIC错误:总线忙,复位总线,可能直接打断别的地方IIC操作,做好保护措施\r\n");3 y" W8 G% l9 g9 b% ?
  716.                 IIC_SoftReset(pHandle);7 H1 Q' F; Q$ R( T7 b
  717.                 8 m* b0 w5 R0 U: j* m& j
  718.                 if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)        //忙
    ! u- ]! v2 W$ D' n$ G/ a5 o$ h% {
  719.                 {
    4 d( u$ I- S/ p8 ?4 x, v, Z
  720.                         DEBUG("IIC错误:总线忙,复位后未恢复\r\n");
    ( k2 x5 W8 Y- O
  721.                         Error = IIC_BUSY;
    3 ^, a, e2 r8 [4 i+ Y
  722.                         goto end_loop;; `: [! X' p, g/ x6 c7 _
  723.                 }
    ' r' Y1 L- A" U/ v  ]
  724.         }
    2 E, f. P  R( t  K
  725.         8 f) Q$ b4 i$ [/ y
  726.         IIC_ClearISR(pHandle, IIC_GetISR(pHandle));                //复位错误状态
    8 n5 ^- F: }, n+ M7 r" o# h
  727.         IIC_ClearCR2(pHandle);                                                //复位CR2寄存器
    : t( `; T9 Z2 I! Z- `$ Z, n2 G
  728.         //主设备请求发送从机地址以及寄存器地址-会切换到写方向,并发送START
    7 g3 U- H& V7 z+ k
  729.         Error = IIC_MasterRequestWriteAddr(pHandle, SlaveAddr, RegAddr, is8bitRegAddr,FALSE,  pHandle->TimeOutUs);
    & N/ C! j3 }) v3 V5 U( Q9 f( W
  730.         if(Error != IIC_OK). ^: ]1 r6 V  C8 T$ P" y* l
  731.         {
    # o4 G. n7 F8 a/ w, S/ Q
  732.                 goto end_loop;3 [8 @4 q( @/ u/ a
  733.         }
    & I/ g/ h5 Z, m
  734.         //发送后续数据
    5 ?1 K) T- U0 ^9 Z2 w: J- I
  735.         if(WriteByteNum > 255)                        //如果超过255字节,则需要分多次写入-后续还有数据,需要重载
    7 ]8 P7 @7 c7 f# m$ A
  736.         {8 v0 E, i) l: W. L
  737.                 ReadCount = 255;                        //本次需要写入的数据长度2551 ?' Q/ Y% X# F6 @% J+ b' z+ t, w' b
  738.                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_RELOAD_MODE, IIC_NOSTART_WRITE);        //传输相关配置-不启动传输的写入               
    # l# ^* x/ A0 K
  739.         }$ |/ F$ X% r1 D& `8 k
  740.         else
    5 f+ L# `- R' s# i. U) J
  741.         {
    - f; r. g$ y1 E: I# p% q- m1 K( ^
  742.                 ReadCount = WriteByteNum;        //记录本次需要写入的数据长度-最后一次通讯后自动结束2 N, N, z- S$ @7 D. W
  743.                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_AUTOEND_MODE, IIC_NOSTART_WRITE);        //传输相关配置-不启动传输的写入: n+ l2 A* L1 o0 L- {
  744.         }, y3 u$ N! h7 A6 ]9 |
  745. ) x# c- }7 h5 p' t0 @2 d. X% c
  746.         //循环发送数据
    0 `" r- E2 r0 c7 k( ]" g
  747.         do
    & U5 C" u. n& k; F4 C7 u
  748.         {& D" e6 E6 [  G) q
  749.                 Error = IIC_SendByte(pHandle, *pDataBuff, pHandle->TimeOutUs);        //发送一字节 $ h0 s- o* I1 q$ U1 j" S5 }
  750.                 if(Error != IIC_OK)
    + A: p! L2 ^0 C6 _+ Q
  751.                 {  v/ t2 H, I' s) K, i/ ]1 R
  752.                         goto end_loop;
    ) K! T( i! k" M$ B; q
  753.                 }2 d; k8 p7 M' H) d/ Z3 O
  754. - x8 h' }+ F& F" F5 E4 ]8 ~
  755.                 ReadCount --;
    % \# M: M9 |$ e6 q- a! d4 h2 B
  756.                 WriteByteNum --;% E& X: m: c% @* g% L
  757.                 pDataBuff ++;
    7 Q5 Z4 [, i3 K
  758.                
    , @0 f( t' B8 S0 U
  759.                 if((WriteByteNum > 0) && (ReadCount == 0))        //还有数据要读取7 b. k7 G% }$ O; }3 t0 d. w- j
  760.                 {
    $ n" o8 D1 I3 I9 Y
  761.                         if(WriteByteNum > 255)        //如果超过255字节,则需要分多次读取
      ^. b9 H) u) m4 f
  762.                         {, ]: v& Q9 S) q# ~9 P! S8 |6 M
  763.                                 ReadCount = 255;        //本次需要写入的数据长度255-后续还有数据,需要重载
    & o7 _) j2 [0 H( R8 W; N7 `2 d
  764.                                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_RELOAD_MODE, IIC_NOSTART_WRITE);        //传输相关配置-不启动传输的写入
    : J. \/ T4 Q: K% p3 D5 |: R- n2 M
  765.                         }
    3 ]# _( Q$ C  v0 |6 e9 O
  766.                         else2 O. V# w; Y# z% p. ?
  767.                         {2 o+ E2 ?9 z1 V6 E. R
  768.                                 ReadCount = WriteByteNum;        //记录本次需要写入的数据长度-最后一次通讯,自动结束, p3 Z& l! V0 Z3 K: o' a; ~; w) Q5 @
  769.                                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_AUTOEND_MODE, IIC_NOSTART_WRITE);        //传输相关配置-不启动传输的写入                ) _3 b, {, ]  U
  770.                         }8 ?* n  S( P% q2 c
  771.                 }( U, m- ~. d- A+ U) ]
  772.         }while(WriteByteNum);        3 D" i8 x& S  Z2 y. Q$ u

  773. % D7 H  E$ h* a) [- S; A
  774.         //写入完成了,等待STOP位有效
    * ?, Z' g; V9 r' ]9 {1 X
  775.         Error = IIC_isWaitSTOPF(pHandle, pHandle->TimeOutUs);' h  R4 a; R" C# H3 z; g+ Q# \& ^2 n' _8 B
  776.         if(Error != IIC_OK)
    0 {7 `- f1 C: I
  777.         {; H4 F2 [& W7 T0 w8 |
  778.                 Error = IIC_STOP_ERROR;" S: o/ v2 M( Q/ B0 Q
  779.                 goto end_loop;2 l3 e7 N4 Y1 ~  }) f6 F# n
  780.         }% t3 e) r0 g' }' V$ r6 u3 B
  781.         IIC_ClearISR(pHandle, IIC_GetISR(pHandle));                //复位错误状态  R3 J5 v$ F4 J( S/ S' v! d- Y+ B
  782.         . I( u: ^( _8 ~* Q9 L3 X
  783. end_loop:        
    ) F1 @/ h; O3 M: e/ V/ T
  784.         IIC_ClearCR2(pHandle);                                                        //复位CR2寄存器        7 }5 B, f2 N  K
  785.         if(Error != IIC_OK)
    ' B! u/ k' M$ x* W$ U4 N
  786.         {
    5 \! m# ~, V5 o- @' F% G
  787.                 IIC_SoftReset(pHandle);                                                //IIC软复位,清除掉错误( E8 j! n% S: o
  788.                 DEBUG("[IIC W错误]:%d\r\n", Error);
    + M! w9 o- S) l' z( I
  789.         }! N* ?+ ]! m) B' M, P: W
  790.         
    8 S& s' b2 Y* c# [
  791.         if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                        //忙,注:奇怪的是高速读取的时候,此处可能会检测到忙,TC标志有效,正常此处不应该有TC标志的
    : c) z3 v, {+ C# F
  792.         {
    8 ?# L3 T( H) Y6 O
  793.                 IIC_SendStop(pHandle);                                                //总线忙,发送一个STOP,释放掉总线- Z2 ~) K6 L8 g! F  E+ ~: ^
  794.                 DEBUG("IIC W结束:总线忙 ISR=0x%X\r\n", pHandle->I2Cx->ISR);                0 `/ A4 G) S) t1 Y  O
  795.         }
    0 U4 e: q5 @; _# U4 I( X5 k
  796.         return Error;/ R0 k0 u8 s8 g$ t( J, l
  797. }$ K1 l, b8 v+ R# _8 n  o
  798. . l2 M: @8 B2 I# m# ?6 k7 q& U2 P

  799. & H2 t$ ^$ E9 D1 Z- j* g
  800. /*************************************************************************************************************************4 K# w5 b: Y0 M2 }; R: \* @5 p
  801. * 函数                        :        void IIC_SoftReset(IIC_HANDLE *pHandle)
    ) H# s$ K! m1 S* K) I
  802. * 功能                        :        硬件IIC软复位(会使能IIC)* g2 w1 |6 x3 w
  803. * 参数                        :        ch:IIC通道
    # K! C1 _7 T; |
  804. * 返回                        :        IIC_ERROR% v" }, E9 `" \+ V
  805. * 依赖                        :        底层宏定义( O0 }1 k7 T) l" i4 s
  806. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
      I4 p) z" ~$ i% `  _
  807. * 时间                        :        2020-02-15" _9 S2 B8 D' X& {& U4 ?" E
  808. * 最后修改时间         :         2020-02-15/ E( i0 z+ M" M9 p1 B1 j' p- t  x
  809. * 说明                        :         IIC软复位;必须使 PE 保持低电平持续至少 3 个 APB 时钟周期,才能成功执行软件复位。
    ' l7 |0 W+ G3 d
  810. *************************************************************************************************************************/
    $ Z5 A3 Q/ Z0 e9 x, |
  811. static void IIC_SoftReset(IIC_HANDLE *pHandle)
    2 u, [1 W' G$ ?' t
  812. {2 |: _3 |. A& q7 S5 I
  813.         pHandle->I2Cx->CR1 &= ~BIT0;                //关闭IIC后执行软复位+ Q  x$ d2 V4 Z
  814.         Delay_US(1);        3 M: M8 _& \8 ], M
  815.         if(pHandle->I2Cx->CR1 & BIT0)' |3 g9 f8 Y; g4 W9 i# q3 Z! N/ D6 n
  816.         {# Q: s+ c6 ~+ O  ]: Q$ e
  817.                 DEBUG("IIC软复位失败\r\n");3 t$ \( J1 y+ c3 a
  818.         }
    . s0 @% l2 j; W1 h9 q, ^# D0 c$ l
  819.         pHandle->I2Cx->CR1 |= BIT0;                        //重新启动
    5 u& k5 L* `# H3 r
  820.         Delay_US(1);        * g+ j' Z4 \; z+ p5 m. W2 V
  821. }
    $ A  F! Q4 b! T2 k7 H# ~* Y
  822. + [: C3 x  E1 B6 J  ]
  823. ' S. [& t5 i) R9 p8 p( C! X

  824. # P! R. D% G4 S- u4 a1 Z
  825. /*************************************************************************************************************************2 ]2 S/ i) @2 K8 {
  826. * 函数                        :        static u32 IIC_CalculationTiming(u16 Speed_KHz)' e/ Q  U2 J. ?
  827. * 功能                        :        硬件IIC时序计算/ S  U/ V9 M: z( F! R
  828. * 参数                        :        ch:IIC通道;Speed_KHz:速度10-10001 M# D5 _# }7 G1 u' U2 u
  829. * 返回                        :        IIC_ERROR
    0 a* [. Q( u/ F/ Y0 z" o5 I) h
  830. * 依赖                        :        底层宏定义8 ~" F, I( P! c/ x6 I! E$ x, m' P
  831. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    6 V' w: Z) L( @, K0 O. }8 ^4 t; R$ P
  832. * 时间                        :        2020-02-15; E/ ^- H; v  h! ]! _
  833. * 最后修改时间         :         2020-02-15% A4 R$ Z6 I6 c
  834. * 说明                        :         IIC使用的是APB1时钟,将IIC总线时钟控制在100KHz        0 w! P3 n" F6 H* [$ R9 P) H
  835.                                         APB1时钟:最大不能超过45MHz        
    6 V" e1 ^& z6 o0 ]
  836.                                         如果速度是100,则按照SMBUS时序) F: e6 q4 y4 j% T
  837. *************************************************************************************************************************/$ @8 L6 m7 [7 `. g$ \( ?$ Y' ^
  838. static u32 IIC_CalculationTiming(u16 Speed_KHz)
    4 z* X9 Q% ?2 q4 ?, f
  839. {
    , L% g- k  X) ]1 v0 T( }4 R, _- N
  840.         u32 tTime = 0;# F4 Y: E" Y# R- ]+ B. i$ R
  841.         u32 temp;
    7 \+ u9 _' B% y2 q, T# s
  842.         u32 time_temp = SYS_GetAPB1ClockSpeed() / 1000000;                //先获取APB1时钟速度
    " b* U, q. m. y* K( P$ J% M
  843.         u32 Th = 1000/Speed_KHz/2;                                                                //计算高电平时间(低电平时间一样),单位ns
    % E, I6 Z$ S* W. ^* P
  844.         1 A% z: o1 A  C* o5 F2 p
  845.         if(time_temp < 20) time_temp = 20;* X8 m' ?3 T; m7 P+ H
  846.         time_temp = 1*1000 / time_temp;                                                        //单位ns8 D5 R2 u2 ~( C, x* L
  847.         uart_printf("IIC时钟计算->APB1周期:%dns\t", time_temp);  T- e3 V: @) s: ]
  848.         if(Speed_KHz == 100)        //如果是100,则按照SMBUS时序
    ! G- E* c! w8 b! F
  849.         {2 L' e) S3 R, d3 P: a5 X
  850.                 //主时钟分频系数固定为3; h* B: }& p1 p5 {" n$ i" {
  851.                 time_temp *= 3;                        //主时钟周期* p& e: @7 M* x% D9 q0 T* S
  852.                 uart_printf("IIC时钟周期:%dns\t", time_temp);
    ' M& H# a* I0 @3 Q; K1 y
  853.                 tTime |= (3-1) << 28;        //PRESC,时钟预分配
      ^4 b1 [( V+ X0 k8 _! Z
  854.                 //计算数据建立时间,要求最小250ns
    * J0 ^0 k' |; x. Z8 M" ?! \% E
  855.                 temp = 250 / time_temp;4 y% d7 H- R* r( [1 j, k
  856.                 if(temp > 15) temp = 15;
    + D& r% Z: R# A% W' l& V* ^! V
  857.                 if(temp < 1) temp = 1;
    / d# _8 F8 L( |& k- b8 c
  858.                 tTime |= temp << 20;
    8 I1 l% x/ h/ y5 m  E
  859.                 //计算数据保持时间,要求至少300ns" u9 Q' U. s; P2 H8 z. m
  860.                 temp = 300 / time_temp;- W3 a8 N$ u8 ]4 Z5 q
  861.                 if(temp > 15) temp = 15;" [1 G% c( C" y
  862.                 if(temp < 1) temp = 1;
    9 x( h* A; C0 {( x" X$ `
  863.                 tTime |= temp << 16;- c8 i7 W0 M3 f' V# e( R, V
  864.                 //计算高电平周期5us2 b: V  _; ]$ d) p& {
  865.                 temp = 5*1000 / time_temp;
      m8 m: @0 S+ i$ z- @( i
  866.                 if(temp > 255) temp = 255;8 Q! C) }7 N5 V! C9 Y- j
  867.                 if(temp < 1) temp = 1;( K2 R: f5 Q' ^3 K
  868.                 tTime |= temp << 8;6 t8 N! y! P  U2 n) Y! N$ J5 c' a
  869.                 //计算低电平周期5us6 Y% F8 B0 v9 ^" N
  870.                 temp = 5*1000 / time_temp;
    % C6 M$ H0 D$ x7 a9 Z
  871.                 if(temp > 255) temp = 255;9 s5 S3 [+ V4 H8 h, z5 O  E( u
  872.                 if(temp < 1) temp = 1;
    4 ^$ Z, X! }8 c# I; z  `
  873.                 tTime |= temp << 0;
    2 w- A1 \. t$ @$ ?) A& R# ?. V% T- _
  874.         }
    5 S" D6 S5 O9 B) j
  875.         else if(Speed_KHz < 100)
    & l) W' ?8 N- J7 c0 I% F: `* r
  876.         {/ q2 G) h+ `/ h+ o0 O% ~
  877.                 //主时钟分频系数固定为6# ]& p4 Z. A6 W. _' F. K) x
  878.                 time_temp *= 6;                        //主时钟周期
    & w0 H9 v& q1 [* l
  879.                 uart_printf("IIC时钟周期:%dns\t", time_temp);! _8 |( c5 @5 n2 v5 f- p; |
  880.                 tTime |= (6-1) << 28;        //PRESC,时钟预分配
    3 F2 v& c3 G  t1 h% T# u  b  g' V; }
  881.                 //计算数据建立时间,要求最小250ns5 T. X3 ]4 x2 z, O7 |! T
  882.                 temp = 250 / time_temp;9 o6 M4 ^8 S% B0 `8 {- t( j0 t
  883.                 if(temp > 15) temp = 15;; n: s# u% Q6 p7 W! l' _# Y/ j
  884.                 tTime |= temp << 20;
    ! x' V/ k: G# {
  885.                 //计算数据保持时间,要求至少300ns
    & W6 O+ Q# A; \( J; B! s) r8 ^
  886.                 temp = 300 / time_temp;
    & Q( e; V9 `8 L! Z9 U3 G2 K
  887.                 if(temp > 15) temp = 15;2 }0 d* s) z+ h6 J0 H8 C4 {: [/ A
  888.                 tTime |= temp << 16;, r3 G* l0 j7 c" _* e$ O5 K  `$ n
  889.                 //计算高电平周期Th us. v! I1 S; x! D' S
  890.                 temp = Th*1000 / time_temp;
    ( C! {! w$ K6 m+ a: _* {
  891.                 if(temp > 255) temp = 255;
    9 n& [7 k8 R; W/ v) Q9 _7 }, f/ E+ O
  892.                 if(temp < 1) temp = 1;
    ; [2 f8 }6 o# l. Y
  893.                 tTime |= temp << 8;
    3 Z7 B+ X: j" ^  {; l) R$ C
  894.                 //计算低电平周期 Th us
      A! ?* ]6 C( f( {
  895.                 temp = Th*1000 / time_temp;
    : |7 l6 X1 i9 H, n- f& n
  896.                 if(temp > 255) temp = 255;
    3 R7 T* h5 u+ v% v
  897.                 if(temp < 1) temp = 1;
    % t. |' x* C+ s8 K
  898.                 tTime |= temp << 0;  S, ^2 H! Q2 B& n5 C7 m4 D
  899.         }4 |; z6 p" Q8 Y& `2 r
  900.         else //>100% V& }  U8 G8 L: r( z8 @6 W# X
  901.         {
    2 M; M7 Q3 t3 I4 l+ {+ G3 m
  902.                 //主时钟分频系数固定为2
    0 y; ?  z. [3 K3 [( `6 r6 E8 ^
  903.                 time_temp *= 2;                        //主时钟周期
    7 a. t1 ]" y7 Z& m
  904.                 uart_printf("IIC时钟周期:%dns\t", time_temp);
    0 D% E4 P. P# G6 g' Y7 W$ B7 v3 Z
  905.                 tTime |= (2-1) << 28;        //PRESC,时钟预分配& ?1 Y# k  o, q4 N. i! H% B
  906.                 //计算数据建立时间,随便给100ns$ u: Z3 N) R, _0 A5 ?. }
  907.                 temp = 100 / time_temp;
    0 S  @- Y, k( \9 W8 u' i1 ]9 b
  908.                 if(temp > 15) temp = 15;6 }% d1 h- }3 e; c
  909.                 tTime |= temp << 20;, m& I) w4 a" @. Q. V$ U% y$ R' h& a4 O  f
  910.                 //计算数据保持时间,给100ns
    0 q! @0 q( d  d4 G' n! t, t( G1 b, i
  911.                 temp = 100 / time_temp;- Y6 \5 I9 R1 l! T4 q+ @
  912.                 if(temp > 15) temp = 15;
    7 L* \; I) Z$ {
  913.                 tTime |= temp << 16;
    ; J9 G6 K3 X# f; U# X: G) E/ r7 h
  914.                 //计算高电平周期Th us* g" B+ H* L, L9 y3 U, ?( B
  915.                 temp = Th*1000 / time_temp;5 a1 K* k0 {, j: [$ e
  916.                 if(temp > 255) temp = 255;
    2 m/ x' F$ i% U$ O; O
  917.                 if(temp < 1) temp = 1;* D$ Q) C5 x+ y! ^' d- j% ~
  918.                 tTime |= temp << 8;
    " }9 c/ b1 O. {: P# U3 K. I, w
  919.                 //计算低电平周期 Th us9 ~3 C( m  V- w6 a/ C
  920.                 temp = Th*1000 / time_temp;! c. N5 Y8 ^8 g; T  q8 `
  921.                 if(temp > 255) temp = 255;/ d2 K# d2 e# U: k) m
  922.                 if(temp < 1) temp = 1;  w4 r( X( l3 V% J6 k* E& U% S- y
  923.                 tTime |= temp << 0;
    7 v  [% }3 c) H* ^3 q7 }1 R. x- h
  924.         }" y3 }" V& t- \* f# ~+ i
  925.         
    % r8 x5 D. ]! Z' X
  926.         uart_printf("时序寄存器结果为:0x%X\r\n", tTime);* O* U! L) s7 T3 @7 m8 h
  927.         
    1 @$ B( E5 G$ z% y: Y0 H( ?
  928.         return tTime;
    + o& f; z# ]$ f' n5 S- ~0 u
  929. }
复制代码

7 W* l6 _8 d# R+ \/ a* c7 v+ X0 K  |8 A! L# H8 L% V2 ]
  1. /*************************************************************************************************************
    8 j- m4 n7 w% S7 J8 n/ i
  2. * 文件名                :        stm32f7_iic.h
    + [, `$ r/ Y5 B2 a; p
  3. * 功能                        :        STM32F7 IIC接口驱动- k& F4 G  s6 f  g8 g5 E% |% a8 ^
  4. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    - b* }/ i  X+ L- C
  5. * 创建时间                :        2020-02-09
    , ~: Y; r' e( B* S1 o
  6. * 最后修改时间        :        2020-02-093 G& Y( b% Q, B' F( a4 `
  7. * 详细:                        
    ; W$ e+ z% M( _- z; `" B
  8. *************************************************************************************************************/                3 S/ F; Y4 Q3 O! B/ f0 \! `
  9. #ifndef __STM32F7_IIC_H_: ?8 D- T6 O/ N1 {$ t1 c
  10. #define __STM32F7_IIC_H_
    ' [' Z# ?& Y; y0 f- T$ m& ]
  11. #include "system.h" $ t! _; ^+ r5 D* {* {

  12. * w( m; u( c( f+ V( a& F" ^) L
  13. //16位整形数高低对调5 ]" i) t- v$ K
  14. #ifndef SWAP16! V7 x! w& a5 ]$ e
  15. #define SWAP16(x)   (((x & 0xff00) >> 8) | ((x & 0xff) << 8))8 S3 ?& |. s! t# k3 y
  16. #endif  //SWAP16
    % B: L8 b' k  C' T1 t4 r
  17. 9 o5 C% k1 Y0 C* A' h# G4 s
  18. //硬件IO口选择
    5 ?; G( z8 M6 z7 X( T. {. X
  19. //I2C1 IO定义与选择
    ' z: Y7 R0 Q; ~1 F
  20. #define IIC_CH1_PB6_7                                0                                        //PB6,PB7
    ! Z% h1 S7 g# A0 L( e: p
  21. #define IIC_CH1_PB8_9                                1                                        //PB8,PB9# T$ i0 h# Y( e# @) o
  22. #define IIC_CH1_IO_SELECT                        IIC_CH1_PB6_7                //选择I2C1 的IO        
    : H0 Q( |6 |7 ^" Z0 x4 p- h

  23. # a: M. H" H$ m8 H$ \2 ~' r4 K' d0 }
  24. //I2C2 IO定义与选择
    # J' ^, O; Q' @; D5 N3 L2 F' N
  25. #define IIC_CH2_PB10_11                                0                                        //PB10,PB11
    : C  e$ p% z8 x2 H! K
  26. #define IIC_CH2_PF0_1                                1                                        //PF0,PF14 c9 d- y; i" R
  27. #define IIC_CH2_PH4_5                                2                                        //PH4,PH5
    4 j7 Z$ `2 K2 F0 c! ?
  28. #define IIC_CH2_IO_SELECT                        IIC_CH2_PB10_11                //选择I2C2 的IO! E: _; O' C0 r7 [1 b6 J/ h; r
  29. + N( w  q) i3 p# G$ X
  30. //I2C3 IO定义与选择& U! l8 ?4 {3 j/ A# @2 c1 C: K
  31. #define IIC_CH3_PH7_8                                0                                        //PH7,PH8# ?/ s1 m( T* K0 _3 Q. @  ?
  32. #define IIC_CH3_PA8_PC9                                1                                        //PA8,PC9) N+ {) z' i- a$ Z% [8 w5 W% b
  33. #define IIC_CH3_IO_SELECT                        IIC_CH3_PH7_8                //选择I2C3 的IO
    : \- ], i( t" S* y& K2 R
  34. 0 i# D+ E. O4 Q9 ?, q
  35. //I2C4 IO定义与选择8 w% n- {$ T6 J8 _: A' A
  36. #define IIC_CH4_PD12_13                                0                                        //PD12,PD13+ t$ V! E1 E0 N, V/ {
  37. #define IIC_CH4_PF14_15                                1                                        //PF14,PF15% C0 H: ^8 q9 g6 k: `7 u2 _
  38. #define IIC_CH4_PH11_12                                2                                        //PH11,PH129 y# N& J( [- z
  39. #define IIC_CH4_IO_SELECT                        IIC_CH4_PD12_13                //选择I2C4 的IO
    . k; Q* E  }' d+ b! ], C

  40. * G5 U4 ?# Z1 Z( ]: _
  41. //IIC硬件接口选择
    # a3 @6 Z" A" s. Q0 Z
  42. typedef enum
    & h# I0 I  E1 S" L+ d7 y) J
  43. {1 f; o$ Z  Y, c# D9 ?9 k
  44.         IIC_CH1        =                0,        //IIC1
    " E; y  }+ B5 `5 E& g  v* v
  45.         IIC_CH2        =                1,        //IIC22 W; a  F. f' L3 f
  46.         IIC_CH3        =                2,        //IIC33 O, O8 i7 K; p' E
  47.         IIC_CH4        =                3,        //IIC4
    0 ?) I! ]4 W. b8 Z$ Q" F# ?7 s
  48. }IIC_CH_Type;
    / I: u% [& l' a4 T
  49. #define IIC_CH_COUNT        4        //4个IIC& s: O' H8 F( w# i3 l3 l' K5 ~0 j
  50.   I, A) [: d8 e9 u/ H

  51. / s! d0 l3 d) Y
  52. //中断状态- e' @/ e0 d: i' k! g
  53. #define IIC_FLAG_TXE                    BIT0        //发送数据寄存器为空(发送器); 当 I2C_TXDR 寄存器为空时,该位由硬件置 1。下一个待发送的数据写入 I2C_TXDR 寄存器时,该位被清零。8 x! R, Q0 g# q; z& u0 n* @! x
  54. #define IIC_FLAG_TXIS                   BIT1        //发送中断状态(发送器); 当 I2C_TXDR 寄存器为空时,该位由硬件置 1,待发送的数据必须写入 I2C_TXDR 寄存器。
    4 A. n. R) Z8 s9 X) r, G
  55. #define IIC_FLAG_RXNE                   BIT2        //接收数据寄存器不为空(接收器); 当接收到的数据已复制到 I2C_RXDR 寄存器且准备就绪可供读取时,该位由硬件置 1。读取I2C_RXDR 时,将清零该位。
    ; R' g# f4 M  u1 X3 f
  56. #define IIC_FLAG_ADDR                   BIT3        //地址匹配(从模式); 接收到的地址与使能的从设备地址之一匹配时,该位由硬件置 1。该位由软件清零,方法是将ADDRCF 位置 1。7 B9 \" X7 P8 r+ t, F! j
  57. #define IIC_FLAG_NACKF                  BIT4        //接收到否定应答标志; 传输完字节后接收到 NACK 时,该标志由硬件置 1。该标志由软件清零,方法是将 NACKCF位置 1。; @( L1 T9 m& r
  58. #define IIC_FLAG_STOPF                  BIT5        //停止位检测标志; 当在总线上检测到停止位,且外设也参与本次传输时,该标志由硬件置 1
    0 s. B& c' X/ I$ V! \
  59. #define IIC_FLAG_TC                     BIT6        //传输完成(主模式); 当 RELOAD=0、AUTOEND=0 且 NBYTES 数据传输完成时,该标志由硬件置 1。当 START位或 STOP 位置 1 时,该标志由软件清零。" O8 G9 Q, u7 z- N
  60. #define IIC_FLAG_TCR                    BIT7        //传输完成等待重载; 当 RELOAD=1 且 NBYTES 数据传输完成时,该标志由硬件置 1。当 NBYTES 写入一个非零值时,该标志由软件清零。
    ) H8 R/ f( q7 f) O' S! U
  61. #define IIC_FLAG_BERR                   BIT8        //总线错误; 当检测到错位的起始位或停止位,而外设也参与传输时,该标志由硬件置 1。在从模式下的地址阶段,该标志不会置 1。该标志由软件清零,方法是将 BERRCF 位置 1。$ D* O, z6 b/ E( |2 o3 C
  62. #define IIC_FLAG_ARLO                   BIT9        //仲裁丢失; 发生仲裁丢失时,该标志由硬件置 1。该标志由软件清零,方法是将 ARLOCF 位置 1。( Q9 k9 `7 m. k, w& e- O/ A
  63. #define IIC_FLAG_OVR                    BIT10        //上溢/下溢(从模式); 在从模式下且 NOSTRETCH=1 时,如果发生上溢/下溢错误,该标志由硬件置 1。该标志由软件清零,方法是将 OVRCF 位置 1。! i9 b) z( }" q& O) n
  64. #define IIC_FLAG_PECERR                 BIT11        //接收期间的 PEC 错误; 当接收到的 PEC 与 PEC 寄存器的内容不匹配时,该标志由硬件置 1。接收到错误的 PEC 后,将自动发送 NACK。该标志由软件清零,方法是将 PECCF 位置 1。
    6 |1 g' `! P' W
  65. #define IIC_FLAG_TIMEOUT                BIT12        //超时或 tLOW 检测标志; 发生超时或延长时钟超时时,该标志由硬件置 1。该位由软件清零,方法是将 TIMEOUTCF 位置 1。6 e- }- b3 a. B/ u5 L
  66. #define IIC_FLAG_ALERT                  BIT13        //SMBus 报警; 当 SMBHEN=1(SMBus 主机配置)、ALERTEN=1 且在 SMBA 引脚上检测到 SMBALERT 事件(下降沿)时,该标志由硬件置 1。该位由软件清零,方法是将 ALERTCF 位置 1。
    2 ^8 E' P, j  A- {
  67. #define IIC_FLAG_BUSY                   BIT15        //总线繁忙; 该标志用于指示总线上正在进行通信。当检测到起始位时,该位由硬件置 1。当检测到停止位或 PE = 0 时,该位由硬件清零。
    8 g5 s) ~1 I) L  W, U  f
  68. #define IIC_FLAG_DIR                    BIT16        //传输方向(从模式); 该标志在发生地址匹配事件时 (ADDR=1) 更新。;0:写;1:读
    3 w8 `% x  N: T2 _& ^

  69. 2 ?; o* l7 d# x* @4 q/ N
  70. //通讯错误状态
    6 P' k0 F, h+ }# X( N
  71. typedef enum+ f% P1 ~) B% l+ }; s
  72. {
    " Z5 S4 G' a0 ]
  73.         IIC_OK                                        =        0,        //没有错误. A) W5 V: a: y0 }% T0 t9 F) C2 b
  74.         IIC_PARAMETER_ERROR                =        1,        //参数错误, E3 I3 O* q& R  C" N3 h
  75.         IIC_TIMEOUT                                =        2,        //超时错误,也可能是底层错误3 o$ B& O" v) q, F
  76.         IIC_HAL_ERROR                        =        3,        //底层错误
    6 O) r7 z$ f6 m- l  t1 J
  77.         IIC_STOP_ERROR                        =        4,        //等待结束错误. w6 \% f, |+ d7 l. X5 C6 G
  78.         IIC_BUSY                                =        5,        //硬件忙
    2 i) D, U- |2 Q+ N8 }6 c
  79.         IIC_NACK                                =        6,        //收到NACK了
    , }# U% a8 i5 B
  80. }IIC_ERROR;
    $ d9 V* ~- D( z5 X1 A! E7 o
  81. ' b3 n- t+ p1 S0 l- K7 U% e
  82. 1 X3 |& A9 O1 F# X( ?. I1 z. Q$ J
  83. bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs);        //硬件IIC初始化/ i$ m% ]2 V% \/ \
  84. IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 ReadByteNum);        //IIC读取寄存器(可以读取1个或者多个寄存器)' t, d- L, N: _7 T; E9 J
  85. IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 WriteByteNum);        //IIC写寄存器(可以写1个或者多个寄存器)
    , R" n/ l/ E9 R+ z

  86. ! @1 M/ [0 v- }  u) T- S, r( G

  87. 1 w8 U6 d3 I; ^3 |) ~, W
  88. #endif //__STM32F7_IIC_H_
复制代码

; s6 e  @8 X, l
" B# B0 x2 a( y3 F7 b4 [9 |//初始化- K" s5 h" T& G+ o5 v: Y2 Q
( N$ P$ T- x# j) }3 o: y/ l
  1. IIC_Init(IIC_CH3, 200, 0);        //硬件IIC初始化
复制代码

# ^0 N& J. E) B2 @- O
7 g& j. Z: w$ r% E//调用1 w* M) r. t2 ]! V% E1 F
  1. 6 t) U0 N) z' I  V% s
  2. //触摸屏IIC读取寄存器接口
    2 _( w( [  v! O
  3. bool TP_FT5336_IIC_ReadReg(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)' `5 f8 X5 U" z. D2 ^4 P
  4. {& W0 o# i& N$ H/ L: o3 D  f
  5.         if(IIC_MasterReadReg(FT5336_IIC_CH, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum) == IIC_OK)
    $ u: W1 f1 J, T9 l& C1 ?/ U% U( E6 [
  6.         {# E0 b) j9 E* J( ]0 i8 A
  7.                 return TRUE;" ?1 ?6 `" w2 l
  8.         }) p4 a/ x* }9 V0 U1 i
  9.         else
      r5 U- {; {  D' Z, V
  10.         {
    $ k2 e! p; k+ ?; c! r: C
  11.                 return FALSE;6 s1 V4 E0 I, Q$ U# ~4 M( c
  12.         }# Q* |5 F4 h# q
  13. }3 s# X# B4 p5 X  N

  14. * p8 Y/ s( H0 B
  15. //触摸屏IIC写寄存器接口
    , @: g/ x/ N7 @( h3 e; N+ S# }$ D
  16. bool TP_FT5336_IIC_WriteReg(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)
    ) {0 O! x/ f! |
  17. {' q7 r/ F; t9 [/ O, D* a; r
  18.         if(IIC_MasterWriteReg(FT5336_IIC_CH, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum) == IIC_OK)
    ) f. X) c# e: X' Q2 B# ]9 `# b
  19.         {) p" x: o7 Q4 _, W! \# M+ H
  20.                 return TRUE;7 C# ?( w. F1 ^3 j1 j
  21.         }1 q: B8 s& v0 O9 O/ q
  22.         else
    9 h  d% v' \$ z3 ~, e
  23.         {& m. |# l' K! f& j( n2 k
  24.                 return FALSE;, K- i- a% {! c6 e- g0 J6 f- \& A
  25.         }
    6 Q2 {* ?$ D" N

  26. " L# M7 j- r# O! i' t6 @
复制代码

0 @$ H  q7 v2 G! J: C$ ^7 O2 |4 F( @" d7 q
/ I6 o1 i6 P# t' b0 f
赞 收藏 评论0 发布时间:2021-12-11 12:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版