|
我是老温,一名热爱学习的嵌入式工程师; D% l3 A8 m4 q' L2 s) c
关注我,一起变得更加优秀!嵌入式软件开发过程中,为了提升工作效率,避免重复造轮子浪费时间,经常会复用一些C语言代码片段。
# m. O0 [& J; V8 u) P) S; i3 v; ]以下是一些利剑级别的C语言工具代码示例,以及它们的简要讲解,分享给各位老铁,大家按需使用。
* k \7 m6 {& x% M5 E9 w1、循环队列(Circular Buffer)
' f7 D) P2 O* m% ?9 [typedef struct {
0 b) o& ?6 }1 A5 Z3 ~ int buffer[SIZE];
H- G) y: s5 D+ s$ E U int head;8 j; p' e( X% i) m% |4 t* P
int tail;
q: [9 R. n- p6 q9 j int count;3 U0 @7 b- R5 \8 B. \
} CircularBuffer;% m5 L( Z; _+ U
void push(CircularBuffer *cb, int data) {
1 p! X i' t) Z! D* e' Z5 G7 I if (cb->count SIZE) {; }8 \3 e/ Z: B( m7 J, f$ `5 `$ W
cb->buffer[cb->head] = data;
6 E7 X+ V/ ~3 W; V cb->head = (cb->head +1) % SIZE;# f* t/ I% ~6 P- G
cb->count++;
/ J. o7 N7 j# i& v% w1 w }
* L9 D! ^2 e0 D. r o}
; n: d- `) Z! b% P zint pop(CircularBuffer *cb) {
4 \1 C4 P2 O) l. J- k# p if (cb->count >0) {) B: Z. x1 s9 d1 z6 w6 Y' a
int data = cb->buffer[cb->tail];. H6 e) U# E' p* n7 e9 m* V
cb->tail = (cb->tail +1) % SIZE;1 m4 C# e/ O6 v! K
cb->count--;
- j) s* w4 B* P1 \+ G6 C( s return data;
* k v8 l7 \, V% ^$ J" Y9 `" {2 z }; ~0 v; p8 S3 L: D, P
return-1; // Buffer is empty/ h' D' ~7 B/ r# ^( j4 g0 L" n6 K1 p
}4 G, I* O. J+ a3 S% j; C
循环队列是一种高效的数据结构,适用于缓冲区和数据流应用,例如串口通信接收缓冲。2 J6 z2 m ]" D( k
2、断言(Assertion)
7 L4 }0 l+ M% O: {9 o#define assert(expression) ((void)0); Q+ m+ t* S1 U9 y
#ifndef NDEBUG8 t7 j: ~. x6 t# Z
#undef assert3 v4 A- t* {3 |3 Z1 O
#define assert(expression) ((expression) ? (void)0 : assert_failed(__FILE__, __LINE__))7 Z) M0 K/ X& d) Z" k
#endif
5 A3 @0 f, X; H- Avoid assert_failed(const char *file, int line) {
% B$ Q5 z' C2 r7 k& D7 ^ printf("Assertion failed at %s:%d- ^1 k, P0 k6 K$ t7 }5 N# I! I5 t
", file, line);) P! C/ [, V$ R
// Additional error handling or logging can be added here
- k( _' V* |, ]! O}
$ v# ^; v. }# T3 a& I断言用于在程序中检查特定条件是否满足,如果条件为假,会触发断言失败,并输出相关信息
: m: l5 }8 P+ c( b5 e+ t3、位域反转(Bit Reversal)* m' i, l3 G5 }6 D) K0 }( h
unsigned int reverse_bits(unsignedint num) {( ^% c# h4 G( c# k
unsignedint numOfBits =sizeof(num) *8;+ {* m( v% R7 h! s8 Z0 L2 z }
unsignedint reverseNum =0;
4 @8 b; K/ x/ { for (unsignedint i =0; i numOfBits; i++) {
8 z' V" U0 H: `% j* g9 h if (num & (1 i)) { Z* t1 F. N K* Z+ e6 r
reverseNum |= (1 ((numOfBits -1) - i));6 f0 ?% ^$ I: l, W# w9 T4 ?3 w. z
}
2 D/ }2 ?- W s2 m& p$ V- j7 k# W }) s* [/ s& o9 ^' q3 v- k! P
return reverseNum;
& x" e; \" N- L- x9 Q}
7 F) x7 F* X% `5 t3 u8 F5 I该函数将给定的无符号整数的位进行反转,可以用于某些嵌入式系统中的位级操作需求。
i9 E+ n% h' }3 A4、固定点数运算(Fixed-Poin Arithmetic): Q1 ?& M- C; I
typedef int16_t fixed_t;' p/ |% |, z9 N; }) N5 r
#define FIXED_SHIFT 8
4 `0 X# A, q" s! L#define FLOAT_TO_FIXED(f) ((fixed_t)((f) * (1 + p1 j; h% V6 l2 j7 O' m/ U- a; E+ a
#define FIXED_TO_FLOAT(f) ((float)(f) / (1 : x$ Q: @2 E! Y
fixed_t fixed_multiply(fixed_t a, fixed_t b) {: s6 r4 a5 f; e3 N z& D( S) C2 N0 d
return (fixed_t)(((int32_t)a * (int32_t)b) >> FIXED_SHIFT);
9 v# a/ U0 I7 A. _5 y% y3 J}
; y& r- x( q' |, F( K2 G$ f# J在某些嵌入式系统中,浮点运算会较慢或不被支持。因此,使用固定点数运算可以提供一种有效的浮点数近似解决方案。
6 ~+ p% n! j9 n3 a# ^5、字节序转换(Endianness Conversion)3 w3 A. T, R% k% t% q! u: u
uint16_t swap_bytes(uint16_t value) { return (value >> 8) | (value 8); }用于在大端(Big-Endian)和小端(Little-Endian)字节序之间进行转换的函数。
4 d& @# r: B% E3 ]" q6、位掩码(Bit Masks)
- t4 H) |, g |( ]7 W#define BIT_MASK(bit) (1
' ]. q* F' s( {. r/ i0 U M用于创建一个只有指定位被置位的位掩码,可用于位操作。$ {" z2 Q. z Q
7、计数器计数(Timer Counting)
/ W1 H& y `! a6 C/ B8 D#include
' z/ Y S5 W4 ]+ E+ ?4 zvoid setup_timer() {0 Z& O. R' V t7 \- Z% }
// Configure timer settings: a# c, M- j& f, F8 T1 ?. I
}% g; w) S8 K- _# s* @
uint16_t read_timer() {
+ G1 I! I! z3 b$ C* ^ return TCNT1;
; \1 x. Z( m! n9 q3 E P}, J3 a) D0 s) ^* |5 _# W3 }
在AVR嵌入式系统中,使用计时器(Timer)来实现时间测量和定时任务。
; s+ l! B/ b q6 e% ]8、二进制查找(Binary Search)# m, s- W, f$ X0 s. v6 u
int binary_search(int arr[], int size, int target) {4 i4 m; n: j2 M. b# S P
int left =0, right = size -1;
2 [' L% k/ D6 ^2 F while (left right) {
; n: s% d. S/ `0 ~" ^- Y( Z& @4 O! q9 } int mid = left + (right - left) /2;
6 c7 p% _1 `4 u if (arr[mid] == target) {
; Z: }, ~" p9 `8 E% S% m! H return mid;
8 L8 C6 a1 @" S } elseif (arr[mid] target) {
: H5 f0 T2 l" b7 s( o( C' W+ S* h left = mid +1;2 K; R& s4 F" G H8 \
} else {2 q( b( X' n9 b
right = mid -1;9 g$ n% @( }0 P! Y# _" V
}
0 @: T4 F1 }4 i8 T }* X0 A0 ^% A, k) Q3 b& r5 P
return-1; // Not found
% v2 \. I9 P0 S% r}
5 Q5 U- S- h G5 u* p用于在已排序的数组中执行二进制查找的函数。
: j! x% \9 F% K2 v, f. m% L9、位集合(Bitset)
3 c1 d5 F" I2 f( O8 T! E) J( U1 N#include ' [8 ~' R5 v9 b
typedefstruct {
. M' E9 C7 a6 ]% ] uint32_t bits;( L; | ^5 ^$ L1 b5 A
} Bitset;
1 p h1 q4 V. v7 A" u6 F! tvoid set_bit(Bitset *bitset, int bit) {6 x- f2 A8 f D1 x- M
bitset->bits |= (1U bit);8 j: j8 ^' f4 `! s
}
4 e6 d& `: n& z6 S' mint get_bit(Bitset *bitset, int bit) {
6 T% u8 a v# d/ { return (bitset->bits >> bit) &1U;
5 k- f' e7 S" u; y4 I}
; j2 g( e& \/ K4 p7 U0 b5 @实现简单的位集合数据结构,用于管理一组位的状态。- ?: v/ ^' e# j. y' V5 G: u" [
这些代码示例代表了嵌入式开发中常用的一些利剑级别的C语言工具代码。它们在嵌入式系统开发中具有广泛的应用,有助于优化性能、节省资源并提高代码的可维护性。: n: Z' j8 p1 Z2 L% p6 ^
来源 | 知乎-晓亮Albert6 E0 J0 d0 Y3 u4 t
-END-& D* Z+ n& _1 A
往期推荐:点击图片即可跳转阅读9 G& v! p* P" p8 q( L
phbos4l5rwh64014340709.jpg
/ V9 w: t, s/ J7 I2 k最近在画图,电源稳定性对嵌入式硬件设备来说,实在是太重要了!1 }+ b: `! }1 H9 A. H- C
shb5rn5ppue64014340809.jpg
~4 J R: |/ P嵌入式设备能在LCD屏幕上显示中文,是基于什么原理?
; u% X# \6 T9 K( B3 e( Q' X
5kfpsuosmv164014340909.jpg
# W C( j0 v. d% N5 j
嵌入式软件,代码的可读性与可运行性,哪个更重要?" g, d7 |2 I' O: d, h% J
我是老温,一名热爱学习的嵌入式工程师* d% Q8 P# o% d2 Y6 I' W: T1 N' @
关注我,一起变得更加优秀! |
|