前言
+ }0 j& m7 J5 W/ `8 e4 c客户反应使用我们的 STM32F446 的 CEC 库的时候,输出的数据和数据长度始终不匹配,跟电视通信不正常,如果输出的数据始终比长度多一个字节.客户试着按字节数减一去做输出,但是又不能输出一个字节的情况./ Y6 A; ]" L% V1 a, F
& Z8 |' O& V6 N+ g; A; @4 d
调研
2 ] \1 G2 M4 m T7 M+ y; x, m首先,我们来看看 CEC 发送数据的过程:
5 j- H: f6 j& V1,数据格式,包含一个起始位,header OPCODE 以及 0 到 14 个字节的 OPERAND 数据.以及一个 EOM 和 ACK.$ S8 k, o2 X' f4 H7 [
* |6 \' \' ?- [7 H. K2 w5 t( ]
" p) H) Z; F7 ~0 ]
8 ^+ x# Y6 o2 o- F+ i
2 发送过程: 从下面两个寄存器的描述来看,当我们发送最后一个字节之前,要将 EOM 置位.而每一次发送数据的第四位时候,它会发出 TXBR 的请求(请求发送下一个数据); p- [. o% c4 l2 F) U) e( `( E
$ r, \0 q; J. p. ]! g& {
" i1 D- `3 n4 Y# M& _4 o& z m" G( P3 T& Q2 K
4 M7 E* o6 [- @2 y$ o4 s
0 m0 L8 U3 a; U* ^
3 发送函数: 当客户在调用下面发送函数的时候,数据跟长度不匹配.
3 ~" G# o* n8 ^5 r1 _% X4 i. |) ?& R
HAL_CEC_Transmit_IT(&hcec,InitiatorAddress ,DestinationAddress, (uint8_t *)&Tab_Tx, TxSize);
, j; t/ [8 r' r k+ E# p; M5 H" H- HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t
: O/ L5 h1 r* X- i- P* S* u( c3 b - DestinationAddress, uint8_t *pData, uint32_t Size)8 U& p ~- k L) V
- {1 j5 |$ g5 P3 P
- /* if the IP isn't already busy and if there is no previous transmission
1 ~# `+ Y. I- m; E6 m9 G - already pending due to arbitration lost */7 ^+ L0 ~" M4 f/ A
- if (hcec->gState == HAL_CEC_STATE_READY)
) q0 j" R7 {/ f2 a N - {& H6 E- N/ F; y+ T* N
- if((pData == NULL ) && (Size > 0U))
; _/ k' }1 V' N - {
7 ]" ~ q4 F$ I6 I& g* l - return HAL_ERROR;- ?2 d* X6 d' e0 M5 m* a/ Y
- }
, r0 s& ?, v4 \0 _ - /* Process Locked */2 f, y+ G S3 q3 ~& j% ^! r
- __HAL_LOCK(hcec);; e" `5 J+ q0 x! r4 G
- hcec->pTxBuffPtr = pData;) [. ?9 l/ p! F( S
- hcec->gState = HAL_CEC_STATE_BUSY_TX;2 l) _) V. U4 L% o; P
- hcec->ErrorCode = HAL_CEC_ERROR_NONE;
; O* _% J- Y8 T7 v7 s) E4 q# P& J
+ q4 Q2 F- `3 S- /* initialize the number of bytes to send,
# N7 c7 \8 ^* D5 w: x, j; z - * 0 means only one header is sent (ping operation) */$ U3 u/ s8 t& G8 n6 S: b
- hcec->TxXferCount = Size;' J3 ~. W4 b+ b2 v
% f+ ]5 Z( F! |! P, }% B) \" w- /* in case of no payload (Size = 0), sender is only pinging the system;
8 v7 a' g' ], i! l- J0 P2 p, y - Set TX End of Message (TXEOM) bit, must be set before writing data to TXDR */& }" ?) U7 B& Q) p, S
- if (Size == 0U)
/ h* H$ U7 F/ u1 M" W8 ?6 C5 f - {8 L' g0 S9 k; E; K/ h j" I
- __HAL_CEC_LAST_BYTE_TX_SET(hcec);
7 A8 W1 T$ J; l, n* P; M/ S - }1 D" W$ ~5 h" ?, R: L) H9 \5 Y
- /* send header block */8 y$ R9 L4 X2 A
- hcec->Instance->TXDR = ((uint8_t)(InitiatorAddress << CEC_INITIATOR_LSB_POS) |(uint8_t) DestinationAddress);
& `$ d% n2 K0 [" P+ G - /* Set TX Start of Message (TXSOM) bit */0 F) P! _* r, v' B! @. i
- __HAL_CEC_FIRST_BYTE_TX_SET(hcec);4 H/ i6 ^3 ] u; i# K/ J
$ c: a. h ~2 ~: G- /* Process Unlocked */
" U. H3 J/ e+ s0 Z4 T' Z) \ - __HAL_UNLOCK(hcec);4 _( u5 w3 B- P
, I) j3 R+ M8 [- s; P- return HAL_OK;
, Z4 h) k c7 [0 d7 ?' @+ W - }$ l' L( r0 K# d3 g3 `' T& @# V
- else
7 A, G, X: G: E7 v' Y - { i: q8 Z8 \$ W# v1 i
- return HAL_BUSY;# `/ g* \' b4 k z+ _. s0 n
- }
* \& F5 m' y S. F0 X ]. @ - }
复制代码
6 y( Z& j4 i/ W$ Z3 B: M* i
) X# U+ g3 k9 @+ d) N2 c% `例如 :发送 2 个字节(TxSize=2) 0x44 和 0x43,但是我在后面发觉多出来一个字节(如下图),而如果我们将 TxSize 设为 1,反而数据发送正确. 从上面的函数来看,并没有什么错误.它仅仅开始发送了 HEADER 和开始发送. 8 B; e% P3 [6 m# ~2 v4 u
1 z' z3 w/ J2 t1 |5 m4 W& q
' o i# V- c, n$ S. c* q `
/ t' e; e, F1 @; h2 c8 i; \4 中断处理函数: ' _( [% u; Z$ \: j
- Y- O: B( k- H: F
- void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
0 y& ~9 n. h; v' b1 [" u5 J' } - {
% w. e+ {( w/ S9 K- _ T - …………………………………………………………….; E5 y/ r% F$ i# N0 P' E9 z7 z% N. k
- /* CEC TX byte request interrupt ------------------------------------------------*/8 C) L. M$ k% `& }
- if((reg & CEC_FLAG_TXBR) != RESET)0 D7 |+ p5 J2 n8 z% u
- {/ N1 A' g/ X5 [6 x( y! \
- if (hcec->TxXferCount == 0U)
: c. e1 J. |! d9 b* A5 G - {. K+ M) A3 |! b3 a
- /* if this is the last byte transmission, set TX End of Message (TXEOM) bit */
5 X# H) h' A+ t2 W* v( E- u0 \2 H8 g - __HAL_CEC_LAST_BYTE_TX_SET(hcec);
' t" S( I: z3 K# r" ]5 }; Q - hcec->Instance->TXDR = *hcec->pTxBuffPtr++;
7 R) Z/ L( r# g: w# {& Q - }
6 s- w) A; K3 X# V - else! G, l6 _& h/ p3 `7 ^3 j
- {
% }+ p# W& r" {2 _* J) C - hcec->Instance->TXDR = *hcec->pTxBuffPtr++;7 Z3 ~+ ?- e: P( P \7 }( |( O
- hcec->TxXferCount--;
: e6 Z, t' D& B - }
e8 w' u7 x7 P6 p - /* clear Tx-Byte request flag */
0 B/ t. y6 E+ g. h8 b - __HAL_CEC_CLEAR_FLAG(hcec,CEC_FLAG_TXBR);" b' P- Q" G; A! t& P5 D
- }! w+ ^0 N: e% l% N2 N
- :. m r9 L& o- x( y
- :
复制代码
) k2 M: f5 ^5 {- B% b0 R- t: @
% P0 F5 ^. ?1 C$ o9 u- q6 {从上面的函数来看当我们发送字节数大于 0 的时候,他每次发送一个字节,而当等于 0 的时候它置位 EOM,并且再次放了一个字节进入 TXDR,看到这里就明白了,错误出现在这里了,既然是发送字节为 0 了,为什么还要放一个字节呢?这里应该是最后一个字节的时候,置位 EOM 和发送一个字节数据,而当再次中断来这里 SIZE 变为 0 的时候什么都不做.: i/ S& r/ U' T( t2 Q! A' {
/ ^, K- m% f% _' e
解决方法:4 ]/ p9 Z4 J: ?3 L
按照下面的方法修改中断处理函数,送给客户验证,能够正常发送数据并且跟电视通信正常
1 C. n; K8 P ]1 C! s
0 A3 S& O3 L- J. y+ B8 N9 b- void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
# Q; _4 v: V7 L. Z - {
, G$ [" Q# E4 q) T) y' y" L; P! A - …………………………………………………………….
; Q3 w# ~" T& I/ R: {& C - /* CEC TX byte request interrupt ------------------------------------------------*/
) Y; V3 u. e9 ^) q7 G z* A - if((reg & CEC_FLAG_TXBR) != RESET)
6 [) B ^+ X }, ~# } - {# h. u2 H+ h$ b' D* J$ ^
- if (hcec->TxXferCount == 1U)% C s7 U' f! R) l. {5 z8 Y' J. `1 b6 |
- {
3 j! u% @: z+ w# j0 u' F4 o' T7 [ - /* if this size is zero ,do nothing */
4 A/ A b/ u7 u* B; F2 ~8 g - }
$ p2 u; V/ {, i7 c; p - else if (hcec->TxXferCount == 1U)
) v& x, e/ a* x - {
7 V7 l2 J7 t- i G6 n/ I! P - /* if this is the last byte transmission, set TX End of Message (TXEOM) bit */( x" g; O7 Y. r8 S7 j1 T1 L
- __HAL_CEC_LAST_BYTE_TX_SET(hcec);: f- z3 D% l) [% ^% }
- hcec->Instance->TXDR = *hcec->pTxBuffPtr++;
* m$ V; ^; H+ A; n$ c; F& B8 c - hcec->TxXferCount--;
# D9 X+ n# L5 S' G1 o8 _: ` - }; |0 ?1 e% w% o
- else! ~3 ^+ ^+ B! P. e; P
- {. O# X+ m0 Q$ ?, A6 y
- hcec->Instance->TXDR = *hcec->pTxBuffPtr++;
- w R* t% L, g, Y4 o3 o - hcec->TxXferCount--;% g; m: q9 {. E2 K% I
- }, ?; f8 J4 F/ C4 P
- /* clear Tx-Byte request flag */
) E3 e, d) k' S+ S- r4 k - __HAL_CEC_CLEAR_FLAG(hcec,CEC_FLAG_TXBR);
5 w3 T6 F1 Q# t - }5 T" U3 R2 }3 _' y3 _% ?/ A; G
- :- k w6 }- i2 I5 X0 P9 h0 N
- : + A- R, ~' Z# n$ N# H3 i
复制代码 $ f' y9 Y# C. \5 n9 ~1 T( L/ O
3 R9 Z; Q& ~" z5 }
|