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

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

[复制链接]
STMCU小助手 发布时间:2021-12-11 12:00
目前只实现了主设备模式,一般也只用到主设备模式,IIC如果不能使用硬件方式,读取大量数据的时候效率很大,由于只有1个字节的缓冲区,根本不能使用中断模式(实际使用过程中,IIC会造成100us以内间隔的中断,单片机根本扛不住的),所以建议数据少就直接阻塞,1个字节也就几十us,数据多直接用DMA,将线程阻塞,等待DMA传输完成,而不会阻塞CPU(上传的代码没有实现DMA部分,便于理解)。- o# y/ [2 S$ Y0 t: l5 j6 l! F

8 B4 S6 G7 O2 V) E5 T4 T# W# p& e目前已经做了完善的错误处理,读写操作前都会清除中断,遇到错误会软复位,所有位置均做了超时处理,防止程序卡死,目前只测试了几个字节的读写,大量的,长时间的读写均表现稳定,目前手上开发板没有eeprom,无法做大数据的连续读写,如果你在使用过程中遇到问题,欢迎指正。+ u$ d6 q# f( z8 e* q

' o; n# f$ B  i1 ]1 A下面是IIC读写的时序例子,可以先熟悉一下,这样比较容易上手,哪一个环节出了问题也要调试。' B% @$ g5 y" Z; \7 _( g, o: a- J
# Q0 j) l5 |' r$ Z% }; g9 i& S
20200216194202434.png

2 I6 I. z1 \4 `% b2 j' @8 _. f9 v/ y# v8 D+ N) ?3 D
20200216194219185.png
3 l; h  `) z- q
0 l& {# p" d7 Z, @# K
20200216194234908.png
/ L8 V" S& _: d# a, D: a* t, o. L6 M4 X
+ F( C2 d3 {$ W& g: G; A( H. t
$ o! V/ Y6 Z7 R6 m
下面简要说明一下STM32F7硬件IIC的驱动设计方式(建议先百度学习一下IIC的时序要求):, z9 r0 l) Q2 z8 P' }8 F
' i, R+ X# Q0 i8 J9 B: Z% ?% ^8 G
[基本的初始化]) u+ ]3 x+ h; i3 U* D# Z, X% X- j3 a
- x7 h0 l! u, n) O/ B
1.初始化IIC时钟,IO(IIC IO必须设置为复用开漏输出,这个很重要)。6 \1 G! I8 D1 E, t/ t

% D3 v( I$ I8 V: K" |$ T. P) k2.CR1先赋值为0,复位IIC.
8 b# Y0 z# H) e( s! P( R( s
7 C  f2 N4 [/ Z9 N& n1 z% ^0 B- D# K3.除了TIMINGR寄存器需要自己计算设置好,其余寄存器全部复位为0
& [$ m, M' i! H; F* @# ]0 V( k/ Q7 x
4.设置CR1使能IIC。) E7 n" m# r' C" I, j( l) X0 C4 Q  I
9 s- S) v, v8 u8 h
注意:上面说到,IIC的IO必须初始化为复用开漏输出,我之前初始化为复用推挽输出,测试很久,只要一启动传输,就会立马收到NACK,然后是STOP中断,数据根本没法发送,弄了好久才发现是这个IO初始化的问题。
. \2 I0 d& ^# ]$ z% j  \
, {; L3 _- Q( a  j. ^0 C0 j' r$ P2 ^+ B  A' r

" K; b% ~! Q# N. o& t. q& I( o3 ^[读取]7 v3 O5 W. p$ X( l) E# F

# n, t3 `' I; I1.检查总线是否忙,如果忙的话可以根据你的需要时推出还是直接复位总线,清除中断状态。
9 e5 E  D( k5 Y; W2 O# y
+ z, J0 x2 c6 \5 [2.设置CR2寄存器,从机地址,待写入数据长度(就是后面要发送的寄存器地址长度,通常1-2字节)软件STOP,写模式,启动传输。
7 e+ q/ x; T1 p+ `# x# a0 O; x% x4 n* G
3.等待TXIS置位,然后写入1字节的寄存器地址,如果寄存器地址有2个字节,重复上面过程。; O& _# y5 o0 F+ T4 n7 `" e. Z
7 M9 W9 f1 e, I
4.等待TC置位,意味着上面的1-2字节的寄存器地址以及写完成了。1 U2 h5 Y# h, y( m2 _. v, h& l! l
2 |6 q$ A4 @, o+ S
5.根据要读取的数据长度,去设置CR2寄存器,由于一次最大只能读取255字节(计数器只有8位),如果超出了就要分多次,这里有2种情况,如果当前是最后一包,则将自动STOP使能,RELOAD禁止;如果后面还有数据要发送,则将RELOAD使能自动STOP禁止;这2个是二选一的,而且RELOAD优先级高一些。- j' n( L; Q5 o
7 m1 i% Q( A( X) t8 B. B
6.设置了从机地址,要读取的数据长度,之后设置方向为读取,然后启动START(从写切换到读要重新发送START,这个跟软件模拟是一模一样的)。; p/ i* c. K1 e' i
, K* Z, x( L7 T& G
7.循环一个字节一个字节的读取数据,字节读取需要等待RXNE有效,只有读取RXDN寄存器,直到所有数据读取完成。& H, g3 D2 M' q; N( E
; G7 `( I+ S7 d: \
8.读取完成后等待STOP有效,因为前面在最后一包数据读取的时候使能了自动STOP,这个时候检查STOP是否生成。
- s* l. N/ K0 I# C7 e% [2 X/ R9 J
9.需要注意的是,所有的操作都要给超时,并且是自己可控的,绝对不要有死循环,之所以一直说STM32的IIC死机很大程度上都是由于这个地方没有涉及好,我的程序设计方法是:一旦出现了异常,就复位IIC,如果不复位就会导致下次进去的时候IIC一直忙,因为还处于上一个通讯过程。3 n$ w- B7 W3 W7 k% Z! u
. y% `8 e+ b4 D/ U

1 ^2 d' z; I) j; k- T  V1 ]+ v8 ~# v( N: {' h' G! I% S$ }9 h
[写入]
) j& B/ v& L: T6 e* ~0 F: F9 s
$ U3 T/ X% f: h1.检查总线是否忙,如果忙的话可以根据你的需要时推出还是直接复位总线,清除中断状态。2 [! j0 h9 K3 ]5 u
& h$ d( ]& h# T' K9 |3 p. ]
2.设置CR2寄存器,从机地址,待写入数据长度(就是后面要发送的寄存器地址长度,通常1-2字节)自动重载,写模式,启动传输。) m1 r7 M. }, q" X& O
8 w; x1 u6 C* o$ r* V  m: k) c/ z
3.等待TXIS置位,然后写入1字节的寄存器地址,如果寄存器地址有2个字节,重复上面过程。
* }# u+ d* e* n$ g; f3 n( k0 Q, x: ~2 I5 ?, |/ s) E3 [
4.等待TCR置位,意味着上面的1-2字节的寄存器地址以及写完成了,已经发生重载了,后续可以继续写入数据了。" Q+ f/ Z: q7 ?1 o' t" }$ c6 J0 l
% j- M+ P! l+ t* p) t
5.根据要写入的数据长度,去设置CR2寄存器,由于一次最大只能读取255字节(计数器只有8位),如果超出了就要分多次,这里有2种情况,如果当前是最后一包,则将自动STOP使能,RELOAD禁止;如果后面还有数据要发送,则将RELOAD使能自动STOP禁止;这2个是二选一的,而且RELOAD优先级高一些。+ B1 z  Z) Q7 X) E* \; X

* H( I, X) A& a8 Y% `. W! A6.设置了从机地址,要写入的数据长度,之后不用切换方向,不用启动START(都是写,不用重复发送START,这个与读取有区别)。
/ I  |1 M6 q) w1 \5 o: K% f2 r. D7 M$ w9 A
7.循环一个字节一个字节的写入,字节写入与步骤3一样,等待TXIS置位,就可以写入数据到TXDR。2 l/ d2 E# k2 \( c: {% [1 N: J1 U
8 G, j% k) U% Y0 z8 {& L
8.等待STOP有效,因为前面在最后一包数据写入的时候使能了自动STOP,这个时候检查STOP是否生成。7 E+ o1 a' B4 [" E" n
. c  H* M- H# w4 Y
9.需要注意的是,所有的操作都要给超时,跟读取一样。
, [8 o3 F8 Q) K& `3 J) @! q
  T" z2 H( E1 u4 L- Y. {' @
1 x0 Y6 Y/ l: ]  b+ Q+ Z8 m7 d6 I
+ h% J5 j* T' ^9 Z* s注意:IIC的读取实际很短,超时也不用给很长,以标准的100KHz通讯时钟速度,一个字节大概在90us左右,超时可以给个5-10B时间,也就是450-900us左右。
! Y( W) N( C: e
# d( X3 r9 ?, [! b8 B, P) ^( B; H6 M0 |+ s: o

+ W" I. w! \' O- j1 W+ ?好了说了这么多,具体的看代码中的注释,直接上代码(我只测试过I2C3,其余的理论上都是一样的,就是IO初始化部分有区别,别的通道没有硬件进行测试)! R( V4 u; |& L5 H+ C- P

) a& v5 F; o; m0 b: }: p  d; [; N
  1. /*************************************************************************************************************1 k: i) ?# a# l( Z
  2. * 文件名                :        stm32f7_iic.c
    ! E" m, b9 d; Q
  3. * 功能                        :        STM32F7 IIC接口驱动: y$ o$ c8 I1 Y1 E% x
  4. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    " d$ f. i$ T" l
  5. * 创建时间                :        2020-02-09' {6 x! g3 J$ Z: K* t; _. V2 `
  6. * 最后修改时间        :        2020-02-09, z3 K3 E, c0 h& L0 |
  7. * 详细:                        只支持主机模式,7bit地址,默认APB1为IIC提供时钟
    0 t; f3 S6 X/ ?0 I( W" o+ n- U5 u
  8.                                         涉及到读写1字节的超时时间是us,其余的是ms
    % b7 u" D! B. }2 n* o
  9.                                         注意:IIC的IO必须初始化为复用开漏输出。
    4 c- V+ o5 c0 U% ~
  10. *************************************************************************************************************/        
    ! s; F6 K- w6 q, B
  11. #include "stm32f7_iic.h"1 u& Q4 T. R! d  O
  12. #include "system.h"
    + I: O( ]- Q/ f6 g6 ?
  13. #include "dma.h"' P7 j# e1 g9 l

  14. 6 u# s4 k1 D4 ?! `/ A  z9 _1 o
  15. #define IIC_FLAG_MASK  ((uint32_t)0x0001FFFF)        //中断标志掩码
    " v  e/ M( M& ^9 f& D

  16. 4 ~% Z/ N% i/ h1 @$ P7 @
  17. //自动结束或自动重载设置(重载与自动结束只能二选一,或者都不选)/ H* c, W+ y! ]- ]% z, f
  18. typedef enum
    + i6 ^7 v& d  h
  19. {6 y  h: @# }2 X1 T- I1 Z4 S9 t
  20.         IIC_SOFTEND_MODE                =        0,        //手动结束,并不开启重载
    4 u* Y+ N% F! J: A8 R$ s8 x
  21.         IIC_AUTOEND_MODE                =        1,        //自动结束,用于最后一次通讯完成后自动发送STOP结束通讯' E* ^: z3 t' E+ J+ j
  22.         IIC_RELOAD_MODE                        =        2,        //后续还有数据,本次通讯后自动重载,重新设置后继续通讯
    6 a9 l  y/ H, b3 z2 m
  23. }IIC_RELOAD_END_MODE;9 d, J$ V0 b( J8 }) q+ S
  24. * _+ H9 D$ y. v
  25. //读写与开始模式控制
    7 q$ X( B- p  B* W& o
  26. typedef enum9 F8 I; n8 l% t
  27. {  x8 g6 O! z9 ]
  28.         IIC_NOSTART_WRITE                =        0,        //没有开始的写-用于后续数据的写入* R+ S. A5 @/ s( x* b
  29.         IIC_NOSTART_READ                =        1,        //没有开始的读-用于后续数据读取1 y- ^0 O/ H8 ]; C
  30.         IIC_START_WRITE                        =        2,        //生成开始写-用于通讯开始时,写地址或数据
    ) A3 I2 H+ R: B- K
  31.         IIC_START_READ                =        3,        //生成开始读-用于读取数据时切换到读取方向,并读取后续数据$ {/ c# [! M$ t* a
  32. }IIC_START_WR_MODE;
    & v# U# c* b+ o! ]
  33. 4 [* U8 H, N: [2 r! T2 U
  34. //IIC句柄: V; T5 g  m8 {# i  {5 M
  35. typedef struct
    7 e/ A2 [1 R# k% Y0 `
  36. {
    ' {7 v: s2 R; g" l. s; U* o* ]1 }
  37.         IIC_CH_Type ch;                        //当前通道
    # @6 t8 f: K( b
  38.         I2C_TypeDef *I2Cx;                //当前通道外设结构体, T7 w9 \: @" w5 G# _0 D
  39.         u32 TimeOutUs;                        //操作超时,单位us* X* N! ?8 ?% S4 x; r/ X& k. F
  40.         u16 Speed_KHz;                        //通讯速度,单位KHz
      S! s% r4 F5 c8 U( v
  41.         bool isMasterMode;                //是否为主设备模式-目前只支持主设备模式
    & }" l( X: T9 P  Y
  42. }IIC_HANDLE;) g8 m9 S$ V3 Z1 ]* X
  43. + N& L( l4 G0 W2 S
  44. //IIC外设结构指针; c1 R8 u" a; p; {; e1 X, f
  45. static const  I2C_TypeDef * const I2C_TYPE_BUFF[IIC_CH_COUNT] = {I2C1,I2C2,I2C3,I2C4};
    ; F; f& }" A9 {5 S2 U6 I: ~
  46. //IIC通道句柄定义
    2 i0 r% h3 {" d/ h5 |2 b
  47. static IIC_HANDLE sg_IIC_Handle[IIC_CH_COUNT];
    " u; K: }2 T! }$ c
  48. % u: O% Y0 Y( N3 E" [
  49. //发送NAK: a" L9 k3 t" j" e0 f
  50. //static __inline void IIC_SendNAK(IIC_HANDLE *pHandle) {pHandle->I2Cx->CR2 |= BIT15;}
    - _$ l+ C5 F6 s! Y& `
  51. //发送STOP
    8 T9 d. c6 ^1 U5 b* X
  52. static __inline void IIC_SendStop(IIC_HANDLE *pHandle) {pHandle->I2Cx->CR2 |= BIT14;}( l$ m) B/ y, `0 `6 m
  53. //发送START
    * r# Y9 y2 a3 W+ i7 a
  54. //static __inline void IIC_SendStart(IIC_HANDLE *pHandle) {pHandle->I2Cx->CR2 |= I2C_CR2_START;}
    6 `3 ^, _5 r9 i* Y  A
  55. //获取中断状态
    9 ?& F' X# H( z
  56. static __inline u32 IIC_GetISR(IIC_HANDLE *pHandle) {return pHandle->I2Cx->ISR & IIC_FLAG_MASK;}
    ! d0 |( A: T  e! G) J9 O
  57. //清除中断状态
    8 @, M1 N) @, y: t# M
  58. static __inline void IIC_ClearISR(IIC_HANDLE *pHandle, u32 IsrFlag) {pHandle->I2Cx->ICR = IsrFlag & IIC_FLAG_MASK;}' ^) }+ D8 P& p3 |
  59. //复位CR2寄存器2 o, ^$ r0 z0 G0 b) o7 y4 M
  60. static __inline void IIC_ClearCR2(IIC_HANDLE *pHandle) {pHandle->I2Cx->CR2 = 0;}/ U7 |% b: f9 \7 o) N$ _4 \

  61. + C4 B/ j6 [4 L# a) ]7 R8 n
  62. static void IIC_SoftReset(IIC_HANDLE *pHandle);//硬件IIC软复位(会使能IIC)7 L: I! ^  U- z
  63. static u32 IIC_CalculationTiming(u16 Speed_KHz);//硬件IIC时序计算
    0 h' g. w  X/ X. K( K

  64. 8 t' _% R, r" `" E- m& r

  65. 3 D( R+ h# T: V
  66. /*************************************************************************************************************************
    8 {& k# F, h; l" k) [
  67. * 函数        :                        bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs)
    & v& e9 p7 ]& {) w- Q8 F% C
  68. * 功能        :                        硬件IIC初始化9 [9 i/ I' @, B( t6 F! z: I& c/ R
  69. * 参数        :                        ch:IIC通道;Speed_KHz:速度10-1000(如果速度是100,则按照SMBUS时序);TimeOutUs:操作超时us(0:自定计算超时)
    - b3 L  f0 |. g1 I) D) P
  70. * 返回        :                        IIC_ERROR# h3 G, ?) ]4 Y9 ?$ R# M5 }* p
  71. * 依赖        :                        底层宏定义
    2 ]3 c, Y" Q/ y& K. ^! B2 r; I
  72. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>% Z) J* n" y5 w1 [9 Z& H# p: A
  73. * 时间        :                        2020-02-158 h: f2 `$ k5 J. V. y3 A9 L
  74. * 最后修改时间 :         2020-02-154 Q4 x6 Y* E8 P- ?
  75. * 说明        :                         速度只是个大概的计算值,设置为100KHz时会严格的按照SMBUS时序,其余的不保证SMBUS兼容,正常情况下只要时钟速度符合要求,4 w0 I7 b$ ]4 K3 p+ w: n
  76.                                         时钟上升沿到来前数据以及稳定的切换了即可保证通讯稳定性; g5 s7 y9 m2 Q1 z/ l
  77. *************************************************************************************************************************/# }$ l3 q( l  \1 ^2 Y9 m
  78. bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs)
    / @5 I9 c- v4 F! ]
  79. {
    7 q! J" L2 X; x" X4 o  f0 R) u1 j
  80.         SYS_DEV_CLOCK DevClock;
    ; x; C) Y% I) O5 Y: N
  81.         IIC_HANDLE *pHandle;
    2 B) ~1 p$ m$ P. T) P7 K/ `
  82.         
    7 P$ t3 ]: c7 F6 g  }! w! U
  83.         switch(ch)7 Z& I' M: l& H5 L- ^
  84.         {! G  s* `2 ~# U8 X% Z
  85.                 case IIC_CH1        :        //IIC1
    + R( |' p9 F  z
  86.                 {( g( I/ O, D! q, E2 I! |6 g. i( d
  87.                         RCC->DCKCFGR2 &= ~(0x3 << 16);        //清除设置,使用APB1作为时钟源2 D! H, x, T, Y/ [+ L
  88.                         DevClock = DEV_I2C1;# }2 u# ?; g8 j- f$ X& |5 C
  89.                         //初始化I2C IO
    / R- C. K! f2 @* I* t  j5 Q. H, P
  90. #if(IIC_CH1_IO_SELECT==IIC_CH1_PB6_7)        //I2C1        使用PB6/7+ x) s4 F  p4 V7 K
  91.                         SYS_DeviceClockEnable(DEV_GPIOB, TRUE);                                //使能GPIOB时钟2 C9 Q6 O" y  d
  92.                         SYS_GPIOx_OneInit(GPIOB, 6, AF_OD, SPEED_25M);                //PB6
    ' D- [5 l; M- `# K( t1 `2 I
  93.                         SYS_GPIOx_OneInit(GPIOB, 7, AF_OD, SPEED_25M);                //PB7
    ; e6 u* g7 P0 s- y: g+ S
  94.                         SYS_GPIOx_SetAF(GPIOB, 6, AF4_I2C1);                                //AF41 J& l3 U, `/ q1 l- h, t1 I
  95.                         SYS_GPIOx_SetAF(GPIOB, 7, AF4_I2C1);                                //AF4: e( o3 \2 m* B0 B
  96. #elif(IIC_CH1_IO_SELECT==IIC_CH1_PB8_9)        //I2C1        使用PB8/98 L9 _6 a& l3 j; u1 o; k5 `
  97.                         SYS_DeviceClockEnable(DEV_GPIOB, TRUE);                                //使能GPIOB时钟0 a0 {8 {# D2 E
  98.                         SYS_GPIOx_OneInit(GPIOB, 8, AF_OD, SPEED_25M);                //PB8- O, W6 W* ]% A+ l9 @
  99.                         SYS_GPIOx_OneInit(GPIOB, 9, AF_OD, SPEED_25M);                //PB98 w7 i+ B  r% F2 m" F
  100.                         SYS_GPIOx_SetAF(GPIOB, 8, AF4_I2C1);                                //AF4
    8 [- s9 `6 I& F  R8 p) s. j) a% O
  101.                         SYS_GPIOx_SetAF(GPIOB, 9, AF4_I2C1);                                //AF44 c! J7 e& [1 X7 [- K, c
  102. #else" Y' N2 v7 h- M9 M; U! }( z
  103.                         #error("无效的I2C1 IO选择");
    5 s9 T5 N# [8 w6 j  T# D8 [  \
  104. #endif //IIC_CH1_IO_SELECT
    ; s% Q2 U. G& H; F" s
  105.                 }break;
    ! U$ A! o9 e% ?8 L
  106.                 case IIC_CH2        :        //IIC2
    8 p: S! z4 n! @4 @0 c3 m  O' \7 X
  107.                 {3 D5 j- L( K( S  H" Q3 c
  108.                         RCC->DCKCFGR2 &= ~(0x3 << 18);        //清除设置,使用APB1作为时钟源" b: m# W9 T5 ?7 U% @
  109.                         DevClock = DEV_I2C2;/ h8 n* D4 u+ e2 }2 e- ~' f
  110.                         //初始化I2C IO
    % Q$ B+ b' u9 F* o4 x
  111. #if(IIC_CH2_IO_SELECT==IIC_CH2_PB10_11)        //使用PB10,PB11
    ; D; W: A9 a6 b2 m  p
  112.                         SYS_DeviceClockEnable(DEV_GPIOB, TRUE);                                //使能GPIOB时钟
    3 U' e# c6 k: v1 W2 v. R1 _
  113.                         SYS_GPIOx_OneInit(GPIOB, 10, AF_OD, SPEED_25M);                //PB10
    ( N  Q& P" m: `- x4 g% D. e
  114.                         SYS_GPIOx_OneInit(GPIOB, 11, AF_OD, SPEED_25M);                //PB11
    5 b* y/ c& y! k+ W; h- ^8 `
  115.                         SYS_GPIOx_SetAF(GPIOB, 10, AF4_I2C2);                                //AF4
    1 G$ t* ?! Q. k0 Z& n" X
  116.                         SYS_GPIOx_SetAF(GPIOB, 11, AF4_I2C2);                                //AF4
    3 }& I+ }, `/ {9 B) S8 L1 T0 K, c
  117. #elif(IIC_CH2_IO_SELECT==IIC_CH2_PF0_1)        //PF0,PF1
    9 `5 M4 a+ d: N9 |0 ]7 Y
  118.                         SYS_DeviceClockEnable(DEV_GPIOF, TRUE);                                //使能GPIOF时钟
    " B* F& J3 a5 w3 r
  119.                         SYS_GPIOx_OneInit(GPIOF, 0, AF_OD, SPEED_25M);                //PF0# x( x5 t  u; I. F
  120.                         SYS_GPIOx_OneInit(GPIOF, 1, AF_OD, SPEED_25M);                //PF1/ N" i' `! q$ m" h+ n
  121.                         SYS_GPIOx_SetAF(GPIOF, 0, AF4_I2C2);                                //AF4* [  t7 B" f8 C+ p. [4 s: h% L
  122.                         SYS_GPIOx_SetAF(GPIOF, 1, AF4_I2C2);                                //AF45 r# A; U& j7 l5 n; o
  123. #elif(IIC_CH2_IO_SELECT==IIC_CH2_PH4_5)        //PH4,PH5
    # @6 B+ ]1 \! ~$ T7 b
  124.                         SYS_DeviceClockEnable(DEV_GPIOH, TRUE);                                //使能GPIOH时钟
    7 h" e) e; ~1 S- f- r
  125.                         SYS_GPIOx_OneInit(GPIOH, 4, AF_OD, SPEED_25M);                //PH4
    % B& R+ X' A' E
  126.                         SYS_GPIOx_OneInit(GPIOH, 5, AF_OD, SPEED_25M);                //PH5( v! T% k# N& K8 [$ v, z1 b
  127.                         SYS_GPIOx_SetAF(GPIOH, 4, AF4_I2C2);                                //AF48 x( U( z# z) D4 z7 u) e/ t2 [
  128.                         SYS_GPIOx_SetAF(GPIOH, 5, AF4_I2C2);                                //AF4                        
    ( y& H: T1 D( ~# x2 E4 N
  129. #else
    ) r. k/ h) f% ]  v/ r1 D
  130.                         #error("无效的I2C2 IO选择");8 [6 S" i" L2 l5 `$ }& D+ M
  131. #endif //IIC_CH2_IO_SELECT
    1 r7 u7 n5 G* r* o
  132.                 }break;                        
    - z/ R  c1 T1 X3 m! h) c
  133.                 case IIC_CH3        :        //IIC36 J% P4 X1 y) D$ A( j' @" D
  134.                 {* W( b" Q) E' {2 t, |& L
  135.                         RCC->DCKCFGR2 &= ~(0x3 << 20);        //清除设置,使用APB1作为时钟源  N' R* a) k' K0 R+ |8 [' @1 U9 U
  136.                         DevClock = DEV_I2C3;: M4 a& |# o$ D! t/ w! {" f
  137.                         //初始化I2C IO  p. |1 p4 D/ h: Q
  138. #if(IIC_CH3_IO_SELECT==IIC_CH3_PH7_8)                //PH7,PH8  \/ w" ]- b: P" R, Y
  139.                         SYS_DeviceClockEnable(DEV_GPIOH, TRUE);                                //使能GPIOH时钟
    , n& l8 {/ N5 Y6 [1 j# N
  140.                         SYS_GPIOx_OneInit(GPIOH, 7, AF_OD, SPEED_25M);                //PH7
    6 r# ]- T" W9 p2 p' ?/ n% K, K
  141.                         SYS_GPIOx_OneInit(GPIOH, 8, AF_OD, SPEED_25M);                //PH8; ^+ ^5 N- p% V2 n2 L
  142.                         SYS_GPIOx_SetAF(GPIOH, 7, AF4_I2C3);                                //AF4
    # ~- R2 ^! T& b  u5 Z" }# F
  143.                         SYS_GPIOx_SetAF(GPIOH, 8, AF4_I2C3);                                //AF4' c( R0 I5 c$ T0 D
  144. #elif(IIC_CH3_IO_SELECT==IIC_CH3_PA8_PC9)        //PA8,PC99 |% C  u  c0 }6 Z+ i  A( Q
  145.                         SYS_DeviceClockEnable(DEV_GPIOA, TRUE);                                //使能GPIOA时钟1 G# {1 M: F: `2 \6 `
  146.                         SYS_DeviceClockEnable(DEV_GPIOC, TRUE);                                //使能GPIOC时钟" v  H) ]8 R# T+ Y, A8 a9 P; l6 _
  147.                         SYS_GPIOx_OneInit(GPIOA, 8, AF_OD, SPEED_25M);                //PA8
    & J4 N  a% X3 R6 D
  148.                         SYS_GPIOx_OneInit(GPIOC, 9, AF_OD, SPEED_25M);                //PC9) f' ~3 K2 \7 h. X
  149.                         SYS_GPIOx_SetAF(GPIOA, 8, AF4_I2C3);                                //AF4# z. m" }4 e* P0 U; H
  150.                         SYS_GPIOx_SetAF(GPIOC, 9, AF4_I2C3);                                //AF4               
    ' u3 p% }4 i5 c" p
  151. #else' }6 [" n  ^; ?" `- b
  152.                         #error("无效的I2C3 IO选择");! L4 O) u' F- K, G* V
  153. #endif //IIC_CH3_IO_SELECT                        ) M  Q+ u6 Y7 D! @# K- r
  154.                 }break;                        # `! j# i( r7 U  {/ d
  155.                 case IIC_CH4        :        //IIC4+ c+ @3 t2 i2 l  Z% |0 F! H
  156.                 {$ n+ P; E: E0 `' c
  157.                         RCC->DCKCFGR2 &= ~(0x3 << 22);        //清除设置,使用APB1作为时钟源
    $ i* r, P1 {$ k3 r0 o+ T2 O9 K8 a
  158.                         DevClock = DEV_I2C4;' E0 u8 [4 Y& a3 `$ Y! h  l
  159.                         //初始化I2C IO) V" g! X# y& W9 Z) r
  160. #if(IIC_CH4_IO_SELECT==IIC_CH4_PD12_13)                //PD12,PD13" X( Y  `7 K  c/ I( Z7 P
  161.                         SYS_DeviceClockEnable(DEV_GPIOD, TRUE);                                //使能GPIOD时钟
    : i/ M5 I8 c' g0 M3 t; F. \2 E' X
  162.                         SYS_GPIOx_OneInit(GPIOD, 12, AF_OD, SPEED_25M);                //PD12
    " L2 ~$ E9 |& q" b
  163.                         SYS_GPIOx_OneInit(GPIOD, 13, AF_OD, SPEED_25M);                //PD137 \' N4 E/ d% s8 ]. |( q2 C* o
  164.                         SYS_GPIOx_SetAF(GPIOD, 12, AF4_I2C4);                                //AF4
    9 _9 y0 L# q+ n4 K% U5 s9 I; z
  165.                         SYS_GPIOx_SetAF(GPIOD, 13, AF4_I2C4);                                //AF4' }4 T4 t9 Q9 I6 y* u% V
  166. #elif(IIC_CH4_IO_SELECT==IIC_CH4_PF14_15)        //PF14,PF15
    # X3 o8 b% b7 J, V7 O; Q( c2 U. a
  167.                         SYS_DeviceClockEnable(DEV_GPIOF, TRUE);                                //使能GPIOF时钟: i" _( g9 f( x# [
  168.                         SYS_GPIOx_OneInit(GPIOF, 14, AF_OD, SPEED_25M);                //PF14) k7 j+ D7 B& X9 J. u6 |
  169.                         SYS_GPIOx_OneInit(GPIOF, 15, AF_OD, SPEED_25M);                //PF151 n/ Y& h3 _  z- q% e% E
  170.                         SYS_GPIOx_SetAF(GPIOF, 14, AF4_I2C4);                                //AF4
    " I0 o) c* P5 l. C# N( L/ _
  171.                         SYS_GPIOx_SetAF(GPIOF, 15, AF4_I2C4);                                //AF4
    ( P: {4 |1 C% _/ ~
  172. #elif(IIC_CH4_IO_SELECT==IIC_CH4_PH11_12)        //PH11,PH12- [4 N" ^' n  ?% ^, L' L. i
  173.                         SYS_DeviceClockEnable(DEV_GPIOH, TRUE);                                //使能GPIOH时钟+ @: C+ d1 ^  Z% P' f: {% r4 ~
  174.                         SYS_GPIOx_OneInit(GPIOH, 11, AF_OD, SPEED_25M);                //PH11
    ( ^! S6 n5 u( H* i2 V4 M
  175.                         SYS_GPIOx_OneInit(GPIOH, 12, AF_OD, SPEED_25M);                //PH12
    7 ]( N7 Q$ i* [0 ^2 ]7 Z
  176.                         SYS_GPIOx_SetAF(GPIOH, 11, AF4_I2C4);                                //AF4
    ' L! F' ]) U) q  ^
  177.                         SYS_GPIOx_SetAF(GPIOH, 12, AF4_I2C4);                                //AF4                        
    ; ?; K) ~6 |, }7 q8 U
  178. #else
    1 G3 A( ]' I; k; c' C" D
  179.                         #error("无效的I2C4 IO选择");
    ) ^6 a5 T2 b9 |0 n8 _" y
  180. #endif //IIC_CH4_IO_SELECT                        4 {7 Q1 }( B6 L
  181.                 }break;6 ~0 z  t" u( J7 N- a# ]
  182.                 default:
    ) W5 ^: o7 E! M
  183.                 {
    " i1 [5 f# Y( @
  184.                         DEBUG("初始化IIC失败:无效的IIC通道%d\r\n", ch);; y8 ^( E! c, f; @$ V
  185.                         return FALSE;; H( ?  I, l, G( I* F- x; L3 u5 }. {9 H6 w
  186.                 }
    4 e0 H& i; Y' a& v# ]
  187.         }& o- w1 Z6 a; D& \" p
  188.         pHandle = &sg_IIC_Handle[ch];                                                        //获取相关通道的句柄  D' l9 v# b6 q0 M$ [+ a
  189.         if(pHandle == NULL)
    5 k( l# E+ n6 }# u* M5 Z
  190.         {$ u( Q% f9 V6 T; W  q
  191.                 DEBUG("初始化IIC失败:无效的IIC句柄\r\n");
    ) t7 t! Q2 R+ y1 K5 x/ Z3 n% j
  192.                 return FALSE;
    / q: l1 v7 i' J5 U1 c6 x
  193.         }* Z4 w6 v+ k% C) s; X' c$ t* n) _
  194.         
    . ~" h2 X6 [: A, Q4 X! X% F
  195.         SYS_DeviceClockEnable(DevClock, TRUE);                                        //使能时钟' x( J9 @1 n: G  d7 V) l
  196.         SYS_DeviceReset(DevClock);                                                                //外设复位- x- _+ G3 f- [# K
  197.         pHandle->I2Cx = (I2C_TypeDef *)I2C_TYPE_BUFF[ch];                //外设指针' |1 B7 \6 |7 ^# H; u+ c7 a( P
  198.         pHandle->I2Cx->CR1 = 0;
    5 w1 H; Q5 ?- ~8 o$ Q) p; O
  199.         Delay_US(1);                                                4 c: ~" z1 q: r5 ?
  200.         pHandle->I2Cx->CR1 |= 2<<8;                                                                //设置噪声滤波器,关闭所有中断( r. _7 W! c+ Q% D/ e; Y" R: C3 x- r
  201.         pHandle->I2Cx->CR2 = 0;
    3 t/ k) g# U) [% I) u0 g# F
  202.         pHandle->I2Cx->OAR1 = 0;
    ' a3 v4 V9 A! x
  203.         pHandle->I2Cx->OAR2 = 0;8 u- F( s6 D2 L4 I6 q
  204.         if(Speed_KHz > 1000) Speed_KHz = 1000;4 ^0 G3 B3 O6 f- C& n( {7 K6 S
  205.         if(Speed_KHz < 10) Speed_KHz = 10;% F& U& o; j! C- V8 F5 x/ M
  206.         pHandle->Speed_KHz = Speed_KHz;                                                        //记录速度
    , _: F2 _8 h/ x. ]8 H) Q* ]$ m; \
  207.         if(TimeOutUs == 0)                                                                                //需要自动计算超时时间,时钟周期*10*10 : y8 t$ v; `4 K) f- R( j& M
  208.         {+ M% Y# I- P* D: T& p
  209.                 TimeOutUs = 1000/Speed_KHz;                                                        //时钟周期
    ! o$ h5 J9 L! X& W
  210.                 TimeOutUs *= 10;                                                                        //字节周期5 n2 L, _. f9 R' q$ r: b. k2 P% v
  211.                 TimeOutUs *= 10;                                                                        //超时时间为10个字节时间* |5 H7 k$ a, |8 T; N- B2 i0 l" B# G
  212.         }
    0 X" h( v. F! \0 u
  213.         if(TimeOutUs < 3) TimeOutUs = 3;0 V; D% h4 w5 U. M# C3 u) p- y
  214.         pHandle->TimeOutUs = TimeOutUs;                                                        //记录通讯超时时间6 h, a! @- A3 F% Z. l
  215.         uart_printf("IIC超时时间:%dus\r\n", pHandle->TimeOutUs);
    ) Z1 j+ w4 f( c$ m2 [4 k+ h' H1 ]
  216.         pHandle->I2Cx->TIMINGR = IIC_CalculationTiming(pHandle->Speed_KHz);//0x40912732;                                        //时序
    5 t7 V) Q' [4 `1 k' e% [! n( z
  217.         pHandle->I2Cx->CR1 |= BIT0;                                                                //使能IIC& R' n- f6 w2 ^  @
  218.         pHandle->isMasterMode = TRUE;                                                        //主设备模式
    : A  ?( q% W) B  Z4 [
  219.         Delay_US(1);
    2 X6 |5 R8 H9 q% `0 [5 X

  220. ( H1 {: S! i8 ^4 ]% O# ~; i. E
  221.         return TRUE;
    * Z/ n% S; _; C* Z
  222. }
    1 _+ ~2 u# N  x
  223. / b4 k( }' `: [5 y4 e

  224. % h9 E5 r; o  N/ i
  225. /*************************************************************************************************************************# m3 r) [8 D0 f7 {
  226. * 函数        :                        static IIC_ERROR IIC_isCheckNackFlag(IIC_HANDLE *pHandle, u32 TimeOutUs)
    " o( M& W$ k+ I" e& o) E
  227. * 功能        :                        检查是否有NACK中断状态,如果有则清除掉- L& g  Y3 a9 N. v) W
  228. * 参数        :                        pHandle:句柄;TimeOutUs:超时时间,单位us" B3 O) s0 g7 I  e9 Q$ z
  229. * 返回        :                        IIC_ERROR
    ) C& J- \& [3 a' o( g( s& u/ l6 l
  230. * 依赖        :                        底层宏定义
    3 i" M  i- m& D9 i
  231. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>+ b) g: [1 v# w3 T( T
  232. * 时间        :                        2020-02-15) {6 s& J& c! |* N4 d
  233. * 最后修改时间 :         2020-02-15
    % ~( b2 l' V0 v9 ?
  234. * 说明        :                         如果有NACK中断,则先产生停止位,然后清清除掉所有的中断,并复位IIC,然后返回错误
    : z5 A, r* i, w% ~7 k
  235. *************************************************************************************************************************/  + m( }* W! R' O: k6 X& M
  236. static IIC_ERROR IIC_isCheckNackFlag(IIC_HANDLE *pHandle, u32 TimeOutUs)
    ; O  U- ]5 Z8 l* o, L1 m+ v% N
  237. {
    1 e% \2 B5 i# Y4 w
  238.         IIC_ERROR Error = IIC_OK;
    ; y% t& _; Q' K, {% b
  239.         0 M& M' j7 Y0 q% W( e. H% L
  240.         if(IIC_GetISR(pHandle) & IIC_FLAG_NACKF)        //接收到否定应答标志+ U8 r- d( I8 B, n0 @- Y* q* ?3 f
  241.         {
    , L: p1 g5 _5 S* \$ \/ {; I
  242.                 uart_printf("NACK : IIC_isWaitTXIS:CR1=0x%X\t", pHandle->I2Cx->CR1);1 q( G! @+ V5 h; `
  243.                 uart_printf("CR2=0x%X\t", pHandle->I2Cx->CR2);( z4 u8 w7 g& `8 ]" y
  244.                 uart_printf("ISR=0x%X\r\n", IIC_GetISR(pHandle));
    8 h4 s! D0 _! o/ w; X, \2 |
  245.                 //主设备下,如果没有开启自动产生停止位,则手动产生停止位( M- h% C) P: L) C1 L0 b! K, N7 ^
  246.                 if(pHandle->isMasterMode && ((pHandle->I2Cx->CR2 & I2C_CR2_AUTOEND) == 0))
    . F% s) }; t" k2 Y+ F
  247.                 {
    3 }  e1 {! V3 X* |3 i6 I
  248.                         IIC_SendStop(pHandle);                        //send stop( ?" i" y9 B! Z& ?& _8 p: J( N
  249.                 }
    1 x) v( \  h/ D* W1 ]
  250.                 //等待STOP标志有效) k9 y  m; x* j4 P
  251.                 while((IIC_GetISR(pHandle) & IIC_FLAG_STOPF) == 0)
    ' a; g" K0 I/ d
  252.                 {
    $ w" x8 f* o" m3 }
  253.                         if(TimeOutUs == 0)                                //检查是否超时了
    % b% ]  o1 A4 Q" x( r; F
  254.                         {
    & ~( Z5 T( L' y. `/ ?
  255.                                 break;& C; P. L8 L& C/ L8 w; N
  256.                         }                        
    " D9 E: y3 L  ^, Y0 ~1 N# A4 W) {  O
  257.                         TimeOutUs --;
    8 @% C( @' u. C9 V. ]: R6 d# E2 X' L
  258.                         Delay_US(1);                                                //延时
    9 |) a/ H9 O  F( x+ `
  259.                 }
    $ o4 d4 O# P# h2 _6 [' R
  260.                 //清除相关的中断标志/ P- y9 b3 l* I& `- O
  261.                 IIC_ClearISR(pHandle, IIC_FLAG_NACKF | IIC_FLAG_STOPF);        //清除NACK,STOP标志+ h; M8 i% Z8 {* u" y9 P
  262.                 pHandle->I2Cx->CR2 = 0;                                                                                //清除CR2寄存器
    + W, R: u! h: q
  263.                 IIC_SoftReset(pHandle);                                                                        //执行软复位" P$ M* T8 d' e. [
  264.                 if(TimeOutUs == 0)                                                //没有超时,就是硬件通讯出错了
    ) l/ K3 ^! U: k; R" o* h' K2 c
  265.                 {
    ; h) h9 h; x& ^* J( ?' \
  266.                         DEBUG("IIC发送stop超时\r\n");
    $ W2 q+ P% I. w- Z0 }7 T
  267.                         Error = IIC_TIMEOUT;                                //超时
    ) Q7 J3 K/ s* m5 ^: ^# j8 a
  268.                 }
    % _+ H7 L, i# A' `0 R, W3 `
  269.                 else
    0 n7 G1 U3 [2 ~" k
  270.                 {
    * z1 ^0 D+ v$ H$ F5 b2 @8 s
  271.                         Error = IIC_HAL_ERROR;                                //底层错误9 E0 h2 P2 G: d% i
  272.                 }7 u: }% E8 V, @7 E! h6 ?, _
  273.         }
    $ @4 d/ {) ?3 \- T& f2 D9 N
  274.         
    6 D0 L. m' q  T0 u
  275.         return Error;3 y1 @1 g2 O# n7 Y- x3 T4 v  }
  276. }
    3 _% p7 T% o5 v  R  F$ A
  277. 4 G) g( d1 R; |

  278. 1 s# y5 b' ~+ i$ L/ Z
  279. % @1 ~  X7 {8 x) t* x
  280. /*************************************************************************************************************************
    ' z9 o  d$ b& P0 Q! s0 I9 w
  281. * 函数        :                        static IIC_ERROR IIC_isWaitTXIS(IIC_HANDLE *pHandle, u32 TimeOutUs)% \" @& O4 k6 d" R0 B
  282. * 功能        :                        等待TXIS中断有效(等待 I2C_TXDR 发送寄存器为空)
    6 H( C0 K- M0 X$ p6 h
  283. * 参数        :                        pHandle:句柄;TimeOutUs:超时时间,单位us
    ' x  J: I& I" J7 r
  284. * 返回        :                        IIC_ERROR2 m- e5 @; V, \  X1 g5 C
  285. * 依赖        :                        底层宏定义
    6 w. x+ P) b, G9 B- [  `1 h, P; o
  286. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>. t# M' b: k( i9 E2 Y
  287. * 时间        :                        2020-02-156 n& ^2 c" E! j% C5 t* W
  288. * 最后修改时间 :         2020-02-15
    3 T0 A+ r; [! `$ g
  289. * 说明        :                         会先检查NACK中断,如果有NACK会直接退出的2 [/ X- Z3 @! I- w, Z7 K1 n
  290. *************************************************************************************************************************/  
    ( G4 P5 ^+ S$ {& f: ^( f4 f
  291. static IIC_ERROR IIC_isWaitTXIS(IIC_HANDLE *pHandle, u32 TimeOutUs)
    , X7 U1 @7 i) d4 O. n6 P% d
  292. {
    / f4 X. W# u. o4 l
  293.         //等待TXIS中断有效
    : M$ b1 a% g8 U3 q7 X" k
  294.         while((IIC_GetISR(pHandle) & IIC_FLAG_TXIS) == 0)
    6 G9 Q! o) e, c4 j+ z  o
  295.         {
    # t  s- C  [' i& H- a
  296.                 //有NACK中断,进行处理: W+ _9 `0 T" L
  297.                 if(IIC_isCheckNackFlag(pHandle, TimeOutUs) != IIC_OK)        
    ! N  T4 s$ F% N. i
  298.                 {- p& _$ S0 h5 V' F, g2 Z; b+ u& |6 n
  299.                         DEBUG("检测到NAK错误\r\n");& g4 ~8 u4 L3 D) l. K; e5 a& b2 Y
  300.                         return IIC_NACK;
    5 ]# v0 B* s' E/ F- a" ^) F
  301.                 }2 n( K+ ]* u" T1 P6 E9 p+ L
  302.                
    ; x+ t9 Z0 @: w- q# d
  303.                 if(TimeOutUs == 0)                                        //检查是否超时了
    2 l& C) U6 }4 [. {0 V
  304.                 {
    + ^* ?' C! v) U: x, X& c
  305.                         uart_printf("IIC_isWaitTXIS:CR1=0x%X\t", pHandle->I2Cx->CR1);5 g7 a3 t) x  \, }1 i: M5 T
  306.                         uart_printf("CR2=0x%X\t", pHandle->I2Cx->CR2);
    7 m+ Y( d+ l, ~* g  q8 V
  307.                         uart_printf("ISR=0x%X\r\n", IIC_GetISR(pHandle));
    3 r% h/ l+ U# O/ ^8 z
  308.                         
    " k- s" [# ]. F! ~. @; g
  309.                         IIC_SoftReset(pHandle);                //执行软复位4 n- u5 X$ j4 F1 m2 g! Q0 V
  310.                         return IIC_TIMEOUT;                                //超时
    $ G/ g( `- r& v- z9 d7 ~" o6 K; U2 o$ t
  311.                 }                        8 g  W. b/ l" W# J/ L( V- S" X
  312.                 TimeOutUs --;9 U- `% S( n0 a( c2 N
  313.                 Delay_US(1);                                                //延时
    1 z$ Y8 R4 X" M
  314.         }
    / _# L. p$ ~* U" a3 S
  315.         
    ) Z, x9 \/ X1 Q7 x6 o% J) a
  316.         return IIC_OK;
    ( i, O  r& H# p
  317. }6 h3 f) M3 P7 I8 w: y
  318. 5 L" H" z# q1 b- U4 ]$ Q6 z$ c6 ~
  319. 6 C. L* M8 z9 T; |
  320. /*************************************************************************************************************************4 _; F: j; u+ Q1 x
  321. * 函数        :                        static IIC_ERROR IIC_isWaitSTOPF(IIC_HANDLE *pHandle, u32 TimeOutUs)9 ]1 o+ y5 ~7 U9 y; C$ ^
  322. * 功能        :                        等待STOP中断有效(等待 发送结束 )
    - d3 R  O$ I9 s% D- ~+ n! \
  323. * 参数        :                        pHandle:句柄;TimeOutUs:超时时间,单位us
    5 z/ c) P4 C' b/ Q$ T
  324. * 返回        :                        IIC_ERROR
    , ?* d% I, {( A3 V' L6 @
  325. * 依赖        :                        底层宏定义
    6 t) ]' N* Q  `9 c; ~' |8 |+ U/ a
  326. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>6 Y$ d, Y' ~9 R; }' Q
  327. * 时间        :                        2020-02-15
    , C( n& g8 b! Y  B, r  N& K
  328. * 最后修改时间 :         2020-02-15. m2 A; W% G. \
  329. * 说明        :                         会先检查NACK中断,如果有NACK会直接退出的( V, @9 d7 k6 a& s" U) A: }: ?# q
  330. *************************************************************************************************************************/  
    3 H, d0 A' J& y" f: y' g; [* C1 v/ {
  331. static IIC_ERROR IIC_isWaitSTOPF(IIC_HANDLE *pHandle, u32 TimeOutUs)
    , S5 l# A& v/ l% z- n
  332. {4 a. j5 I  l; x
  333.         //等待STOPF中断有效* f" n; p% G7 I# a8 q
  334.         while((IIC_GetISR(pHandle) & IIC_FLAG_STOPF) == 0), d& b' f. r1 m* W, A; c$ S" E
  335.         {+ c  [5 G) h1 N0 ]; s0 o8 }/ S
  336.                 //有NACK中断,进行处理$ I' R4 o  V" C9 M  e1 x3 n: G
  337.                 if(IIC_isCheckNackFlag(pHandle, 5) != IIC_OK)        % w) K& w  C8 F3 y
  338.                 {8 c1 A! P9 f* i. M
  339.                         return IIC_HAL_ERROR;
      ]% j2 p6 i- D/ a3 t8 m0 c' v
  340.                 }
      ~3 T+ h! W: v5 j
  341.                 3 G$ X- D6 R4 N. S' B$ ]  e
  342.                 if(TimeOutUs == 0)                                        //检查是否超时了
    1 e% c2 `5 {3 `" D
  343.                 {
    0 o6 L% p5 j) ]; n
  344.                         IIC_SoftReset(pHandle);                //执行软复位
    3 ~" e+ {& k$ P# r* m7 R" {
  345.                         DEBUG("IIC等待结束超时\r\n");
    " v4 z0 u: H) m7 k$ B
  346.                         return IIC_TIMEOUT;                                //超时  _8 E, J' m0 {
  347.                 }                        
    9 x+ i  B4 ?: u: R1 j2 w
  348.                 TimeOutUs --;
    / O1 x, T: z& H9 Z
  349.                 Delay_US(1);                                                //延时
    . L( v- U& M2 ^8 [1 b
  350.         }
    + N' Y% w+ N- m# _: {
  351.         & |5 r2 r9 K" }5 a, \! w' R1 D& F. n
  352.         return IIC_OK;5 b: {2 N7 ^! d
  353. }( P! x- p5 m2 {- S8 K" s# s: Y

  354. ; }2 F* Z9 n1 q/ T2 V# r7 ^
  355. 9 h$ m6 a/ [* K: P& ~
  356. /*************************************************************************************************************************
    $ |8 T7 J# c6 U( l& V
  357. * 函数        :                        static IIC_ERROR IIC_isWaitFlag(IIC_HANDLE *pHandle,u32 Flag,bool isWaitFlagSet, u32 TimeOutUs)
    1 l* y9 X$ V( X/ ]& |
  358. * 功能        :                        等待中断有效" s' k  a/ @1 Q
  359. * 参数        :                        pHandle:句柄;Flag:需要等待的flag,见IIC_FLAG_xxx;isWaitFlagSet:TRUE:等待标志有效,FALSE:等待标志复位;TimeOutUs:超时时间,单位Us
    0 t/ @8 N4 B& X/ o) J, l, R
  360. * 返回        :                        IIC_ERROR
    3 ^" o( ~+ \2 u6 P2 A
  361. * 依赖        :                        底层宏定义8 K' Q. o% y6 ?" h3 r' A& m; `
  362. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>9 `1 l+ H! f3 N- a
  363. * 时间        :                        2020-02-15
    & ^  |9 m$ v# S. @- x$ a7 J
  364. * 最后修改时间 :         2020-02-15
    + b/ s% d% M+ A% ^
  365. * 说明        :                        
    ( _7 R! U) u- r$ B; X4 P# V' b
  366. *************************************************************************************************************************/  . v& J7 R9 {. N% P- ?
  367. static IIC_ERROR IIC_isWaitFlag(IIC_HANDLE *pHandle,u32 Flag,bool isWaitFlagSet, u32 TimeOutUs)
    6 x) H9 |$ @8 g) q* Y' x+ v
  368. {
    $ A9 Z% F7 O& w+ l
  369.         if(isWaitFlagSet)        //需要等待标志有效
    . X( Y. I2 O8 }  [7 K3 q) ^7 A% H6 l
  370.         {
    4 \0 l. B' C3 i
  371.                 while((IIC_GetISR(pHandle) & Flag) == 0); i# d/ a% X8 H1 o/ o
  372.                 {! a% j, @) c; W0 _0 R* H3 d
  373.                         if(TimeOutUs == 0)                                        //检查是否超时了
    7 `7 ^" R& O% m% ]
  374.                         {
    ! `; ]* a) ?" x( L
  375.                                 return IIC_TIMEOUT;                                //超时
    4 M, t& V  m6 m
  376.                         }                        . K  X. L8 h9 G, c. G
  377.                         TimeOutUs --;- t* Z8 e+ \& Z# G  B
  378.                         Delay_US(1);                                                //延时& u" G% R5 x* \) h, |( O# m' u
  379.                 }
    ) }+ {9 V! [7 l. s  V- g$ d( n
  380.         }- ?) e. X3 N1 m/ [! z
  381.         else                                //需要等待标志复位+ Z& A$ v# H' J" h$ j
  382.         {
    " l3 o# J( v. T8 Q, n, z  x! d
  383.                 while((IIC_GetISR(pHandle) & Flag) != 0)- i9 x" b  s$ J! I/ F: a
  384.                 {7 m/ `, N" m6 B6 l* L$ @9 P7 N
  385.                         if(TimeOutUs == 0)                                        //检查是否超时了
    / u( u. V* v; ~4 d, P
  386.                         {% q6 [4 a6 K& x% @; h0 P
  387.                                 return IIC_TIMEOUT;                                //超时
    0 ^5 z. x" N/ m3 s
  388.                         }                        7 p/ e8 a: T) Z, I) T; u
  389.                         TimeOutUs --;
    # ^  B, l9 _, H" f9 G) z, E
  390.                         Delay_US(1);                                                //延时
    ) e. X3 d" G' N1 a8 e# S: ]  F
  391.                 }
    / |8 ]8 j. b7 u/ d& @' d. \; Q
  392.         }
    ) `) N9 s2 O+ {# ]- S3 u
  393. , s; s( H. m) n* Y3 {% @' T) I) ?
  394.         return IIC_OK;
    ' e, R! ^& W% W0 a& O
  395. }, [. F* K) |5 N  M

  396. : l7 X/ K2 k' Y/ @$ w, r+ u5 K
  397. $ ^6 ]9 S! i/ ^+ j
  398. + ^2 d! x/ Z! h: S

  399. # M) g# Z# p9 O8 O
  400. /*************************************************************************************************************************$ Z5 F9 I8 U: c8 Q
  401. * 函数        :                        static void IIC_MasterTransConfig(IIC_HANDLE *pHandle, u16 SlaveAddr, u8 TransByteCount, IIC_RELOAD_END_MODE EndorReload, IIC_START_WR_MODE StartAndWR). j) u7 L' }( Q
  402. * 功能        :                        主设备传输配置(配置CR2寄存器)
    ; K8 u: v6 F5 K2 T
  403. * 参数        :                        pHandle:句柄;SlaveAddr:从机地址;TransByteCount:需要传输的数据长度;EndorReload:自动结束还是重载设置,见IIC_RELOAD_END_MODE;StartAndWR:开始读写控制,见StartAndWR0 p" y3 |+ \6 F! p* T& c3 [
  404. * 返回        :                        无
    * n: N5 d/ i  W0 e! u
  405. * 依赖        :                        底层宏定义
    9 x0 k) l) L# ?* O% B
  406. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>" C/ w, j1 `+ f1 C9 r! K- G7 L
  407. * 时间        :                        2020-02-15
      h7 D- [; `  N
  408. * 最后修改时间 :         2020-02-16
    9 z  C. c6 ]6 O# s# a0 Y4 n1 B) \
  409. * 说明        :                         在往 NBYTE 中设置最后一次传输的字节数前,必须把 RELOAD 位清零便于后续自动发送STOP。
    + i% X5 z8 Q3 B
  410.                                         当 RELOAD 位置 1 时,AUTOEND 位将不起作用;
      E  |6 A" S* Q5 y
  411. *************************************************************************************************************************/  ) b8 e5 c! z4 e5 W- @
  412. static void IIC_MasterTransConfig(IIC_HANDLE *pHandle, u16 SlaveAddr, u8 TransByteCount, IIC_RELOAD_END_MODE EndorReload, IIC_START_WR_MODE StartAndWR)
    0 w" G/ e2 V( F" e# z( f# ?
  413. {% h8 g% T' [3 q3 W6 g
  414.         u32 temp = 0;0 d% M5 q% r- ~( k; X
  415.         
    ! C5 x  w( ?: W3 J3 [( b
  416.         //先读取CR2寄存器的值
    ' |! F& R8 I' H
  417.         temp = pHandle->I2Cx->CR2;
    " E) N& N; y' M: U! l
  418.         //清除掉相关的字节0 H4 y( U, W9 H% X9 ?+ m1 K! ]5 E
  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 X1 d) ?6 {/ L3 x' x% U
  420.         //生成配置数据( Y% O8 M% d4 a9 I! O' h. o9 y6 G+ ]
  421.         temp |= (u32)(((u32)SlaveAddr & I2C_CR2_SADD) | (((u32)TransByteCount << 16 ) & I2C_CR2_NBYTES));% K4 X9 J2 e/ T& H# h
  422.         //重载与自动结束只能二选一# M* m( y9 `4 }, v; \
  423.         if(EndorReload == IIC_AUTOEND_MODE)         1 h4 V* m7 u) ^$ A9 L8 I& e
  424.         {+ h( E( K) {# [6 z$ X: A
  425.                 temp |= I2C_CR2_AUTOEND;        //自动结束模式
    / M% U3 Y/ F1 l) K
  426.         }7 U- Z: A; N2 W# Z( {/ N
  427.         else if(EndorReload == IIC_RELOAD_MODE)
    ( Z# A! ]" x& Y2 W& _: D
  428.         {/ P6 Q7 r' g, K! [, [3 L
  429.                 temp |= I2C_CR2_RELOAD;                //NBYTES 重载模式( @8 N4 v  c0 ~; x3 x3 y3 t
  430.         }
    " p  d  [* n  [6 k
  431.         
    ) U: A1 p% J* e& T# ~6 t. D
  432.         switch(StartAndWR)
    " ^! X  Y8 D! l* L4 a) Q
  433.         {- }! E7 Q& |5 P% s
  434.                 case IIC_NOSTART_WRITE        :        break;        //没有开始的写-默认就是这样的
    4 d8 f# H7 c2 ?1 B, d- N9 I7 j
  435.                 case IIC_NOSTART_READ        :                        //没有开始的读-用于后续数据读取
    . l5 e1 f: f2 g" W& d1 `
  436.                 {8 c+ M" D& k7 Y9 o7 t' M  g
  437.                         temp |= I2C_CR2_RD_WRN;                        //读取
    % `. P, V1 G# H, q
  438.                 }break;8 {7 S0 i1 p& p  }; v5 m
  439.                 case IIC_START_WRITE        :                        //生成开始写4 C- R7 p( [, G- d0 G. P) A1 N
  440.                 {/ v/ o+ R% M8 a+ G+ q3 P! h
  441.                         temp |= I2C_CR2_START;                        //启动传输* X: ~$ Y8 y8 r! n
  442.                 }break;5 J) s# r. w+ C6 q0 R! o. i
  443.                 case IIC_START_READ                :                        //生成开始读        
    # e1 \  A2 B6 |! Q% E- B
  444.                 {( N. _: K5 ]7 T1 \
  445.                         temp |= I2C_CR2_RD_WRN;                        //读取
    2 C8 @& a. u; w" G& J& N4 h+ o
  446.                         temp |= I2C_CR2_START;                        //启动传输
    - w5 S+ l, k3 _  a9 t+ l
  447.                 }break;
    3 F# `3 H) R8 {  Y' J; w
  448.                 default:break;
    " N! T* B! u" e' l" H: K, F; x
  449.         }
    9 T$ f% e! w! H, f
  450.         
    5 a: b4 _( h% [' {" C: S  B: M% i# v- j
  451.         //uart_printf("准备写入CR2=0x%X\t", temp);/ x+ q3 ~; @* r  I# X% y9 O
  452.         //更新到寄存器
    . A0 N# b$ j, z3 Y8 I' [+ P
  453.         pHandle->I2Cx->CR2 = temp;  //测试. @9 b0 ]* o0 ]7 t1 D
  454.         //uart_printf("ISR=0x%X\r\n", pHandle->I2Cx->ISR);
    3 C: i+ W; o# o$ @
  455.         Delay_US(100);
    - p$ h: H! r+ P) I, ~; e" f; J
  456. }1 k  T1 l1 I. c) n

  457. 8 v4 X! `/ j4 e- S# j
  458. . f: @) f! ?0 c  v
  459. /*************************************************************************************************************************
    * L( H* f' e! v, K6 C" z2 I# U
  460. * 函数        :                        static IIC_ERROR IIC_SendByte(IIC_HANDLE *pHandle, u8 data, u32 TimeOutUs)' [1 U+ b/ q/ V' j, _
  461. * 功能        :                        IIC发送一字节
    ' f$ U! k" X) B/ _- z4 X
  462. * 参数        :                        pHandle:句柄;data:待发送数据;TimeOutUs:超时时间,单位us
    % C: ^4 @; t& f, q9 g" v8 c
  463. * 返回        :                        IIC_ERROR5 m3 s# f' X1 {2 [/ o- U' R
  464. * 依赖        :                        底层宏定义. F, E% x, b( X3 @+ ]" u
  465. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    ; ^$ y8 A) {& ^
  466. * 时间        :                        2020-02-155 {+ m  B+ D0 D: Y: P! a1 d
  467. * 最后修改时间 :         2020-02-16
    ' Z" e# }' D6 c
  468. * 说明        :                         TXIS有效后才会进行数据发送,不会检查数据发送是否完成。
    ' B9 ]& }) o: ~' Z0 R" i5 \* s, X
  469.                                         如果最后一个字节发送完成后不会再触发TXIS中断,只会触发TC中断
    ; n1 \. C& V; m& O
  470. *************************************************************************************************************************/  
    3 H' a# V* j) ?& T  d* T
  471. static IIC_ERROR IIC_SendByte(IIC_HANDLE *pHandle, u8 data, u32 TimeOutUs)- n# b) P! E; i( G! S  }& Q* ]
  472. {
    3 e: T3 F1 a+ [) [
  473.         IIC_ERROR Error = IIC_isWaitTXIS(pHandle, TimeOutUs);                                //先等待可以发数据% l8 s. S3 A2 B0 P
  474.         if(Error != IIC_OK) return Error;
    + Z8 C/ I2 Y2 Z6 ]0 Z% I! u0 o
  475.         pHandle->I2Cx->TXDR = data;                                                                                        //写数据到发送寄存器-不会等待数据发送完成        " A2 g7 }8 m' z: C# W9 B; q8 s; B

  476. 7 T" Q1 l  w% G! p
  477.         return IIC_OK;
    ; y: P1 q9 T& r! L: x! `( X9 T9 g$ ?
  478. }
    * m# w( ^* v* h- [. G' y$ d
  479. % p8 i7 {& B' u
  480. /*************************************************************************************************************************
    " c! ], @( u) F$ \  C8 O: G) c: u
  481. * 函数        :                        static IIC_ERROR IIC_MasterRequestWriteAddr(IIC_HANDLE *pHandle, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, 4 s* ?' r& j: x( R# \& j4 A9 v
  482.                                                 bool isRead,u32 TimeOutUs)' V$ H* @4 U  F- p: d: i2 k
  483. * 功能        :                        主设备请求发送从机地址与目标寄存器地址
    1 J# ]$ J- Y' b5 J  X' i. K
  484. * 参数        :                        pHandle:句柄;SlaveAddr:从机地址;RegAddr:寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,9 \" l; _& k! J0 h
  485.                                                 FALSE:16bit寄存器地址;isRead:TRUE:这个操作是读取寄存器;否则是写入寄存器;TimeOutUs:超时时间,单位us
    4 p- j: F9 g5 h* @- Q4 i9 ]* g
  486. * 返回        :                        IIC_ERROR: }# u- b* Z8 n% R+ C0 S' m
  487. * 依赖        :                        底层宏定义
    5 H- z, V' [8 x8 K- @# I/ s9 o; U/ _9 j
  488. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    3 a$ u5 I* ~% I  z; ]& @
  489. * 时间        :                        2020-02-15* H2 o/ R' ?8 o7 }( ]0 `
  490. * 最后修改时间 :         2020-02-165 k# ?% F1 @1 d) X; R; q  `
  491. * 说明        :                        
    : j6 f3 p) r& Z/ W, P
  492. *************************************************************************************************************************/  9 p2 X! ~0 {9 s! D1 a  s% D5 M
  493. static IIC_ERROR IIC_MasterRequestWriteAddr(IIC_HANDLE *pHandle, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,bool isRead, u32 TimeOutUs)' S1 K2 ^9 R( R  }$ D; {
  494. {        2 P- p8 t9 }0 w. y' ^6 \
  495.         IIC_ERROR Error;
    ( V  n0 \# o9 U! v3 G# j
  496.         
    # d6 F7 X5 g1 l% @3 p1 e% J
  497.         //uart_printf("WriteAddr1:CR1=0x%X\t", pHandle->I2Cx->CR1);
    % ~& d6 a3 B$ f( d4 `# F6 r
  498.         //uart_printf("CR2=0x%X\t", pHandle->I2Cx->CR2);6 a3 b3 k( A$ q1 G' z
  499.         //uart_printf("ISR=0x%X\r\n", pHandle->I2Cx->ISR);3 J" T5 t2 J- F4 r
  500.         //传输配置,并启动传输,发送起始序列,开始IIC传输了! \( z& s/ U9 S( L) ]
  501.         //如果是读取则使能软件结束,如果是写则是自动重载0 r  [  q- {" h
  502.         IIC_MasterTransConfig(pHandle, SlaveAddr, (is8bitRegAddr==FALSE)?2:1, (isRead)?IIC_SOFTEND_MODE:IIC_RELOAD_MODE, IIC_START_WRITE);        //传输相关配置-写,并启动传输
    8 K( @2 [+ {' q2 O
  503.         - r/ ^+ B$ G  `. {
  504.         //开始发送寄存器地址+ k5 |) F; b1 g
  505.         if(is8bitRegAddr==FALSE)                                                                                                //寄存器地址是16位的,IIC通常是MSB高位在前,需要进行高低位对调
    : l+ j- R3 g; f% _. W5 q- a
  506.         {
    9 _% ?9 U5 N) V& Y8 b, V
  507.                 Error = IIC_SendByte(pHandle, RegAddr>>8, TimeOutUs);        //先发送MSB-非最后一字节  D# ?1 y# C2 p+ ?! [1 @, K
  508.                 if(Error != IIC_OK)
    3 v0 x4 r9 F3 m% G4 j
  509.                 {
    $ \% Q2 G& Y, ~# @% s
  510.                         DEBUG("IIC发送寄存器地址MSB失败\r\n");
    6 Y; K) b- D7 s1 {9 I
  511.                         return Error;  |7 F* }0 `* o
  512.                 }        : v' T( _3 M- s5 q* g8 d* D: `! U
  513.         }, G0 i! {' Z; r% }
  514.         Error = IIC_SendByte(pHandle, RegAddr & 0xFF, TimeOutUs);        //再发送LSB-最后一字节
    9 s  p1 W% f3 O1 r1 n
  515.         if(Error != IIC_OK)( `4 e) \/ j0 W$ f3 l( u* n
  516.         {0 [" C$ e, C& u1 G& A. _) [
  517.                 DEBUG("IIC发送寄存器地址LSB失败\r\n");
    0 ?7 J& S6 q9 v) f+ q& x
  518.                 return Error;
    . a2 M* T- G0 A( }. W+ s# ]* r
  519.         }
    - c: Q$ j3 `! g- X2 `7 H* H% P! P
  520.         //等待全部数据发送完成
    9 r. n2 y6 a5 e& j2 G
  521.         if(isRead)        //读取方向-非重载,等待数据传输完成 当 RELOAD=0、AUTOEND=0 且 NBYTES 数据传输完成时,该标志由硬件置 1。
    6 G" x% {- C+ h) k' K) d; |9 V9 \
  522.         {! n) X$ ^2 N% u$ @$ f
  523.                 if(IIC_isWaitFlag(pHandle, IIC_FLAG_TC, TRUE, TimeOutUs) != IIC_OK)" R! |! q5 T- [
  524.                 {
    ! h1 v- F- ?) e! B+ v
  525.                         return IIC_TIMEOUT;
    % E5 v0 {: T4 r5 M5 i; M& G& @% F
  526.                 }7 F5 N% f) p- Z! N' F6 g
  527.         }        
    . C* O$ j  ^6 l9 {4 s% b0 h
  528.         else //写入方向,等待重载
    : h0 Q1 k& t0 d& k: Z/ v* l
  529.         {2 I3 h+ I8 a) R5 v; k& ]* {7 x
  530.                 if(IIC_isWaitFlag(pHandle, IIC_FLAG_TCR, TRUE, TimeOutUs) != IIC_OK)) V! n$ d. q! k- m6 U
  531.                 {/ S" |4 O& W$ T. i! O
  532.                         return IIC_TIMEOUT;
    : j9 _' ]* Y/ q
  533.                 }
    " S7 p. N; `$ P* p9 N) B( w( s
  534.         }
    ) R( g$ p5 Z1 x
  535.         
    9 x/ m: d2 J" N; s! z
  536.         return Error;6 \+ V2 J$ }; K. I: H: q5 p7 T
  537. }
    6 D  f4 ?5 b' P0 c9 B2 n- D1 Z

  538. , D8 _2 {' A# x/ U
  539. ) L6 G: a/ [' y" x$ l
  540. /*************************************************************************************************************************
    ( O1 Q% D9 S6 W2 g
  541. * 函数        :                        static IIC_ERROR IIC_WaitRxOneByte(IIC_HANDLE *pHandle, u8 *pData, u32 TimeOutUs)" Z" a/ S/ k* f  q: L" }
  542. * 功能        :                        等待接收一字节数据
    & [2 ~3 y* Z: d
  543. * 参数        :                        pHandle:句柄;pData:接收的字节数据缓冲区;TimeOutUs:超时时间,单位ms
    ! @3 F- C1 f5 c) S
  544. * 返回        :                        IIC_ERROR
    6 R; p/ W) b5 v1 J# K7 Q
  545. * 依赖        :                        底层宏定义$ ]4 o# ~% F2 }. `" U) k
  546. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>1 Y6 p; f0 W3 J" f; z( K, d4 m, U
  547. * 时间        :                        2020-02-15# A# ]/ Y# `$ q0 y, O4 ^8 D
  548. * 最后修改时间 :         2020-02-156 k  S' J# [* G6 p5 X! A/ d5 U
  549. * 说明        :                         当RXNE有效后读取一条数据,否则可能会超时
    5 z$ z2 q. ~* ]0 U" \6 ^
  550. *************************************************************************************************************************/  
    " ?- @# `& {7 G  d* O
  551. static IIC_ERROR IIC_WaitRxOneByte(IIC_HANDLE *pHandle, u8 *pData, u32 TimeOutUs)5 Y% V4 F8 H' o/ U) Q4 K
  552. {
    ( i/ u, O+ a+ N* d; E: L
  553.         while((IIC_GetISR(pHandle) & IIC_FLAG_RXNE) == 0)        //等待RXNE有效
    # P# G1 g5 |2 Q! y( O' R
  554.         {  y. N) _) c; O( b
  555.                 if(TimeOutUs == 0)                                        //检查是否超时了
    ! S3 Q4 I5 N1 A
  556.                 {
    ' C( U% o' |; J2 t
  557.                         DEBUG("IIC等待接收超时\r\n");( I+ C7 i" A3 d9 ^9 ^
  558.                         return IIC_TIMEOUT;                                //超时6 n8 Y. s8 X# {  B2 m+ a
  559.                 }                        ; l& z$ r7 z& ?6 b' s  E/ e+ H4 j8 L
  560.                 TimeOutUs --;9 U& ]7 S" O& {- P5 Z( V
  561.                 Delay_US(1);                                                //延时
    & H* Z5 o' B1 n+ i8 U
  562.         }' t7 Y% j" U7 C% \3 f5 M$ V  [% c
  563.                   d. n+ L; u/ [  t9 ]! Q
  564.         *pData = pHandle->I2Cx->RXDR;                                                        //读取收到的数据
    $ m& o, B, h& M
  565.         return IIC_OK;
    7 I* t# x3 H% k7 y
  566. }
    4 n5 T3 j; |0 k! }# y# }
  567. 9 g2 P5 a2 T. K4 A/ r5 A& E
  568. ! V5 M) e7 S. J7 a' u
  569. /*************************************************************************************************************************+ W! k1 a& X* P; F- c. O' l* M# s
  570. * 函数        :                        IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr,
    + t6 L9 o; [! O; {1 Z
  571.                                                 u8 *pDataBuff, u16 ReadByteNum)' ~( m) {2 d( D* P
  572. * 功能        :                        IIC读取寄存器(可以读取1个或者多个寄存器)' R9 g; x0 T. A$ e- b5 l! C6 I
  573. * 参数        :                        ch:IIC通道,见IIC_CH_Type;SlaveAddr:从机地址;RegAddr:要读取的寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,FALSE:16bit寄存器地址;
      P! A5 Q- z* o. I1 W
  574.                                                 pDataBuff:接收的字节数据缓冲区;ReadByteNum:要读取的寄存器数量;3 F1 u- d( m4 f/ `$ C2 T
  575. * 返回        :                        IIC_ERROR, Y' L) w6 p6 `, v
  576. * 依赖        :                        底层宏定义& U7 y* k- r9 m" B. a1 r) V) {
  577. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>' @& k( E0 T+ j! w2 A
  578. * 时间        :                        2020-02-159 \: y' ]% H9 N# `
  579. * 最后修改时间 :         2020-02-15
    / A$ p. ?' B$ _4 k, K* g
  580. * 说明        :                         读取的数据都是小端模式,如果是16bit的寄存器,请读取偶数个数据,并且需要另外进行高低字节对调最后组成16bit数据* I) ~. ?2 @: K
  581.                                         可能的意外:比如一个异常的操作可能会导致IIC一直忙,此处检测到忙后会直接复位IIC,但是必须在应用层做好重入保护,比如! q3 e$ d! U0 t
  582.                                                 增加信号量0 `+ a' }) B4 H* Z( p2 @: M( x
  583.                                         通过测试发现:在函数进入的时候,清除掉中断状态,之后几乎检测不到IIC忙的情况,当然在结束的时候如果检测到忙会主动发送一个STOP,在
    8 x& q5 L* A6 i/ Z9 f1 ]9 c
  584.                                                 操作失败的情况下,会对IIC进行软复位,确保本次的错误不会影响下一次的IIC操作。5 _5 ]* m( N, Z- N
  585. *************************************************************************************************************************/. [  U9 H& L! {1 z$ n  {* {
  586. IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 ReadByteNum)9 I; z  T, x) X* J+ N
  587. {9 B1 }3 E, u) H  v+ [
  588.         IIC_ERROR Error = IIC_OK;
    ( d3 t* _1 q6 h7 G' @, O+ N
  589.         u16 ReadCount;  h7 T" [1 A7 x5 J* `* N/ H! Z
  590.         IIC_HANDLE *pHandle;! J' T( O9 n3 C
  591.         
      o4 g, E# }* \" L7 K4 S9 G* k- \5 [
  592.         if(ch > (IIC_CH_COUNT-1) || pDataBuff == NULL || ReadByteNum == 0)
    % k! J/ ]9 R9 b4 t
  593.         {
    ' }; \) Y7 _3 I* Z# W
  594.                 DEBUG("IIC错误:无效的参数\r\n");/ R3 P0 W. u* G% ]" Q3 c
  595.                 return IIC_PARAMETER_ERROR;
    4 T, {6 R8 ?, _0 S1 k  @. D6 s
  596.         }
    + y' q, K" ^+ ~" k, d$ K
  597.         pHandle = &sg_IIC_Handle[ch];                                        //获取相关通道的句柄
    + C/ S! T' `2 G- c  t- x- G
  598.         2 p! g# g: z/ L* i3 u1 b: B" T
  599.         if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                        //忙1 B; F# l7 y. z
  600.         {8 u( B, _$ ]" p) W* Y! ?
  601.                 IIC_SoftReset(pHandle);
    0 v, w; L4 K7 i; D' |) ?$ Y
  602.                 DEBUG("IIC错误:总线忙,复位总线,可能直接打断别的地方IIC操作,做好保护措施\r\n");
    , X3 A5 r( B4 d" Y- U
  603.                 if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                //忙( E9 m* O& A4 |6 a8 |
  604.                 {" {- I" a* Z, L$ a3 x" p
  605.                         DEBUG("IIC错误:总线忙,复位后未恢复\r\n");7 V% U, g2 ~* S1 H3 @* a
  606.                         Error = IIC_BUSY;, b- Q, o, d4 t% B' r; K
  607.                         goto end_loop;7 w8 H2 `$ F9 k! W
  608.                 }
    : G% {: x% g" K! Z9 I, d' ~
  609.         }! ^9 Y5 h6 r4 q6 @1 ^, P' J
  610.         IIC_ClearISR(pHandle, IIC_GetISR(pHandle));                //复位错误状态' {4 ^9 A7 ?" P2 K3 R6 b6 a) g
  611.         IIC_ClearCR2(pHandle);                                                        //复位CR2寄存器
    : y% s% r2 {, m( U: `/ l* b
  612.         //主设备请求发送从机地址以及寄存器地址-会切换到写方向,并发送START4 d0 D" _/ c5 u
  613.         Error = IIC_MasterRequestWriteAddr(pHandle, SlaveAddr, RegAddr, is8bitRegAddr,TRUE, pHandle->TimeOutUs);+ U* _3 V' P2 q+ F/ D: r5 V
  614.         if(Error != IIC_OK)# P* Y9 B; T- }3 A  c4 S% d0 \! }
  615.         {
    $ E3 Y, Y( _( @3 e- k
  616.                 goto end_loop;
    5 G. K' W5 I& s& R( t" W2 P3 k4 o6 Z
  617.         }8 q! ^% ?) _/ A$ d
  618.         //发送后续数据, W* h4 {/ j  v4 n7 K
  619.         if(ReadByteNum > 255)        //如果超过255字节,则需要分多次读取-后续还有数据,需要重载
    1 W( S; w+ T9 h1 |# I
  620.         {- u/ |  n! V- s/ N
  621.                 ReadCount = 255;        //本次需要读取的数据长度255) u& W( l  d& i$ a) V2 Z6 F
  622.                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_RELOAD_MODE, IIC_START_READ);        //传输相关配置-读取,并启动传输               
      X' e0 @4 u) @$ m- a/ Q
  623.         }
    % g) P8 a, x3 K
  624.         else" V& |$ e8 }- X( m1 z
  625.         {8 {) d+ ~& A7 n& g
  626.                 ReadCount = ReadByteNum;        //记录本次需要读取的数据长度-最后一次通讯后自动结束
    $ ^' s8 {9 z1 A: d3 Z) z
  627.                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_AUTOEND_MODE, IIC_START_READ);        //传输相关配置-读取,并启动传输
    0 h2 T/ x: K6 X8 r
  628.         }+ G" U! U$ O8 D/ `
  629.         
    & L' a' f3 }) U5 j8 j8 O$ Z; ^3 h! z
  630.         //循环等待接收数据完成
    1 ^8 o: {' ^9 j# L
  631.         do
    ' _1 E% N7 C+ l9 l0 ]" i
  632.         {
    ! w: c% ~! a$ q$ h3 p% Q# b+ {
  633.                 //uart_printf("读ISR=0x%X\r\n", pHandle->I2Cx->ISR);: ]7 {# }2 S( ]) ~
  634.                 Error = IIC_WaitRxOneByte(pHandle, pDataBuff,  pHandle->TimeOutUs);                                        //接收1字节数据3 S# x1 [* K- X/ H, g
  635.                 if(Error != IIC_OK), r# W! R7 H( `7 a2 z6 O
  636.                 {" {0 }1 J' Y& H( Y
  637.                         goto end_loop;# J0 n* R* R  v$ L" B
  638.                 }, [  v0 `1 R! O$ U0 W
  639.         & |6 V7 g$ o0 P8 ^( A0 W
  640.                 pDataBuff ++;; @: h! J5 q5 O
  641.                 ReadCount --;
    8 e7 J! ?7 k9 L6 i$ w9 m
  642.                 ReadByteNum --;
    6 L, W3 }, A9 a& s
  643.                 if((ReadByteNum > 0) && (ReadCount == 0))        //还有数据要读取! A/ y7 K: P$ m$ I( s' w% y: h
  644.                 {2 K. a7 r- M" t! P! g) E7 y
  645.                         if(ReadByteNum > 255)        //如果超过255字节,则需要分多次读取
    $ S8 l8 H: O1 C  G0 a
  646.                         {5 d3 b; p, y# J4 _( e. e
  647.                                 ReadCount = 255;        //本次需要读取的数据长度255-后续还有数据,需要重载# J# p- S  X8 S5 D2 J7 n4 _
  648.                                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_RELOAD_MODE, IIC_NOSTART_READ);        //传输相关配置-读取,不启动传输                        
    & I0 h' v+ V, t& f' g1 {
  649.                         }
    5 {3 e4 k( }% S; p7 P
  650.                         else
    " P8 H7 Y" j" A* g: l, i: M
  651.                         {3 |# O) Y3 P9 ~' F
  652.                                 ReadCount = ReadByteNum;        //记录本次需要读取的数据长度-最后一次通讯,自动结束( S; X. T5 `' ?: e2 ]
  653.                                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_AUTOEND_MODE, IIC_NOSTART_READ);        //传输相关配置-读取,不启动传输                        
    ( P- [! n& @0 h6 R( Y4 c0 d) ^8 Q4 _
  654.                         }
    1 Y- m3 |) H7 q0 z1 ]
  655.                 }
    9 y( f6 I9 p, A/ m
  656.         }while(ReadByteNum);9 `" m; |' V1 }: j. m. A
  657.         //读取完成了,等待STOP位有效
    ) c: ?5 v2 F; J6 e4 [/ t( f5 @
  658.         Error = IIC_isWaitSTOPF(pHandle, pHandle->TimeOutUs);8 n9 q  X5 K* c0 ?
  659.         if(Error != IIC_OK) " K3 f/ S6 e* ?! L8 s
  660.         {2 I/ J9 O6 C- N8 _8 [
  661.                 Error = IIC_STOP_ERROR;' y) y9 P  P, I" b- ~) m0 z
  662.                 goto end_loop;
    8 n: k8 ^8 F$ @( ?
  663.         }        
    4 y: l0 m. I0 H: W
  664.         IIC_ClearISR(pHandle, IIC_GetISR(pHandle));                //复位错误状态8 \* y; c+ g8 x4 H; N
  665.         
    / {8 A' d: y. h, @& Z' O
  666. end_loop:        
    ' v% {* o2 @) B
  667.         IIC_ClearCR2(pHandle);                                                        //复位CR2寄存器        " h, r7 C' n5 {) |9 _* A
  668.         if(Error != IIC_OK)/ Q9 n+ c: f, C; q+ V
  669.         {
    * @8 m1 V3 A! B) b) |6 T
  670.                 IIC_SoftReset(pHandle);                                                //IIC软复位,清除掉错误8 {" S& c: T! _' ]  Q( Y) w
  671.                 DEBUG("[IIC R错误]:%d\r\n", Error);2 @, Q. c1 h8 n2 m, C, S
  672.         }0 h" C: G5 f! R, S# U. T. G
  673.         if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                        //忙,注:奇怪的是高速读取的时候,此处可能会检测到忙,TC标志有效,正常此处不应该有TC标志的
    : s" V& ^9 ^' e
  674.         {+ X; r% Q/ D' D" Z4 _
  675.                 IIC_SendStop(pHandle);                                                //总线忙,发送一个STOP,释放掉总线: Y1 n1 [5 w* Y$ ~6 A6 q) \5 k/ g4 V
  676.                 DEBUG("IIC R结束:总线忙 ISR=0x%X\r\n", pHandle->I2Cx->ISR);                9 }8 p8 c7 j3 X* a
  677.         }* H/ g2 x6 A; x' \' p1 X' z7 M
  678.         / g. |/ j( o- X" p2 S8 Y! `6 i, ~3 t
  679.         return Error;
    7 y% t: d7 b/ D2 `
  680. }
    $ V# M1 l) ^1 N- a) y& i8 \

  681. 1 @8 y/ i- w1 ^- C; z9 g& w( v
  682. ( |/ b1 C6 ]( _( W/ m: J
  683. /*************************************************************************************************************************  k; X/ Z" }, R  X& x6 Z5 w4 W& H0 c
  684. * 函数        :                        IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, 4 I2 _+ b) O9 q4 F! o, H
  685.                                                 u8 *pDataBuff, u16 WriteByteNum)
    7 ~6 K( @* D* p
  686. * 功能        :                        IIC写寄存器(可以写1个或者多个寄存器)" d/ g+ c& A2 o& t7 o* z$ c
  687. * 参数        :                        ch:IIC通道,见IIC_CH_Type;SlaveAddr:从机地址;RegAddr:要写入的寄存器地址;is8bitRegAddr:TRUE:8BIT寄存器地址,FALSE:16bit寄存器地址;
    9 @  U) {8 P2 T5 `9 P- x
  688.                                                 pDataBuff:写入的字节数据缓冲区;WriteByteNum:要写入的寄存器数量;  a% B- ?- k4 V6 r
  689. * 返回        :                        IIC_ERROR
    , ^! ?1 e" y4 S) r+ y) S
  690. * 依赖        :                        底层宏定义! S- \6 ?! K$ u) q
  691. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>7 w; Y! l: F2 F, T: X! ^
  692. * 时间        :                        2020-02-16/ [$ r5 E) h+ q$ e/ q/ ~1 S+ y
  693. * 最后修改时间 :         2020-02-168 T7 |9 |3 P% @, K. e, Q. d; N
  694. * 说明        :                         写入的数据都是小端模式,如果是16bit的寄存器,请写入偶数个数据,并且需要提前进行高低字节对调最后组成高字节在前的数据buff. r  _: u2 `" u. ^
  695.                                         可能的意外:比如一个异常的操作可能会导致IIC一直忙,此处检测到忙后会直接复位IIC,但是必须在应用层做好重入保护,比如# e+ b, {+ u2 V7 K! [
  696.                                                 增加信号量
    2 Z, `6 }) n/ \
  697.                                         通过测试发现:在函数进入的时候,清除掉中断状态,之后几乎检测不到IIC忙的情况,当然在结束的时候如果检测到忙会主动发送一个STOP,在: N: H' t5 y! U! r
  698.                                                 操作失败的情况下,会对IIC进行软复位,确保本次的错误不会影响下一次的IIC操作。
    : W" e4 d! S, B% w+ @$ V8 V, G, o
  699. *************************************************************************************************************************/# W- h  f" ]2 [: m
  700. IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 WriteByteNum)
    0 I4 v# O  X( K7 V! j
  701. {/ c3 W+ g) K2 H
  702.         IIC_ERROR Error = IIC_OK;& |1 n& J" I7 S$ T) P
  703.         u16 ReadCount;; I& h/ H0 K* _2 q
  704.         IIC_HANDLE *pHandle;6 K; d1 l2 Y$ r
  705.         
    $ F' n5 A$ Q- C; V0 O1 y! {
  706.         if(ch > (IIC_CH_COUNT-1) || pDataBuff == NULL || WriteByteNum == 0)
    : @5 P+ i5 `# w- n3 [5 ?
  707.         {
    " y  N# |. ^8 M1 i3 U  r' ~3 W
  708.                 DEBUG("IIC错误:无效的参数\r\n");- U  I8 t1 t! B4 N7 x+ A
  709.                 return IIC_PARAMETER_ERROR;$ s* g# k- K8 C" H: F  E- e
  710.         }
    . p/ R1 R) ]: a, g7 ^
  711.         pHandle = &sg_IIC_Handle[ch];                                        //获取相关通道的句柄& Z5 q+ ^4 u8 a' ^( n+ e# F
  712.         
    2 ]+ z. f; [1 S. u. H: o: c
  713.         if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                //忙* Z8 {7 E- ?. `6 u+ o
  714.         {
    3 W: Z" V( L9 {0 B; u4 h
  715.                 DEBUG("IIC错误:总线忙,复位总线,可能直接打断别的地方IIC操作,做好保护措施\r\n");+ D. l* {) W- x' B& v& n
  716.                 IIC_SoftReset(pHandle);
    8 H# R" }4 w; `! K/ J) w& g4 `9 o
  717.                 7 h( e6 B7 b, {/ z+ j( G7 X, n8 F
  718.                 if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)        //忙# f& ]- ?( p$ L) `; [
  719.                 {8 ]0 _; s% ?! j. m/ q1 h
  720.                         DEBUG("IIC错误:总线忙,复位后未恢复\r\n");% b, f. o/ F3 S4 P; N$ r: E' }* T
  721.                         Error = IIC_BUSY;, o  T! C# h* I
  722.                         goto end_loop;% [- R  G: @- ]* I8 J8 B. n
  723.                 }, }& h4 p8 p8 |6 i
  724.         }
    / {( i# |2 J% k% G4 \
  725.         
      I. D3 O: x- I2 |
  726.         IIC_ClearISR(pHandle, IIC_GetISR(pHandle));                //复位错误状态% v$ e. n% j1 ~7 ~4 y8 N( m" b
  727.         IIC_ClearCR2(pHandle);                                                //复位CR2寄存器- s+ A+ s* V0 ^6 V! v
  728.         //主设备请求发送从机地址以及寄存器地址-会切换到写方向,并发送START0 N( Y1 Q8 o6 y+ L  U3 O
  729.         Error = IIC_MasterRequestWriteAddr(pHandle, SlaveAddr, RegAddr, is8bitRegAddr,FALSE,  pHandle->TimeOutUs);
    $ R& X; z3 e+ r
  730.         if(Error != IIC_OK)5 C# Q3 }' z2 M) \) ^
  731.         {7 x$ M0 z& V  ~$ F  L2 \- d+ ?. C
  732.                 goto end_loop;3 b, n% u) ~+ P: f/ x4 s  e
  733.         }
    ' l& F6 H+ s% t) w: B
  734.         //发送后续数据' t% i8 C) x6 C4 n* [" @# e/ A- B
  735.         if(WriteByteNum > 255)                        //如果超过255字节,则需要分多次写入-后续还有数据,需要重载; w7 ]% e9 k; P/ _! M% s; O) D; ]
  736.         {+ U- X0 h) f" `( y$ P
  737.                 ReadCount = 255;                        //本次需要写入的数据长度255+ A, Q1 P4 y) |) }7 O' u* y
  738.                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_RELOAD_MODE, IIC_NOSTART_WRITE);        //传输相关配置-不启动传输的写入                2 J8 e& S' _9 L6 @6 o
  739.         }+ o  v, R( O: }2 c! W
  740.         else
    9 P' B/ f: ^  r
  741.         {: Y! Y5 Y9 |% T
  742.                 ReadCount = WriteByteNum;        //记录本次需要写入的数据长度-最后一次通讯后自动结束* l) F5 O* Q4 d+ S* w8 t  w1 i, P
  743.                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_AUTOEND_MODE, IIC_NOSTART_WRITE);        //传输相关配置-不启动传输的写入
    / h$ K5 l% c9 P! [  f7 P9 L
  744.         }) M# _" @3 ^! m
  745. 3 }$ }! ^) Y% u
  746.         //循环发送数据
    9 w5 r" C& l6 s3 }. ?+ w
  747.         do
    $ L+ J2 Y# X( t
  748.         {! l! @, f# p* N
  749.                 Error = IIC_SendByte(pHandle, *pDataBuff, pHandle->TimeOutUs);        //发送一字节 . Z' @' b: o; J
  750.                 if(Error != IIC_OK) ; G( s# ?( x, `6 g, ~) G3 O
  751.                 {* f* w! c7 R! r) w% D( x8 V
  752.                         goto end_loop;
    5 k2 u7 b" q; ]& ]
  753.                 }" V6 V. W" y. V5 L; }+ ^( @
  754. * N' s0 I. t) G) D
  755.                 ReadCount --;+ ^' ?5 X' y7 x* q, h
  756.                 WriteByteNum --;. ?/ J2 {" G4 k( _; S
  757.                 pDataBuff ++;
    8 p- D* D+ \8 w/ z  t
  758.                
    & |7 J& P% A$ M( q; q5 N
  759.                 if((WriteByteNum > 0) && (ReadCount == 0))        //还有数据要读取
    0 X/ }6 H/ e1 H" p6 i, i2 n; ?
  760.                 {- H0 B+ H; c" R# ]
  761.                         if(WriteByteNum > 255)        //如果超过255字节,则需要分多次读取! d) I  g' l) k, d
  762.                         {
    + r% x6 h( S3 A( n1 W! r7 n+ J
  763.                                 ReadCount = 255;        //本次需要写入的数据长度255-后续还有数据,需要重载8 @6 C) l. R+ l5 M6 h1 J# t
  764.                                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_RELOAD_MODE, IIC_NOSTART_WRITE);        //传输相关配置-不启动传输的写入
    8 q" |0 F( E" b
  765.                         }
    * u0 f# @0 A6 e# i. l
  766.                         else! b5 a  R) z( I. d5 P
  767.                         {! T+ G8 K. K; [4 m  f
  768.                                 ReadCount = WriteByteNum;        //记录本次需要写入的数据长度-最后一次通讯,自动结束$ C9 Y7 {1 H4 T$ u( S, v
  769.                                 IIC_MasterTransConfig(pHandle, SlaveAddr, ReadCount, IIC_AUTOEND_MODE, IIC_NOSTART_WRITE);        //传输相关配置-不启动传输的写入                % F- }" c7 F0 y$ ~9 v
  770.                         }* z) R; U1 Z2 }) U# R% E
  771.                 }
    0 U# V$ ^# A2 s
  772.         }while(WriteByteNum);        4 L, _6 W/ u4 D; A
  773. 0 b" Y4 R6 r8 v5 w# j. p
  774.         //写入完成了,等待STOP位有效7 C2 e8 T! z* B# i7 A3 H2 e
  775.         Error = IIC_isWaitSTOPF(pHandle, pHandle->TimeOutUs);
    7 x% D$ E8 v( I% e2 A: m, @3 ]/ u
  776.         if(Error != IIC_OK) + _. b4 y' A/ {$ U
  777.         {6 t1 q4 Q% W9 l: `* Z3 A
  778.                 Error = IIC_STOP_ERROR;4 s3 Z6 o! Z% K
  779.                 goto end_loop;
    - {" J' w7 p" _; X
  780.         }
    * p# g' M" w. g- }; {
  781.         IIC_ClearISR(pHandle, IIC_GetISR(pHandle));                //复位错误状态7 H; b; R* |7 l
  782.         
    : O5 E% c* J( r  f3 a9 A& D
  783. end_loop:        
    - p  a0 f8 A4 P3 \; v$ s
  784.         IIC_ClearCR2(pHandle);                                                        //复位CR2寄存器        ; E. z& i1 Y- z+ O1 w
  785.         if(Error != IIC_OK)$ Z0 {; r; L+ V- B$ g2 @! ^
  786.         {
    ! ~/ V, F, ^4 H' Q+ ~6 u7 Q
  787.                 IIC_SoftReset(pHandle);                                                //IIC软复位,清除掉错误
    # W( i! U9 j( y3 m: N. a4 U' J
  788.                 DEBUG("[IIC W错误]:%d\r\n", Error);
    # }! ^' L' I4 k/ r% b
  789.         }# t8 Q" k0 q2 `2 w; T
  790.         
    0 x0 x% [7 G, e' ]7 i" Z' o  ^
  791.         if(IIC_GetISR(pHandle) & IIC_FLAG_BUSY)                        //忙,注:奇怪的是高速读取的时候,此处可能会检测到忙,TC标志有效,正常此处不应该有TC标志的
    % x) C0 v* H0 j' E; |
  792.         {
    / Q9 H9 b! q$ D# C  [7 D/ x  [
  793.                 IIC_SendStop(pHandle);                                                //总线忙,发送一个STOP,释放掉总线  a: _  B! U0 Q
  794.                 DEBUG("IIC W结束:总线忙 ISR=0x%X\r\n", pHandle->I2Cx->ISR);                ! R5 B# h; m( i8 q2 ^8 L( m
  795.         }$ _' o4 c9 m" r) E( J, G+ q2 z
  796.         return Error;) {+ t; r3 _% k1 p/ ?
  797. }$ Z" p% s/ d8 s

  798. & D+ l. k; c) v' ^; j( Z

  799. / R' ~5 Y3 ?; v/ L& g; Y0 H$ n, ^
  800. /*************************************************************************************************************************( _- R, p  M' Z3 g: a
  801. * 函数                        :        void IIC_SoftReset(IIC_HANDLE *pHandle)
    , U) ~/ i( T1 X6 c  H
  802. * 功能                        :        硬件IIC软复位(会使能IIC)
    ! s. V& T* J6 j; k% t& E
  803. * 参数                        :        ch:IIC通道
    $ l# D. v: X# T( u8 }( D1 ?
  804. * 返回                        :        IIC_ERROR
    : q5 {" V) v9 q3 |5 Q6 U
  805. * 依赖                        :        底层宏定义6 F. H+ R( `% S# z7 o, k7 W
  806. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>; R) l* ^% M+ n. d
  807. * 时间                        :        2020-02-15
    % o) }; ]' S) W4 [6 e& P3 `
  808. * 最后修改时间         :         2020-02-15
    # g1 L& Y  r) A8 r" \4 X
  809. * 说明                        :         IIC软复位;必须使 PE 保持低电平持续至少 3 个 APB 时钟周期,才能成功执行软件复位。
    ( O: ?9 G- p2 l: M
  810. *************************************************************************************************************************/+ \# k- G9 c$ _% e- ], {, q( G
  811. static void IIC_SoftReset(IIC_HANDLE *pHandle)$ R6 u: @$ \) s, ?
  812. {
    " F& O& f& V' G: t6 x7 ?* j: q
  813.         pHandle->I2Cx->CR1 &= ~BIT0;                //关闭IIC后执行软复位
    ) c! @/ e7 T5 w) E5 g+ y" g/ ~
  814.         Delay_US(1);        
    ' v3 Q" a. y, H( N" o; h
  815.         if(pHandle->I2Cx->CR1 & BIT0)
    4 V7 ?3 g- P' V" b; Q
  816.         {* \, t7 k: _! G% b
  817.                 DEBUG("IIC软复位失败\r\n");
    # |! z0 N% N5 ]! x# u) x4 @' z
  818.         }7 h" l$ O3 V& G; F! B' ^) D% e
  819.         pHandle->I2Cx->CR1 |= BIT0;                        //重新启动/ A, |8 h) w# Z
  820.         Delay_US(1);        
    ' U! L7 m, k& K
  821. }1 D; m1 a1 E: a. B( n4 r
  822. # |" ~! U5 b2 u# Q: [0 T/ j

  823. " _! R8 g% P+ L6 j- e. ^0 P

  824. - n0 p1 U* n( m0 d0 c; h, @1 e+ K0 p
  825. /*************************************************************************************************************************
      R6 x* F4 R& `4 j3 J
  826. * 函数                        :        static u32 IIC_CalculationTiming(u16 Speed_KHz)( z. o* Q" t" C6 w1 i7 ]  a
  827. * 功能                        :        硬件IIC时序计算
    * N1 Z# ]$ y. ?$ k( J% {, H7 X
  828. * 参数                        :        ch:IIC通道;Speed_KHz:速度10-1000
    $ y5 e& b. p, H
  829. * 返回                        :        IIC_ERROR
    % Q6 v% M6 m% R: q3 w; N
  830. * 依赖                        :        底层宏定义
    ! U+ W( S8 N7 L2 V; i4 S& e
  831. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    4 _/ Z/ P) \# y/ y* {- A0 J3 g
  832. * 时间                        :        2020-02-15: i( r6 ~8 B- R, N
  833. * 最后修改时间         :         2020-02-15& S* L1 i8 X5 K( j% x
  834. * 说明                        :         IIC使用的是APB1时钟,将IIC总线时钟控制在100KHz        
    2 T, u; p/ e! t- \/ f' V* U. @/ h
  835.                                         APB1时钟:最大不能超过45MHz        ; j6 K3 P. H) h7 Z, P6 c( u
  836.                                         如果速度是100,则按照SMBUS时序3 }0 @8 Q! ?5 |2 i7 Q
  837. *************************************************************************************************************************/$ ]- F) ^% S8 a+ O6 h' F, Z
  838. static u32 IIC_CalculationTiming(u16 Speed_KHz)
    1 ?- l/ i, q/ L
  839. {$ n4 ~! }. x/ h; ]
  840.         u32 tTime = 0;
    8 X+ q2 B- |$ p; |! F
  841.         u32 temp;
    ' y, t! Y1 m0 k8 j# k$ j% X2 O6 N
  842.         u32 time_temp = SYS_GetAPB1ClockSpeed() / 1000000;                //先获取APB1时钟速度
    ) @: N- {3 a( g5 Y
  843.         u32 Th = 1000/Speed_KHz/2;                                                                //计算高电平时间(低电平时间一样),单位ns
      o" R' b3 ^. g$ Z& ~: d
  844.         / T; {0 D, Q8 d5 w2 O. l% }
  845.         if(time_temp < 20) time_temp = 20;) L1 P6 N* n1 l4 C
  846.         time_temp = 1*1000 / time_temp;                                                        //单位ns3 D2 h6 B4 E8 S3 d7 C9 Y& c
  847.         uart_printf("IIC时钟计算->APB1周期:%dns\t", time_temp);; n; y6 k+ j) h
  848.         if(Speed_KHz == 100)        //如果是100,则按照SMBUS时序+ R- L( A2 i( w: R0 z
  849.         {% L& y+ D+ P6 |  Y( B& {
  850.                 //主时钟分频系数固定为33 B6 O2 O. K) |
  851.                 time_temp *= 3;                        //主时钟周期
    2 `+ F+ u1 x" r4 [% Q$ H: v0 j
  852.                 uart_printf("IIC时钟周期:%dns\t", time_temp);) l" A5 F$ ]' I) ~
  853.                 tTime |= (3-1) << 28;        //PRESC,时钟预分配
    . f9 o  {( {2 l
  854.                 //计算数据建立时间,要求最小250ns
    0 i% v0 K# H' g& n: m5 x
  855.                 temp = 250 / time_temp;
    $ A: Y# T3 b" D, b
  856.                 if(temp > 15) temp = 15;7 N' ?; ^& V* \( T
  857.                 if(temp < 1) temp = 1;
    : }* S% w. i( z+ \+ f7 }7 u5 G! a: t
  858.                 tTime |= temp << 20;) j$ o* A8 O: d3 X. ~: S$ i
  859.                 //计算数据保持时间,要求至少300ns
      v+ |, N$ e6 D0 d& a9 L' d
  860.                 temp = 300 / time_temp;
    - i; x# h" `! I2 K' ?# p, [' H" w
  861.                 if(temp > 15) temp = 15;5 N5 R' o4 p" o$ ~
  862.                 if(temp < 1) temp = 1;) a5 K& A$ d9 ~& U' w
  863.                 tTime |= temp << 16;. M3 p' m" t/ R6 K% p
  864.                 //计算高电平周期5us9 x; f7 N. K% \, c) l( |
  865.                 temp = 5*1000 / time_temp;/ _$ y8 ^5 I$ g7 O2 K
  866.                 if(temp > 255) temp = 255;4 u& a7 l4 N0 C/ e& _
  867.                 if(temp < 1) temp = 1;
    : H- s7 ~3 {# u. R- g, ~
  868.                 tTime |= temp << 8;# r/ D" c: G; D2 T' l/ @3 X
  869.                 //计算低电平周期5us
    * E- @2 K+ r/ d4 d# D
  870.                 temp = 5*1000 / time_temp;& d% ?/ x2 l8 R; [9 {3 A+ K7 y. S
  871.                 if(temp > 255) temp = 255;1 R9 \5 ^" o3 N: E! O4 E
  872.                 if(temp < 1) temp = 1;8 Z3 L+ m8 u' A" f
  873.                 tTime |= temp << 0;8 I/ \; L& e( I8 q' g
  874.         }% h, ^: t6 R/ A, t0 q9 d
  875.         else if(Speed_KHz < 100)
      ~6 `; ?$ m  e/ C
  876.         {
    * w; T5 y0 R2 [3 T' a0 B* u
  877.                 //主时钟分频系数固定为6! V  R2 T0 V9 `" t) s6 {8 {
  878.                 time_temp *= 6;                        //主时钟周期% ~. M& v$ y% A4 V. H
  879.                 uart_printf("IIC时钟周期:%dns\t", time_temp);* d: d! U1 ]( l4 }" w: U6 B; ^$ x( f- m2 h
  880.                 tTime |= (6-1) << 28;        //PRESC,时钟预分配& {# w+ F+ H! Y: G7 U
  881.                 //计算数据建立时间,要求最小250ns
    7 y& V/ a7 u$ z' n! q6 ~+ A" U6 i, b
  882.                 temp = 250 / time_temp;
    ) g! Y+ v2 ~8 t2 A% S2 N
  883.                 if(temp > 15) temp = 15;
    ( A# n! a8 K  J  S
  884.                 tTime |= temp << 20;% \) j5 _7 V  W9 Y7 Z5 O2 O; }8 }
  885.                 //计算数据保持时间,要求至少300ns
    4 m) [; U3 @5 @% f# K
  886.                 temp = 300 / time_temp;
    # T4 j0 ?' s; _! d; y4 t& _3 u
  887.                 if(temp > 15) temp = 15;
    ; c% C% P1 i$ E. j* n1 d7 S
  888.                 tTime |= temp << 16;
    # l. v5 J: l% `* \# p3 ^; x/ a: C# w
  889.                 //计算高电平周期Th us
    3 ?: g. o  _! E" l% X+ a
  890.                 temp = Th*1000 / time_temp;
    / |! a1 I) \0 _
  891.                 if(temp > 255) temp = 255;
    , [( ~4 C) D8 x5 D+ T
  892.                 if(temp < 1) temp = 1;
    ( E4 N9 t2 d) C8 l. I2 t0 _
  893.                 tTime |= temp << 8;5 f" k2 a! f( l! j7 N$ E8 S2 M, T) a
  894.                 //计算低电平周期 Th us; k* N( k! Z8 [+ A2 K# `# U
  895.                 temp = Th*1000 / time_temp;7 z) r* _- }0 h, ]" g5 F7 r8 k
  896.                 if(temp > 255) temp = 255;& j0 w2 i6 p5 P2 `* j0 f0 {
  897.                 if(temp < 1) temp = 1;( y: f" A! j' ^
  898.                 tTime |= temp << 0;
    & B: S  z3 f3 u
  899.         }8 I7 G, {5 h9 A' _3 ^
  900.         else //>100
    & D9 v( r- L3 V* p, z
  901.         {" k3 C8 {3 `& U5 S8 a/ ^
  902.                 //主时钟分频系数固定为2
    / T* ?6 W0 ]# T- x, F$ M! L3 i8 P
  903.                 time_temp *= 2;                        //主时钟周期
    0 ^: A; X- N4 w0 A. g5 f( N1 Z! \
  904.                 uart_printf("IIC时钟周期:%dns\t", time_temp);
    $ v3 D$ A: ~; C- N" a( y/ K
  905.                 tTime |= (2-1) << 28;        //PRESC,时钟预分配
    5 J' u5 a* u( _/ g. O8 P
  906.                 //计算数据建立时间,随便给100ns1 x  K0 z0 e7 \! L
  907.                 temp = 100 / time_temp;* N1 N( U" b9 r+ ^' L) e9 [: ]& W
  908.                 if(temp > 15) temp = 15;) z6 G9 d1 @4 H3 i
  909.                 tTime |= temp << 20;9 Q- f! Z1 V8 ~' {  X
  910.                 //计算数据保持时间,给100ns3 r1 v* l/ f% ?- }3 V: D0 |6 S* f% {
  911.                 temp = 100 / time_temp;' ^# G) q  ~/ j' R' J! a
  912.                 if(temp > 15) temp = 15;
    1 p3 Q: g8 Z7 H2 [" X& l+ z( N+ r
  913.                 tTime |= temp << 16;
    $ W! X  _% V; m" x6 |
  914.                 //计算高电平周期Th us
    * a6 a: e: {3 o- O6 G
  915.                 temp = Th*1000 / time_temp;
    ) q( f8 v+ H1 k  B8 u' d2 e
  916.                 if(temp > 255) temp = 255;
    3 A" y, ?, N  L0 K$ g5 L3 g0 Q
  917.                 if(temp < 1) temp = 1;
    , o9 ^" o) I3 E% l( H
  918.                 tTime |= temp << 8;1 U8 i' d# x% @( \7 i/ j" E
  919.                 //计算低电平周期 Th us
    ! d7 O3 f( Y9 e, f1 F
  920.                 temp = Th*1000 / time_temp;- `5 b4 s* h: D- D7 E) t
  921.                 if(temp > 255) temp = 255;
    : y. p; o/ w4 Z3 K3 F
  922.                 if(temp < 1) temp = 1;
    9 G7 e/ ~2 T* {2 Q9 G6 |7 m7 r4 G7 x! j
  923.                 tTime |= temp << 0;
    ( H/ \- [3 c2 e, k9 q
  924.         }2 Z0 r! J( C, g% G
  925.         
    & y9 w6 D* T8 q
  926.         uart_printf("时序寄存器结果为:0x%X\r\n", tTime);
    ' w; c6 o- D" q) J7 I' ^8 p! p
  927.         
    4 o/ ~5 g) {/ k1 \" o9 f! j1 \: g
  928.         return tTime;
    4 F% f* M6 d+ {$ C8 r0 o
  929. }
复制代码

9 x. j( g# q9 I6 T, |# v. u# n+ Y9 d( e3 f; D- I
  1. /*************************************************************************************************************
    ' h, X; Q9 T! y
  2. * 文件名                :        stm32f7_iic.h+ F, R7 E* h. ]  _1 N% X- _
  3. * 功能                        :        STM32F7 IIC接口驱动$ U/ y! x$ T$ Q( D2 I" V
  4. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>8 R+ y# Q0 p1 r2 j4 {+ G# E. M5 {
  5. * 创建时间                :        2020-02-09; f# C9 j- j, c0 [4 i+ X- [
  6. * 最后修改时间        :        2020-02-091 V* M+ j" U" u  L' J8 d
  7. * 详细:                        + v+ [; q! H8 ^- s
  8. *************************************************************************************************************/               
    9 @2 i5 A% m, Y) S' ]0 d. }. N
  9. #ifndef __STM32F7_IIC_H_4 i9 C! w) K. u
  10. #define __STM32F7_IIC_H_
    9 D2 H7 x! J6 [* Z: ]  b! Q! d% z3 l
  11. #include "system.h"
    5 e5 D9 r+ |' Y/ l  z
  12. , e, T2 r7 Z1 i* U" j$ I2 f, n6 M
  13. //16位整形数高低对调
    & m% x# y2 {* h7 _0 t* J3 J9 Y
  14. #ifndef SWAP16. A& B5 P3 a- R0 `7 W0 x
  15. #define SWAP16(x)   (((x & 0xff00) >> 8) | ((x & 0xff) << 8))! i1 X, K  N' o
  16. #endif  //SWAP16. n6 s- u0 ^8 b: u0 ?- K

  17. + R. c8 C. }. I! B# L/ {
  18. //硬件IO口选择
    ; C0 F* }' J% e/ n: f, T+ N8 ]
  19. //I2C1 IO定义与选择
    $ g2 C/ d- S* Q9 K4 w& S
  20. #define IIC_CH1_PB6_7                                0                                        //PB6,PB7& r# s; A9 _+ F. J6 x; ~7 t  K
  21. #define IIC_CH1_PB8_9                                1                                        //PB8,PB9! J, L4 U6 @- |" {; e0 E' q
  22. #define IIC_CH1_IO_SELECT                        IIC_CH1_PB6_7                //选择I2C1 的IO        1 J/ a: l1 [: {1 z% x

  23. 5 {1 _7 m9 q" Z& _+ \2 H
  24. //I2C2 IO定义与选择! N* K! A. d4 v, a3 d# J
  25. #define IIC_CH2_PB10_11                                0                                        //PB10,PB11
    4 F# l: s1 W  O4 B7 c. s
  26. #define IIC_CH2_PF0_1                                1                                        //PF0,PF1
    ! f+ N7 G" ?3 H
  27. #define IIC_CH2_PH4_5                                2                                        //PH4,PH5
      [; W) M2 b0 l
  28. #define IIC_CH2_IO_SELECT                        IIC_CH2_PB10_11                //选择I2C2 的IO
    3 ^/ y0 x  u" i1 ?& V5 v

  29. % i. r* x3 ?- C$ d6 K
  30. //I2C3 IO定义与选择
      T# L# M& ]# M3 K. x2 x7 b
  31. #define IIC_CH3_PH7_8                                0                                        //PH7,PH8% ^, x3 f& }; d; v' I
  32. #define IIC_CH3_PA8_PC9                                1                                        //PA8,PC9) p/ j1 D  h( b/ A1 T1 N
  33. #define IIC_CH3_IO_SELECT                        IIC_CH3_PH7_8                //选择I2C3 的IO
    1 |) o8 C7 S  M/ ~- b  n* i
  34. ' F4 B- T7 s4 Q& q  W$ `; i- e
  35. //I2C4 IO定义与选择: K) E  {8 J3 y. Q; C6 W
  36. #define IIC_CH4_PD12_13                                0                                        //PD12,PD13: f4 |2 E8 Y. a" l" \
  37. #define IIC_CH4_PF14_15                                1                                        //PF14,PF15
    & u2 {9 O+ h% T+ S1 V
  38. #define IIC_CH4_PH11_12                                2                                        //PH11,PH12, y1 V* u! K& K" C$ [9 m$ T+ I
  39. #define IIC_CH4_IO_SELECT                        IIC_CH4_PD12_13                //选择I2C4 的IO( ^1 o& D! s- [, r9 @- E8 H3 H

  40.   [6 [( p4 b0 }! D5 m, b) Q6 f
  41. //IIC硬件接口选择6 ?1 d- Z- W; N& n& c
  42. typedef enum* ~( ~1 A' z" x9 u1 s% M: N, B# M
  43. {
    7 y: f* p. T) b7 R
  44.         IIC_CH1        =                0,        //IIC1
    , R! V3 E/ i/ M3 l8 w
  45.         IIC_CH2        =                1,        //IIC2
    2 h1 U2 c9 N; `" _$ ^6 z1 Z
  46.         IIC_CH3        =                2,        //IIC38 i7 {8 W5 d9 Q5 L& r1 X
  47.         IIC_CH4        =                3,        //IIC4
    1 m! a% R7 E# v
  48. }IIC_CH_Type;
    ! f, Z3 K/ a, v& @2 C
  49. #define IIC_CH_COUNT        4        //4个IIC
    ; M0 L  ?/ x) B( \$ |/ ?4 C2 g
  50. ' h5 B" t- {% Y  ^( m, Y

  51. - T5 M' s) o; }. t, t2 l' k
  52. //中断状态$ c1 n, x; y, M1 Y" _7 J. G: M
  53. #define IIC_FLAG_TXE                    BIT0        //发送数据寄存器为空(发送器); 当 I2C_TXDR 寄存器为空时,该位由硬件置 1。下一个待发送的数据写入 I2C_TXDR 寄存器时,该位被清零。6 H( M0 A% u' r4 s/ ?
  54. #define IIC_FLAG_TXIS                   BIT1        //发送中断状态(发送器); 当 I2C_TXDR 寄存器为空时,该位由硬件置 1,待发送的数据必须写入 I2C_TXDR 寄存器。
    5 X- a& S2 v0 }% U- ^. n
  55. #define IIC_FLAG_RXNE                   BIT2        //接收数据寄存器不为空(接收器); 当接收到的数据已复制到 I2C_RXDR 寄存器且准备就绪可供读取时,该位由硬件置 1。读取I2C_RXDR 时,将清零该位。
    ; b/ ~9 e( l: r
  56. #define IIC_FLAG_ADDR                   BIT3        //地址匹配(从模式); 接收到的地址与使能的从设备地址之一匹配时,该位由硬件置 1。该位由软件清零,方法是将ADDRCF 位置 1。/ _- j& V6 x9 p' y( R, D
  57. #define IIC_FLAG_NACKF                  BIT4        //接收到否定应答标志; 传输完字节后接收到 NACK 时,该标志由硬件置 1。该标志由软件清零,方法是将 NACKCF位置 1。
    % u- U0 A7 Z& ^+ X
  58. #define IIC_FLAG_STOPF                  BIT5        //停止位检测标志; 当在总线上检测到停止位,且外设也参与本次传输时,该标志由硬件置 1, h, z' @5 k4 _: z; N$ E. x0 s
  59. #define IIC_FLAG_TC                     BIT6        //传输完成(主模式); 当 RELOAD=0、AUTOEND=0 且 NBYTES 数据传输完成时,该标志由硬件置 1。当 START位或 STOP 位置 1 时,该标志由软件清零。
    ( r, W& ^( y1 O4 z
  60. #define IIC_FLAG_TCR                    BIT7        //传输完成等待重载; 当 RELOAD=1 且 NBYTES 数据传输完成时,该标志由硬件置 1。当 NBYTES 写入一个非零值时,该标志由软件清零。7 [% j4 P# q. F
  61. #define IIC_FLAG_BERR                   BIT8        //总线错误; 当检测到错位的起始位或停止位,而外设也参与传输时,该标志由硬件置 1。在从模式下的地址阶段,该标志不会置 1。该标志由软件清零,方法是将 BERRCF 位置 1。
    2 P2 E3 Z* C/ |1 z$ L+ E2 b  D* G
  62. #define IIC_FLAG_ARLO                   BIT9        //仲裁丢失; 发生仲裁丢失时,该标志由硬件置 1。该标志由软件清零,方法是将 ARLOCF 位置 1。8 x$ ]/ v) P- C
  63. #define IIC_FLAG_OVR                    BIT10        //上溢/下溢(从模式); 在从模式下且 NOSTRETCH=1 时,如果发生上溢/下溢错误,该标志由硬件置 1。该标志由软件清零,方法是将 OVRCF 位置 1。
    # m" n6 B& e6 h3 W2 e, o% H) N3 X* l
  64. #define IIC_FLAG_PECERR                 BIT11        //接收期间的 PEC 错误; 当接收到的 PEC 与 PEC 寄存器的内容不匹配时,该标志由硬件置 1。接收到错误的 PEC 后,将自动发送 NACK。该标志由软件清零,方法是将 PECCF 位置 1。
    ( G8 o0 w5 y: R- m
  65. #define IIC_FLAG_TIMEOUT                BIT12        //超时或 tLOW 检测标志; 发生超时或延长时钟超时时,该标志由硬件置 1。该位由软件清零,方法是将 TIMEOUTCF 位置 1。
    : {7 G% Y- H- V$ r
  66. #define IIC_FLAG_ALERT                  BIT13        //SMBus 报警; 当 SMBHEN=1(SMBus 主机配置)、ALERTEN=1 且在 SMBA 引脚上检测到 SMBALERT 事件(下降沿)时,该标志由硬件置 1。该位由软件清零,方法是将 ALERTCF 位置 1。
    6 S, ~& D3 U& W" _2 W. b
  67. #define IIC_FLAG_BUSY                   BIT15        //总线繁忙; 该标志用于指示总线上正在进行通信。当检测到起始位时,该位由硬件置 1。当检测到停止位或 PE = 0 时,该位由硬件清零。
    3 r! y8 ?* ~3 E( g
  68. #define IIC_FLAG_DIR                    BIT16        //传输方向(从模式); 该标志在发生地址匹配事件时 (ADDR=1) 更新。;0:写;1:读) @# @4 R- A0 P. {% K' m! |, T

  69. : ~, I4 [$ c6 r: f' I/ A' z4 b
  70. //通讯错误状态' g+ G& w1 H5 W5 V7 G! \
  71. typedef enum2 a/ F8 z" R; A8 l* ]7 @' V/ ^
  72. {
    / n. N0 s/ i& r# A( q6 q  g2 o
  73.         IIC_OK                                        =        0,        //没有错误4 m. ^- T8 w: G& o) _( h
  74.         IIC_PARAMETER_ERROR                =        1,        //参数错误* H2 {* e& f* F6 K0 D+ ^
  75.         IIC_TIMEOUT                                =        2,        //超时错误,也可能是底层错误5 W% x7 ^4 j) B) o. g
  76.         IIC_HAL_ERROR                        =        3,        //底层错误3 N" V# }3 S7 ^2 u1 I4 [; d
  77.         IIC_STOP_ERROR                        =        4,        //等待结束错误: w7 ^% g+ X/ A, v: ?9 Y& z
  78.         IIC_BUSY                                =        5,        //硬件忙0 e1 N$ d4 X' l2 Z
  79.         IIC_NACK                                =        6,        //收到NACK了
    * k. Y/ U1 \9 I: @8 G
  80. }IIC_ERROR;& O- H% k, s1 d5 Y$ k9 b7 x0 Q
  81. + S* l& X+ w, b* Y/ D' U
  82. 8 y' g# m+ K9 a4 M$ U0 W* U/ ?
  83. bool IIC_Init(IIC_CH_Type ch, u16 Speed_KHz, u16 TimeOutUs);        //硬件IIC初始化: W& R$ {+ f8 U2 r3 C$ B
  84. IIC_ERROR IIC_MasterReadReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 ReadByteNum);        //IIC读取寄存器(可以读取1个或者多个寄存器)
    : k/ w# D# w' a- y+ g; ~* F
  85. IIC_ERROR IIC_MasterWriteReg(IIC_CH_Type ch, u16 SlaveAddr, u16 RegAddr, bool is8bitRegAddr, u8 *pDataBuff, u16 WriteByteNum);        //IIC写寄存器(可以写1个或者多个寄存器)
    # C1 A& l# n( z$ I( ]1 E; d2 c
  86. 9 L3 j6 W4 k+ c" b5 l

  87. 1 _! i0 ^$ P8 o* U* _
  88. #endif //__STM32F7_IIC_H_
复制代码
) M' W: ^9 X* K& x: b, X0 \& j
" L) q- y8 m+ o* M
//初始化. v# i! W2 r4 g5 u+ E

4 i3 G# d) Y" `2 ]! Q
  1. IIC_Init(IIC_CH3, 200, 0);        //硬件IIC初始化
复制代码
. m8 u$ q1 _: k. M* ^  a

. X7 d7 _; a9 m* q; g//调用8 B# \; X+ H  M/ k9 p* M" j
  1. * S5 Z* j$ \' {  C, d
  2. //触摸屏IIC读取寄存器接口
    5 \4 d" N# \0 L8 u! @" S& R
  3. bool TP_FT5336_IIC_ReadReg(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)
    " V& E2 v! E! T, @0 k
  4. {
    - Q/ `8 T! u. C* |8 n3 ~3 |0 i1 P
  5.         if(IIC_MasterReadReg(FT5336_IIC_CH, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum) == IIC_OK)
    4 J: N: }- M8 e) A$ D
  6.         {
    3 ^0 p' B7 F5 @
  7.                 return TRUE;
    . v1 C, M; {6 O: v5 v
  8.         }
    . i4 P3 a# ~( E) w! i( C
  9.         else
    8 D6 s* K8 ^2 U5 Q# Q, ^5 j
  10.         {
    $ ^& `- N/ C  U
  11.                 return FALSE;
    8 l7 L) }" U$ G$ L& Q9 w; L
  12.         }
    & @& F; F/ z4 Q% Y3 G! Z
  13. }
    + K% K4 c/ F& u" }& y6 T4 L  j- p

  14.   N& v  C6 r, M
  15. //触摸屏IIC写寄存器接口
    9 f3 A- r0 ~4 A$ l, p& H' x5 g
  16. bool TP_FT5336_IIC_WriteReg(u16 SlaveAddr, u8 RegAddr, u8 *pDataBuff, u16 ByteNum)" d, }2 g7 O% h
  17. {
    2 Z+ E! z4 H: s4 u" l* P
  18.         if(IIC_MasterWriteReg(FT5336_IIC_CH, SlaveAddr, RegAddr, TRUE, pDataBuff, ByteNum) == IIC_OK), g5 S5 c" c% s  u
  19.         {
    6 w# Y2 _6 |% o- a; G. b  h
  20.                 return TRUE;" Y6 I1 K$ b- ^
  21.         }
    : U  j4 A/ ]+ i8 u9 A% w
  22.         else
    6 y% e% R7 y$ D% K
  23.         {
    1 P. t- v* Q8 ?1 x
  24.                 return FALSE;4 w. w& [) `* V& B$ i
  25.         }
    2 q8 ~# M6 L$ V

  26. 2 A4 T% _% C" F3 o  @8 F
复制代码

$ k8 S' m# o2 \7 O/ u. `* K
! v; I1 c+ V4 q, D/ S7 d
% s/ \: S$ ]. j# i+ I/ H
收藏 评论0 发布时间:2021-12-11 12:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版