|

我是老温,一名热爱学习的嵌入式工程师+ W& V; B4 C: _9 [) C
关注我,一起变得更加优秀!嵌入式软件开发过程中,为了提升工作效率,避免重复造轮子浪费时间,经常会复用一些C语言代码片段。
/ H6 ?5 d* |6 |7 S/ M) p以下是一些利剑级别的C语言工具代码示例,以及它们的简要讲解,分享给各位老铁,大家按需使用。% B. a, L6 W) h
1、循环队列(Circular Buffer)
( \2 h" Z. G1 d8 |2 Z' a) ftypedef struct {
: e- B( T1 W5 I8 i$ k: c* C int buffer[SIZE];
/ {4 |5 q6 T3 x! L int head;( {9 r, o% e: V; o( ^. K
int tail;
1 E) w" B+ t! C7 u1 N7 V int count;
9 g5 f9 X2 I) C7 P# K8 y" f} CircularBuffer;1 ?* d0 u$ n8 m$ `
void push(CircularBuffer *cb, int data) {, p! T q- q a8 v' D
if (cb->count SIZE) {1 K I) {( K# `: F: C4 }3 |
cb->buffer[cb->head] = data;
) P0 A4 V/ M. p; W5 L cb->head = (cb->head +1) % SIZE;; s$ E9 t& o( g& t' l# k' {: Y
cb->count++;5 Z1 C1 d: s9 b7 _- o( V3 S5 E* i
}
- K# A3 `8 |' S7 t$ E9 s& E$ d4 S}+ h+ D* G" S9 z7 Z
int pop(CircularBuffer *cb) {
) Y; l1 }8 j3 `& T }; u: p7 | if (cb->count >0) {
2 r. r) Q3 c; ]: l int data = cb->buffer[cb->tail];
# A1 G1 v5 i | cb->tail = (cb->tail +1) % SIZE;' f' [) P+ f! d/ X" } q) S0 }# ]
cb->count--;' D [5 v+ I7 v4 O$ w+ l! F6 C
return data;( {8 M) b* q, V! A% E/ ]
}
# {3 W3 z! R6 t1 [) Y- ^ return-1; // Buffer is empty
5 ~ C/ ]& S* J- D: G}
% H" f# H+ F. _3 s1 j循环队列是一种高效的数据结构,适用于缓冲区和数据流应用,例如串口通信接收缓冲。
6 v# @& R' r( C; }2、断言(Assertion)0 U5 O/ e5 K' q: I, T- E# J
#define assert(expression) ((void)0)8 [8 Y- r' Z5 g" q
#ifndef NDEBUG1 S# j3 Z& m5 {6 d
#undef assert& ]" M7 V# Q( _2 {" A
#define assert(expression) ((expression) ? (void)0 : assert_failed(__FILE__, __LINE__))
: u8 z! V0 h+ }! @#endif; Q5 v1 U3 d1 p4 Q5 x* s5 E
void assert_failed(const char *file, int line) {
& `" m+ j$ r P4 L5 f/ K/ g printf("Assertion failed at %s:%d
; g* v4 Y, [2 @8 ]0 q- s$ \; t", file, line);* y! \# F8 X) a$ z0 D1 X+ k
// Additional error handling or logging can be added here5 y9 _. w* [( @
}; U9 L0 i6 k. s: G& p; w+ y
断言用于在程序中检查特定条件是否满足,如果条件为假,会触发断言失败,并输出相关信息; y& r+ N" }, J! i
3、位域反转(Bit Reversal)
# K1 v6 e: |, u/ H1 A& S( Gunsigned int reverse_bits(unsignedint num) {
' w% M+ U& t+ N# r1 |2 u unsignedint numOfBits =sizeof(num) *8;
% O( Q R: L& B unsignedint reverseNum =0;9 s' j. i1 r; e9 ]: l- M
for (unsignedint i =0; i numOfBits; i++) {
' w9 }; \8 Q. Z4 J; S$ [- m) K if (num & (1 i)) {3 d+ e$ j* j) M! j6 l9 K( Z) h: v/ t
reverseNum |= (1 ((numOfBits -1) - i));
8 M% h5 ~- [% y2 S, x( O }. u4 o! W# F5 B' ?% q: }; V
}6 Y( u' j8 d' k* Y
return reverseNum;' x3 y) X+ M' U; J, d0 }
}
9 j5 `" D V5 }- ^5 t9 }% n( Q该函数将给定的无符号整数的位进行反转,可以用于某些嵌入式系统中的位级操作需求。5 F* z: g/ z ?' q& g
4、固定点数运算(Fixed-Poin Arithmetic)1 u, i" S& W0 }* I
typedef int16_t fixed_t;% m8 Z# S! h6 y$ a- _7 C! F. E
#define FIXED_SHIFT 8
! j5 y6 }0 T7 }' m#define FLOAT_TO_FIXED(f) ((fixed_t)((f) * (1 ( e* D. @- ?7 h* z
#define FIXED_TO_FLOAT(f) ((float)(f) / (1 : l% A# k W9 q& s+ d
fixed_t fixed_multiply(fixed_t a, fixed_t b) {
1 ~7 k, F* |$ P- c' N' r return (fixed_t)(((int32_t)a * (int32_t)b) >> FIXED_SHIFT);
* E4 Z$ x3 S+ M& Y! k}$ E0 l& L% s+ ?* ?/ k6 U& K* Q* ]
在某些嵌入式系统中,浮点运算会较慢或不被支持。因此,使用固定点数运算可以提供一种有效的浮点数近似解决方案。6 s- _9 q& P6 Y m# s
5、字节序转换(Endianness Conversion)& v' q& y2 e3 R9 L4 ?
uint16_t swap_bytes(uint16_t value) { return (value >> 8) | (value 8); }用于在大端(Big-Endian)和小端(Little-Endian)字节序之间进行转换的函数。
* F m) T- K( X( e6、位掩码(Bit Masks)
1 c' o8 }+ w1 `9 {4 q, s#define BIT_MASK(bit) (1 0 e, ^+ j- H& b4 O
用于创建一个只有指定位被置位的位掩码,可用于位操作。5 y6 d9 E* ~& y' K+ Q m
7、计数器计数(Timer Counting)
. F2 s9 V! ` V$ _: x#include ! b4 X( m5 o* Y
void setup_timer() {
! k/ m9 g5 r+ w9 g3 W // Configure timer settings" C0 Q. F5 I4 ?. N3 x
} G1 _+ i3 R" ^- M
uint16_t read_timer() {, |$ z9 N8 U" M) T
return TCNT1;- c8 h8 y4 t5 r
}* `7 N1 p- d! v" `2 Q0 V) C7 K! s* q
在AVR嵌入式系统中,使用计时器(Timer)来实现时间测量和定时任务。
1 ^& M. E0 t4 h- O' o9 y8、二进制查找(Binary Search)4 B/ }: g: g% I; x) s
int binary_search(int arr[], int size, int target) {" E# Q. J) G/ g7 T( E
int left =0, right = size -1;
( v: m% k3 w; H, k8 P1 N3 _0 v* L while (left right) {( N$ x; }' T6 I# p$ T- U
int mid = left + (right - left) /2;
+ G' W1 U8 B% Q if (arr[mid] == target) {
# b R* v$ W4 ]% o0 p; z return mid;" I7 t, v( V! }* T" G2 ?
} elseif (arr[mid] target) {, d! w' ]' }- J: Q3 P1 b
left = mid +1;
- N a. q' o; s' }6 i: \% V! n' M; f } else {3 K; j/ l/ W' g/ E- O
right = mid -1;
# w! U' ?, A4 m9 G+ I }. `/ k: g1 r2 D3 }. Q) N) R) q
}8 F0 l. K& w) g4 J; ?- n/ \; L) B, _
return-1; // Not found: u- k! j+ d, U, H, H
}
9 a; J5 y) V) y. q2 U用于在已排序的数组中执行二进制查找的函数。
7 @5 l- i/ L( t# q3 X/ \9、位集合(Bitset)) H9 T" U' S/ Q( {$ s% ?. w$ Q
#include
; w: g. @ K' h; dtypedefstruct {
~4 y" I) b/ n! N- L uint32_t bits;+ A5 |; L& S8 T$ I. I
} Bitset;
- z- H3 t1 }, f: |1 evoid set_bit(Bitset *bitset, int bit) {/ _5 p9 ?1 t2 t$ U
bitset->bits |= (1U bit);
6 M* P7 {: w& K& \' F* n}
1 m- g9 A" y/ X* g( L! nint get_bit(Bitset *bitset, int bit) {/ L" b2 y4 J5 e
return (bitset->bits >> bit) &1U;9 b0 c. V; \2 E0 B! x2 Y
}6 k( r7 |2 v$ U; S+ Q# I3 @& C' ^
实现简单的位集合数据结构,用于管理一组位的状态。
+ H% w! P+ k: @$ y$ P) B4 d( y; a这些代码示例代表了嵌入式开发中常用的一些利剑级别的C语言工具代码。它们在嵌入式系统开发中具有广泛的应用,有助于优化性能、节省资源并提高代码的可维护性。
M, B z3 z4 M# t" o来源 | 知乎-晓亮Albert
/ @& p F1 ]/ x* a0 s$ B) y% ^- j-END-2 x; F4 R9 f) h4 b: R* @
往期推荐:点击图片即可跳转阅读
0 F6 d6 ^) u: ]$ n
phbos4l5rwh64014340709.jpg
) L W) h3 A4 n( ]" Y1 o4 W最近在画图,电源稳定性对嵌入式硬件设备来说,实在是太重要了!7 M/ k8 Q! K* h
shb5rn5ppue64014340809.jpg
6 X6 W( G; _/ f* v( ?# l- j嵌入式设备能在LCD屏幕上显示中文,是基于什么原理?
. I! r ` g% G3 ]. a2 E$ B1 x' N
5kfpsuosmv164014340909.jpg
4 G; X* D- m8 o9 e" O2 x' [: j
嵌入式软件,代码的可读性与可运行性,哪个更重要?
+ i- ~7 c6 l; m2 S( S$ U我是老温,一名热爱学习的嵌入式工程师' Y/ I9 }) ~) y/ Z6 w' w! O/ J! i6 C! w
关注我,一起变得更加优秀! |
|