|
我是老温,一名热爱学习的嵌入式工程师
' U9 D, t; X5 _. }( L4 F/ U关注我,一起变得更加优秀!嵌入式软件开发过程中,为了提升工作效率,避免重复造轮子浪费时间,经常会复用一些C语言代码片段。4 T+ j$ ^; T8 p4 B" L
以下是一些利剑级别的C语言工具代码示例,以及它们的简要讲解,分享给各位老铁,大家按需使用。/ E& G! j6 j; C! E$ L
1、循环队列(Circular Buffer): S9 _. i& @% H: H* j
typedef struct {! F2 S5 W- y) t
int buffer[SIZE];: Q$ K$ {6 k0 b' O* t, ]
int head;0 v$ B) V) A- m: Z
int tail;: w0 u8 r7 B' f& F$ p
int count;. d; ^5 s" C* e) u; @3 K
} CircularBuffer;
+ e- c0 _7 N% g f6 C3 p) g) a9 |' Ivoid push(CircularBuffer *cb, int data) {' k7 q9 P' S) s o) d
if (cb->count SIZE) {
1 R# m! `& \2 f0 j9 D1 D0 ` cb->buffer[cb->head] = data;
# W- h) V/ r" N. E1 [' n( \- g9 | cb->head = (cb->head +1) % SIZE;6 ^4 K* }6 u6 w. t3 k7 j
cb->count++;
0 t( e& t( S. D' Z2 R- V w }
& c& ^; |# i, A: B# l! Z3 a}
& G8 k5 z( I* H# }( z& J6 @1 yint pop(CircularBuffer *cb) {
+ ?$ G2 Y7 m. t4 K if (cb->count >0) {
% K/ I6 @; S6 m int data = cb->buffer[cb->tail];
% a% G' i# f! X5 f# b/ | cb->tail = (cb->tail +1) % SIZE;9 O3 K" |' F6 K! T
cb->count--;
6 M e+ X2 r6 E return data;
$ r9 ^! |- b- r! X }
. u" x6 L6 t \/ ~$ B) m1 Y7 ` return-1; // Buffer is empty
" O5 H7 e$ s6 _1 i3 m. n}
3 c ]4 ]3 ^; d) i; q6 [8 J n循环队列是一种高效的数据结构,适用于缓冲区和数据流应用,例如串口通信接收缓冲。. P F# m- ?; J1 d' D( O4 ~
2、断言(Assertion)
L i' U; }! M+ x5 G8 w#define assert(expression) ((void)0)
' l. _% |1 M/ O4 \#ifndef NDEBUG
" N; O% S p5 e5 i. i- S#undef assert$ F7 S( c/ z% N( n
#define assert(expression) ((expression) ? (void)0 : assert_failed(__FILE__, __LINE__))
. K N* Y+ Z) y5 \#endif
' Q/ j1 r4 m' |! ]void assert_failed(const char *file, int line) {
( N5 w! k6 I# v/ D, [3 ]/ q printf("Assertion failed at %s:%d
& |$ a! C" y7 r/ w", file, line);
; I$ P( [( H% q3 ^4 c0 j1 w // Additional error handling or logging can be added here
8 e, U( f \+ G8 M5 u& X0 p" M9 x6 V}* \! v8 |; k) g5 p: y% t
断言用于在程序中检查特定条件是否满足,如果条件为假,会触发断言失败,并输出相关信息' s4 ]& }" b) s1 v/ \
3、位域反转(Bit Reversal)
: D) T ]8 D1 u% kunsigned int reverse_bits(unsignedint num) {
) Y3 D) @" a9 U8 O5 A$ z2 k unsignedint numOfBits =sizeof(num) *8;, B' @2 P1 h7 ]2 E/ s/ k' i
unsignedint reverseNum =0;
% R' F+ x. `" x! v for (unsignedint i =0; i numOfBits; i++) {) `; @' M4 w1 _9 F1 n- V/ H8 n% w
if (num & (1 i)) {
1 O2 q3 T) P- y' y/ }; y reverseNum |= (1 ((numOfBits -1) - i));
! W( v. Q! @; r P! q }( J% |) z6 T$ f8 X
}$ w$ E: d3 @9 _0 N
return reverseNum;
. ]5 o, Y. [& \( g! B. a n}: F+ I* \1 ~" F" v$ c4 p8 G* Q
该函数将给定的无符号整数的位进行反转,可以用于某些嵌入式系统中的位级操作需求。; e2 Q N7 H5 G3 Q/ ^1 {, ]" G
4、固定点数运算(Fixed-Poin Arithmetic)8 Q- j8 K' p. A
typedef int16_t fixed_t;1 w* x+ N7 q$ X, T' J
#define FIXED_SHIFT 8/ W$ u% Q" s( q9 X) U( l, ?
#define FLOAT_TO_FIXED(f) ((fixed_t)((f) * (1 - u( u/ q1 P/ y$ k. Q
#define FIXED_TO_FLOAT(f) ((float)(f) / (1 1 M n3 H7 D0 g3 E n! g
fixed_t fixed_multiply(fixed_t a, fixed_t b) {) _, G2 `5 Z) L" W" B3 w# j l' z
return (fixed_t)(((int32_t)a * (int32_t)b) >> FIXED_SHIFT);
7 k3 B' H: q# ^( r}% p! a2 r2 W8 f- M, x7 W: W# Q
在某些嵌入式系统中,浮点运算会较慢或不被支持。因此,使用固定点数运算可以提供一种有效的浮点数近似解决方案。. o5 Q) f& X2 K0 N- E/ v G! Y
5、字节序转换(Endianness Conversion)2 c4 o" C$ d' t: R& O/ ~
uint16_t swap_bytes(uint16_t value) { return (value >> 8) | (value 8); }用于在大端(Big-Endian)和小端(Little-Endian)字节序之间进行转换的函数。
( K/ {1 i4 s: P+ c6、位掩码(Bit Masks)8 d2 H: H8 V2 ]/ t% q) m
#define BIT_MASK(bit) (1 / Z# c0 G* f* }& a* T
用于创建一个只有指定位被置位的位掩码,可用于位操作。
1 P6 I$ y! K0 ~' }7、计数器计数(Timer Counting)5 N" R1 [- x: p0 X# R( A) J, T
#include
" M* Y& P9 O" L* a7 F4 u! N5 v2 r! Pvoid setup_timer() {& S% _8 `2 t( `; ~
// Configure timer settings% }6 D7 m! ? [' d' h
}
+ P2 G. \* Y% k, G3 [$ ruint16_t read_timer() {& a" B& w W: c+ [$ Z& w. U6 \
return TCNT1;
6 J; B& U0 D1 [ @}
" x- j! N! Z+ ^% ^, {2 a0 I在AVR嵌入式系统中,使用计时器(Timer)来实现时间测量和定时任务。& ?! r/ L1 P' F+ D, |3 D
8、二进制查找(Binary Search)
; r' ?1 |/ w3 U; A6 ^6 _$ \int binary_search(int arr[], int size, int target) {4 Z9 ?0 z# G+ Q5 t! @5 n1 D
int left =0, right = size -1;, I+ @ Q- c& _2 t
while (left right) {3 ?# Q5 e8 u1 H$ q* m
int mid = left + (right - left) /2;
+ T6 O( t* @1 s. {- H1 m# t if (arr[mid] == target) {; S+ l! B3 R R( W$ y7 J* |
return mid;
3 }$ k- w. @ { } elseif (arr[mid] target) {
9 q" I# y) B& v8 Z# \9 t left = mid +1;. |* y! A# N% R/ ?8 t
} else {
( H- M. A( N S8 \3 }3 ?) t right = mid -1;/ a3 |2 y# j8 E: S2 C$ o
}
* `+ m: o( H4 g3 C' S$ G }
( W- V0 T0 W7 s- r8 R8 u. x return-1; // Not found2 K! ]( o' j& S& b( A# K9 Q
}
+ A0 s, q& e6 g" K* }% i用于在已排序的数组中执行二进制查找的函数。
, D' o+ b) E2 \3 t9、位集合(Bitset)
0 u# U4 H, n4 u3 _/ ?' H#include ( j" @$ X* P( z. p
typedefstruct {9 L8 t" L3 M+ K$ i; M/ q
uint32_t bits;
l. N0 v6 m- D( a} Bitset;6 g% W' U& V4 c7 R4 |: p
void set_bit(Bitset *bitset, int bit) {) b! e& n8 b3 V" j
bitset->bits |= (1U bit);
: N3 h$ v O5 O" t$ d f}
6 h6 R" E/ r9 o, O7 M- Wint get_bit(Bitset *bitset, int bit) {! R, C! K+ ]: |$ E# o5 X3 {; l+ V
return (bitset->bits >> bit) &1U;. f, W1 y; c3 d
}. F" ~: p+ ^4 C! E$ x u- \
实现简单的位集合数据结构,用于管理一组位的状态。
8 @. y; _2 _! W6 z这些代码示例代表了嵌入式开发中常用的一些利剑级别的C语言工具代码。它们在嵌入式系统开发中具有广泛的应用,有助于优化性能、节省资源并提高代码的可维护性。7 V l, z+ G3 O& X$ P' M% j
来源 | 知乎-晓亮Albert
' ]! S. A( L, [0 r-END-" O; v7 G5 A7 Z! V
往期推荐:点击图片即可跳转阅读9 N! W' O! w: m
phbos4l5rwh64014340709.jpg
; P% F5 y4 g4 V$ d1 L2 b4 Z! V, G' V
最近在画图,电源稳定性对嵌入式硬件设备来说,实在是太重要了!9 c# ?0 g' K! r; ~* O+ B: ~: h: N
shb5rn5ppue64014340809.jpg
6 b5 a6 n5 G/ K+ d3 ?
嵌入式设备能在LCD屏幕上显示中文,是基于什么原理?7 u+ Z, q, H9 Q) _" x2 F
5kfpsuosmv164014340909.jpg
' I1 l6 o6 a8 I- S) I8 N嵌入式软件,代码的可读性与可运行性,哪个更重要?
; C! e7 X! c5 U8 k1 A我是老温,一名热爱学习的嵌入式工程师
; @4 M# h! N$ Y" T) ]2 o关注我,一起变得更加优秀! |
|