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

【经验分享】STM32F1(CAN)

[复制链接]
STMCU小助手 发布时间:2021-11-26 17:00
1,开发环境" F6 E$ E& q! \. K- g- e" F+ X' j: ~
0 X# h5 W5 v3 [# b$ s) ^' c% T2 U) V
1,固件库:STM32F10x_StdPeriph_Lib_V3.5.0
; O4 a7 L1 V; n& R  F
  _  v" @8 [0 a  n& m5 I- e/ M2,编译器:ARMCC V5.06- R; F) v* L# N8 e

( Z( v1 T: N& r( n  G3,IDE:Keil uVision5
# ]; B# {3 B+ ^- T) n7 g. k1 J, ?$ {& V- t3 x
4,操作系统:Windows 10 专业版
% Q1 p1 [% S, i  C7 S  L1 G. O0 N3 x7 ]6 j  u( \" A. b! E

; Q9 i. R# \$ R7 S2,程序源码
  {: V4 I5 X) j$ C' C* i6 t( G) d5 H3 [% C6 Y8 H0 I$ u
RingBuffer.h 文件
0 E9 t% \0 f; O9 X: e4 R. T, `
  1. /**/ j2 K7 I( Z' \) v- v8 Z1 @4 a4 H/ V6 R
  2.   ******************************************************************************) t/ T. W* w$ \0 g" Y5 O! H
  3.   * @file    RingBuffer.h
    ; ?* P  o  l6 K4 w
  4.   * @author  XinLi0 @9 f% K0 Q' g/ Q0 u1 U% g
  5.   * @version v1.16 w0 g. K( Z6 q, M8 K, h
  6.   * @date    15-January-20182 _0 B! W7 W% C6 c8 g) r$ a
  7.   * @brief   Header file for RingBuffer.c module.& X' L+ M3 s& C$ y5 F
  8.   ******************************************************************************
    9 u: `" ?4 B5 z; @" L& e* a
  9.   * @attention" j3 D: u: i. I
  10.   *
    : a) m" s/ ^6 T  Z
  11.   * <h2><center>Copyright © 2018 XinLi</center></h2>, E3 _! Z0 S, k1 ^: b
  12.   *
    4 w) ~% w* x4 d. B9 ~2 m' h  x
  13.   * This program is free software: you can redistribute it and/or modify5 _( ]' X$ \2 z: |' n3 n
  14.   * it under the terms of the GNU General Public License as published by
    ( F. u9 g, \8 g! D
  15.   * the Free Software Foundation, either version 3 of the License, or
    $ N  Y% f7 X8 R) [$ G
  16.   * (at your option) any later version.
    ; v; ^1 p9 n6 H, i8 Q
  17.   *7 m/ G; O; ~/ w! ~+ Y- R8 [
  18.   * This program is distributed in the hope that it will be useful,, ~* l9 v( q' D+ r" C8 R
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of- E& S  q/ ?% J$ I3 @+ z
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the& @- E  w& G4 l5 K" z& a7 s2 G
  21.   * GNU General Public License for more details.
    6 ^$ {& v) z3 B$ A, C2 A
  22.   *
    + h3 I) Z' G3 B1 i: h
  23.   * You should have received a copy of the GNU General Public License
    * @* v9 m$ [5 }" R) k" x$ d
  24.   * along with this program.  If not, see <<a href="https://www.gnu.org/licenses/>." target="_blank">https://www.gnu.org/licenses/>.</a>0 |* i" i8 J# _( `: P
  25.   *
    : s! ]; u+ \1 \& X
  26.   ******************************************************************************2 j* ]- g9 y; b* u. \
  27.   */% q- a$ v' j0 F& A4 x

  28. : F) N4 I" L$ Y' a
  29. #ifndef __RINGBUFFER_H& r" ]' e" Q; J! j$ M1 o( j
  30. #define __RINGBUFFER_H% P+ E: M; _. a6 F3 g. `

  31.   W6 a1 \  \# v: V& `" N+ {
  32. #ifdef __cplusplus' ]5 T$ \5 @6 m  h, k6 a
  33. extern "C" {
    $ a3 c% d( M* ~% |- Z( k) w
  34. #endif
    0 A1 t+ A0 A$ W. T% v: q/ g
  35. , l0 D# Y1 v& K% @4 n
  36. /* Header includes -----------------------------------------------------------*/; L4 C7 u. r; j' B
  37. #include <stdint.h>
    9 v1 Q/ G# Q: O2 x7 F* ]
  38. #include <stdbool.h>/ L# P* g6 m1 `9 I# w& F2 f
  39. #include <stdlib.h>9 J7 J: d; x! K' t# J

  40. - @0 a: i1 T6 \7 {% h/ l5 A% x3 }4 u* w
  41. /* Macro definitions ---------------------------------------------------------*/
    # p, m2 U! \" L2 H# l
  42. #define RING_BUFFER_MALLOC(size)  malloc(size). D2 J* _+ k/ u( ]
  43. #define RING_BUFFER_FREE(block)   free(block)- n" m+ _- C: v3 R; t, T

  44. & [0 D" @+ R' I) h
  45. /* Type definitions ----------------------------------------------------------*/0 l2 N' l" f0 ^' o5 |4 j
  46. typedef struct+ k1 t. d: p6 j4 t" k* R& A
  47. {
    8 u2 h" o$ Y' [3 i, F3 j4 s
  48.   uint8_t *buffer;! z' j3 ~7 _/ l' c: b" u" @
  49.   uint32_t size;
    ; n& P( g# V6 [3 `
  50.   uint32_t in;+ E2 }7 \7 w* P0 W6 ?
  51.   uint32_t out;
    1 A% D/ Z1 {& r  M! W" r3 [( k
  52. }RingBuffer;
    2 e9 _9 L% r  ]4 F& X/ S
  53. / ^+ T% v8 [5 o* B" R! A  t: F
  54. /* Variable declarations -----------------------------------------------------*/
    6 p! S' Q/ `! M( P! `$ a; E$ \
  55. /* Variable definitions ------------------------------------------------------*/
    " o' f4 z; H' g0 d/ U1 V; s
  56. /* Function declarations -----------------------------------------------------*/3 g3 a" N. ]) S
  57. RingBuffer *RingBuffer_Malloc(uint32_t size);
    ; E* H0 k0 Z% p" w* f
  58. void RingBuffer_Free(RingBuffer *fifo);) H# P  ~' @- W( `/ u/ c/ r+ T4 Z

  59. 1 v# a1 h7 x9 R2 a7 ~
  60. uint32_t RingBuffer_In(RingBuffer *fifo, void *in, uint32_t len);
    : K5 p9 e0 m7 l. A
  61. uint32_t RingBuffer_Out(RingBuffer *fifo, void *out, uint32_t len);" f3 _) y- T$ o$ C: i5 b' {- K  t/ Q

  62. 8 h1 ^1 O0 ~7 C5 S
  63. /* Function definitions ------------------------------------------------------*/+ J: Q( z) M4 D! [+ ?: y9 x

  64. ( `, M9 r( y' ]. }0 N" L8 _, [$ B+ @
  65. /**
    . B- l( L$ C- }7 }8 z# l5 a
  66.   * @brief  Removes the entire FIFO contents.
    ' V, s( }3 p" B, ~+ D
  67.   * @param  [in] fifo: The fifo to be emptied.! h, W+ x/ t0 ?& R
  68.   * @return None.
    4 Q+ |  L6 g% M3 k
  69.   */
    & `. [: l7 S' K% h# ~
  70. static inline void RingBuffer_Reset(RingBuffer *fifo)
    9 l2 V' ^9 y- n* n6 \6 r
  71. {7 m- i) v$ M* h7 s
  72.   fifo->in = fifo->out = 0;- n3 j2 g1 Y5 `7 P$ e" \
  73. }
    , f6 x) q) F6 L& X7 J
  74. 6 T* \6 s4 I" `/ N2 F3 F% s
  75. /**; n0 C# x; O$ D+ O% J* O
  76.   * @brief  Returns the size of the FIFO in bytes.8 e1 \* d& w( _; |. P/ j4 J
  77.   * @param  [in] fifo: The fifo to be used.
    9 s" @3 A# l. _7 ]% o
  78.   * @return The size of the FIFO.
    . x  Q% x% d8 y7 @' x  P" l+ I
  79.   */
    ( n# k$ t2 Y- T$ l4 X
  80. static inline uint32_t RingBuffer_Size(RingBuffer *fifo)! F! H' O* K3 F1 X+ F
  81. {
    * J* f8 S/ y+ q
  82.   return fifo->size;
    ; O. W. q* i. P1 U6 W! I
  83. }
    / ~6 g* @8 }* g+ q) ~5 E( Z5 g

  84. # z$ C1 u+ F+ |* y3 X; ^$ J. [
  85. /**
    % b6 ?% R$ }% T  i* S
  86.   * @brief  Returns the number of used bytes in the FIFO.
    # T; U( W  z( Q. b0 K
  87.   * @param  [in] fifo: The fifo to be used.
    * V; P3 U# ?0 w6 l% l$ E" Y) O$ x
  88.   * @return The number of used bytes.) u, }. A) g6 g1 h
  89.   */
    , [' j9 m9 K: U. [/ A" ~
  90. static inline uint32_t RingBuffer_Len(RingBuffer *fifo)
    # @4 K' [, T2 O* a: e
  91. {2 }6 e* P0 z+ s4 Z0 t6 b
  92.   return fifo->in - fifo->out;
    . C( Y9 Q# d% ?1 W. E1 A+ i
  93. }
    3 I: U0 g9 w) u$ ]8 A. ]
  94. 9 L: A2 S) u0 q9 @
  95. /**
    # {  X3 U. ~" \9 E8 ?
  96.   * @brief  Returns the number of bytes available in the FIFO., r1 q/ i* Z! q! K) w
  97.   * @param  [in] fifo: The fifo to be used.
    : l2 l* b/ L! G# m2 |# S2 j8 }
  98.   * @return The number of bytes available.
    4 p  ^0 N7 e/ B; C
  99.   */5 t+ Y% W( U* o
  100. static inline uint32_t RingBuffer_Avail(RingBuffer *fifo)) S- o5 h! C7 M/ @+ Z; s
  101. {
      _4 n  B/ d1 C6 F
  102.   return RingBuffer_Size(fifo) - RingBuffer_Len(fifo);7 w( N1 F1 L; D1 P. h4 h
  103. }5 x1 l7 r2 d) h9 f; M4 Y
  104. , A/ y3 J' s2 Q& H& a
  105. /**( F' t4 \9 P$ l8 C
  106.   * @brief  Is the FIFO empty?) C, Z+ {; S2 r# Q0 b
  107.   * @param  [in] fifo: The fifo to be used.2 K; v# Q: O8 |/ E) e1 X
  108.   * @retval true:      Yes.5 o% w  T+ j* |
  109.   * @retval false:     No.
    * Q  I8 N5 B  o
  110.   */  s" [$ u- B) F" i5 \8 C
  111. static inline bool RingBuffer_IsEmpty(RingBuffer *fifo)
      ~, o. ^0 ?3 W; M) N4 K
  112. {% h( o( n5 _0 T2 k2 S5 m' Y
  113.   return RingBuffer_Len(fifo) == 0;
    ) X3 x' D  E8 e- h4 S
  114. }/ @5 V( S6 y# Q0 j( t( |

  115. 5 j. ^2 H% ^0 K$ a( `; w$ a; b& r& y
  116. /**
    " z* i) ~( f% p+ ^8 X9 I
  117.   * @brief  Is the FIFO full?
      N' k2 O) v5 q
  118.   * @param  [in] fifo: The fifo to be used.+ l: I! X2 C; L5 _
  119.   * @retval true:      Yes.6 ?: M1 G) X# g4 T
  120.   * @retval false:     No.
      j& j2 w( q9 o; T6 G
  121.   */( E$ G8 j! p9 a$ P4 z) G3 q8 V
  122. static inline bool RingBuffer_IsFull(RingBuffer *fifo)
    + p# V+ T6 ]$ H: L8 a# ?
  123. {
    2 D0 {1 c: q) |" h$ e* H6 G; B% _  R3 ^
  124.   return RingBuffer_Avail(fifo) == 0;) \% K; {( {. M  ?$ o+ t) l
  125. }
    ; X' }% A8 ?* E& F0 b) @4 ?
  126. & H$ Y" B# Z% V& z: y' S7 B
  127. #ifdef __cplusplus
    3 T. D8 m: I  E  B% a
  128. }' D: F8 ?% [: t  {
  129. #endif- f# y4 l# A& k6 o- g& @& }8 n- k

  130. , H7 y$ d$ R1 v6 B+ T8 X
  131. #endif /* __RINGBUFFER_H */$ l4 o3 L( ~' v3 ]& F
复制代码

2 j$ M; |$ S! C: u5 x; z( P5 ?2 I, O. C/ ?: R- U$ V# U, Z
RingBuffer.c 文件/ B8 ?, H5 V, _! v: _
  1. <div>/**
    ; P2 b( \$ E- y* o9 |
  2.   ******************************************************************************
    / ]- ?  Y8 T$ D% j! p( F% P$ g
  3.   * @file    RingBuffer.c' s+ G% V+ Y8 s' n$ i
  4.   * @author  XinLi
    % \) ~7 |) C5 ^
  5.   * @version v1.1
    5 S+ @& }& p# D! I
  6.   * @date    15-January-2018
    ' U8 z5 O9 O9 D. z( g
  7.   * @brief   Ring buffer module source file.
    3 a+ K* a# `" J) ?9 u( m
  8.   ******************************************************************************
    5 s& F+ f( c% Z5 \8 n( m
  9.   * @attention
    ( V; D! P9 [6 N- }4 c
  10.   *
    # V" b' @, R) @
  11.   * <h2><center>Copyright © 2018 XinLi</center></h2>4 m; |* F( }7 o* n% L+ U
  12.   ** U1 D8 I2 p( C, Q! d2 _
  13.   * This program is free software: you can redistribute it and/or modify/ l0 v- t. O  t; _
  14.   * it under the terms of the GNU General Public License as published by! n( ]$ c% z) P4 C  t3 t$ i
  15.   * the Free Software Foundation, either version 3 of the License, or& L( ^/ m4 P  Y$ l5 {  Y
  16.   * (at your option) any later version.% M* h$ y) t6 z8 s- O5 l
  17.   *
    % C: z) i0 v  K# n, c, {
  18.   * This program is distributed in the hope that it will be useful,
    3 V3 G) a/ e1 N* c  Y# _: I
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5 I  h9 t. L# T: Q$ ^
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    * M: j6 A! i8 g+ D- x
  21.   * GNU General Public License for more details.
    . i, C" q( p4 I( ^  R6 w6 ]2 r( G
  22.   *
    3 A  r& {; h+ J. {
  23.   * You should have received a copy of the GNU General Public License" i% w; D" Z& k6 o$ t1 A
  24.   * along with this program.  If not, see <<a href="https://www.gnu.org/licenses/>." target="_blank">https://www.gnu.org/licenses/>.</a>1 g  }1 N& @. }- k  f
  25.   */ b8 Q/ L; H9 g: y& ~- b+ ?
  26.   ******************************************************************************
    4 A' E0 ]2 \* M, _4 j
  27.   */( P5 K  K' \, Q% Q- t  G* W" n2 Q

  28. 1 A- ^7 t: o& p. Y5 M7 Y+ C
  29. /* Header includes -----------------------------------------------------------*/
    5 r% e; Z# ^9 f' K# K- m
  30. #include "RingBuffer.h"
    / F5 v* `& B, D7 V# q1 j# }* _& x
  31. #include <string.h>' t# g; m' j5 x7 l2 P2 S. y
  32.   _5 B) V3 x( o, [/ a" b
  33. /* Macro definitions ---------------------------------------------------------*/
    ! {$ t5 A( O* Q+ b0 I
  34. #define min(a, b)  (((a) < (b)) ? (a) : (b))+ q# _; V3 F7 z. n

  35. & ^! x! A; u( a! m: }6 [3 U# _
  36. /* Type definitions ----------------------------------------------------------*/7 H0 V) M" y7 X  I+ y1 S
  37. /* Variable declarations -----------------------------------------------------*/
    ! U8 r& r$ O& E# D- ]! t5 G
  38. /* Variable definitions ------------------------------------------------------*/: Q- n' j- D: w* |5 X% O
  39. /* Function declarations -----------------------------------------------------*// ~5 A) S8 l3 I; U0 c
  40. static bool is_power_of_2(uint32_t x);
    $ g" a; D. b4 C" u9 ?3 j
  41. static uint32_t roundup_pow_of_two(uint32_t x);
    % C3 J# x5 z3 [7 }6 i
  42. 0 u# k+ h  ?. f% i$ q# l0 k
  43. /* Function definitions ------------------------------------------------------*/
    & N; u# ]2 _: b7 I1 }" j
  44. 6 {7 ^* e# D3 H5 a# n8 Q( [
  45. /**) y; ]5 [& }0 U( G0 {* D- M: W: q
  46.   * @brief  Allocates a new FIFO and its internal buffer.
    4 k  E: p5 B; K4 K' O, T, W
  47.   * @param  [in] size: The size of the internal buffer to be allocated.
    " y1 @4 v+ Q2 r0 ]
  48.   * @note   The size will be rounded-up to a power of 2.
    " @' X+ p8 A, }
  49.   * @return RingBuffer pointer.
    * C' p0 i) q- B& S) ~6 P9 R8 H; C
  50.   */
    8 N# z, X) q1 T. z" X
  51. RingBuffer *RingBuffer_Malloc(uint32_t size)4 i( K% W) t& F
  52. {
    0 L. A4 s2 ?7 @- j9 T4 Q. K
  53.   RingBuffer *fifo = RING_BUFFER_MALLOC(sizeof(RingBuffer));% u5 V/ m. V  f2 H( t, S+ V% N

  54. 7 a- Z8 S! r! a, e) `3 T. d
  55.   if(fifo != NULL)4 a" ]8 F& _" w% L
  56.   {
    1 \: X. J- F! N4 F2 A
  57.     if(is_power_of_2(size) != true)
    ! j- |4 W2 f. {* h/ S3 ^* n
  58.     {; ], B; W+ }6 O, I& K( i! e
  59.       if(size > 0x80000000UL)4 Y3 c. b5 \8 f0 E
  60.       {
    - d" L$ |+ D3 i9 u
  61.         RING_BUFFER_FREE(fifo);
      Y5 ]+ B" L$ N
  62.         return NULL;3 @( x4 A0 i: z
  63.       }
    # X6 ?2 K) M5 Z6 E

  64. ' _/ b2 X: ^: j( M" i  ^) P0 M
  65.       size = roundup_pow_of_two(size);
    ' V& b6 m- z9 W6 p# t, K) j4 d
  66.     }
    9 v( g- w% r/ L/ Q' |$ V* r
  67. 7 O  k5 w9 ?" a6 S% |. o
  68.     fifo->buffer = RING_BUFFER_MALLOC(size);/ h9 `! J" b2 r) b

  69. ( T  y! @) a1 J( E( d7 B( {
  70.     if(fifo->buffer == NULL)1 T0 L: s( |' O+ B% ^5 G
  71.     {
    3 g& n  Z6 E: B6 d( _  i2 J
  72.       RING_BUFFER_FREE(fifo);
    % _4 x1 H0 n3 {( \+ w; z
  73.       return NULL;
    / N% ?8 Z) J0 t* v
  74.     }
    4 z, A" J0 W+ X' Y; Q7 T0 E' q

  75. " w' D" \2 w& ~% B, M
  76.     fifo->size = size;* @0 W+ [5 I2 t! q1 `
  77.     fifo->in = fifo->out = 0;# |* v% v7 m. ^4 |% c, p, d$ n: s
  78.   }2 W: z8 V& f( P! Q  j: v" G
  79. " ~- g! l. k3 v- Z# F/ K
  80.   return fifo;& q: |3 V! w3 @9 I5 [
  81. }) @( v! _% X& a( r' s- r& _3 F1 j

  82. 2 a; L6 q8 S& X
  83. /**: z( a) b3 s1 k5 i5 ~
  84.   * @brief  Frees the FIFO.7 {9 e4 T5 W) J/ M5 L# F
  85.   * @param  [in] fifo: The fifo to be freed.- v/ Q% p8 n, u9 b+ n
  86.   * @return None.
    1 z( {2 g$ }8 ^7 c% ~
  87.   */( X2 ?" A1 i4 c* y. M+ H3 e- I
  88. void RingBuffer_Free(RingBuffer *fifo)
    1 `+ x- _* S, I1 S" y, t+ h$ ~
  89. {" E: f0 r  s* N! C# J! [# U
  90.   RING_BUFFER_FREE(fifo->buffer);
    % Y8 Z$ M% f( J! d
  91.   RING_BUFFER_FREE(fifo);
    1 l) |& x+ j7 @( b; p* ]8 O
  92. }
    ) p# O5 P3 E/ m/ e3 {, U

  93. . X8 F# D6 C4 a: [6 c
  94. /**
    ' ^. Q* y5 D/ c3 y' ^4 g
  95.   * @brief  Puts some data into the FIFO.7 G0 I8 ]' P. s+ J
  96.   * @param  [in] fifo: The fifo to be used.
    % {( C/ P  D/ j* D6 U
  97.   * @param  [in] in:   The data to be added.
    / r$ q4 q8 i0 A& a3 j7 l
  98.   * @param  [in] len:  The length of the data to be added.
    + a! p% p# ?% A5 A
  99.   * @return The number of bytes copied.
    # T& j& i$ G+ w2 Q6 n# }+ |) p0 h: W
  100.   * @note   This function copies at most @len bytes from the @in into
    2 r" B# U8 L2 _& V7 @) n1 f
  101.   *         the FIFO depending on the free space, and returns the number
    / o' a) u: }8 p5 Y8 [; e. r1 G
  102.   *         of bytes copied.$ a) f' p& ~8 _/ s/ O
  103.   */
    1 c  v4 Z$ I4 p/ I; s; Y
  104. uint32_t RingBuffer_In(RingBuffer *fifo, void *in, uint32_t len)( p8 m! h* W8 r
  105. {: |! ^. F. J6 X( S
  106.   len = min(len, RingBuffer_Avail(fifo));
    $ I) X  q; I4 b- F0 h6 E

  107. ( d6 l$ b7 v" l8 P7 y
  108.   /* First put the data starting from fifo->in to buffer end. */7 D# ]' E  R6 Q
  109.   uint32_t l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));" w2 @/ E2 k8 N5 i/ P8 H
  110.   memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), in, l);$ z5 A6 f" f2 ]9 C
  111. 3 k( y9 H: e/ G: Q% ~5 W$ y0 O9 w% m
  112.   /* Then put the rest (if any) at the beginning of the buffer. */
    8 Z0 n, K1 ~. ]5 y8 M2 R2 V
  113.   memcpy(fifo->buffer, (uint8_t *)in + l, len - l);2 X2 H/ r9 h6 R; J6 k: }9 @

  114.   O! e# [* p9 p$ {$ X5 p" ]8 {1 q
  115.   fifo->in += len;
    % T# M3 q! l0 p. k' S! j

  116. 2 Q0 d+ l' u- O/ X  H
  117.   return len;
    9 g6 X, J% c* c
  118. }# s& }# @# w( F; U% d7 A

  119. : N6 q6 a: h( w
  120. /**% c' Q4 v- W  Z: y# \* K
  121.   * @brief  Gets some data from the FIFO.7 K6 S8 h/ e) s, }/ ?
  122.   * @param  [in] fifo: The fifo to be used.
    - J9 [; D* U& z3 R  \& ]
  123.   * @param  [in] out:  Where the data must be copied.5 d% f; o; \. E* b+ B* g
  124.   * @param  [in] len:  The size of the destination buffer.
    0 s9 o. m: C5 I9 [/ T' u
  125.   * @return The number of copied bytes.
    9 a) b! u* Y0 Q4 k
  126.   * @note   This function copies at most @len bytes from the FIFO into5 O" a; T" \1 D
  127.   *         the @out and returns the number of copied bytes.$ o1 ^" b! a, M0 g( d
  128.   */
    : |4 {/ k! R, p6 t: G# O
  129. uint32_t RingBuffer_Out(RingBuffer *fifo, void *out, uint32_t len)
    3 k4 d9 O& B8 N. y' e
  130. {
    & J  c% f1 O( Y2 K" C
  131.   len = min(len, RingBuffer_Len(fifo));/ g4 Q  Y3 ?+ g3 e$ S& [1 U  Z
  132. / Z- B" _7 ~- r5 T* Z1 _2 ^3 a' O( h
  133.   /* First get the data from fifo->out until the end of the buffer. */- Z- [* c! I" N# s& s, Y3 _% _) x
  134.   uint32_t l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
    6 w/ E7 Y1 N) L% L5 v5 ]
  135.   memcpy(out, fifo->buffer + (fifo->out & (fifo->size - 1)), l);; g8 M* y- m3 t

  136. + U9 [! W) o, n) v- j5 o
  137.   /* Then get the rest (if any) from the beginning of the buffer. */
    0 V1 D* W& R0 K; j9 R2 v
  138.   memcpy((uint8_t *)out + l, fifo->buffer, len - l);
    ( J: T2 t5 Q% u; H& {; B5 C
  139. ; }/ T- b3 q9 ]1 ^
  140.   fifo->out += len;
    % b- e" P2 h0 k# L0 q! w- K

  141. 8 c+ V% D  @  A. m
  142.   return len;- R* M) D. I4 J! s1 f- K
  143. }) X! \$ s0 U/ \4 z
  144. 1 O5 J+ A; a; J* k' {
  145. /**- c- _+ U7 k# H+ x1 M0 a  x
  146.   * @brief  Determine whether some value is a power of two.
    7 E4 Z) _" Q6 p* K! e/ u
  147.   * @param  [in] x: The number to be confirmed.
    , t. m& D( U, t1 W, i
  148.   * @retval true:   Yes.8 w9 G/ g$ K3 S  T# o
  149.   * @retval false:  No.
    1 z( M& F% Z+ v
  150.   * @note   Where zero is not considered a power of two.) v- E' y$ P/ }; C  c
  151.   */
    5 z4 v5 `: |" ^- d0 t* L9 w
  152. static bool is_power_of_2(uint32_t x)
    ! ^5 b4 J/ h0 h
  153. {- o- n5 H. v$ |0 G& M/ D4 M
  154.   return (x != 0) && ((x & (x - 1)) == 0);
    6 e3 z/ w. F  D$ F
  155. }' z0 B! t) m& i3 d& M, S7 H

  156. ! G+ {1 N% k+ w& q  j9 y
  157. /**
    9 I2 ~2 o+ ~6 P0 U6 m' y
  158.   * @brief  Round the given value up to nearest power of two.
    0 |8 _1 U( X7 A! Q/ I9 w6 \1 _
  159.   * @param  [in] x: The number to be converted.0 e/ q# K+ Y8 r2 T6 j! d/ W/ o, k" u
  160.   * @return The power of two.
    ) X# `, k% ]8 x1 }6 _5 r
  161.   */) h, F2 I1 A8 j3 Z
  162. static uint32_t roundup_pow_of_two(uint32_t x)
    ' y: `# v6 o& |- _+ z, ?  x4 B
  163. {
    ; v- h- d! r* b* l! \! ]
  164.   uint32_t b = 0;
    0 N- ~/ `3 ]$ z! w. c

  165. 0 R% I* ^# g) a" a
  166.   for(int i = 0; i < 32; i++)  d9 h; a9 \% ~5 l' P# I* y
  167.   {
    9 F: }8 ^& e1 E* u' G
  168.     b = 1UL << i;2 {" n2 K5 x1 r

  169. 6 [6 H# H& f: v  q5 Y) x* Q
  170.     if(x <= b)
    6 g3 r! {. z3 h: q" _9 k7 K, t
  171.     {+ i( M' m" G5 _2 h" d: `, [: T
  172.       break;$ U( Y% N" S1 r
  173.     }2 u* q9 w3 |  y
  174.   }3 |# B4 o* u. J* w
  175. : F8 |0 ]% I( C% w! v3 k, g0 t% q
  176.   return b;% S3 N/ `- ?* f  `
  177. }</div><div></div>
复制代码
5 a" C) g$ N2 W. H( u: p

8 Z- {+ }% s& HCAN.h 文件
) b' z  c: A' s; D4 m
  1. /**' d) {) Z' u% c# h- `# z
  2.   ******************************************************************************
    9 K1 ]$ f7 t5 q
  3.   * @file    CAN.h
    ; r0 }! M% K5 c0 }7 w8 \, }
  4.   * @author  XinLi
    ' q8 T6 K# H. [! L0 E
  5.   * @version v1.0
    3 y$ {% N. u/ ?! l: q" m
  6.   * @date    24-June-2018, \& ]; E& S" {* Y4 E% k/ k
  7.   * @brief   Header file for CAN.c module.
    ' S/ _8 K% i( L5 R! B9 _6 G
  8.   ******************************************************************************
    2 e$ W3 F* Q) Q- O! R" Y# a% p
  9.   * @attention' Z% F8 `* t0 D
  10.   *7 ^$ a- q9 ^. D+ ~4 P; K0 p+ l
  11.   * <h2><center>Copyright © 2018 XinLi</center></h2>/ S* _: R) C) k# ?- g
  12.   *4 l! `; S* ]; Q2 W0 y. S! D
  13.   * This program is free software: you can redistribute it and/or modify
    . g% ~9 m# g; q: \: A
  14.   * it under the terms of the GNU General Public License as published by7 s* {' I8 v4 {! Z, Q: X- U
  15.   * the Free Software Foundation, either version 3 of the License, or4 F: c4 a- U2 k# V! I/ a
  16.   * (at your option) any later version.
    6 L0 `0 J' Z: ^& Y) F4 s
  17.   *! D, H( {& U. R3 B
  18.   * This program is distributed in the hope that it will be useful,3 p; U& ~6 @4 ^. g
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    $ M' `, C% s1 G8 `
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    " D! E0 ]$ U' v1 c0 n% m
  21.   * GNU General Public License for more details.
    6 n% E! L9 Q6 n* `
  22.   *
    - l$ e; L6 ~/ i4 O
  23.   * You should have received a copy of the GNU General Public License
    - q; ^" [' J9 J
  24.   * along with this program.  If not, see <<a href="https://www.gnu.org/licenses/>." target="_blank">https://www.gnu.org/licenses/>.</a>
    ' z, Y$ ^% ^* O' q$ q6 I
  25.   *( A" E/ H# u' o3 i# F
  26.   ******************************************************************************
    & x/ a' C. v% |1 F# D, O
  27.   */
    * a; r- R: W4 a+ [% \4 E
  28. ! g/ F. r' i9 |4 \
  29. #ifndef __CAN_H, T! r' U3 [- r" R
  30. #define __CAN_H
    * }$ V0 M& C/ y& y$ \/ q

  31. . K7 L" e! |$ ]. p
  32. #ifdef __cplusplus; b5 m5 V' y, s% e% K
  33. extern "C" {. T$ L& \0 x8 p
  34. #endif8 B$ y2 a  u' d0 R, u% t5 \

  35. / G+ a" W0 U# m. \
  36. /* Header includes -----------------------------------------------------------*/% _  X% }& o/ |# [5 @
  37. #include "stm32f10x.h". D/ D3 g; n5 m" f2 t6 R' q# H
  38. #include <stdbool.h>% z+ l3 @! t+ T' V2 y

  39. 0 Q2 g/ W- R2 E9 x% Z& @# s
  40. /* Macro definitions ---------------------------------------------------------*/
    " ]3 t1 m- Q( a8 M0 A2 e+ R

  41. " p+ s. u( M% }8 W% A; z7 O  B
  42. /******************************* CAN1 Configure *******************************/9 @+ V; \5 U$ f' F
  43. #define CAN1_TX_BUFFER_SIZE        (16)
    : j4 {$ G6 _- d7 u
  44. #define CAN1_RX_BUFFER_SIZE        (16)
    - Z5 g8 [$ e8 J, ?, I+ a
  45. 1 @; u( ~- K- x0 t# U% j
  46. #define CAN1_TX_GPIO_CLOCK         RCC_APB2Periph_GPIOB; g0 Y8 G& ?; y5 h
  47. #define CAN1_RX_GPIO_CLOCK         RCC_APB2Periph_GPIOB
    2 R1 q1 t4 R3 ^, u( ^% j/ ?

  48. $ }% Z' \. [. o7 Z
  49. #define CAN1_TX_GPIO_PORT          GPIOB
    5 u* I: e  \9 V4 x! Z
  50. #define CAN1_RX_GPIO_PORT          GPIOB2 ?- q; J# T. {- P( H# D% V
  51. / C- P( z$ o+ b  l
  52. #define CAN1_TX_GPIO_PIN           GPIO_Pin_9. {$ b: X5 F/ t, L
  53. #define CAN1_RX_GPIO_PIN           GPIO_Pin_87 w& j( F$ e5 k3 @$ ~' c
  54. ( z8 ?9 @2 t( Z4 H* g7 p
  55. #define CAN1_IRQ_PREEMPT_PRIORITY  (0)) V3 `  m- G  f6 ~8 K
  56. #define CAN1_IRQ_SUB_PRIORITY      (0)- c$ X% _8 G) M1 m! Z/ d- I

  57. 3 R+ V# p/ |. G. \) Y& j
  58. #define CAN1_PORT_REMAP()          GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE)& A8 s% D' l8 t* y
  59. /******************************************************************************/, y; R3 P0 Y# a  o- {/ d3 \  r

  60. 4 E  w  {5 T4 |. ~3 @
  61. #ifdef STM32F10X_CL
    : [4 P7 t& k& w1 F- A  K" P- t
  62. /******************************* CAN2 Configure *******************************/
    * Z1 Q, E+ T# u! o8 G6 H
  63. #define CAN2_TX_BUFFER_SIZE        (16)9 \1 U, b2 z2 |! h2 l
  64. #define CAN2_RX_BUFFER_SIZE        (16)$ ~% j# l# t$ ?: g1 D( O
  65. 5 t" b2 r8 h/ h
  66. #define CAN2_TX_GPIO_CLOCK         RCC_APB2Periph_GPIOB
    * @& |- `1 {) Q; p+ p, U
  67. #define CAN2_RX_GPIO_CLOCK         RCC_APB2Periph_GPIOB3 B' W# a4 Q; }# S7 w
  68.   @4 f! b: r' [. x; h6 D
  69. #define CAN2_TX_GPIO_PORT          GPIOB
    4 c. n% T3 j4 V* k8 C
  70. #define CAN2_RX_GPIO_PORT          GPIOB- F8 C' D3 R3 K, ~2 |1 q! P- A& V
  71. 4 k6 e* R+ z$ x4 X
  72. #define CAN2_TX_GPIO_PIN           GPIO_Pin_13
    7 I- h6 ^- d: i8 t( G
  73. #define CAN2_RX_GPIO_PIN           GPIO_Pin_12* ?. y( i3 c2 J1 B

  74. - `( ]( f2 N( f! @4 b7 |
  75. #define CAN2_IRQ_PREEMPT_PRIORITY  (0)
    % n- V$ L: ?$ B4 W- F4 e
  76. #define CAN2_IRQ_SUB_PRIORITY      (0)6 w5 v0 c' K' e( z$ B; o

  77. % m% {: O% T5 b% z7 l: G
  78. #define CAN2_PORT_REMAP()          GPIO_PinRemapConfig(GPIO_Remap_CAN2 , DISABLE)
    & _/ U+ j% \3 u. y8 `+ x" C. D
  79. /******************************************************************************/# R; T& ?7 |: l( A) B1 F: {
  80. #endif /* STM32F10X_CL */
    . @3 V5 L4 P, ?5 z% a
  81. ) J3 a5 C- i6 Y% ~
  82. /* Type definitions ----------------------------------------------------------*/. w; B+ K1 m+ ]# d; r; s& J
  83. typedef enum
    % ]' A6 _! W' e% \; P+ W1 U
  84. {8 @, k- j4 v( M! F( C
  85.   CAN_WorkModeNormal   = CAN_Mode_Normal,
    $ h- u- d$ J. y) k' S. c) s8 H% p
  86.   CAN_WorkModeLoopBack = CAN_Mode_LoopBack  y. x9 s. Y8 H
  87. }CAN_WorkMode;
    / j( y- H; o5 @' w& g
  88. % b7 g/ g& b9 y/ Q0 q
  89. typedef enum
    5 a: _* H' ~0 R% z
  90. {
    7 q4 v+ L& I4 U& n  o. b, _
  91.   CAN_BaudRate1000K = 6,
    4 j' x$ [1 ]7 Q3 T% t1 X
  92.   CAN_BaudRate500K  = 12,
    ( J$ Y4 p$ A5 o! }6 H' C/ \  x
  93.   CAN_BaudRate250K  = 24,
    % w5 v3 g2 h7 q+ p; ]% P; R
  94.   CAN_BaudRate125K  = 48,
    ( H9 A. E8 O/ J: ^
  95.   CAN_BaudRate100K  = 60,
    $ U6 h4 ~, @% `6 H" `. {4 p
  96.   CAN_BaudRate50K   = 120,
    # |! T' w" T$ m+ w0 s6 V2 n8 l
  97.   CAN_BaudRate20K   = 300,% [, O6 Y. o  ^! l
  98.   CAN_BaudRate10K   = 600! R! Q3 r2 ]5 S- H) L9 E
  99. }CAN_BaudRate;4 Y) D, t" ~+ W" X* U
  100. : X6 E/ C  I& s6 M; q8 p: r
  101. /* Variable declarations -----------------------------------------------------*/
    ) A' w, l+ q9 l1 z* |) H
  102. /* Variable definitions ------------------------------------------------------*/7 |4 `: Z, D% P+ c+ H: {
  103. /* Function declarations -----------------------------------------------------*/8 I& A, h& [# s
  104. void CAN_Configure(CAN_TypeDef *CANx, CAN_WorkMode WorkMode, CAN_BaudRate BaudRate, uint32_t StdId, uint32_t ExtId);
    % `6 |. {; ~4 {) f
  105. void CAN_Unconfigure(CAN_TypeDef *CANx);; h6 |. \6 O! p7 }# c' }: X! a& m

  106. $ O( q9 C7 P! H
  107. void CAN_SetTransmitFinishCallback(CAN_TypeDef *CANx, void (*Callback)(void));
    / F" G% {9 T: g
  108. void CAN_SetReceiveFinishCallback(CAN_TypeDef *CANx, void (*Callback)(void));
    - m, e/ O- C; k- t
  109. ! C4 r! o4 ?7 M2 C: M
  110. uint32_t CAN_SetTransmitMessage(CAN_TypeDef *CANx, CanTxMsg *Message, uint32_t Number);8 g& t2 W6 B' l" U
  111. uint32_t CAN_GetReceiveMessage(CAN_TypeDef *CANx, CanRxMsg *Message, uint32_t Number);  s" @; |/ w7 I0 K: i: f. L1 S

  112. $ h7 ~5 q: ]8 `
  113. uint32_t CAN_GetUsedTransmitBufferSize(CAN_TypeDef *CANx);2 E3 `/ I$ b( v: V) X
  114. uint32_t CAN_GetUsedReceiveBufferSize(CAN_TypeDef *CANx);2 q* M2 b7 L5 m: {( s
  115. uint32_t CAN_GetUnusedTransmitBufferSize(CAN_TypeDef *CANx);
    9 u) O3 X9 d' B. B- t* ~
  116. uint32_t CAN_GetUnusedReceiveBufferSize(CAN_TypeDef *CANx);. J+ a. }! q0 f; [* T- I

  117. 2 {4 l6 A" L3 J/ D& H
  118. bool CAN_IsTransmitBufferEmpty(CAN_TypeDef *CANx);
    ' E4 H" e! X" C. Q; |* T$ |
  119. bool CAN_IsReceiveBufferEmpty(CAN_TypeDef *CANx);
    2 q, v3 e  u; ?5 ]9 @5 c6 a
  120. bool CAN_IsTransmitBufferFull(CAN_TypeDef *CANx);6 D2 j$ U$ q* \7 Z* o
  121. bool CAN_IsReceiveBufferFull(CAN_TypeDef *CANx);7 E2 i8 f" g9 `  ~

  122. / ]5 p5 o7 o0 Z2 }
  123. void CAN_ClearTransmitBuffer(CAN_TypeDef *CANx);
    ) p5 P8 y7 S& B; a5 @) t
  124. void CAN_ClearReceiveBuffer(CAN_TypeDef *CANx);0 f  I$ n7 x* w! z2 r7 ?

  125. 1 O! W" i- i5 K/ U9 m4 ?3 V8 U# E
  126. bool CAN_IsTransmitMessage(CAN_TypeDef *CANx);
    , ~9 D) G0 _: B) J1 v" |

  127. ; l) l: a! s1 e0 q+ n
  128. /* Function definitions ------------------------------------------------------*/: Z4 W4 J; @' b1 _2 M% Y

  129. , Z( ~  q- ^, P
  130. #ifdef __cplusplus
    ( N. Y, o$ n) ]: {, w
  131. }
    ; X7 O) R) D/ Y
  132. #endif( K# b, y4 D, Y: |0 O

  133. # ^! B' H2 S. J% x4 h) Z* u
  134. #endif /* __CAN_H */
    0 W* e  l* ?6 _7 O
复制代码
9 S1 \5 a/ I7 C  r: m4 k4 R6 [. \
/ w! Q4 m1 s3 ?3 m0 a8 T

  s, v* z- J+ o; F$ L; Q! g9 oCAN.c 文件' v( q5 C" a. ?4 A* J

6 {7 {, y& K. {' L0 ~# S
  1. /**
    / Y; Q4 m) h3 K1 R# |
  2.   ******************************************************************************
    3 H4 {; C; Q5 C. a9 s
  3.   * @file    CAN.c( f% }" w4 y7 D4 v. k# L5 D
  4.   * @author  XinLi2 x) k" g# c0 _7 F. V
  5.   * @version v1.0
    ) d) S! O- E& G1 M
  6.   * @date    24-June-2018
    * E- R- `; K$ a; p0 T. l
  7.   * @brief   CAN module driver.) T$ T1 t  A! C* \6 c( p
  8.   ******************************************************************************
    2 `: q& X4 L* Z( b% ~& z
  9.   * @attention# e1 c2 [. N" z  j. k2 ]
  10.   *
    : @7 t; c! U/ _3 E. Q8 B
  11.   * <h2><center>Copyright © 2018 XinLi</center></h2>! U# F/ e1 g' m1 Q  P7 U) P9 n7 e
  12.   *1 s  r' F# f* U1 l, J& _% {6 s& ?
  13.   * This program is free software: you can redistribute it and/or modify
    7 R5 k. w- o; z. W
  14.   * it under the terms of the GNU General Public License as published by" h  S9 o( T2 c- {8 r
  15.   * the Free Software Foundation, either version 3 of the License, or
    " E3 q1 Y& h; ~9 R; N5 r& P
  16.   * (at your option) any later version.
    8 b1 |% n: t( I
  17.   *
    3 m/ c! h$ }: F0 b
  18.   * This program is distributed in the hope that it will be useful,
    , {# T' o4 d( R! j. q2 `* t
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    " E9 j% H% t: z* G
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the0 [! V% g, f+ j5 S" |& [9 `: h" ?
  21.   * GNU General Public License for more details.
    ) y( K* R/ c5 A; h7 M1 v
  22.   *
    " z4 K/ a9 S/ T) y9 K5 W1 U
  23.   * You should have received a copy of the GNU General Public License, K$ ]# ~3 I# [( X5 p
  24.   * along with this program.  If not, see <<a href="https://www.gnu.org/licenses/>." target="_blank">https://www.gnu.org/licenses/>.</a>% ^: H8 {  d1 {% Y7 l
  25.   *
    3 P/ x' y) o1 Q" s2 b& R
  26.   ******************************************************************************
    9 i& O/ V5 L  O' Z+ r' T2 m
  27.   */1 M7 a- W; ?) K$ I& N
  28. + \5 W9 Q- t( z% K$ v2 t
  29. /* Header includes -----------------------------------------------------------*/+ F5 Z8 [, f# e) t: N6 p; c- Y
  30. #include "CAN.h"
    ; k: f9 Y% {/ m0 Z* X
  31. #include "RingBuffer.h"' n- Z: Q# U2 A* T, ^; e* K

  32. + v4 [7 ]; A/ I/ L! R! w
  33. /* Macro definitions ---------------------------------------------------------*/
    ! y4 m- k2 u# b* Q' u8 v5 h
  34. /* Type definitions ----------------------------------------------------------*/
    - m- o. j3 k0 \
  35. /* Variable declarations -----------------------------------------------------*// L: t, w, X/ Z( j6 ~
  36. static volatile bool can1InitFlag     = false;
    + e- k0 {" ]* k4 c- _" C
  37. static volatile bool can1TransmitFlag = false;! B  C7 n4 a7 g0 {5 t" o9 t4 c7 n8 d
  38. ; Q1 e2 A4 o" _
  39. static volatile void (*can1TransmitFinishCallback)(void) = 0;
    2 E) g8 t6 c& G& ]7 ~4 D
  40. static volatile void (*can1ReceiveFinishCallback)(void)  = 0;
    6 C) q, ~  Y8 l

  41. 8 A4 ^0 n1 m4 D" e) W) C
  42. static RingBuffer *can1TxBuffer = 0;
    % m. b! h8 W4 U9 f6 n
  43. static RingBuffer *can1RxBuffer = 0;
    $ P. s9 v  ^1 l7 I1 [) O# w

  44. " @+ V0 o1 D) {) j5 o/ `  H
  45. #ifdef STM32F10X_CL; ?( ^0 h9 ]6 O- F" m
  46. static volatile bool can2InitFlag     = false;3 i* N+ I; ?  F2 [( ]4 ~) y
  47. static volatile bool can2TransmitFlag = false;6 a& O' F) u( D% K9 L( H

  48. & O% y" ^+ H7 g! B# `5 p
  49. static volatile void (*can2TransmitFinishCallback)(void) = 0;! c3 N5 t( c3 V
  50. static volatile void (*can2ReceiveFinishCallback)(void)  = 0;
    * V3 z, N! B: V6 C0 ~
  51. . d  \( ]; X. W% n  ]& D( e
  52. static RingBuffer *can2TxBuffer = 0;
    - i/ z/ v4 D, z8 z, r
  53. static RingBuffer *can2RxBuffer = 0;$ H$ q/ E! ^: [
  54. #endif /* STM32F10X_CL */
    + k- K1 m0 {; V9 d
  55. 2 K0 G! Q, ]7 ]1 ?
  56. /* Variable definitions ------------------------------------------------------*/
    2 ~+ y. a. U$ g+ @: k: F
  57. /* Function declarations -----------------------------------------------------*/4 _1 g7 p. [$ X, s
  58. /* Function definitions ------------------------------------------------------*/; d9 e9 p; q' M, \& u9 q, r
  59. 5 A0 w0 O/ T4 l. D" u# F3 e
  60. /**! X$ o, M" s9 J3 w, X  t( |
  61.   * @brief  CAN configure., O" K8 D# r' m5 a* G; z1 g
  62.   * @param  [in] CANx:     Where x can be 1 or 2 to select the CAN peripheral.
    : K1 n7 J1 l; `: F- D. W
  63.   * @param  [in] WorkMode: Work mode.8 C1 z; P, T( ]5 q3 @, j
  64.   * @param  [in] BaudRate: Communication baud rate.
    . V+ T& X0 e1 A1 Y, h4 z
  65.   * @param  [in] StdId:    Filter standard frame ID.3 [; O, d! z% u; y7 E+ s/ b
  66.   * @param  [in] ExtId:    Filter extended frame ID.& ~" D  y- b3 M/ @9 I; F
  67.   * @return None.
    1 ^  c$ P& T4 Z$ l' H; G9 L* L
  68.   */' m3 {! k! U. a' q
  69. void CAN_Configure(CAN_TypeDef *CANx, CAN_WorkMode WorkMode, CAN_BaudRate BaudRate, uint32_t StdId, uint32_t ExtId)  d/ `( P1 ]' X. B
  70. {. q5 c& N! q- G( d/ J# y7 q
  71.   GPIO_InitTypeDef      GPIO_InitStructure      = {0};
    % c& v6 @3 u$ K! m/ H1 S
  72.   CAN_InitTypeDef       CAN_InitStructure       = {0};
    . B/ `0 g9 @# U0 O" N
  73.   CAN_FilterInitTypeDef CAN_FilterInitStructure = {0};
    6 M& n. Y, m) R" h
  74.   NVIC_InitTypeDef      NVIC_InitStructure      = {0};5 `' u2 C/ I1 B$ Y+ t. k/ u
  75. & B0 K5 t; N: [0 [: u
  76.   if(CANx == CAN1)6 w$ G3 L% ^' E5 B: M# J
  77.   {# }0 i  l' ]  _- w$ C' I3 L
  78.     if(can1InitFlag == false)/ c& W. s# m# P* f9 F7 e! X2 u
  79.     {1 d. S7 c" C1 h- _  C2 W
  80.       can1InitFlag = true;
    ! F5 P% b, w5 V% e  \( M

  81. 6 `4 u7 R, ^3 Z2 H) w% |3 [8 V
  82.       can1TransmitFlag = false;0 o% ]4 E( o: _0 d; w! v# `% g3 o& O
  83. 5 J9 u, B3 j1 M# z% r
  84.       can1TransmitFinishCallback = 0;
      P% i% J1 M1 w3 C) F) S4 m
  85.       can1ReceiveFinishCallback  = 0;3 a4 @4 D6 [' ^& T; \" ?
  86. ; m: y5 M# ?! r6 s2 _/ l
  87.       can1TxBuffer = RingBuffer_Malloc(sizeof(CanTxMsg) * CAN1_TX_BUFFER_SIZE);$ m- B. p" p% I
  88.       can1RxBuffer = RingBuffer_Malloc(sizeof(CanRxMsg) * CAN1_RX_BUFFER_SIZE);1 y/ K1 v: S9 p* I- x/ U
  89. 6 t6 e: {" B0 z: f. @1 A; `/ Y, z
  90. #ifdef STM32F10X_CL
    " W5 r+ {3 @# P4 Z, \
  91.       if(can2InitFlag == false)/ B: a0 K  o7 C' |  K1 U6 f% J
  92. #endif /* STM32F10X_CL */
    6 z# P# K# E2 p& U& c9 e0 C! f. B" O
  93.       {
    4 Z& h& s: l2 ^( ?+ U2 \3 }3 S
  94.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
    ; |, B; H8 e7 t6 x* `
  95.       }$ F' n# O" [5 M8 z0 o, {  d

  96. 9 h3 J5 F: U; Q7 V( h
  97.       RCC_APB2PeriphClockCmd(CAN1_TX_GPIO_CLOCK | CAN1_RX_GPIO_CLOCK | RCC_APB2Periph_AFIO, ENABLE);5 ]5 l* x. _3 V

  98. ; L  u2 G& C/ D' A7 }) l
  99.       GPIO_InitStructure.GPIO_Pin   = CAN1_TX_GPIO_PIN;5 |: E; N6 i) l' Z" a! E5 _2 ?4 |6 w
  100.       GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;' I# g" \" [/ E0 }
  101.       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  q% ]. W* T( p* S" E8 Z1 Y
  102.       GPIO_Init(CAN1_TX_GPIO_PORT, &GPIO_InitStructure);0 l2 A; ?/ u& u
  103. ) {0 {& S! i- j
  104.       GPIO_InitStructure.GPIO_Pin   = CAN1_RX_GPIO_PIN;
    $ ~* Y1 u0 a) Z# W% |- ^$ p' ~& k
  105.       GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    9 b6 C' \# K/ |  }; V( h3 N
  106.       GPIO_Init(CAN1_RX_GPIO_PORT, &GPIO_InitStructure);4 A9 E; l$ r5 X7 j/ P$ r' [5 d! J' k8 S

  107. 6 ?! `. v# ?1 Y; B2 n% s
  108.       CAN1_PORT_REMAP();2 m8 ]4 R. r# m  q

  109. % Z4 z  b2 X; r- k6 o
  110.       CAN_InitStructure.CAN_Prescaler = BaudRate;, S% X, f0 i% O: e/ w
  111.       CAN_InitStructure.CAN_Mode      = WorkMode;
    * X& `: {/ C4 U$ X) ~" c( J
  112.       CAN_InitStructure.CAN_SJW       = CAN_SJW_1tq;
    7 _) T6 D# @  Y* D
  113.       CAN_InitStructure.CAN_BS1       = CAN_BS1_3tq;5 T% ^$ x: ^6 j7 Y) F# v
  114.       CAN_InitStructure.CAN_BS2       = CAN_BS2_2tq;, x8 u4 N! G+ O2 O' D
  115.       CAN_InitStructure.CAN_TTCM      = DISABLE;: s0 _7 N( L0 Y8 N5 g% ~; G/ U
  116.       CAN_InitStructure.CAN_ABOM      = ENABLE;
    # Z8 ^. \4 I! l% E( v: @
  117.       CAN_InitStructure.CAN_AWUM      = DISABLE;6 J: K# s/ C) R5 R8 T- Y( _
  118.       CAN_InitStructure.CAN_NART      = ENABLE;( L2 D8 N3 ~# o  B! [- g5 v
  119.       CAN_InitStructure.CAN_RFLM      = DISABLE;
    ' ?2 O) u3 ^8 Q7 x
  120.       CAN_InitStructure.CAN_TXFP      = ENABLE;
    0 g7 l; ^1 T& i# ~+ M

  121. 3 M  ?6 C3 [8 h6 w
  122.       CAN_DeInit(CAN1);, A5 w! V: _+ @" K3 r5 J8 Y2 i
  123.       CAN_Init(CAN1, &CAN_InitStructure);
    + n! v# ?' {  i- V* s
  124. ! U+ v2 G* N' n* b# b
  125.       CAN_FilterInitStructure.CAN_FilterIdHigh         = (uint16_t)((((StdId<<18)|ExtId)<<3)>>16);
    0 H! z: I9 I2 r$ z( U
  126.       CAN_FilterInitStructure.CAN_FilterIdLow          = (uint16_t)(((StdId<<18)|ExtId)<<3);8 Q7 n4 E) N- @* r5 {
  127.       CAN_FilterInitStructure.CAN_FilterMaskIdHigh     = (~((uint16_t)((((StdId<<18)|ExtId)<<3)>>16)))&0xFFFF;# y3 O+ a/ R" Y" Y1 h
  128.       CAN_FilterInitStructure.CAN_FilterMaskIdLow      = (~((uint16_t)(((StdId<<18)|ExtId)<<3)))&0xFFF8;: [1 ^+ A" O6 s5 D: g& L# s
  129.       CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;" k: r2 U* Q+ l' q
  130.       CAN_FilterInitStructure.CAN_FilterNumber         = 0;1 C% K3 `8 l, n# i3 g  Z& u9 t8 ]+ X
  131.       CAN_FilterInitStructure.CAN_FilterMode           = CAN_FilterMode_IdMask;
    % W. \" m. j9 B/ j
  132.       CAN_FilterInitStructure.CAN_FilterScale          = CAN_FilterScale_32bit;7 |9 Z4 A! A3 H0 N  I$ O; b6 L
  133.       CAN_FilterInitStructure.CAN_FilterActivation     = ENABLE;( }3 F' [& Z4 C5 y, _/ _+ Y% b
  134.       CAN_FilterInit(&CAN_FilterInitStructure);
    6 |' D  K0 i0 K

  135. ; Z1 {& p8 z4 `& E# r
  136.       CAN_ITConfig(CAN1, CAN_IT_TME | CAN_IT_FMP0 |CAN_IT_FF0 | CAN_IT_FOV0 | CAN_IT_FMP1 | CAN_IT_FF1 | CAN_IT_FOV1 |, Z/ G, q% @( L0 V5 O& o
  137.                          CAN_IT_WKU | CAN_IT_SLK  |CAN_IT_EWG | CAN_IT_EPV  | CAN_IT_BOF  | CAN_IT_LEC | CAN_IT_ERR, DISABLE);
    # `' h* c) X4 ^) U7 f) y
  138.       CAN_ITConfig(CAN1, CAN_IT_TME | CAN_IT_FMP0, ENABLE);
    * b7 D- C# R5 [, K' G, p* U* P
  139. 2 ?3 }' i/ e' u) f
  140. #ifdef STM32F10X_CL
    + Q+ r, g( U4 n7 g% l
  141.       NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_TX_IRQn;4 ]6 y9 i/ ~' k/ r& D
  142. #else
    7 q2 g( z) s: O) g5 l5 @) G/ ]
  143.       NVIC_InitStructure.NVIC_IRQChannel                   = USB_HP_CAN1_TX_IRQn;& U# |" G/ q2 m0 m
  144. #endif /* STM32F10X_CL */
    ' }! |0 o2 r2 b" k
  145. 7 u3 r% l; v& y; ~+ a
  146.       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN1_IRQ_PREEMPT_PRIORITY;
    - g- Y1 u! H4 J# Y, h/ L
  147.       NVIC_InitStructure.NVIC_IRQChannelSubPriority        = CAN1_IRQ_SUB_PRIORITY;
    / k* n4 P+ B* q, G; _$ d5 [$ g0 }
  148.       NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
    ) G$ f* R9 q  D- o* _" K/ Z
  149.       NVIC_Init(&NVIC_InitStructure);& L: h5 E, K4 n8 a# Y
  150. 5 }; o* `. u' n8 i# C$ d. T$ L
  151. #ifdef STM32F10X_CL
    : f* R0 K9 F$ i% t, p7 p
  152.       NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_RX0_IRQn;. K% Q2 U3 Q# |2 r' h7 E
  153. #else
    8 F: x" Z* t* V& ~6 {
  154.       NVIC_InitStructure.NVIC_IRQChannel                   = USB_LP_CAN1_RX0_IRQn;. B+ Z# q- r, o- Q* c
  155. #endif /* STM32F10X_CL */
    ) w- T+ o; f0 h) r, c/ M4 l

  156. : j! X+ b2 A% J; Y3 l( K
  157.       NVIC_Init(&NVIC_InitStructure);
    , ?6 p% A* u- a2 C
  158.     }
    * v& q9 a& q3 Q. B7 j5 P
  159.   }
    8 v) l4 F9 E+ ^0 L) \

  160. 7 g4 H  T2 q3 l; B
  161. #ifdef STM32F10X_CL. L. p2 R5 I( l+ u8 ?# L6 Y$ m
  162.   if(CANx == CAN2)2 u8 n- r/ \; g8 v* @  W
  163.   {
    5 ^1 e! h6 @$ ?; r) k0 B& C
  164.     if(can2InitFlag == false)
    5 y2 J1 c% C4 U$ R5 ]
  165.     {
    9 n$ {% t8 h: z
  166.       can2InitFlag = true;  w$ [) `7 w8 n1 O0 G" k. h# j

  167. - |2 {% N, M9 T4 f7 }$ [: q; J
  168.       can2TransmitFlag = false;$ o+ I7 h7 J! m3 P
  169. 7 x0 U' p& K3 A$ H' q9 y) r
  170.       can2TransmitFinishCallback = 0;) `3 w1 {- r% M$ ]8 l
  171.       can2ReceiveFinishCallback  = 0;
      @' a4 _5 ~# C5 X( F4 e3 F. t
  172. ; A2 x. H* w5 z8 q6 A4 T* S# X- }
  173.       can2TxBuffer = RingBuffer_Malloc(sizeof(CanTxMsg) * CAN2_TX_BUFFER_SIZE);( v# C5 g3 H& g4 }) G3 j. Z7 r6 D. \
  174.       can2RxBuffer = RingBuffer_Malloc(sizeof(CanRxMsg) * CAN2_RX_BUFFER_SIZE);
    & h% s/ i* g& L) {! W  a
  175. ) h6 n/ I+ K7 r6 M" E2 T" q+ u
  176.       if(can1InitFlag == false)" y. |" c; C+ y4 W  J2 B$ e
  177.       {
    - s( p2 q2 c0 d- |% C! W1 Q
  178.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
      {5 k) j* n# Q1 B  D9 z( r$ w1 w. W
  179.       }# g* C  ^% f7 d; q# [4 Y' [' z
  180.   _6 d( p) E& G% S5 N) a5 p
  181.       RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);2 F( H8 y; p: X# V- v: d) ]
  182.       RCC_APB2PeriphClockCmd(CAN2_TX_GPIO_CLOCK | CAN2_RX_GPIO_CLOCK | RCC_APB2Periph_AFIO, ENABLE);  X  i  ?" j+ z4 ~- x

  183. 3 \0 E' Y# W8 N
  184.       GPIO_InitStructure.GPIO_Pin   = CAN2_TX_GPIO_PIN;/ ?: q+ }2 `% g$ j$ l& M
  185.       GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;  I; y9 N$ j$ z: t  u7 M
  186.       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    ! i  x- `* s* p# u, v
  187.       GPIO_Init(CAN2_TX_GPIO_PORT, &GPIO_InitStructure);
    ' i. R6 y+ H5 K; K; P0 \
  188. - N( n: h- e) W) |6 X. ?9 z4 C
  189.       GPIO_InitStructure.GPIO_Pin   = CAN2_RX_GPIO_PIN;
    ; e; z% N. a, N5 E
  190.       GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    # ^- F& A# O1 x; R! a% N
  191.       GPIO_Init(CAN2_RX_GPIO_PORT, &GPIO_InitStructure);9 l) h; T, d6 j0 b( d
  192. 5 V: P. D3 W) z7 j1 g* H# m
  193.       CAN2_PORT_REMAP();
    1 [9 E6 V3 j/ q  _9 a7 D/ ~, p( O
  194. ' I2 e9 m9 n9 H# d7 ?7 y+ U
  195.       CAN_InitStructure.CAN_Prescaler = BaudRate;
    * s$ ^3 v' a1 s
  196.       CAN_InitStructure.CAN_Mode      = WorkMode;, y; x, d1 n5 P. P: Z
  197.       CAN_InitStructure.CAN_SJW       = CAN_SJW_1tq;  Q+ s0 {2 K& S! q2 _3 |* Y
  198.       CAN_InitStructure.CAN_BS1       = CAN_BS1_3tq;1 u0 W( t2 b4 i  b
  199.       CAN_InitStructure.CAN_BS2       = CAN_BS2_2tq;5 Y) E9 E1 r/ X
  200.       CAN_InitStructure.CAN_TTCM      = DISABLE;
    * B" I8 h6 ]: I5 B) m
  201.       CAN_InitStructure.CAN_ABOM      = ENABLE;
    / z0 o5 D8 S" a$ `
  202.       CAN_InitStructure.CAN_AWUM      = DISABLE;
    0 i' x2 J) e2 n2 i
  203.       CAN_InitStructure.CAN_NART      = ENABLE;5 f7 {% m6 o( r  e9 U
  204.       CAN_InitStructure.CAN_RFLM      = DISABLE;' f7 D/ g% K  Q) l- o+ @& c! P% u! X
  205.       CAN_InitStructure.CAN_TXFP      = ENABLE;. g+ ?2 s& {9 k1 |3 N& O

  206. ) `5 u! P* J3 ]  Y4 k7 y  h  p
  207.       CAN_DeInit(CAN2);
    # I9 \! _! B( G- L) T' Q$ n* w
  208.       CAN_Init(CAN2, &CAN_InitStructure);
    % Y3 D# J  w2 @- _- i& e0 D& O7 y
  209. 2 q4 q' b; e1 I
  210.       CAN_FilterInitStructure.CAN_FilterIdHigh         = (uint16_t)((((StdId<<18)|ExtId)<<3)>>16);
      _/ S5 R' L, O4 u) U
  211.       CAN_FilterInitStructure.CAN_FilterIdLow          = (uint16_t)(((StdId<<18)|ExtId)<<3);
    4 Z1 J5 K6 f) ~. k+ V) b  F( D
  212.       CAN_FilterInitStructure.CAN_FilterMaskIdHigh     = (~((uint16_t)((((StdId<<18)|ExtId)<<3)>>16)))&0xFFFF;4 o( r6 D! f: C2 V
  213.       CAN_FilterInitStructure.CAN_FilterMaskIdLow      = (~((uint16_t)(((StdId<<18)|ExtId)<<3)))&0xFFF8;) M. ~# S, w8 g# G9 s
  214.       CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
      E5 s: p8 c2 O* r# w; b
  215.       CAN_FilterInitStructure.CAN_FilterNumber         = 14;0 z/ I& {0 Z9 A' t
  216.       CAN_FilterInitStructure.CAN_FilterMode           = CAN_FilterMode_IdMask;5 P+ n% K" h$ K. F+ N
  217.       CAN_FilterInitStructure.CAN_FilterScale          = CAN_FilterScale_32bit;
    ; N6 R* P/ Z, M
  218.       CAN_FilterInitStructure.CAN_FilterActivation     = ENABLE;+ U# R  q3 V& f5 \4 {. {
  219.       CAN_FilterInit(&CAN_FilterInitStructure);
    6 P+ w& c0 P  ]2 z+ X: J" b

  220. 9 W3 I& f' q7 h& I9 G6 q1 `
  221.       CAN_ITConfig(CAN2, CAN_IT_TME | CAN_IT_FMP0 |CAN_IT_FF0 | CAN_IT_FOV0 | CAN_IT_FMP1 | CAN_IT_FF1 | CAN_IT_FOV1 |( t+ m$ L. u' [$ R; q3 Y! o' j
  222.                          CAN_IT_WKU | CAN_IT_SLK  |CAN_IT_EWG | CAN_IT_EPV  | CAN_IT_BOF  | CAN_IT_LEC | CAN_IT_ERR, DISABLE);
    0 D1 P* w& b2 ~' ^. D
  223.       CAN_ITConfig(CAN2, CAN_IT_TME | CAN_IT_FMP0, ENABLE);
    , x" \6 D; A0 f  A

  224. - W9 N) ^/ ~; k' Z. u
  225.       NVIC_InitStructure.NVIC_IRQChannel                   = CAN2_TX_IRQn;- d9 h  ^! f% n7 [0 ?
  226.       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN2_IRQ_PREEMPT_PRIORITY;' i8 r9 ]) Y3 n- c
  227.       NVIC_InitStructure.NVIC_IRQChannelSubPriority        = CAN2_IRQ_SUB_PRIORITY;! b5 v$ U, S) a$ I8 H5 X
  228.       NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;4 i! s0 n) o" v" j& `  r
  229.       NVIC_Init(&NVIC_InitStructure);
    2 E1 G( [4 l$ U% b" C# v9 M
  230. + W3 F* y7 y0 u& G
  231.       NVIC_InitStructure.NVIC_IRQChannel                   = CAN2_RX0_IRQn;& W: Q. P$ f: E' j: T6 {" c
  232.       NVIC_Init(&NVIC_InitStructure);
    " |% x5 C: m2 }2 N
  233.     }
    ) f: S6 y* a- U# w" s
  234.   }4 O% o9 [% F) O& ~+ G. y
  235. #endif /* STM32F10X_CL */8 w7 A3 }1 k( x* i4 l
  236. }, e, F% \) y9 b* I# j0 l. E

  237. : Q- A8 G2 b3 C& u9 F5 g
  238. /**
    6 E/ l1 m7 d& Q/ R5 }6 O
  239.   * @brief  CAN unconfigure.
    8 E. s; T2 P8 y- F5 }" B
  240.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.$ Y2 ~, a& |4 {% ]
  241.   * @return None.
    , j: V3 u( F+ v
  242.   */2 [5 U" J5 _* T3 B$ [
  243. void CAN_Unconfigure(CAN_TypeDef *CANx)( [" o4 j% Z6 M) K$ K
  244. {' J, [, r$ Y! E) T
  245.   NVIC_InitTypeDef NVIC_InitStructure = {0};: e! p: ]5 ^: W
  246. 1 Y0 H, B) r- y2 y
  247.   if(CANx == CAN1)& E0 O$ ^, p) `' V2 @
  248.   {6 y. I- w  I( r6 P. `5 j7 |/ b
  249.     if(can1InitFlag == true)
    7 G% h3 R: O2 `& C) t
  250.     {
    ' a0 L; j% R- X! T& p* N! k) }
  251.       can1InitFlag = false;5 z0 g6 q" C) k6 D; _! p

  252. " J7 l4 K# T: _3 ?' m
  253. #ifdef STM32F10X_CL' [6 Z8 r4 [6 P1 a% i; S
  254.       NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_TX_IRQn;( v6 S8 |, n+ h4 j, x: N0 a
  255. #else
    6 e' e% V' z9 s# f
  256.       NVIC_InitStructure.NVIC_IRQChannel                   = USB_HP_CAN1_TX_IRQn;+ I7 i' c$ M5 m3 N
  257. #endif /* STM32F10X_CL */7 I: S/ F+ q( P. x! n

  258. - d0 c5 n& Q: P+ W. B
  259.       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN1_IRQ_PREEMPT_PRIORITY;
    & {' K, I3 W) N* O, P
  260.       NVIC_InitStructure.NVIC_IRQChannelSubPriority        = CAN1_IRQ_SUB_PRIORITY;
    - N' L$ B* P  T7 o8 G
  261.       NVIC_InitStructure.NVIC_IRQChannelCmd                = DISABLE;
      e3 }6 Q- {. O7 ?( D$ y
  262.       NVIC_Init(&NVIC_InitStructure);
    ' I! f" K* U# j$ ^
  263. $ L8 Q( M7 l" T$ B: f9 z/ R' r9 c
  264. #ifdef STM32F10X_CL
    2 q, x" i$ X& A; u: K
  265.       NVIC_InitStructure.NVIC_IRQChannel                   = CAN1_RX0_IRQn;
    ' v' G1 n4 ^0 ^- ]
  266. #else. w; g3 p. V3 F. \7 `8 f
  267.       NVIC_InitStructure.NVIC_IRQChannel                   = USB_LP_CAN1_RX0_IRQn;
    ; z5 s' G( x: v
  268. #endif /* STM32F10X_CL */9 ^4 |' e7 |# \

  269. # g9 X) k5 l+ q
  270.       NVIC_Init(&NVIC_InitStructure);% p$ {1 }6 M9 T

  271. 7 Z2 G5 j0 a) s
  272.       CAN_DeInit(CAN1);
      `/ V& f" N3 j- m+ c

  273. ' O, U' v- ^# v+ @6 ]
  274. #ifdef STM32F10X_CL' c% z% t; K4 E/ T' ?9 r
  275.       if(can2InitFlag == false)
    ) p' w: q' E7 M2 N3 p, F
  276. #endif /* STM32F10X_CL */
    1 X$ S& q) r5 D
  277.       {% V1 D( z3 |9 b, ]& Y0 u1 X0 h
  278.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, DISABLE);
    # s2 |% [9 Y3 i
  279.       }
    $ X  i# j- F! o7 i5 t

  280. , E. ?' B! ?* T  }: ^1 p
  281.       can1TransmitFlag = false;
    4 t" ]1 L" A0 T; {+ z4 {: n
  282. # m0 |4 K: M) u/ G+ i
  283.       can1TransmitFinishCallback = 0;
    4 h% `4 N8 p4 f# F3 r/ u
  284.       can1ReceiveFinishCallback  = 0;
    " G2 H" u) Y1 d# r9 T+ X4 y

  285. : D/ m" ?5 i0 P2 _$ n. U& Z6 u
  286.       RingBuffer_Free(can1TxBuffer);/ q1 j( ~& T# ~6 B& ]1 ~
  287.       RingBuffer_Free(can1RxBuffer);
    ! [& Q1 [* u6 M- p1 ]% ?/ V
  288.     }( U+ M. _9 @: E5 \! s
  289.   }
    0 O: p+ }4 e$ \
  290. 7 j9 ^9 F& r# B8 o: k# v# Q
  291. #ifdef STM32F10X_CL
      d! B: K% Q( a0 O$ }" [6 Z
  292.   if(CANx == CAN2): o/ }- D. |* F
  293.   {
      g5 P( Y; m0 ^3 Z5 A
  294.     if(can2InitFlag == true)+ T$ `$ F0 X! `- ]" m
  295.     {. [- u( ^% h# H$ {5 D
  296.       can2InitFlag = false;, E9 e2 G6 _2 G( z% O8 \' \
  297. 0 n1 P2 L  N6 f- G( Q( A' k; y# w
  298.       NVIC_InitStructure.NVIC_IRQChannel                   = CAN2_TX_IRQn;
    ) H$ U4 K6 v' z; g- M( l+ y
  299.       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN2_IRQ_PREEMPT_PRIORITY;) p" s- p9 u3 u
  300.       NVIC_InitStructure.NVIC_IRQChannelSubPriority        = CAN2_IRQ_SUB_PRIORITY;$ I7 x4 j! b8 z/ E4 d, X
  301.       NVIC_InitStructure.NVIC_IRQChannelCmd                = DISABLE;
    & I- H, K# f: Q1 X- z
  302.       NVIC_Init(&NVIC_InitStructure);
    * l$ W3 [0 F! a0 r& J

  303. 7 d9 u. ?" o; j' [5 f7 R6 F/ S
  304.       NVIC_InitStructure.NVIC_IRQChannel                   = CAN2_RX0_IRQn;
    9 ^  }/ e8 k5 x6 h
  305.       NVIC_Init(&NVIC_InitStructure);
    + m9 w# n/ n: v4 E0 \" h; T2 \) P" b

  306. 1 p; C. V& v# i, B6 I0 B
  307.       CAN_DeInit(CAN2);) y) Z5 C5 K4 |. k3 V1 N2 r( {1 R9 W

  308. 6 r$ I: ?3 Y1 ?2 ?3 D& q
  309.       if(can1InitFlag == false)
    1 d5 H$ M- d7 `! T  H/ u
  310.       {1 S* o; U8 d: S+ ~) j; T
  311.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, DISABLE);4 s9 J5 H, \; d0 H/ B$ A9 {
  312.       }) P% U& y9 ]" B* G  ^( q% P

  313. 6 r7 g. \6 i& z  [: w
  314.       RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, DISABLE);
    / c6 O# P# B3 ~; T' H8 n: W% I
  315. ( p2 q+ {0 i! v- v, _
  316.       can2TransmitFlag = false;+ F' \* w6 [: e4 m' V# k$ Y" C  ]7 }: R
  317. 7 V: G+ {- P* F; Y# z0 X
  318.       can2TransmitFinishCallback = 0;/ U" z9 \, C% n# G; \" W
  319.       can2ReceiveFinishCallback  = 0;' ~, G) p6 D2 R5 {' h5 ]
  320. & O+ m- A  k; H/ D* M. _8 Z9 U
  321.       RingBuffer_Free(can2TxBuffer);" F+ P! w2 i. ^' B9 ~% P
  322.       RingBuffer_Free(can2RxBuffer);
      |" e4 _; k- ^4 A4 a, f
  323.     }
    $ O# f, T( d8 j2 D% @6 A
  324.   }; ~9 k" ?1 `4 g" F' R% s
  325. #endif /* STM32F10X_CL */
    ( G# K$ Q/ A- L2 u# F( V2 F# Y
  326. }: i, y; s2 n* O3 M( G, T; b

  327. ; X6 @# }. k4 A, g4 I
  328. /**
    0 O; ^# W) B2 i
  329.   * @brief  CAN set transmit finish callback.
    ; v2 L+ `/ r/ u- P0 b
  330.   * @param  [in] CANx:     Where x can be 1 or 2 to select the CAN peripheral.
    0 B' w. @: _; s5 q) V. v/ }
  331.   * @param  [in] Callback: Callback.
    7 c" U% {4 G) m4 G
  332.   * @return None.+ f0 e3 E) ^7 J# t, O2 o# d  u- Y
  333.   */" G8 u5 k  Z; o1 w, m
  334. void CAN_SetTransmitFinishCallback(CAN_TypeDef *CANx, void (*Callback)(void))6 [, U3 N' h! j2 v& {
  335. {3 f% t$ _- s) l. N8 `+ h$ V7 N
  336.   if(CANx == CAN1)& e0 r- {+ m0 ^) y' \3 c+ ~
  337.   {
    % z. m( U! x1 ?/ V: p
  338.     if(can1InitFlag == true)  O% J  z3 p, Y
  339.     {
    " T7 X9 r* K7 `; s3 A- r9 @* o
  340.       can1TransmitFinishCallback = (volatile void (*)(void))Callback;
      B2 A, A0 y% _0 C- N4 a: p, q
  341.     }% M9 |+ l! z) F& ~; u0 b' X* i
  342.   }
    $ {" O' @. u& B' T) p

  343. " r" o* S2 S" |3 t2 \
  344. #ifdef STM32F10X_CL
    4 ~' ~- M& ^- p
  345.   if(CANx == CAN2)2 t$ U" ?# D- A2 P7 q
  346.   {
    $ ]7 ^) ~  I8 J* z- |8 \% C
  347.     if(can2InitFlag == true)
    # c' ^1 |& G: B6 z# s
  348.     {
    : {' H2 Q0 T2 r# ~9 l( G( M
  349.       can2TransmitFinishCallback = (volatile void (*)(void))Callback;; M0 A9 @% v& T# V" X  Z
  350.     }; n5 r; ?' j& @! R6 p1 |; T, l; O" L: D: V
  351.   }
    5 R. ?6 w+ I" Q' A
  352. #endif /* STM32F10X_CL */; h" P! t5 q: |" i  z6 c# O
  353. }+ F0 o5 I# [  m' w! U5 W

  354. * w6 V- v1 V6 x7 x5 w+ c
  355. /**! ?. ]; A1 e, ~# g7 ~
  356.   * @brief  CAN set receive finish callback.! c; H) k( u- q/ F7 [; _6 ~
  357.   * @param  [in] CANx:     Where x can be 1 or 2 to select the CAN peripheral.  P, ~+ c& A8 _3 D! M  b' P
  358.   * @param  [in] Callback: Callback.
    0 |$ T# r4 T: ?6 ?, s5 q
  359.   * @return None.
    + o" Q0 I! O% v( C8 j' L
  360.   */2 O# d( e$ z, C( q5 N
  361. void CAN_SetReceiveFinishCallback(CAN_TypeDef *CANx, void (*Callback)(void))
    8 Q6 l% n0 A) i4 r7 l1 @
  362. {0 n+ a0 h* i% i/ f; f' q# D
  363.   if(CANx == CAN1)5 D) Q8 g# c2 ^' i8 Y& ]% Z) H7 V; _% _
  364.   {
    # Z6 D. {9 h5 Q% G9 K8 F
  365.     if(can1InitFlag == true)% k8 G2 I  X6 O: U2 H
  366.     {
    : y+ x& Y/ m( q! d. _5 B; m* P
  367.       can1ReceiveFinishCallback = (volatile void (*)(void))Callback;. X1 t, N, [& H& |+ _
  368.     }
    4 f7 e8 e' D4 x  Z6 D: H
  369.   }) z2 F) |1 I. ~( J# }% k
  370. / B  [/ ]( @4 R% R- ~6 G; ]
  371. #ifdef STM32F10X_CL4 f# V" d* Y. y- J! n( x( A
  372.   if(CANx == CAN2)6 d/ w  [+ a$ [3 T7 ^9 W5 e3 R( I6 Y
  373.   {
    0 C% r. P7 W* R8 _% d, f+ o
  374.     if(can2InitFlag == true)
    8 X; t6 \' s6 P& C
  375.     {
    + a5 [9 v, l; P1 ^
  376.       can2ReceiveFinishCallback = (volatile void (*)(void))Callback;* r: r! M( c& p' B8 `1 T9 p
  377.     }
    2 I1 q% D2 C( L4 G7 \
  378.   }
    + K9 r' p2 `7 f/ ]) s" p+ K* B. Y
  379. #endif /* STM32F10X_CL */
    ' d" Q; x( L: n" ^
  380. }; E6 \( q' `7 L  E- o; r
  381. 3 |, k( {  N3 e/ N% Z# S4 g" O, ]
  382. /**1 b; P, D* R/ U
  383.   * @brief  CAN set transmit message.5 F, Q0 o; i+ ~4 p: _; k% l0 s
  384.   * @param  [in] CANx:    Where x can be 1 or 2 to select the CAN peripheral.; Y' n# r/ A4 D, C  A/ u( M
  385.   * @param  [in] Message: The address of the message to be transmit.
    ; Z- @7 S4 j+ \! D8 F, Q7 [+ V0 t
  386.   * @param  [in] Number:  The number of the message to be transmit.% V6 F' ]! \! @8 a0 Z
  387.   * @return The number of message transmit.6 B0 e0 T* w$ q. [7 k, G
  388.   */
    # e& X# b7 I! ^
  389. uint32_t CAN_SetTransmitMessage(CAN_TypeDef *CANx, CanTxMsg *Message, uint32_t Number)! u6 E5 o( g; I2 \0 ]( F$ H
  390. {
    - O( L" \* D$ F1 t- u4 B$ ~
  391.   if(CANx == CAN1)+ B/ z& Z7 C/ x* `8 ^
  392.   {
    - C& }9 Z2 h  j8 m5 X
  393.     if(can1InitFlag == true)5 r8 m5 M& n( G# _% C. c  t/ U
  394.     {
    7 e& v& ?, D+ W) i2 w
  395.       uint32_t available = RingBuffer_Avail(can1TxBuffer) / sizeof(CanTxMsg);% M! t3 u# F& e* b* P

  396. / Q( R( B3 S% {+ ^0 K- ]3 X" d) p
  397.       if(available > Number)6 z6 j9 h+ C' D! {
  398.       {8 H7 H: F3 k+ S8 A5 p' d& o
  399.         Number = RingBuffer_In(can1TxBuffer, Message, sizeof(CanTxMsg) * Number) / sizeof(CanTxMsg);- v. d0 ~3 p4 ?# C' a( _0 y
  400.       }1 B) j$ i- j2 R: j, `' d1 o3 `
  401.       else
    5 u, Y4 E2 C# z( Q1 ^0 ]6 F$ Z) [
  402.       {
    ' c, R8 ~& w: O0 j/ I; {! a
  403.         Number = RingBuffer_In(can1TxBuffer, Message, sizeof(CanTxMsg) * available) / sizeof(CanTxMsg);
    5 B$ A. W- ?4 U: Z: M) e$ p
  404.       }, \9 c# v2 R$ ?7 V6 E& K

  405.   b' j. u, a* D4 X0 e
  406.       if(Number > 0). `/ t  E9 l/ o5 W: i+ @0 G) L6 L/ L, y( E
  407.       {7 Z; e" l' ]3 D% |/ _) L
  408.         if(can1TransmitFlag == false). N. ^$ M+ I9 z6 b, [* [# X
  409.         {
    ) e3 w3 q* O7 {: b
  410.           can1TransmitFlag = true;
    * N9 a. d6 e% m% J4 G0 j: B
  411. 5 v7 m: L# M; a
  412.           CanTxMsg canTxMsg = {0};( h" H$ i( k* ^' U: ?
  413.           RingBuffer_Out(can1TxBuffer, &canTxMsg, sizeof(canTxMsg));& N' M5 [, i5 {0 ~# W
  414.           CAN_Transmit(CAN1, &canTxMsg);
    , B" U) g/ [) r+ M/ [0 X) V4 {
  415.         }$ e% P3 ]1 O5 v0 M' ~9 ~/ G
  416.       }" g8 c7 C6 M# R3 Q) Z$ X

  417. : d- m# c/ [7 a" H6 v
  418.       return Number;$ m2 K9 E' M! @% k. ?0 j! p1 `3 e
  419.     }6 C! t. H  c# G
  420.   }
    # K% O5 N4 z% K# Z8 O5 ]8 I- u4 Q1 w
  421. 1 X* w- j4 k) @% z$ }
  422. #ifdef STM32F10X_CL* O0 `% i0 L) R4 j& Y
  423.   if(CANx == CAN2)
    . |) R6 }0 `+ n6 z
  424.   {$ W2 M- T! M: y. C5 m: z
  425.     if(can2InitFlag == true)! F) a8 B2 F$ t1 r' q6 P/ b* C! R
  426.     {/ u0 i4 c- h# W* T  d
  427.       uint32_t available = RingBuffer_Avail(can2TxBuffer) / sizeof(CanTxMsg);& X, P; u$ A. q5 w/ q
  428. 8 |0 {& v' Q. v' H: I' P& l+ Q# g
  429.       if(available > Number)1 \/ t4 x: h: c, {' o& @1 G2 B
  430.       {
    % h5 W6 p/ M; y. B! o. O# I
  431.         Number = RingBuffer_In(can2TxBuffer, Message, sizeof(CanTxMsg) * Number) / sizeof(CanTxMsg);
    ; ~% u  E  l/ R" D# I5 b+ T
  432.       }3 ?8 f; ]9 C) x
  433.       else0 K  f7 f7 K' y; _+ G/ H0 D- A' j* e
  434.       {
    1 q2 K* e  S  G* V+ C  C
  435.         Number = RingBuffer_In(can2TxBuffer, Message, sizeof(CanTxMsg) * available) / sizeof(CanTxMsg);
    # p( D' \& ^" w$ x/ M" l$ K) Q
  436.       }3 x7 X' E8 t) u

  437.   p' y# S# @: }& E. Z
  438.       if(Number > 0)
    / }$ Z0 x. l7 n5 X$ {* V
  439.       {- \/ q% A8 n2 @( ~4 a
  440.         if(can2TransmitFlag == false)8 s! n- t9 S& [. A: E  i
  441.         {
    " Q1 v# g' M# z
  442.           can2TransmitFlag = true;
    6 g2 Z! r( C' x) }# U* [" R
  443. 9 e; x9 d7 h& y3 u# q0 x
  444.           CanTxMsg canTxMsg = {0};. Y# Q2 I. d, P$ g! s2 ^
  445.           RingBuffer_Out(can2TxBuffer, &canTxMsg, sizeof(canTxMsg));
    9 t8 M) i$ L5 d* c* t0 P5 i" @: T: s
  446.           CAN_Transmit(CAN2, &canTxMsg);( x. c9 A  [; Y/ U: m9 r6 I
  447.         }, E; N& h+ i# A) y3 {
  448.       }1 V5 m. T* {7 J# S
  449. . o( p) k3 h( ]$ f( x6 h3 c0 D$ [
  450.       return Number;
    $ s8 v( p2 _4 L* L- f( `
  451.     }
    6 @1 y& u- J6 ]9 S, Y
  452.   }
    7 C4 B& a5 u* P4 o5 B* p6 c% J% _
  453. #endif /* STM32F10X_CL */: A& w! Q: `! x& C2 q" J$ r+ u
  454. " [$ ?* C; S3 r; j; B: s2 R4 y
  455.   return 0;( q# l" y" S: s$ i6 _) B+ j
  456. }8 l6 f& D( f  k% x" K

  457. 3 C1 a* V  `* b/ ~. F
  458. /**& j; Y/ `! ~9 U$ ~  W- l
  459.   * @brief  CAN get receive message.
    / c/ C2 I! n; g; E7 G0 f
  460.   * @param  [in] CANx:    Where x can be 1 or 2 to select the CAN peripheral.
    # F6 D/ s6 O- N2 w# o7 c, B
  461.   * @param  [in] Message: To store the address of the receive message.
    # E! q! k# |. X6 b: N9 e
  462.   * @param  [in] Number:  To read the number of the received message./ R7 F! }# O! h- [* A% W
  463.   * @return The number of message obtained.! B: I" {3 }, h( B. ]0 i3 C
  464.   */
    % W' i! V; {' r* X# F8 v3 O; `
  465. uint32_t CAN_GetReceiveMessage(CAN_TypeDef *CANx, CanRxMsg *Message, uint32_t Number)
    * A" t1 I. i# r- h/ z4 O6 @
  466. {2 _0 `( t, ?) N& h. H: |4 o. y9 I
  467.   if(CANx == CAN1)
    ! M- Q9 Z. c' F$ D+ y
  468.   {
    9 ^8 i& D# ?- L. i& U' A
  469.     if(can1InitFlag == true)0 j9 b% @% L5 t2 Z! s0 `
  470.     {  b+ B5 L6 |+ i" o* o
  471.       return RingBuffer_Out(can1RxBuffer, Message, sizeof(CanRxMsg) * Number) / sizeof(CanRxMsg);7 T  n' ^3 E5 Z; j
  472.     }
    ; E4 Z. h) C" `* D1 T6 A& v% q
  473.   }
    * A: Q1 y2 e' I8 [4 ~

  474. / Y3 f) `- B( @
  475. #ifdef STM32F10X_CL1 B$ S3 o# w6 [: o$ Z& ^
  476.   if(CANx == CAN2)
    0 n; o- ~  c/ ]1 P# }" t
  477.   {2 t$ a. ]/ X. W2 k& F9 O- d
  478.     if(can2InitFlag == true)
    - X/ K% Q3 U) Y; P  y! r2 `& L
  479.     {! M/ V0 J' h4 X9 @
  480.       return RingBuffer_Out(can2RxBuffer, Message, sizeof(CanRxMsg) * Number) / sizeof(CanRxMsg);2 f8 B; J: ^) _$ f. T  a
  481.     }
    ( A1 m' C$ C, I2 ^# n
  482.   }
    6 E9 }% b+ p" X: z  B; J
  483. #endif /* STM32F10X_CL */
    : t/ J; R( }9 V/ O$ ^' d: U

  484. 4 n! _9 h7 c+ p# w( K# C& i! G+ `
  485.   return 0;$ X; N/ W  I" b% `! c% q" S
  486. }  O8 y4 l; |- V7 t8 H4 _# m  a

  487. 0 d" J/ ~) o$ d
  488. /**: o8 O0 V7 r1 r+ R- v4 x
  489.   * @brief  Get the size of the CAN transmit buffer used.
    # l* p0 \! G' V& O: H& B* L
  490.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.
    : J0 o6 r5 P- x% W7 g3 Q
  491.   * @return Used the size of the transmit buffer.! h) b  t' E1 ?& g; e" l  c/ s/ G* t  H
  492.   */
    ' E& z3 H. C3 Z1 [" h; _2 W
  493. uint32_t CAN_GetUsedTransmitBufferSize(CAN_TypeDef *CANx)
    ' s0 f3 H1 z6 H) i$ I! U2 x
  494. {6 h8 t5 y9 h8 g2 n& {3 g: s8 o
  495.   if(CANx == CAN1)+ y& c8 k4 T2 N
  496.   {0 ^3 U+ n; P- k" [
  497.     if(can1InitFlag == true)
    - d  J  c9 S3 ?
  498.     {8 m: q4 ~/ V2 j# h4 `; T
  499.       return RingBuffer_Len(can1TxBuffer) / sizeof(CanTxMsg);+ @+ |9 ^; Q& [. x
  500.     }( u- j$ S5 w7 B  F+ E
  501.   }6 J: Q& ]9 r( H( ^- U! n

  502. * o  [) @; }. i4 D: Y
  503. #ifdef STM32F10X_CL/ I: y" q, x: C! c" P8 o  z; b: ^
  504.   if(CANx == CAN2)
    . P4 t  V6 y5 h$ V8 B
  505.   {$ K0 b: e5 J" E1 t% D4 l0 I
  506.     if(can2InitFlag == true)0 m  [; f( R) Q) B% ?! a& A# g( I
  507.     {- N( J, o# q3 I& t- t# g
  508.       return RingBuffer_Len(can2TxBuffer) / sizeof(CanTxMsg);* O0 k* _3 c3 i* J- L5 _! u
  509.     }
      t$ j& f) Z" O/ s9 N# i. a
  510.   }
    3 E: c, h  W; g" R5 S
  511. #endif /* STM32F10X_CL */
    ( N% b3 d4 v, w0 P& o3 s
  512. + G( I; |$ r0 m  K$ x: H
  513.   return 0;
    8 c0 i0 W, ]$ o) D6 y
  514. }  X. Q! J5 l. c0 @

  515. % _, l( O0 ]8 g* y  q
  516. /**
    6 F7 k6 R9 x7 ^/ W! Z- t* `
  517.   * @brief  Get the size of the CAN receive buffer used.1 i7 ]  Y. M, c9 i- c" Q  W
  518.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.' Z! d' k7 E2 D& m
  519.   * @return Used the size of the receive buffer.
    3 x+ ]; Z3 u+ d$ [! y& ]
  520.   */; \% Z- Y1 }1 f" i' g5 Y- ]4 j
  521. uint32_t CAN_GetUsedReceiveBufferSize(CAN_TypeDef *CANx)' x7 p0 D# _7 }) F, e6 g
  522. {
    . t1 D6 D* Z- d! ^: `3 D" ~
  523.   if(CANx == CAN1)3 h7 E* M4 |; i/ F, ^* z
  524.   {
    ) s; [( `! ]% E: X- h4 n+ U+ E
  525.     if(can1InitFlag == true)
    / v2 N" H( @' V5 y9 r% p
  526.     {
    - ^- }9 s% R/ ~9 N7 Q
  527.       return RingBuffer_Len(can1RxBuffer) / sizeof(CanRxMsg);$ d4 X2 }, s! C5 h$ U' V
  528.     }
    " l3 ~5 s2 e0 G2 `0 w& Q2 @3 ^! I
  529.   }% \* K/ \$ A, f& b, }
  530. 5 n) ~* C0 G7 I2 N' w
  531. #ifdef STM32F10X_CL4 ?. \  f: L. A8 Y. C
  532.   if(CANx == CAN2)' X) h- |" j( ^7 M. W$ J
  533.   {! v7 U& q: G* [* a/ F
  534.     if(can2InitFlag == true)5 X6 G; Y. }  Z' x9 F
  535.     {
    ; |: Z' S) _( K0 a8 y* L6 m
  536.       return RingBuffer_Len(can2RxBuffer) / sizeof(CanRxMsg);
    # u' z0 u1 i. z. t6 o/ m
  537.     }
    % o) z9 b: m! w# p3 {" k
  538.   }* }9 C" J) m4 A9 G
  539. #endif /* STM32F10X_CL */
    4 J9 v- J- W& b3 r1 f

  540. 2 x9 D8 o+ `" f
  541.   return 0;9 n9 t: P" s6 w8 }2 w
  542. }. H5 g% u& P, _4 t
  543. $ t' ^/ E" K( s7 y- A) P1 h% ]# c
  544. /**
    * w) f9 E, `: }, g# ^0 H5 b
  545.   * @brief  Get the size of the CAN transmit buffer unused.+ O4 L& ?& a# o7 x5 y2 B
  546.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.
    / A1 O' e; N: f0 `% _* p" f+ t
  547.   * @return Unused the size of the transmit buffer.
    & h- {  I2 |6 @4 X+ Z( m
  548.   */# c" C$ k7 d# |' i6 M+ g
  549. uint32_t CAN_GetUnusedTransmitBufferSize(CAN_TypeDef *CANx)- B' [/ R( Z$ H; y& y
  550. {
    % E) H, t5 Q- Y( Q0 W" H
  551.   if(CANx == CAN1)) P4 f# f* N% u
  552.   {
    * i* h8 }& x( C# |# P
  553.     if(can1InitFlag == true)) N5 d( W/ F6 m
  554.     {
    , }7 c4 n3 b5 Y: p7 C9 s
  555.       return RingBuffer_Avail(can1TxBuffer) / sizeof(CanTxMsg);- t" _- W# w% F5 I
  556.     }9 V* L" \' ~/ O5 i% |2 Z5 a7 I7 O
  557.   }
    ( E, d* |9 Q7 ~

  558. " e+ k9 f3 G6 |1 X
  559. #ifdef STM32F10X_CL  C! v0 U3 g% x0 t, k' l4 C
  560.   if(CANx == CAN2)
    ; M7 o, h4 h( W) ?9 P. R% f1 w
  561.   {; f5 w% {, a7 [$ p! K
  562.     if(can2InitFlag == true)" {! Y+ G- h: n/ `. m. L
  563.     {4 ^2 A$ o' U! _
  564.       return RingBuffer_Avail(can2TxBuffer) / sizeof(CanTxMsg);
    2 R" N& m0 L# b+ B7 ]
  565.     }
    / }8 F/ w# q. a! E) X" T% l3 i9 X
  566.   }' |" l; S! I+ H' d- ~9 J
  567. #endif /* STM32F10X_CL */
    ; k5 s9 ?: v4 w3 |9 o

  568. 7 x3 U1 B, S& h
  569.   return 0;
    ) z- c2 y* i! v# E: a% X, x# A
  570. }
    & l3 G: f% o% n' L6 m, m
  571. 5 z. Q$ i+ J; {6 I
  572. /*** o( M9 D) E! b2 n) D: D. a
  573.   * @brief  Get the size of the CAN receive buffer unused.
    2 m  Z0 e6 D- t" t5 @$ W9 J
  574.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.* ?! R! i3 a3 T+ I( y  u
  575.   * @return Unused the size of the receive buffer.
    : C* m, v/ N+ G
  576.   */
    4 D: C1 l. O. |2 D. r/ C* U
  577. uint32_t CAN_GetUnusedReceiveBufferSize(CAN_TypeDef *CANx)( G& b& b! a% C, M' N! {% h  q! C
  578. {* m4 \3 h4 ^! J) n0 ?" h
  579.   if(CANx == CAN1)
    : N: I% C$ J; e" H* S
  580.   {# E* U$ P( L8 T4 Z
  581.     if(can1InitFlag == true)
    * X+ R; x1 _; p" ^' X' b! x3 k
  582.     {( F6 x: L$ C' r% h7 Z1 v1 ]) ]
  583.       return RingBuffer_Avail(can1RxBuffer) / sizeof(CanRxMsg);
    2 l" I, V: z: f* x0 Q
  584.     }1 @2 q/ m# v. {# }
  585.   }" E+ M+ h4 R1 D. n; C3 F
  586. ! {( Q: q, W# J1 I/ ~
  587. #ifdef STM32F10X_CL' k$ A6 O7 K0 Y" e
  588.   if(CANx == CAN2)( D. d' [- ^9 `, P' Y1 W
  589.   {
    9 ~8 W6 t& o, J' F3 S0 H
  590.     if(can2InitFlag == true)
    0 Y. n6 X: O% h/ b/ Q3 }: i0 X
  591.     {
    & N  \4 D. h+ P7 G$ i! X
  592.       return RingBuffer_Avail(can2RxBuffer) / sizeof(CanRxMsg);
    3 Q6 V9 D) G$ O$ T! X* Y& s  v* R
  593.     }9 U: H) K$ p7 V
  594.   }
    ! _9 o& p4 O0 ?  N& p7 `4 a: Y* y# G
  595. #endif /* STM32F10X_CL */
    4 x8 A# X! c; _- s) h  l

  596. / f* ]' D9 m5 m9 ]  s" X
  597.   return 0;+ F8 y, s7 l/ d$ O9 c5 e* k
  598. }
    4 U' A0 Q) w; o/ M* M4 y# E' r5 d

  599. / I- }' o# g/ @" z" U( ?; A
  600. /**4 x6 a; c1 s7 o2 }, Q/ N! g
  601.   * @brief  Is the CAN transmit buffer empty?
    + d: P7 [: J) q
  602.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.
    8 c9 K* L8 u, p
  603.   * @retval true:      The transmit buffer is empty.  s( o: f  @( _& F+ c) Z
  604.   * @retval false:     The transmit buffer is not empty.& R2 c" l* R( I
  605.   */
    % _. B- [& M  J3 L# d2 p9 j
  606. bool CAN_IsTransmitBufferEmpty(CAN_TypeDef *CANx)8 i* c- t! W4 I+ [5 l: Z
  607. {
    2 `  E5 P$ M5 _, _; V" s
  608.   if(CANx == CAN1)
    5 w6 L4 G4 w3 O% m9 S
  609.   {
    & v5 l) c+ L: k) G- z: P: D
  610.     if(can1InitFlag == true)0 N- Q& b% D2 M" K7 i6 F
  611.     {4 U( K- E: {; D7 D6 j# h/ o
  612.       return !(RingBuffer_Len(can1TxBuffer) / sizeof(CanTxMsg));, i( {; r- k; d' A$ J
  613.     }# i4 O/ R1 b+ x$ b4 S
  614.   }
    ' T5 X6 t8 S: P" W% t6 e" }- v+ C5 o

  615. 8 K4 i, ^' A- ^* w1 h6 {- D+ N
  616. #ifdef STM32F10X_CL
    ) C: a" C& N) i( {/ K
  617.   if(CANx == CAN2)
    * t- j! i4 s6 D6 t
  618.   {; v, K" c5 M. c% R4 B6 ?; N
  619.     if(can2InitFlag == true)
    & I! a- k$ S$ }9 t7 h
  620.     {
    5 A; X( w8 T. v, X, p+ ^
  621.       return !(RingBuffer_Len(can2TxBuffer) / sizeof(CanTxMsg));
    ' j* w# s3 Z. ?! t
  622.     }$ ~* e4 u4 C: R) A0 p
  623.   }
    8 h8 b% a' h* P8 g, C
  624. #endif /* STM32F10X_CL */5 v: B6 R# [+ I5 m. h- A5 o

  625. 7 N% o" m7 d9 ?, c( ~* f: k7 B
  626.   return false;, r! d- v5 z9 E- x
  627. }$ C/ Z/ L/ N. {% D

  628. 4 i; E: k" Y9 n3 R
  629. /**1 e- r/ ~4 u6 @% |
  630.   * @brief  Is the CAN receive buffer empty?
    1 t3 Y" j/ ~0 q9 A& W3 {
  631.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.( W  v! s7 g3 @5 V
  632.   * @retval true:      The receive buffer is empty.
    % w+ B9 d% F0 t  X% O: y
  633.   * @retval false:     The receive buffer is not empty.9 ?0 p9 T- ~% Q2 D
  634.   */
    - D6 Q5 o6 F% [# F6 f
  635. bool CAN_IsReceiveBufferEmpty(CAN_TypeDef *CANx)
    1 w8 [5 N- I3 [9 k
  636. {
    , u/ w' a4 m0 F8 ]
  637.   if(CANx == CAN1)
    3 ?) J2 O& }( P- ]# a" q4 Q
  638.   {
    * u* @; y: P7 J. v: N7 n# Z
  639.     if(can1InitFlag == true)/ l) D( D( P8 r/ T& P! t
  640.     {
    + t' I7 A. e6 i  `+ D
  641.       return !(RingBuffer_Len(can1RxBuffer) / sizeof(CanRxMsg));
    & Q2 w# }3 B) @) e2 @: \+ r
  642.     }, ^7 R! m% u0 q
  643.   }1 q! }( L0 p7 l9 O) x
  644. + g4 B9 K9 t+ E  G/ d8 c
  645. #ifdef STM32F10X_CL
    5 ]9 q0 H" G: q
  646.   if(CANx == CAN2); p9 I$ D0 _- s
  647.   {
    ) G# v0 N! x% T9 T
  648.     if(can2InitFlag == true)
    $ @7 ^) ?  C1 }* `& Z$ l5 X+ e
  649.     {7 g. r: n2 J; M1 [. e
  650.       return !(RingBuffer_Len(can2RxBuffer) / sizeof(CanRxMsg));2 s& x$ x; h- q; l5 n, D: k* d
  651.     }8 e9 i) `  o* h& o
  652.   }
    # ]/ @' Q! q3 C6 q) g. b: k/ b, @' k
  653. #endif /* STM32F10X_CL */. h: W3 ]+ t5 d3 t% Y9 |* q4 _

  654. 2 i! O: a1 T' M9 C1 S5 u! Z, f1 |
  655.   return false;, H3 i2 e" l1 _% J
  656. }
    9 e6 u1 {, x; v2 j5 _3 |1 C

  657. ) n; _& U4 F/ g2 B
  658. /**: y7 o$ r8 `8 \
  659.   * @brief  Is the CAN transmit buffer full?
    ' i, N1 l' \* ~3 ]) K% F4 f
  660.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.
    8 [+ ?* A4 J" T
  661.   * @retval true:      The transmit buffer is full.3 f( }7 r1 {( ~* q' j- t1 {
  662.   * @retval false:     The transmit buffer is not full.( K6 V) h0 r# h' _
  663.   */
    . h% T( D$ p1 R
  664. bool CAN_IsTransmitBufferFull(CAN_TypeDef *CANx)3 x5 b! @+ H; u
  665. {# J2 a1 z; h3 D0 R9 Q
  666.   if(CANx == CAN1)
    % U' t7 D6 a7 q
  667.   {' L7 n4 r" U% W9 I; ?( ^$ O! i
  668.     if(can1InitFlag == true)
    0 A7 ]3 d. O# [/ Q3 M4 [
  669.     {
    & C% s. K% Q4 T2 B/ F" F  N, w
  670.       return !(RingBuffer_Avail(can1TxBuffer) / sizeof(CanTxMsg));2 ~9 r% P/ E6 \2 B/ T1 W0 X
  671.     }
    0 S% |: j/ m, F3 X4 P& _
  672.   }, r. f+ \& _! K. S
  673. 4 }' h: v4 {% f  h
  674. #ifdef STM32F10X_CL+ g8 W# Y) ^4 ^3 u& D
  675.   if(CANx == CAN2)5 D& i. U3 p: n
  676.   {
    , l* x! u% c, q2 Z
  677.     if(can2InitFlag == true)
    * g- }; i6 a0 M2 K! a8 l
  678.     {' H2 q* ~4 |/ y8 z% K
  679.       return !(RingBuffer_Avail(can2TxBuffer) / sizeof(CanTxMsg));( w& I3 o, d# \* u0 u
  680.     }: Z3 x9 Z! m' v5 _4 n0 z3 e) e
  681.   }9 ?% r3 @( i( Z. x6 `2 ?/ h
  682. #endif /* STM32F10X_CL */9 ]' @, b% G; e, G1 M6 _. d8 I
  683. & C. s( @- \; C7 s  B
  684.   return false;" G4 ^5 ?: j& I% R
  685. }
    - ^2 l6 e6 l; I" K$ ~! N
  686. " w4 @( `! d2 p
  687. /**
    2 @4 X$ C3 e& h$ E3 h8 @; l2 j' n. ^" Y/ B
  688.   * @brief  Is the CAN receive buffer full?
    3 Q0 K) Z& E8 k  T$ s$ P$ L7 p
  689.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.& n! Y! L% u) }# }2 O
  690.   * @retval true:      The receive buffer is full.4 t0 I& i$ T3 E" |! P' x# O
  691.   * @retval false:     The receive buffer is not full., e( y6 X5 |/ b+ I- M* Z; Z
  692.   */5 [! P9 E! m3 \" F8 \* \
  693. bool CAN_IsReceiveBufferFull(CAN_TypeDef *CANx)
    " J. Y4 v" @- p7 z/ X
  694. {
    ! Y' B$ T% i- f3 Q% d1 r( u
  695.   if(CANx == CAN1)
    : w5 i# u% i% o, e8 W  b
  696.   {
    + K0 X  R1 X' Y6 k' n5 s/ M
  697.     if(can1InitFlag == true)+ b0 v* ]4 X  |7 r( l& O# K2 I
  698.     {
    4 {" c  B, |+ A
  699.       return !(RingBuffer_Avail(can1RxBuffer) / sizeof(CanRxMsg));: l* n& \% B% N) `
  700.     }
    + E  Q. H$ w$ G
  701.   }
    8 e  P2 \" r& u! z

  702. 6 H6 d( ?" K- ?/ M9 }' s
  703. #ifdef STM32F10X_CL: N/ \+ I4 W* M  x4 M  d
  704.   if(CANx == CAN2)% z& A# S4 O) B5 N4 F/ F# d
  705.   {
    3 ]2 D' x4 u+ n5 i# x/ s
  706.     if(can2InitFlag == true); Z' t: ]! u+ _' Z1 C9 Z0 P# f
  707.     {* V  A9 L: j4 ^9 P- t) Q
  708.       return !(RingBuffer_Avail(can2RxBuffer) / sizeof(CanRxMsg));, y* t% t% i7 R& j
  709.     }
    7 F5 P# i) U- N' v! X1 o
  710.   }6 Z$ X, B& l, C9 `) e/ S+ H
  711. #endif /* STM32F10X_CL */
    " i! [( ?3 y  w! J+ P; v6 F" J
  712. : C( U5 {: M4 e- D1 Q& S7 B. f+ Z
  713.   return false;" j5 E' d. I( K. r3 g
  714. }
    % X( ~) i1 ?4 I# q. \- J9 X

  715. # I: m  o- q  k: [  o( a
  716. /**
    ! [' G$ z( l( I9 e
  717.   * @brief  Clear the CAN transmit buffer.
    $ E3 S# \% U2 T( |9 k2 H+ W% c% i
  718.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.
    7 r( s; x7 H* O! O% z
  719.   * @return None.
    & h  @9 M. V$ [# @1 i4 x6 I
  720.   */( b% }0 p* o% V) P% D
  721. void CAN_ClearTransmitBuffer(CAN_TypeDef *CANx)6 K5 b; Q+ O) U9 P; q+ A
  722. {
    * }. @; v  s; r9 Z# u7 ~0 p) ^
  723.   if(CANx == CAN1)
    % j- X5 `! G1 |; o7 q/ t9 h( f! }7 p
  724.   {; E; d) X! X2 y* P
  725.     if(can1InitFlag == true)
    7 C$ |- j( F$ a9 u
  726.     {
    6 H6 c5 g' M  q+ e8 L
  727.       RingBuffer_Reset(can1TxBuffer);
    + L' N% _( u+ D5 C. Z& I
  728.     }
    9 w' v  `. \3 C7 m1 E
  729.   }
    . A3 ~2 y9 o- X  m
  730. 3 X7 H  o$ n3 S2 M+ [; m) V
  731. #ifdef STM32F10X_CL
    2 n$ r; W- Q; a. T5 b( |" b* @  n5 k
  732.   if(CANx == CAN2)
    ! g8 i- C" u( ]7 |; W- e. ]% t
  733.   {
    $ A8 Q" C2 ~2 \' n
  734.     if(can2InitFlag == true)% U- y) H8 T; z" n# Z
  735.     {
    " y+ C5 d4 m( q, v
  736.       RingBuffer_Reset(can2TxBuffer);
    8 V2 e  I: y/ l( u# |* d
  737.     }
    9 n2 s4 D+ |: a4 y
  738.   }
    : L7 r1 R& C7 i* j8 W$ J  O
  739. #endif /* STM32F10X_CL */
    : A/ f7 e4 L2 G! n* _
  740. }
    # b- p, e6 C& }- u5 s6 O

  741. + [& M0 B& k9 m4 z$ C5 z
  742. /**0 I! Q0 C/ M* `* A
  743.   * @brief  Clear the CAN receive buffer.1 Q0 c5 |- W% f) J6 P: F$ J
  744.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.
    ! O) r0 Q# ]6 e2 k
  745.   * @return None.
    4 E1 M1 N0 \1 L- w9 n+ q, T
  746.   */
      Z+ I; x) s: V
  747. void CAN_ClearReceiveBuffer(CAN_TypeDef *CANx), ?! \8 t5 e6 h, y3 O" Q
  748. {
    3 {7 @. V) L" S/ i  t7 T9 A
  749.   if(CANx == CAN1)
    * U# z8 `. K" f( d4 e" f5 c% Q0 _9 e
  750.   {
    2 m. ~' C1 v  s; C2 c
  751.     if(can1InitFlag == true)# M3 V' U: n9 D) B  n& n$ j
  752.     {7 j; K; {  y$ |1 f- z/ ^4 ^
  753.       RingBuffer_Reset(can1RxBuffer);1 K% H+ k; i; J. C# i' R* ^7 U
  754.     }
    ! @& e! }: B& h# b6 q
  755.   }
    ; b. [5 H6 I4 H# ]0 @

  756. . d# n8 m/ S& m6 [4 v
  757. #ifdef STM32F10X_CL; B/ W/ C- \; h
  758.   if(CANx == CAN2)9 f: v# c' T& T/ m: G8 r* R
  759.   {& Q; j+ F& E8 f* U7 F$ V  S2 y$ X
  760.     if(can2InitFlag == true)
    * b: M# }+ q6 l0 k- @
  761.     {5 z5 F% z) U9 l: I
  762.       RingBuffer_Reset(can2RxBuffer);
    $ a. f# U7 j  S$ e8 N4 f+ b% A
  763.     }* E) i: E& }+ ~8 \$ a" F' @
  764.   }4 j) _: `. T9 m( H$ W0 J
  765. #endif /* STM32F10X_CL */" U" d  A- s7 C4 l! }/ l) r# j6 I
  766. }
    & a' e, P1 R  p# Z9 g
  767.   H- s6 Z  A0 q
  768. /**
    - c6 I) R+ j( r  n+ ?3 j0 i% d
  769.   * @brief  Is the CAN transmit a message?2 |2 Y8 e# {; |) S: R! {
  770.   * @param  [in] CANx: Where x can be 1 or 2 to select the CAN peripheral.
    # E, m) s2 |% r5 c7 Z6 x( V
  771.   * @retval true:      Is transmit a message.6 p8 t: w; U# T- x
  772.   * @retval false:     Not transmit a message.
    # W, d& e. }, f. ?3 W! C4 X1 X
  773.   */
    ) r3 U) S* L8 o
  774. bool CAN_IsTransmitMessage(CAN_TypeDef *CANx)
    3 f+ z' I& L% y% j/ @, j5 h
  775. {
    - L  f  W& G# }  k# ~# F
  776.   if(CANx == CAN1)2 Q1 P, _5 z% X8 C
  777.   {! f) O* P1 s& U/ x" m
  778.     if(can1InitFlag == true), B6 U( c, [4 l/ c( q0 N
  779.     {
    4 r" n" h5 m1 J
  780.       return can1TransmitFlag;0 [  l( m6 J! c) N6 N$ H# w
  781.     }4 i, R. r' S) [: r  S
  782.   }, @2 h. a& ]4 `2 k! N

  783. - J! A, d/ H, ~) M% d5 m3 o
  784. #ifdef STM32F10X_CL" _, }& h8 l+ J
  785.   if(CANx == CAN2)
    & `7 i$ `& W  w- w
  786.   {
    9 j5 K8 |& m- n3 _/ C
  787.     if(can2InitFlag == true)
    ' h/ m$ \4 g4 i
  788.     {2 y$ \, L- }! ?+ @
  789.       return can2TransmitFlag;0 D0 U' B9 ]+ \7 v6 M* w
  790.     }
    7 v9 b4 h" r- s) c7 a9 X3 ?4 Y/ m
  791.   }4 E) E5 {- r; m0 O" r# D, a
  792. #endif /* STM32F10X_CL */$ E6 {8 j9 T/ x' ]; A

  793. % n! s2 v' {# U% u; |  ?6 s: M
  794.   return false;8 ^7 p( j# n" N7 H% q! q$ a
  795. }9 O" e! n' n) c

  796. . ]8 z8 O7 n/ j( R4 }& R0 z
  797. /**
    " o" ?- }) M8 n! J  A2 F5 v
  798.   * @brief  This function handles CAN1 TX Handler.4 F- z" ~# j4 Y* y+ {$ `) m! L
  799.   * @param  None.$ k2 S$ U5 ?0 H* N) N
  800.   * @return None.
    : l% [& F, ~4 ^
  801.   */  A+ T- E9 u% R2 F& Q$ w! K
  802. #ifdef STM32F10X_CL
    ( m! Y0 K! ?! J* D! J" q
  803. void CAN1_TX_IRQHandler(void)  {2 |7 w2 x3 }- q
  804. #else3 V, {2 E3 M( [" \
  805. void USB_HP_CAN1_TX_IRQHandler(void)' k# {: u, o- _9 k" X0 K
  806. #endif /* STM32F10X_CL */
    5 T9 f6 Y# L4 b  |& r
  807. {! E1 Z5 T  G5 [7 O3 H
  808.   if(CAN_GetITStatus(CAN1, CAN_IT_TME) != RESET)% y" I* O. B8 ?2 h! f! [, z7 }
  809.   {
    ) D1 d) j) S8 L3 h  t2 }# \) f
  810.     CAN_ClearITPendingBit(CAN1, CAN_IT_TME);. C3 l: ]3 X. s4 |4 H5 ~

  811. : E! \3 e* k  f& \, s& Q) U
  812.     CanTxMsg canTxMsg = {0};
    # e8 K2 m4 m2 |  E- N+ Z
  813.     uint8_t  number   = RingBuffer_Out(can1TxBuffer, &canTxMsg, sizeof(canTxMsg)) / sizeof(canTxMsg);
      U$ t6 d( N6 Q* W" o

  814. 6 u( S9 W& e# |% \. y. b
  815.     if(number > 0)
    / t9 ^- J7 x% j, u$ l  R2 b
  816.     {
    ! O5 O9 N: S, y' H
  817.       CAN_Transmit(CAN1, &canTxMsg);* q2 r5 B  \4 {+ W/ g: P+ M3 S
  818.     }. c5 c4 s: Q: F5 {
  819.     else
    ) z! p) M  L, `
  820.     {
    : V" Y' K1 {# E  @2 ?! v
  821.       can1TransmitFlag = false;
    ( Q$ L; r5 L3 u. N" q8 J  y

  822. . P6 T' g$ {  A+ n3 y
  823.       if(can1TransmitFinishCallback != 0)
    0 O3 L" ~* y; L6 }0 f& h
  824.       {* `4 g. l+ W( z' Q- e) A
  825.         can1TransmitFinishCallback();
    7 i: M9 R5 F  P" r7 U, U' u7 l9 v) Y
  826.       }8 r( f' P! S* c% b8 h8 I# m
  827.     }: z" N8 \" C& |4 N' w
  828.   }4 p! d' U; J5 p
  829. }
    5 d- l  t$ ?8 A
  830. 1 X1 s7 D* |6 k; P. h( k
  831. /**1 Y; I+ I! _; B( V' G
  832.   * @brief  This function handles CAN1 RX0 Handler.
    6 p' q3 f7 |* d% C
  833.   * @param  None.
    , U% |- T3 B% e, h5 E  R
  834.   * @return None.% p) h/ M- e. q* h; D7 ^
  835.   */, K1 L, b( z* b8 Z3 f5 _& h! u
  836. #ifdef STM32F10X_CL
    8 w/ [7 p# U6 q" z- q1 s: C& [
  837. void CAN1_RX0_IRQHandler(void)
    4 |, i. X2 x# W9 e$ M0 ]0 i( q
  838. #else
    ' T! Z, b1 I( y: X1 ]$ L6 r( z
  839. void USB_LP_CAN1_RX0_IRQHandler(void)
    1 j# h2 s* Q; R. ^* Z
  840. #endif /* STM32F10X_CL */& z6 q. d/ ]( m' K
  841. {
    / k0 V' y( g( E3 A  C
  842.   if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET)% S+ L% g1 A) m! Q
  843.   {
    0 F5 B' K4 o% F8 ?! A
  844.     CAN_ClearITPendingBit(CAN1, CAN_IT_FMP0);9 ~+ v" O* q" G' L% u
  845. + m0 M! N: V! Z  z' v; R0 M
  846.     CanRxMsg canRxMsg = {0};
    - q3 O# X; A% @0 ^  O
  847.     CAN_Receive(CAN1, CAN_FIFO0, &canRxMsg);
    : V/ a% I8 `6 a) E. u6 R
  848. 7 s: B3 \' q, {
  849.     if(RingBuffer_Avail(can1RxBuffer) / sizeof(CanRxMsg) > 0)
    8 u4 H1 h7 n' M/ ~8 O' K
  850.     {
    2 c1 }) {$ V+ ?/ G6 Z5 b- c8 B
  851.       RingBuffer_In(can1RxBuffer, &canRxMsg, sizeof(canRxMsg));7 s6 ]( z! h. I$ T, x
  852.     }
    % h6 P- W6 i. a; `  [' a

  853. " V3 }# x9 V5 u+ @7 e6 d# w; k
  854.     if(can1ReceiveFinishCallback != 0)
    $ Z- ]0 n$ j8 X4 M6 E/ b$ k
  855.     {
    ; g) j, Y1 ]; z6 z& ~+ Y" I7 S) o2 j
  856.       can1ReceiveFinishCallback();# L. w* G9 y0 K5 \) b/ z7 j$ h' J2 ~
  857.     }% F" m: `, _5 I' E
  858.   }( D- d7 x% [: `3 H, m
  859. }( v: X. T- d8 `' R
  860. 7 n% W4 n7 i5 x- Y: E$ Z6 U3 H
  861. #ifdef STM32F10X_CL
    : r  ?& j& L' E, t: R
  862. /**
    5 V9 ]6 g! a1 u2 _3 M
  863.   * @brief  This function handles CAN2 TX Handler.7 N. j  Y" `9 |; y- i" }3 \
  864.   * @param  None.
    4 h% R5 Q+ |4 Z0 K
  865.   * @return None.& V  d: G1 D& m5 m' R# P* P
  866.   */5 n) w% w) u* Q3 S' E6 J( D
  867. void CAN2_TX_IRQHandler(void)
    8 g6 H: S0 @; j) \/ b! X7 P$ L
  868. {
    ( g( r9 |6 i, L* w
  869.   if(CAN_GetITStatus(CAN2, CAN_IT_TME) != RESET)+ \% W# P$ ^, F! P0 a% Z% X
  870.   {2 m( O( D0 L. A; w
  871.     CAN_ClearITPendingBit(CAN2, CAN_IT_TME);
    - f9 e, k* a# H: z  T7 i3 W$ {

  872. ( [5 d$ [8 x8 ^& g8 t/ C5 T: v
  873.     CanTxMsg canTxMsg = {0};+ [- k- P1 `0 `
  874.     uint8_t  number   = RingBuffer_Out(can2TxBuffer, &canTxMsg, sizeof(canTxMsg)) / sizeof(canTxMsg);$ i2 A- i! h  r8 S% A; F9 K$ T: j
  875. ' F+ X& c- x0 q
  876.     if(number > 0)9 z! M4 @% {, ?1 M8 p8 w+ n% Z( l
  877.     {
    ' B0 }4 i4 B# d" H
  878.       CAN_Transmit(CAN2, &canTxMsg);
    6 v4 ?5 v  V, a0 n5 P. e6 b" ?
  879.     }& R% K3 W9 T3 }
  880.     else' ^( R) y3 ^6 J6 W
  881.     {" t- K0 ]8 ~1 b
  882.       can2TransmitFlag = false;
    + _, D$ f4 x! S
  883. + t4 @3 O2 B* c* @2 @
  884.       if(can2TransmitFinishCallback != 0), e+ P3 ~! J" z$ P% k7 v' A4 \
  885.       {+ S4 ?5 G" u+ C2 E+ S" ]
  886.         can2TransmitFinishCallback();6 j9 X) z# P5 {, R3 E8 X0 j
  887.       }
    ) c1 V# m0 {5 m7 @- S
  888.     }3 Q3 z4 I  h* p5 ?
  889.   }
    & N/ P3 j" s3 \0 y+ g, A- W
  890. }
    / w9 d. R" D' K: c3 S0 D( X
  891. + B+ O8 w+ V+ J# |8 e
  892. /**
    ! S) ?3 S2 h' W) G8 c
  893.   * @brief  This function handles CAN2 RX0 Handler.
    ! Y% Y: }/ Y7 D; M* A: ~7 \
  894.   * @param  None.
    ! |* A; [  D; j2 D+ k2 x: S" [
  895.   * @return None.4 n; Z" T& C1 b1 E
  896.   */  @" s' p! w. }) y- @
  897. void CAN2_RX0_IRQHandler(void)
    7 K5 G6 k" m5 C  S& Q" W
  898. {
    1 G  I6 i6 O& l! E: V' y$ E( O
  899.   if(CAN_GetITStatus(CAN2, CAN_IT_FMP0) != RESET)
    & U- u" o* @6 c9 d. r5 U9 T' \
  900.   {9 b% r) @0 \2 {+ t0 O' J
  901.     CAN_ClearITPendingBit(CAN2, CAN_IT_FMP0);
    " S. h) Z1 `. {& K  A- W: W1 Y7 N* i
  902. - R, F* i1 B4 W" v( n& ^
  903.     CanRxMsg canRxMsg = {0};* K+ k) y  @2 r: V  ~! {
  904.     CAN_Receive(CAN2, CAN_FIFO0, &canRxMsg);
    . c' a/ c9 P3 k* ?+ q9 v
  905. 5 c+ Y9 p' L, ~! q8 W  r) E
  906.     if(RingBuffer_Avail(can2RxBuffer) / sizeof(CanRxMsg) > 0)! X& ]1 \9 Q8 t% p+ V
  907.     {5 c: W0 b; o9 L0 K9 N
  908.       RingBuffer_In(can2RxBuffer, &canRxMsg, sizeof(canRxMsg));# o6 D' o  G5 _! o' T9 e6 h
  909.     }
    % e+ g* h) x6 r

  910. / |8 k% H6 h! ^5 |5 q; J
  911.     if(can2ReceiveFinishCallback != 0)$ ~7 q. f% n: w7 [0 C5 A
  912.     {0 A! k  h- i5 _* j6 R5 l# v' k
  913.       can2ReceiveFinishCallback();
    . Z1 T6 e. q& C
  914.     }2 W3 ^. s) G# w: T0 H
  915.   }
    $ J  o! [% C) p, r2 B: r1 Z
  916. }3 o8 T& Y+ M% x# b! s  b) Y
  917. #endif /* STM32F10X_CL */
    - R& r6 D3 a/ H. u9 e1 d' A
复制代码

: o) K" j( Y$ O9 b& I0 a8 `9 K' `; z7 x
main.h 文件+ y% A/ x# q6 w+ ~: ~3 r" S& n
  1. /**
    " d1 U" k2 |( _# f; T; P9 J6 n. c
  2.   ******************************************************************************# Q: L6 q8 |. X, x
  3.   * @file    main.h- _+ x* C- D! I1 h. ^5 H* k3 X9 a5 w
  4.   * @author  XinLi# ]% e4 G- Z& x5 c
  5.   * @version v1.0% g1 f. J" o$ l2 r, \
  6.   * @date    24-June-2018
    6 Z6 d( c/ k+ ?
  7.   * @brief   Header file for main.c module.
    " d6 Y" i& e5 x+ A2 |2 q
  8.   ******************************************************************************, O4 V- x1 I0 x: u
  9.   * @attention
    ' q4 I% c6 D. d  a1 w8 Z
  10.   *( K( F- D# v7 V/ |% U1 n
  11.   * <h2><center>Copyright © 2018 XinLi</center></h2>
    $ S8 b  C2 w) z, k* A* c
  12.   *$ k, O! y+ A- E8 h* c& T/ _
  13.   * This program is free software: you can redistribute it and/or modify! e* q; t, `% p+ I* x
  14.   * it under the terms of the GNU General Public License as published by& \) H# [! G: O! ]) w3 b
  15.   * the Free Software Foundation, either version 3 of the License, or$ Y- i' ?  s, e" w( J1 b
  16.   * (at your option) any later version.
    : i: r8 X) R! |
  17.   *7 B. |5 b& V" H2 D  w( W( C' [6 F
  18.   * This program is distributed in the hope that it will be useful,& c4 K  I( ]" R7 {# S; a7 w4 s
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of2 p0 x/ H1 Q5 x# `
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  ^+ q- x: P! g7 l5 m/ N
  21.   * GNU General Public License for more details.
    8 S3 N; z$ l$ h: {" ~
  22.   *
    . h9 o, F9 I3 \/ `* `6 ~* B$ B* W' I
  23.   * You should have received a copy of the GNU General Public License
    4 A2 z' W# A' F- O2 ^# m8 k
  24.   * along with this program.  If not, see <<a href="https://www.gnu.org/licenses/>." target="_blank">https://www.gnu.org/licenses/>.</a>
    * s# y. E8 V8 D$ V! I
  25.   *$ J4 O1 K( F! @3 {9 z
  26.   ******************************************************************************$ S1 u' x& ?; ]1 y) I
  27.   */9 z( X7 M% _7 K  E  B# D

  28. 8 n5 g$ B/ W! V1 V) o. p
  29. #ifndef __MAIN_H
    0 @3 s: l# s1 v0 ~
  30. #define __MAIN_H
    1 k/ N4 P" c7 Z1 @9 N" q4 U
  31. + m3 l" P- F* Z( k9 a; }0 F/ t; g$ |4 f
  32. #ifdef __cplusplus
    $ ]$ f3 y( j6 ?4 t, c9 |* ^9 y3 K
  33. extern "C" {: u& G& }, Q* X" M
  34. #endif
    ; Y( q* S: J- w" D! S$ r
  35. 1 z( h" i8 p/ R! G* Y4 Z
  36. /* Header includes -----------------------------------------------------------*/0 H# A5 z" k) J3 V8 |% @
  37. #include "stm32f10x.h"
    " l& Y% ^+ @: R) `) c. k

  38. * u6 l: f0 ~0 _0 h1 [, w/ Y
  39. /* Macro definitions ---------------------------------------------------------*/
    ! @3 `4 e( L0 u0 Q  z5 B' G
  40. /* Type definitions ----------------------------------------------------------*// [7 M- K& Y! c4 t. q, g
  41. /* Variable declarations -----------------------------------------------------*/
    , v: q) ^- D+ d* m
  42. /* Variable definitions ------------------------------------------------------*/9 H# m; ?3 y. @3 ^2 E
  43. /* Function declarations -----------------------------------------------------*/3 ~' y3 d6 \( M* _4 N- y8 n! Q# W- E
  44. /* Function definitions ------------------------------------------------------*/) @+ K* Q% r5 V2 Q8 K

  45. ; Y# [2 ^, q3 \; u- M
  46. #ifdef __cplusplus! R- k8 c. B; H, u  g+ n( ?
  47. }
    ! J' c. K& l$ t. v* z+ H
  48. #endif1 s3 w7 Z( ]- E% v2 A' |* w( U
  49. ( k* Q: v! Y9 x% d. t* n5 Q
  50. #endif /* __MAIN_H */
复制代码

% c. P' ~/ c4 t9 r! w3 ?
# K! Z/ s" `5 O2 u6 Q# ?main.c 文件. [4 O" D- c1 k+ a9 D
  1. /**
    7 @. @/ k# p* g( Y( @" s- l
  2.   ******************************************************************************& L, y% G$ O' v) m6 @4 r/ Y
  3.   * @file    main.c$ ~( ~. e/ M- s; _
  4.   * @author  XinLi0 S: w9 C; m3 g' L% p8 i
  5.   * @version v1.0
    & x: R' n% R: W$ R3 M+ _
  6.   * @date    24-June-2018
    2 |! X1 d" Q! U% I9 V1 |
  7.   * @brief   Main program body.. H! B2 o- w% g9 `' ~
  8.   ******************************************************************************
    & b4 |$ w1 X$ b7 d* X$ E5 o
  9.   * @attention
    ! g$ G+ d! h% I( z6 _
  10.   *$ J3 C& |. {- x8 W) M
  11.   * <h2><center>Copyright © 2018 XinLi</center></h2>  W, i; F( Q5 {. Z
  12.   *; U% \9 k. ~: f0 ?
  13.   * This program is free software: you can redistribute it and/or modify0 N: K# O6 y; ?1 `2 ]
  14.   * it under the terms of the GNU General Public License as published by% c5 t7 c* k- y& x( F! K2 F8 k$ e% E
  15.   * the Free Software Foundation, either version 3 of the License, or
    # e9 G6 _, v: p7 a6 C% ^. p
  16.   * (at your option) any later version.
    5 A' w$ [/ s; S0 O! x3 E9 s
  17.   *  B6 |) g+ U$ x4 b
  18.   * This program is distributed in the hope that it will be useful,
    7 s, A/ T& J! o9 b0 V
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    ! E2 g, Q9 l7 S' s& j' W
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the% ]& h0 t" w, a) t
  21.   * GNU General Public License for more details.7 @( Q. N9 W9 o$ K- R
  22.   *
    ( Z9 T2 _" r1 e
  23.   * You should have received a copy of the GNU General Public License2 ^3 z+ }. y% p- Q/ K$ c: K) V/ T0 ?
  24.   * along with this program.  If not, see <<a href="https://www.gnu.org/licenses/>." target="_blank">https://www.gnu.org/licenses/>.</a>3 s% {5 C- L+ B: V# b* V4 a
  25.   *
      M/ ?( ?9 o% n0 [) I2 }% h
  26.   ******************************************************************************) n' V# O( U. a- j
  27.   */
    / M+ D3 O" l: y+ ^3 e; v8 ~- _
  28. 6 w5 R4 g* N( q$ q, d, ^
  29. /* Header includes -----------------------------------------------------------*/! z5 l. D, a$ S+ W. [  b
  30. #include "main.h"
    # |% B- h( b& V+ U& A, d- O4 D9 g
  31. #include "CAN.h"
    7 {- D6 Y# n6 b6 m

  32. & T0 E7 A4 I2 Y& E( N4 E3 d
  33. #ifdef _RTE_
    8 c' ~/ H4 T5 U1 O
  34. #include "RTE_Components.h"
    0 |/ e: z5 n/ g" G
  35. #endif# b; s' ~' }1 d

  36. 4 g0 J7 O4 s5 u
  37. #ifdef RTE_CMSIS_RTOS2; c/ _( D, L0 o; @/ g
  38. #include "cmsis_os2.h"3 W4 I& j3 T" V* M; M
  39. #endif! z! j. x6 x, C
  40. : z7 n% g, f' O7 G7 m0 m
  41. /* Macro definitions ---------------------------------------------------------*/
    , I' [( `7 ?. M( ?2 N; k( h; M' \
  42. /* Type definitions ----------------------------------------------------------*/
    : y% D' t) ~  Q, d; ~7 M
  43. /* Variable declarations -----------------------------------------------------*/
    4 r" t/ s9 c4 L' L
  44. /* Variable definitions ------------------------------------------------------*/
    , _" M' s5 R0 s! E) M! K1 q9 X
  45. static CanTxMsg canTxMsg = {0};
    ) b/ y1 q! J' ^( Q4 s6 L6 w( q9 X$ x
  46. static CanRxMsg canRxMsg = {0};
    , j2 v0 V9 N) ~% k! Q# K1 Q
  47. ) T" d! i; x. M& P
  48. /* Function declarations -----------------------------------------------------*/
    , }8 j- p* Y5 R) @0 ]$ S9 R
  49. static void SystemClock_Config(void);: X1 p& p8 o; V) Z" w4 C& L. x
  50. 5 q8 w9 z  O, f9 _
  51. /* Function definitions ------------------------------------------------------*/$ V, f1 A; b& h& B. u) A( m8 M, z

  52. " _) J' k, \, m# c6 ~9 u
  53. /**
    / m4 q6 t  D9 B) a
  54.   * @brief  Main program.+ {& |. {6 u) T
  55.   * @param  None.
    - X2 Y  |- D& ^0 T) d5 Z1 }1 G
  56.   * @return None.% G, N! h* ?2 S, O0 C3 E) T, C
  57.   */; T/ D3 k3 f  y# K2 `% p
  58. int main(void)
    ! D! O  m1 ?) e: u- T' c9 b) Z
  59. {
    ) e9 ^' {% Q, A/ o
  60.   /* Configure the system clock to 72 MHz */
    % j' u. V8 N5 i! _- @5 U
  61.   SystemClock_Config();0 F9 e7 @5 e3 j$ V
  62.   SystemCoreClockUpdate();( Q: ~# _7 |; D! J# K- |/ V' F
  63. % O1 S3 J  L8 u2 ~
  64.   /* Add your application code here */& e# S( `$ E0 w9 H6 K% T4 P) b
  65.   CAN_Configure(CAN1, CAN_WorkModeLoopBack, CAN_BaudRate250K, 0xAA55, 0x55AA);
    * x: M  Z# I9 e+ {
  66. . f6 M# ~+ H" ?' P; X
  67. #ifdef RTE_CMSIS_RTOS2
    , P# n) J5 E3 l3 p
  68.   /* Initialize CMSIS-RTOS2 */& @" c# ]3 {2 l# g! C/ t7 F0 P. G/ V) Y
  69.   osKernelInitialize();3 Y9 Q# Y  B! p6 Q, U9 W

  70. 7 Y9 z, D, s7 o/ ]/ e  U5 @
  71.   /* Create thread functions that start executing,
    9 D% p& t! K" ]- G2 R5 q3 g
  72.   Example: osThreadNew(app_main, NULL, NULL); */0 |! _8 S4 E/ S0 k# b& v- [

  73. & w5 D. w6 T  Z4 i+ h: j7 S* @% I0 A
  74.   /* Start thread execution */  x! h0 ]: s/ r* Y
  75.   osKernelStart();
    2 _5 ^1 d9 b" `" |0 J& z5 H8 I
  76. #endif* e8 c. |9 I$ t$ A4 L
  77. " m1 K  _9 p& w% l" k% }- E& B
  78.   /* Infinite loop */
    1 [+ I: D, W% D* G% Q( g
  79.   while(1)' g1 U4 `# R" U" g6 {$ [3 d
  80.   {% G% e0 z! z' P( y4 \
  81.     canTxMsg.StdId = 0xAA55;& r5 }' b& m) Z- H+ n0 `
  82.     canTxMsg.ExtId = 0x55AA;, F3 E3 W8 [& H
  83.     canTxMsg.IDE   = CAN_ID_STD;8 n- j- _- G% y& `6 w/ m5 ]
  84.     canTxMsg.RTR   = CAN_RTR_DATA;
    ! C8 x" ?1 ]/ v8 K6 o
  85.     canTxMsg.DLC   = 8;4 S: s1 J* }9 l. w
  86. * U, m+ n5 H; y6 B' r1 `% N% S  X
  87.     canTxMsg.Data[0]++;
    1 n4 C  P' S# E  @" `& D& e
  88.     canTxMsg.Data[1]++;
    4 u  r' w0 M- P) t* {  o
  89.     canTxMsg.Data[2]++;* R& Z* b# F. t; k
  90.     canTxMsg.Data[3]++;) D) h# P# X, _
  91.     canTxMsg.Data[4]++;
    " v7 o8 @4 v: M
  92.     canTxMsg.Data[5]++;
    / D4 J. t$ |; v7 z8 x2 t
  93.     canTxMsg.Data[6]++;. _* F9 j( _6 L( x
  94.     canTxMsg.Data[7]++;
    & q3 D/ e- R! Z" {* B
  95. + K4 d5 q6 s+ h% l% x: D6 V2 X; n" ~
  96.     CAN_SetTransmitMessage(CAN1, &canTxMsg, 1);% X* I& I& t0 ?; w8 p% l

  97. 8 m/ j7 k7 B  w8 [& D+ e9 K
  98.     while(CAN_IsReceiveBufferEmpty(CAN1) == true);
    ' j- H0 {9 a$ ?5 A
  99. ; @. ^0 t) K. v  Q& r
  100.     CAN_GetReceiveMessage(CAN1, &canRxMsg, 1);
    " d% N0 O) O" c! P9 H( ^8 R
  101.   }
    9 [- j" w3 O4 k
  102. }
    6 Y) w( ^- E- s% \! Y5 Z6 L
  103. ( f4 z. @8 F% |0 f  G
  104. /**) w: U4 z$ M) E- d! z% o' G9 P" |
  105.   * @brief  System Clock Configuration.& h4 S3 {2 N3 l$ ~3 h8 ]
  106.   *         The system Clock is configured as follow :
    + I& l4 F7 |8 [! P
  107.   *            System Clock source            = PLL (HSE)" U; e( C# W) |1 B
  108.   *            SYSCLK(Hz)                     = 72000000
    " U; I) s1 d) a7 T3 @
  109.   *            HCLK(Hz)                       = 72000000% H  q, L. b+ A
  110.   *            AHB Prescaler                  = 1# D. a9 }7 S# M  ]5 `$ M5 J7 [
  111.   *            APB1 Prescaler                 = 2
      i, {" F8 @8 w* e6 _; y( T! C/ l
  112.   *            APB2 Prescaler                 = 1% |- n- G2 u5 R: N
  113.   *            HSE Frequency(Hz)              = 8000000+ i( g6 N8 B+ F0 v8 {" j4 t
  114.   *            HSE PREDIV1                    = 15 w# x2 i- U3 Y
  115.   *            PLLMUL                         = 9- X: `% ^: \4 @0 v
  116.   *            Flash Latency(WS)              = 2
    5 s% v9 J9 Y) I3 I3 Z' w* c4 I
  117.   * @param  None.
    ' L7 C3 b$ d: X3 W7 `; K% y
  118.   * @return None.; M& `& ]( _. [
  119.   */
    $ k( w0 |! |/ S1 J  d' k* c
  120. static void SystemClock_Config(void)3 v  v" x! Q: f0 |1 `5 o& P
  121. {
    ) R! r7 }$ z, o2 k" ^
  122.   /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration */3 k. G& Q$ U  d% `- o! a( R
  123.   /* RCC system reset */2 ?7 c" F. K" X  h
  124.   RCC_DeInit();
    : {( X' Z) _* P  W$ h

  125. * U' j- w3 A- B9 N# l
  126.   /* Enable HSE */* n" i* A/ H) h
  127.   RCC_HSEConfig(RCC_HSE_ON);
    0 I) f2 o0 }- R: K
  128. 7 P3 T( f* h) }2 ]  W0 Z7 C, q
  129.   /* Wait till HSE is ready */
    + h' k0 a. R+ F: F* Z
  130.   ErrorStatus HSEStartUpStatus = RCC_WaitForHSEStartUp();
    # g5 j1 Z2 C8 O3 J
  131. " f3 O3 O3 z/ E( L& D4 x6 G( Q; V0 o
  132.   if(HSEStartUpStatus == SUCCESS)2 K3 E; l( X& L2 V
  133.   {
    $ D& A/ V* R. b; a6 I
  134.     /* Enable Prefetch Buffer */5 K7 T  V8 i& D8 F( A$ A3 k; E* Z+ J
  135.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    ' n8 Z4 D" ]2 u8 [, M+ ?+ t

  136. " ]5 G/ n; ~- v( I
  137.     /* Flash 2 wait state *// K5 E: K2 Y! S  M
  138.     FLASH_SetLatency(FLASH_Latency_2);
    # o+ z  T# c) a  x' C1 k$ B
  139. 3 W! C, v3 l$ i9 x
  140.     /* HCLK = SYSCLK */# K: a, c" a" W/ T6 P: V
  141.     RCC_HCLKConfig(RCC_SYSCLK_Div1);
    % i% e+ l& ~) b* f( c
  142. 4 j$ g- W6 p8 d# L" v
  143.     /* PCLK2 = HCLK */
    2 G2 S3 H9 L' s0 q+ b* M! x
  144.     RCC_PCLK2Config(RCC_HCLK_Div1); . S0 G, Q! k- ]' U) m
  145. 5 i4 z& A( K3 k5 [2 E+ n  N% Y
  146.     /* PCLK1 = HCLK / 2 */4 F) ]% M/ q3 ?1 N: y$ Z2 N
  147.     RCC_PCLK1Config(RCC_HCLK_Div2);
    ; N. D) s9 D5 S+ A) i8 Y9 `
  148. , N4 h& V/ z! E6 {# y0 L0 C# E
  149.     /* Configure PLLs */
    5 a- W# q) R) c* _8 K
  150. #ifdef STM32F10X_CL3 B' v6 F. N. u7 L- b9 O' m# E" v
  151.     /* PLL2 configuration: PLL2CLK = (HSE(8MHz) / 2) * 10 = 40MHz */
    ) h# s  W4 c' `0 R5 l
  152.     RCC_PREDIV2Config(RCC_PREDIV2_Div2);
    1 z8 |5 S+ Q/ d6 ?0 w9 |, O9 `, j
  153.     RCC_PLL2Config(RCC_PLL2Mul_10);
    1 \- }3 `2 q4 C6 I) a( B

  154. % b7 H; o' u( f
  155.     /* Enable PLL2 */
    " h; e! n# V& s# K& }# S& Z7 Q
  156.     RCC_PLL2Cmd(ENABLE);
    9 N/ d3 a; A; s' d
  157. - ^' w* e9 K' j( k" j& F  ?
  158.     /* Wait till PLL2 is ready */
    " _  D7 U8 A- Z, r) V* s
  159.     while(RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET);
    1 @) Q7 ?9 M% u8 j' o* i+ M

  160. * @! I: }* \7 V
  161.     /* PLL configuration: PLLCLK = (PLL2(40MHz) / 5) * 9 = 72MHz */3 F0 C+ Y& }* T; }) I8 g
  162.     RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5);
    3 f. k( Z  p+ V% P
  163.     RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);
    ! s" _0 n& u2 E  }9 e1 A- j
  164. #else
    / J( |2 M0 i4 o2 `  n" h
  165.     /* PLLCLK = HSE(8MHz) * 9 = 72MHz */  {& U' s4 d" d7 M/ r8 l7 m
  166.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
    , g7 T' O, k7 p# S
  167. #endif" C9 _' f( r% m

  168. 8 ^* O: q- Z7 _0 P7 I8 j
  169.     /* Enable PLL */
    6 M, ]5 v7 J7 d$ L4 E' \
  170.     RCC_PLLCmd(ENABLE);7 j% a1 M5 q+ M) ~0 `4 K$ ^8 E- ^4 j

  171. 7 _- a2 i7 }" K& M/ [
  172.     /* Wait till PLL is ready */( r# d* g. E/ p3 ^' `
  173.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);9 r% d9 r& _1 j5 k) q
  174. 3 `% O( i  U; ~
  175.     /* Select PLL as system clock source */
    $ s8 r/ z8 P- P6 f1 Q1 P
  176.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);; t/ ?, r5 r& O* X  v

  177. 7 p9 ~. f; ^; i1 u$ Y; ]  P
  178.     /* Wait till PLL is used as system clock source */
    % _8 l1 v1 _/ G& B) W
  179.     while(RCC_GetSYSCLKSource() != 0x08);
    * Q' q: O1 Z/ a5 S4 n2 l
  180.   }5 i4 S% c( A! A- U! S
  181.   else) [' H% j. l6 R1 O0 b- U( `
  182.   {. d7 ]. p2 M+ H0 A* n
  183.     /* Disable HSE */
    0 G4 O' S2 X( T# h  g& ?0 B
  184.     RCC_HSEConfig(RCC_HSE_OFF);  X0 q+ d6 o( f

  185. - A' V/ R* ]& e
  186.     /* Enable HSI */
    6 J' n, h9 ~7 e; I
  187.     RCC_HSICmd(ENABLE);+ ^+ L7 K5 w( M

  188. * G6 J$ Q1 h$ q. P
  189.     /* Enable Prefetch Buffer */0 m" k7 L9 [9 n7 C5 v: F1 e- Y4 Q" i
  190.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);6 H4 `) `- y! H

  191. 9 Q$ B9 e4 K; F
  192.     /* Flash 1 wait state */
    # r7 h- f. t4 d9 V. x1 h- m
  193.     FLASH_SetLatency(FLASH_Latency_1);* o( p' [" B6 K9 x8 O2 L# ?# Q
  194. " Q0 ^4 v  o; p% O
  195.     /* HCLK = SYSCLK */7 o4 p  E# A5 _% F/ A$ [9 u$ }
  196.     RCC_HCLKConfig(RCC_SYSCLK_Div1);   D  H- X+ }' S( Q. ?

  197. . `6 z9 V, r1 a" `! W# {; w
  198.     /* PCLK2 = HCLK */
    - \" t1 d7 @7 h  X' f
  199.     RCC_PCLK2Config(RCC_HCLK_Div1);
    , [. {6 U- }6 Z* ]# a
  200. 8 z# x3 E% W# |6 x  `. ^
  201.     /* PCLK1 = HCLK */
    # a1 U; O& z5 A
  202.     RCC_PCLK1Config(RCC_HCLK_Div1);
    ; l; U& x2 d9 O

  203. , l7 U+ W/ \' U& N8 \
  204.     /* Configure PLLs */7 ~  f! _, b% U, u
  205.     /* PLLCLK = HSI(8MHz) / 2 * 9 = 36MHz */
    9 e) [) P9 i7 u
  206.     RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9);
    6 C7 h4 m* L/ x( P

  207. $ B5 @+ j2 c( D: e+ j9 O
  208.     /* Enable PLL */" f5 _0 r  a/ Z  U# R6 j3 Z
  209.     RCC_PLLCmd(ENABLE);
    4 j7 c. y& S* d4 f

  210. ( b6 o; v" e( J- a2 k: a3 G: q
  211.     /* Wait till PLL is ready */% M- K3 |1 L8 a, w
  212.     while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);( D  j6 R. q* O! t9 T0 ?: s* D: y
  213. 2 |; L' J5 S, o
  214.     /* Select PLL as system clock source */4 K0 r# k1 T: @% r3 }9 j$ N% ]# [
  215.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    * V  W: q# W) J' N

  216. ' Y- V  }! y6 D0 L
  217.     /* Wait till PLL is used as system clock source *// l% U9 {8 X& b3 i
  218.     while(RCC_GetSYSCLKSource() != 0x08);/ ~2 ^! U/ C7 x2 M: l
  219.   }2 @- H, v& {8 C& X$ _3 o
  220. }5 H* F" `. z( Y$ Q6 p* o5 a2 O
  221. + s0 g4 F. b7 R( W' Z- }: f% N
  222. #ifdef USE_FULL_ASSERT
    # q% M/ o6 @# H3 y, O% x) q
  223. /**. Q  c( A/ h2 K
  224.   * @brief  Reports the name of the source file and the source line number' ]2 F; w% S5 c5 e$ S
  225.   *         where the assert_param error has occurred.- g! j1 J6 s9 J
  226.   * @param  file: pointer to the source file name.
    7 A; j1 j- M3 B1 k# e2 ], V* Y9 g
  227.   * @param  line: assert_param error line source number.' ~# q/ J  \0 {0 H. D  c7 r$ E8 o
  228.   * @return None.
    : ]5 u( n0 s5 ?3 c8 M
  229.   */
    ' _8 Y- j0 \' `+ Z$ q! V$ O
  230. void assert_failed(uint8_t *file, uint32_t line)
    , I. {, a* R, n
  231. {8 f3 ~* h3 m" }0 V
  232.   /* User can add his own implementation to report the file name and line number,5 p# |7 _, X9 n* N: {5 U
  233.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    % d8 Y. U% ^3 a: L, A* `  j

  234. 8 z& \7 ?/ p* W9 ~( j% Y! |2 r  |
  235.   /* Infinite loop */
    4 y$ h  @  d. `7 Y8 y
  236.   while(1)
    5 L* Y3 Q, l) P3 J5 ]8 T
  237.   {& ]3 D1 X0 W% Y( ]! y3 w
  238.   }' r1 G$ S- @0 z
  239. }6 i7 e( y/ x1 e& X  ^* s5 y. L
  240. #endif
复制代码

+ i  J1 l2 V9 C$ h) U3,注意. @  L3 K: a9 f) @' E; \* M( _

3 @# g" T7 Y- J. Q6 G6 ZCAN 消息发送缓冲区和接收缓冲区的大小,可以根据应用的需求进行修改,缓冲区使用的是堆内存,需要根据缓冲区大小和应用程序中堆内存使用情况进行配置。
0 h) `0 E3 l1 ~+ |* O+ M( I& F. W3 j& B. O4 [. O  o/ r; `  x" S

7 {5 ?& d' e% g( M) U/ ^, a8 b
% {+ ~# P/ w+ N4 U  ]
收藏 评论0 发布时间:2021-11-26 17:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版