|
我是老溫,一名熱愛學習的嵌入式工程師$ B$ W8 ` D8 v) ^
關(guān)注我,一起變得更加優(yōu)秀!說起通信,首先想到的肯定是串口,日常中232和485的使用比比皆是,數(shù)據(jù)的發(fā)送、接收是串口通信最基礎(chǔ)的內(nèi)容。這篇文章主要討論串口接收數(shù)據(jù)的斷幀操作?臻e中斷斷幀一些mcu(如:stm32f103)在出廠時就已經(jīng)在串口中封裝好了一種中斷——空閑幀中斷,用戶可以通過獲取該中斷標志位來判斷數(shù)據(jù)是否接收完成,中斷標志在中斷服務(wù)函數(shù)中獲取,使用起來相對簡單。void UART4_IRQHandler(void); ^: A9 ~# A7 d7 H$ F2 b
{1 v3 q% ?, d+ N3 A
uint8_t data = 0;
, e0 q/ z$ ]% J* E8 V6 {9 n data = data;) R9 L3 s# B' _3 n2 @5 {2 M( r
if(USART_GetITStatus(LoraUSARTx, USART_IT_RXNE) == SET)1 d* `2 Q% P5 M, s9 W Q
{% P4 ^! R3 p+ w/ d
USART_ClearITPendingBit(LoraUSARTx, USART_IT_RXNE);+ y) U: i2 p0 n7 H
if(Lora_RecvData.Rx_over == 0)- @/ N4 s! l3 [8 [: d% u
Lora_RecvData.RxBuf[Lora_RecvData.Rx_count++] = LoraUSARTx->DR;
+ ]6 W* W; U+ D9 L7 F: b }
" p7 j) A- F) y if(USART_GetITStatus(LoraUSARTx, USART_IT_IDLE) == SET)! g5 \* g: _ [& k0 D& X
{# k7 y/ C1 I. n5 Y, M, H. [4 ?
data = LoraUSARTx->SR;
# v* ^4 f, Q9 y. r data = LoraUSARTx->DR;
2 v6 h& w b0 I4 ^- I9 V
% Q, {- `3 v( {+ [# `- K2 s Lora_RecvData.Rx_over = 1; //接收完成+ j' v7 M- `/ Y2 V. `
}( G2 k0 s4 i5 f/ j% [- b/ B
}例程中,當接收完成標志 Lora_RecvData.Rx_over 為1時,就可以獲取 uart4 接收到的一幀數(shù)據(jù),該數(shù)據(jù)存放在 Lora_RecvData.RxBuf 中。
; d8 M' g% o% U超時斷幀空閑幀中斷的使用固然方便,但是并不是每個mcu都有這種中斷存在(只有個別高端mcu才有),那么這個時候就可以考慮使用超時斷幀了。 w! W8 Q) P2 z, O
Modbus協(xié)議中規(guī)定一幀數(shù)據(jù)的結(jié)束標志為3.5個字符時長,那么同樣的可以把這種斷幀方式類比到串口的接收上,這種方法需要搭配定時器使用。
8 x: x( p* Y4 L0 C8 N; ?其作用原理就是:串口進一次接收中斷,就打開定時器超時中斷,同時裝載值清零(具體的裝載值可以自行定義),只要觸發(fā)了定時器的超時中斷,說明在用戶規(guī)定的時間間隔內(nèi)串口接收中斷里沒有新的數(shù)據(jù)進來,可以認為數(shù)據(jù)接收完成。
9 u* e( {$ Q- q% D4 ]& i. g3 Muint16_t Time3_CntValue = 0;//計數(shù)器初值 x4 A! ^/ T7 r
- _% g" I9 k ?* p z+ h& r' @: L( l
/*******************************************************************************2 [* c% l6 `, t! X2 K& S$ M: Y# L
* TIM3中斷服務(wù)函數(shù)
$ ?8 v2 r- e# h9 G8 D ******************************************************************************/4 T: ]4 }8 J5 f2 v/ w4 i% H4 B
void Tim3_IRQHandler(void)
, o& D: `4 q2 W, b( ~8 z{9 ^0 d+ r: O' C
if(TRUE == Tim3_GetIntFlag(Tim3UevIrq))& ]4 s0 G. F9 i3 g) j W) x, x
{
K; X4 \+ r& u2 e9 T4 x Tim3_M0_Stop(); //關(guān)閉定時器3
1 z* I) X$ I* K Uart0_Rec_Count = 0;//接收計數(shù)清零
4 b' X3 G, I0 |% t' `& h2 n8 g: G0 ? Uart0_Rec_Flag = 1; //接收完成標志; \' u6 {$ {* I5 {2 T c; B6 Q
Tim3_ClearIntFlag(Tim3UevIrq); //清除定時器中斷
) O+ ?+ q) g$ g% E }
7 @5 a" |* M5 Q: {) S9 e! G+ ?. q9 h}
3 ~9 o1 s/ u3 H9 k
# y3 @# ~8 U; [; |void Time3_Init(uint16_t Frame_Spacing)
& h3 Y- I \- b$ j+ c5 V{
. U% V$ U; F. P: T r' J( |' s5 z uint16_t u16ArrValue;//自動重載值" m |; [, b- W
uint32_t u32PclkValue;//PCLK頻率, v# Z- U8 w, G( e; P
1 p( c- j* |2 b. u# t9 R6 L
stc_tim3_mode0_cfg_t stcTim3BaseCfg;
+ |/ S+ e1 z" L- K
; ?0 F( y& o* t, Y) f //結(jié)構(gòu)體初始化清零! n' B9 i2 l0 w, v t
DDL_ZERO_STRUCT(stcTim3BaseCfg);4 r. y9 G" s9 Z( ]' q# h+ e
* t( B# O0 X! }: `' e; S, j
Sysctrl_SetPeripheralGate(SysctrlPeripheralTim3, TRUE); //Base Timer外設(shè)時鐘使能
; k9 T: s0 z7 I9 g! Y& e9 K e2 V1 B 3 Y5 r7 s& `* r: d6 t
stcTim3BaseCfg.enWorkMode = Tim3WorkMode0; //定時器模式) y7 X; _9 A/ J* g
stcTim3BaseCfg.enCT = Tim3Timer; //定時器功能,計數(shù)時鐘為內(nèi)部PCLK
: V$ A* l. y4 Z* W x/ h stcTim3BaseCfg.enPRS = Tim3PCLKDiv1; //不分頻
6 N: X0 Q3 j7 D( d) G! Y stcTim3BaseCfg.enCntMode = Tim316bitArrMode; //自動重載16位計數(shù)器/定時器
4 q( `' O, w( C stcTim3BaseCfg.bEnTog = FALSE;. d4 R3 F2 g7 \! I" H3 d
stcTim3BaseCfg.bEnGate = FALSE;
$ B5 y$ z+ F/ F3 c/ X stcTim3BaseCfg.enGateP = Tim3GatePositive;
0 _* e* W3 y# g8 `: M6 K
+ ^ ~; u' t% B! L Tim3_Mode0_Init(&stcTim3BaseCfg); //TIM3 的模式0功能初始化
4 e2 Z1 a% _1 s' w2 H ; N) Z. h/ i9 z4 |
u32PclkValue = Sysctrl_GetPClkFreq(); //獲取Pclk的值
; @+ A/ p2 X9 ?* n% a; r0 A //u16ArrValue = 65535-(u32PclkValue/1000); //1ms測試
t& `. ]( b5 Z: c) z( V" x7 v: Z5 I. \ u16ArrValue = 65536 - (uint16_t)((float)(Frame_Spacing*10)/RS485_BAUDRATE*u32PclkValue);//根據(jù)幀間隔計算超時時間
* C- r+ G X3 @& Z* o7 U Time3_CntValue = u16ArrValue; //計數(shù)初值
" K6 T- o% j$ ^3 k4 ` Tim3_M0_ARRSet(u16ArrValue); //設(shè)置重載值
* N3 X: \# l2 s) [3 e" ^/ @( ^ Tim3_M0_Cnt16Set(u16ArrValue); //設(shè)置計數(shù)初值
, q5 q9 O7 _" I# _9 z 1 J/ J" _, P2 e
Tim3_ClearIntFlag(Tim3UevIrq); //清中斷標志/ I$ C& y2 N M: V
Tim3_Mode0_EnableIrq(); //使能TIM3中斷(模式0時只有一個中斷)
+ h, ^0 d! r, E. s( u EnableNvic(TIM3_IRQn, IrqLevel3, TRUE); //TIM3 開中斷
# v* n1 v2 ?4 B% X8 Q9 \% J) X! G}
2 \' {" q; ^- v5 X$ k $ S2 [, a7 O8 m1 L/ h; c
/**************************此處省略串口初始化部分************************/
; |; g1 ]# R3 m2 a9 a//串口0中斷服務(wù)函數(shù)* M) d- a3 I0 Q {5 l5 n9 [5 E# ]
void Uart0_IRQHandler(void)
1 ]2 ?9 |! N: v& v{* w5 O- ^7 i: O; i
uint8_t rec_data=0; F; K( z# p! u
5 a( X, w( \% U' P1 N s
if(Uart_GetStatus(M0P_UART0, UartRC)) . X' }# H( W8 e" q- ] c
{
3 ^: H- }. z9 i: H$ C$ i- S Uart_ClrStatus(M0P_UART0, UartRC); & H+ t {& e4 X& X
rec_data = Uart_ReceiveData(M0P_UART0); & Y9 f" U, L+ [, D5 o! y
if(Uart0_Rec_Count[U]//幀長度
1 `* q3 j# Y& V) W* O9 u {- W8 R1 O* o9 R$ D) q" @
Uart0_Rec_Buffer[Uart0_Rec_Count++] = rec_data; 1 ?4 N" T( ^- V+ N; j% `$ p4 F
}
" L% [* r' F5 h& E( Q" V Tim3_M0_Cnt16Set(Time3_CntValue);//設(shè)置計數(shù)初值
# b( H4 H9 x5 \0 N# _- p6 { Tim3_M0_Run(); //開啟定時器3 超時即認為一幀接收完成
3 k4 l7 T! k2 X7 Y& I }0 r5 Z3 G* p- @$ j
}例程所用的是華大的hc32l130系列mcu,其它類型的mcu也可以參考這種寫法。其中超時時間的計算尤其要注意數(shù)據(jù)類型的問題,u16ArrValue = 65536 - (uint16_t)((float)(Frame_Spacing * 10)/RS485_BAUDRATE * u32PclkValue);其中Frame_Spacing為用戶設(shè)置的字符個數(shù),uart模式為一個“1+8+1”共10bits。7 |* n, F! x) \2 A: O) Y
狀態(tài)機斷幀狀態(tài)機,狀態(tài)機,又是狀態(tài)機,沒辦法!誰讓它使用起來方便呢?其實這種方法我用的也不多,但是狀態(tài)機的思想還是要有的,很多邏輯用狀態(tài)機梳理起來會更加的清晰。) ^. \3 C2 {/ V$ Y: H
相對于超時斷幀,狀態(tài)機斷幀的方法節(jié)約了一個定時器資源,一般的mcu外設(shè)資源是足夠的,但是做一些資源冗余也未嘗不是一件好事,萬一呢?對吧。
' O+ w3 Z( l9 d: Q% B//狀態(tài)機斷幀0 }+ D% s2 ~8 Y q
void UART_IRQHandler(void) //作為485的接收中斷, k7 u, v! W3 ~
{
8 w z9 }" a$ w! s! t! f- V uint8_t count = 0;
6 A3 H" `: P; w7 e unsigned char lRecDat = 0;
U) d/ X% M z k) ^, P$ d
6 S5 `. f3 u9 W! l7 V$ p( h if(/*觸發(fā)接收中斷標志*/)
$ K5 T. Y& _! p4 x1 a5 j {+ e( J/ k% n7 P
//清中斷狀態(tài)位, m1 \ Q& d4 f: `2 t
rec_timeout = 5;
5 N# j3 S1 ~: ]9 } if((count == 0)) //接收數(shù)據(jù)頭,長度可以自定義" @5 K* V6 m) [! ]+ i- B( u
{& N. J7 H' ]5 p" V/ w
RUart0485_DataC[count++] = /*串口接收到的數(shù)據(jù)*/;- V/ m4 c- S( z6 y3 J
gRecStartFlag = 1;- g7 G& {" z+ `( ~2 a/ N. {9 d4 _2 w
return;
0 Z2 W2 L8 r. l/ G' U- c }0 `+ K( R& m2 ]# H
if(gRecStartFlag == 1)
- `$ r2 G7 M5 y* b {
+ h' Y2 G& H& {" H$ N, X RUart0485_DataC[count++] = /*串口接收到的數(shù)據(jù)*/;" _, }/ k* U y0 T
0 g- u! H1 z' z1 \
if(count > MAXLEN) //一幀數(shù)據(jù)接收完成
) Y( O8 J4 T# T5 g8 S* |) H8 [& C {
- I$ o4 C- ~- b- Y M count=0;
) I t r. r+ z/ Y5 H/ M7 z4 L X9 n gRecStartFlag = 0;
8 A* W/ c; o) O $ G' M! s* G+ G5 J) R
if(RUart0485_DataC[MAXLEN]==CRC16(RUart0485_DataC,MAXLEN))
" v0 Y* f. P$ {- j' _ {
" D- l1 A& j6 d8 R) f+ Y9 p memcpy(&gRecFinshData,RUart0485_DataC,13);0 z7 |$ U) Z R$ A% W6 K4 K' p
gRcvFlag = 1; //接收完成標志位 `1 Q* W( r3 L. T+ l$ v
}' X) R( g) B; L) v& r& z! x
} $ h2 v/ @' @0 _* w2 H% k) |$ w
}
# P: H; {. K9 g! D) C3 ]( y return;
& O5 U8 R( U! U0 s$ i; |* q* D }
8 Y2 y; J6 q& n& z/ j return ;
/ ]2 z2 I* ?- H' r- K# A}這種做法適合用在一直有數(shù)據(jù)接收的場合,每次接收完一幀有效數(shù)據(jù)后就把數(shù)據(jù)放到緩沖區(qū)中去解析,同時還不影響下一幀數(shù)據(jù)的接收。: H! J" e3 Z- y$ ]' S! z+ S
整個接收狀態(tài)分為兩個狀態(tài)——接收數(shù)據(jù)頭和接收數(shù)據(jù)塊,如果一幀數(shù)據(jù)存在多個部分的話還可以在此基礎(chǔ)上再增加幾種狀態(tài),這樣不僅可以提高數(shù)據(jù)接收的實時性,還能夠隨時看到數(shù)據(jù)接收到哪一部分,還是比較實用的。
& j* }& F2 U+ s, ^ x"狀態(tài)機+FIFO"斷幀記得剛畢業(yè)面試的時候,面試官還問過我一個問題:如果串口有大量數(shù)據(jù)要接收,同時又沒有空閑幀中斷你會怎么做?# Y8 E2 R" N" N
沒錯,就是FIFO(當時并沒有回答上來,因為沒用過),說白了就是開辟一個緩沖區(qū),每次接收到的數(shù)據(jù)都放到這個緩沖區(qū)里,同時記錄數(shù)據(jù)在緩沖區(qū)中的位置,當數(shù)據(jù)到達要求的長度的時候再把數(shù)據(jù)取出來,然后放到狀態(tài)機中去解析。當然FIFO的使用場合有很多,很多數(shù)據(jù)處理都可以用FIFO去做,有興趣的可以多去了解一下。/********************串口初始化省略,華大mcu hc32l130******************/* x" C/ _2 @. ]
void Uart1_IRQHandler(void)$ ^6 [5 M8 X$ Y$ ~; w8 s! w
{, J9 M: y( ~9 {: j* |5 k9 `# ]& |& ~
uint8_t data;
* @" t& ^6 o5 O0 b( F) Z! B, m if(Uart_GetStatus(M0P_UART1, UartRC)) //UART0數(shù)據(jù)接收
Y5 G! y9 n5 I7 s5 p% ~$ r' y {
6 u {6 t( r3 |+ |8 M# o Uart_ClrStatus(M0P_UART1, UartRC); //清中斷狀態(tài)位6 n+ D' H% v5 N) C* j1 I
data = Uart_ReceiveData(M0P_UART1); //接收數(shù)據(jù)字節(jié)
, t, ^5 O) @ y- Y& e comFIFO(&data,1);
# g2 I! z( ~$ A. k. ]2 w- I } 3 Y9 q* J4 F5 r: T2 [( K
}
& e o) t% y+ W6 ? , Q7 J7 E) @- q5 ?3 l( Y. K
/******************************FIFO*******************************/1 `; i# Y; C7 f2 Z
volatile uint8_t fifodata[FIFOLEN],fifoempty,fifofull; y. d) z; J& V
volatile uint8_t uart_datatemp=0;$ r; n$ p' B0 W( w
( K4 L& `! [. H% U, e
uint8_t comFIFO(uint8_t *data,uint8_t cmd)
$ b* B0 \" a5 D% P* |0 N# F{
: M( W; Z( h5 p6 S' O static uint8_t rpos=0; //當前寫的位置 position 0--99
% v3 ^: h2 I1 {2 j: `, R# m static uint8_t wpos=0; //當前讀的位置3 K, D! X) I' P5 Z
9 F+ u, ? r( X) Z
if(cmd==0) //寫數(shù)據(jù) s. t3 F5 w: Z" x2 B
{7 P6 j( e ?6 f0 ^% Z/ |
if(fifoempty!=0) //1 表示有數(shù)據(jù) 不為空,0表示空
/ v+ k; z0 d- s6 y b5 e, j {, I, q/ ?. y& j1 Y: X5 N, I
*data=fifodata[rpos];
n* t% c' I. B0 `) i fifofull=0;- D! ?) _& Y& _9 P8 g1 f) T
rpos++;. ]) |9 u; K3 |* n+ R _. @( J
if(rpos==FIFOLEN) : C k' t: |6 w8 ?. z
rpos=0;9 @! S8 F6 D R( h5 Z0 y% E
if(rpos==wpos)
1 [; E$ v% X3 \5 N% y, A fifoempty=0;
[' [) }' o8 p return 0x01;
; [5 P& n f8 C6 ` e$ g }
+ y" _( t- @2 _# J else! v5 m+ S! F3 E5 l( V3 j! N
return 0x00;5 A- g/ V5 P z- C; P( V
5 d, P: ^6 n7 f; g# K
}
9 _, u- y6 L# ?( V1 H/ n Z else if(cmd==1) //讀數(shù)據(jù)
) [2 Z W/ M# I: B- e" u9 W {
0 R2 y6 ?5 R8 {1 D0 i2 i if(fifofull==0): l+ n/ _) {/ V
{) Q- s! \$ e u6 U5 G+ ?
fifodata[wpos]=*data;- j& I4 P) G! b
fifoempty=1;
; W7 m% V% ^ H: p! u wpos++;
. ?% g& A1 G5 k) F; h, E4 r+ ` if(wpos==FIFOLEN) * C( j8 T2 n3 o
wpos=0;
5 A$ [! C+ P# i& I l if(wpos==rpos) ! |' D3 C9 h5 @0 f- X% T+ l$ Z' ^
fifofull=1;
8 g# ]7 q7 V& ]" l* o return 0x01;' K8 I7 |5 v7 z2 s5 o: ^& U2 F
} else
7 ?% a* K, c5 W return 0x00;
, g4 H& X* i% _0 z, b; U }
8 I2 T+ f8 H) V0 d# j9 J return 0x02;: e u- e! T5 O ?0 |4 j
}/ {) D5 `. t, L$ Z* D3 o
% v" }& |9 Q' y
/********************************狀態(tài)機處理*******************************/. R* e# b) G, i
void LoopFor485ReadCom(void)
) K+ Z. j8 r1 m, I/ w; y4 d{
- K- A T- @9 i uint8_t data;7 K4 E3 e& I' F% C
! M6 c5 z0 q) T* V
while(comFIFO(&data,0)==0x01)
( E7 o7 @! b7 ^" d7 J {
2 b& G: @& |5 E$ k! k" F if(rEadFlag==SAVE_HEADER_STATUS) //讀取頭
! O! c2 a0 x# G0 M2 I. s {
: v! x9 |& p! B* K if(data==Header_H)! _4 U- I+ J+ }+ I
{: n% S! ~2 @$ I1 a0 p; @& t/ m1 |. K
buffread[0]=data;
6 `; h1 ~- N! z4 W# L continue;6 D5 ~" J7 k9 u
}
5 d2 q' g: g& o3 H# W. i, n8 y if(data==Header_L)
) s8 R' Y( i: ^. R9 W; }( ^, D { S$ U) N8 [0 P7 V) V" ?+ y/ C- R
buffread[1]=data;* M3 G% C" ?) ?
if(buffread[0]==Header_H)) z. G* l/ u1 w5 W
{& U2 l7 |. x5 E4 f3 P7 c2 i
rEadFlag=SAVE_DATA_STATUS;" n3 t3 T8 V6 k- c# ~
}8 @# E/ h' g* }' h! O9 B
}
1 r, w- [: a: `* p2 ` else5 _5 i1 v7 i* v% s/ c: `
{
1 [3 w) |. u$ a8 Q% Z; b8 r memset(buffread,0,Length_Data);& |4 ^" T6 l8 o* U1 K# f
}+ ~7 r# ^" r+ y1 X' d: S$ t9 h
} 2 l" `, W/ _ `' x8 M( E$ [
else if(rEadFlag==SAVE_DATA_STATUS) //讀取數(shù)據(jù)* z( U3 ?/ F: ~ [) o, T
{
/ [! K$ ?9 f1 e* e- I1 J8 Z1 K buffread[i485+2]=data;; y; G' X" ]; x4 o# ]0 s$ s
i485++;
5 |, q4 N5 T! ^1 k3 q/ j) ~' ^ if(i485==(Length_Data-2)) //數(shù)據(jù)幀除去頭9 u% R6 o, |% J1 {' r, f
{& p0 B& U$ d, K' |4 j* Y* Y4 F
unsigned short crc16=CRC16_MODBUS(buffread,Length_Data-2);
; r- R' K+ p, n# }# J2 |% I* E if((buffread[Length_Data-2]==(crc16>>8))&&(buffread[Length_Data-1]==(crc16&0xff)))& t: o3 w& ~" v m" A
{
" _. t6 \7 W1 Z! `% J. q1 D, e rEadFlag=SAVE_OVER_STATUS;7 ?2 e) G! ], a" L
memcpy(&cmddata,buffread,Length_Data); //拷貝Length_Struct個字節(jié),完整的結(jié)構(gòu)體
3 [9 i" \3 H# f) e/ ? } + K; [, M1 d5 K7 Q' G+ W
else0 y% [( M4 W! t7 `
{+ E. ^2 {6 |7 ~1 w* j: u$ p8 Y
rEadFlag=SAVE_HEADER_STATUS;
7 ^, g' U# S- L; ^. t- E2 P }/ D$ _3 F; l2 U& q2 F1 W. T4 R
- ]: g. `+ q/ r memset(buffread,0,Length_Data);
$ z2 E9 L! L% R/ W i485=0;
5 C2 i' S) k* [% q/ \; B' a0 F break;& r' b& k' r9 @
}
$ c0 u1 Y& G! k& _ }
" @; `+ [4 H Q6 X$ y& T }+ s2 _& E( A6 t# _" N- W
}原文:https://blog.csdn.net/qq_56527127/article/details/123018515
, |$ F5 m! p, G& W0 z F6 ?
ohb1aidbpas64054373034.png (769.97 KB, 下載次數(shù): 0)
下載附件
保存到相冊
ohb1aidbpas64054373034.png
2024-12-2 23:14 上傳
) Y4 O1 e3 T" J( v( b9 w-END-5 y% Z( D3 \( V( l
往期推薦:點擊圖片即可跳轉(zhuǎn)閱讀
+ @& _# f* C" A) D+ t6 g5 o- ?
; F J, ~, m: D
4 _, {3 L' j3 Y. Q # h$ |% R! X; A+ ]" g5 j" i) d
5 f5 _7 o& b) A; |. N" L1 D
5 B3 N, Z& H. l4 {/ y
ptzib2nqqkv64054373134.jpg (112 KB, 下載次數(shù): 0)
下載附件
保存到相冊
ptzib2nqqkv64054373134.jpg
2024-12-2 23:14 上傳
. c% ]- C, v/ B6 @0 S # U/ ?8 i7 J7 C- M3 P
嵌入式軟件調(diào)試,如何計算任務(wù)的運行周期?0 q7 ]7 M" O0 T8 T7 w- R9 w
0 ?/ d5 U" E6 f # j, Y' e6 S8 Y) y( M
0 @& M- _/ \) [6 H' q: D
6 y% H& ?3 g2 l; b3 T
0 L; Y% A3 e& j5 ^7 w
4 Q6 `8 N0 }6 B& e% X
' ~& _" k5 O4 Q0 }4 V- N! C% h
9 m% F+ Y$ x9 ]' C3 e4 Z
# H/ Y! V- G+ l( K- Y
8 L/ w: G, u( o5 I6 c( W" l* x
iarkvaxoix564054373235.jpg (124.11 KB, 下載次數(shù): 0)
下載附件
保存到相冊
iarkvaxoix564054373235.jpg
2024-12-2 23:14 上傳
q; e0 T; `% Z% K0 ?0 b M1 {
3 i$ w& K; {! x. r% {+ V' y) N 嵌入式軟件,如何把編譯時間加入到bin文件,進行版本管理?% j Z( ^1 T0 E+ O
4 T7 ^, p3 I6 D; y' p 8 A( I S ~' y8 t
) ] ]" M* M$ B( i& m: p; I
- {8 K* A1 Z( ]( h; O
1 l& J% j @; Q* ^& _0 B1 w
5 N+ X8 w: U( N ! ]: ^$ Z/ } _; B" M) `
" t) A3 _8 z$ I' T: ?/ G
7 i" o( T S C2 j2 C) V# k& q # @* ^' m5 Y) J$ G: q4 Z* s
e31rvw53ost64054373335.jpg (258.23 KB, 下載次數(shù): 0)
下載附件
保存到相冊
e31rvw53ost64054373335.jpg
2024-12-2 23:14 上傳
+ \8 ~1 ?8 j2 Y6 Q/ W* H' Z9 O J" r
6 B4 J/ _% }3 A8 E; }- v2 I2 } 嵌入式初學者入門后,應(yīng)該如何開始進階學習?
* w1 T7 z8 W$ J4 \1 h) [! f
: @. e0 @* ?. H7 l- L
$ |2 j' a0 I( F1 r / `3 U$ M' v5 `" W: r ~3 i# k, D
( D) F; z4 M" M
1 b4 z- G+ Q9 [* F+ S我是老溫,一名熱愛學習的嵌入式工程師- O$ q/ c1 x5 N: c
關(guān)注我,一起變得更加優(yōu)秀! |
|