|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 Heaven_1 于 2021-7-2 17:22 编辑 7 g/ ?1 m Y* J6 E
i" d+ i R) f9 c- c$ r& BTWEN-ASR ONE 语音识别系列教程(4)—多线程与消息队列使用
: l2 D4 B/ \5 a) x- z提示:作者使用 TWEN-ASR ONE V1.0开发板进行开发学习。
2 ` e4 c0 R6 m$ J7 `+ ~; z8 Q0 m6 w6 W4 f! g$ o
文章目录
+ }2 M! `5 c7 ?0 o# J0 A$ h2 y9 U$ U前言# P# u+ J0 Q) P! R, u
一、多线程的使用与测试' e! u& H3 T2 A! W9 O- x/ y# h
1.1线程使用说明
0 n4 f6 ]& P+ F: g1.2线程代码编写3 z; m' B$ S4 Q3 j+ Q5 t3 y
1.3线程代码分析
8 p- F7 y! b2 i$ \1.4线程运行测试4 K$ d# P( O- H+ F8 z4 h* v
二、消息队列的使用与测试! T& \& T( N9 x5 P$ Z4 T1 ]' B& K
2.1消息队列使用说明+ S6 U9 o4 A$ D
2.2消息队列代码编写
9 Y7 X5 E7 w1 @, Y. k4 O, ^8 K& c2.3消息队列代码分析
8 W& v+ m& k+ h# H( R1 P$ G2.4消息队列运行测试# J9 ?6 a& b: e7 ^( q
三、总结# H- Q8 B' D% _0 T5 c
前言" _1 g8 q$ i5 q
经过前面的学习,对ASR程序结构有一定的了解。前面有些代码已经使用了线程,可见线程在ASR程序设计里面的重要性。不禁心里会有些疑问,线程工作原理是什么?多线程谁会先执行?多线程之间是否可以进行信息交换?信息交换是不是队列消息?带着这些问题,在本文尝试找到答案。本文主要内容有:
- ?+ C& r8 g: Z) g) G6 V. B1 w
- p# _' f" n9 H+ E, \$ S! U线程的原理与应用;; v) h" j0 B E+ v
队列消息的原理与应用。
7 S I; P! J- D一、多线程的使用与测试; X: ^. D7 G2 J/ {: N5 H: n
1.1线程使用说明4 k. F4 x9 T+ ^5 T4 i E
线程是独立调度和分派的基本单位,是操作系统能够进行运算调度的最小单位。线程和线程之间互不干扰。把需要执行的任务,放在线程块里面,如下图所示:
! e8 ~% |# d8 \ e, E |: S+ e3 @" l9 [( a9 B. u+ c
* U( c; V4 o7 y: M8 [. F图1.1 新建线程程序块
: E' z# r. a) Z+ X* t/ A线程名称、优先级、占用内存是新建线程时需要设置的。线程名称建议用有含义的字符名称,如该线程执行的功能名称。优先级就是执行线程的起始顺序,在很短的时间里,线程执行的顺序,我们人感受不到,因为操作系统有调度。占用内存可根据程序内容进行设置,建议设置128字节以上。线程里一般是重复执行的程序块,重复的程序块里一般放有延时函数。为了线程执行更顺畅。
( z2 \$ _# w% r: Q* _( {: w 多线程的建立。如下图所示,有两个线程,线程的程序是独立的。# F& ] C5 X) D t, P7 z& I
H4 P. r: o1 ^ n: G4 G# @' L0 n
, {5 p) x2 V+ j/ T图1.2 多线程示意图( _3 m; H' V# {! h, k
多线程的工作原理:线程执行通过系统的调度完成的。系统有一个时间Tick,时间Tick到切换任务,优先级高的先执行,任务不断切换如此重复执行。例如:图1.2任务A和任务B(除了任务A和任务B,其他任务忽略)。任务A开始执行(因为优先级高),时间Tick到,调用任务B,任务B开始执行。时间Tick到,调用任务A,任务A接着刚才执行,时间Tick到,调用任务B,任务B接着刚才执行。如此类推。由于时间Tick很短,人会觉得两个任务同时执行。这就是多线程的工作原理,也是系统调度最简单的过程。任务调度的过程可参考下面两张图[1]。多线程调度(1)(2)。
$ V8 P' G: O9 L: \. ~* _9 Q
0 G( z" _8 v! g' c( c4 @, Z: p3 m3 B4 v& X( c& ^
图1.3 多线程调度(1)示意图
8 G, H0 ]. e4 V5 l( e- J " J; z: w# P; [7 q! k
+ v5 A: z0 O" B6 R: M, M
图1.4 多线程调度(2)示意图
, F, W9 B3 ?6 X9 C: \$ F总之,多线程是独立运行的。可以完成各自的任务。5 Q4 s% h: T1 S' l. ]- X, V/ `
4 ]- q- J& b: m6 w, z4 x+ i1.2线程代码编写
( K3 B- D' U; Z 本文多线程使用程序参考官方【5.多线程使用–LED演示范例】。 程序主要是实现蓝灯和绿灯不同频率闪烁,变化时间分别是700毫秒,300毫秒。, a7 b8 p: ?$ A, M% B' y9 ^
, h) X6 M1 Y. C3 Z9 V- v0 T4 \
: _8 D/ x5 i, X* T
图1.5 多线程使用示例程序2 U; r! n# ]1 [' J' h, J
1.3线程代码分析. W |$ c6 V+ m' m
设置了不同的线程名称,优先级一样,占用内容为128字节。如果优先级设置不一样跟容易理解。: S# N; I3 l$ O3 @, Y8 I
5 d0 a1 l4 q h. f
0 q& s( V$ Q6 U5 {3 V' z
+ P; _3 H0 U Y2 X0 n1 K% q0 t
图1.6 多线程使用示例程序的注释
% d) ]2 W, y$ @3 H8 p, a0 [ `" ~1.4线程运行测试
& `9 |3 i! @7 s) l6 z: [% a 蓝灯和绿灯闪烁的节奏不一样,如下图所示。从实验现象我们可以看出,两个线程的程序都在运行,并且互不干扰。
# [: ?- M) l0 m1 L' t5 w4 b+ ^" k) t, @& D. z2 |! _% R- W
# F6 I/ t4 Q4 t9 `& r4 h, Z3 {) { $ E, Z( u+ W- P; ~/ H
二、消息队列的使用与测试 L% v3 {5 m: p' t4 D) t7 h
2.1消息队列使用说明; |* m- r R+ c5 X
消息队列是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传送信息,实现了任务接收来自其他任务或中断的不固定长度的消息。任务能够从队列里面读取消息,当队列中的消息是空时,挂起读取任务,用户还可以指定挂起的任务时间;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息,消息队列是一种异步的通信方式[2]。
* [' }6 M' E' `. l0 V$ i; Y J TWEN-ASR ONE 可用程序块有4个,如下图所指示。
7 x; M/ i+ I; Z% n# K9 L
0 ]% F& ] d0 ?, C* ~0 u# \! c6 F! s
图2.1 消息列队相关程序块
2 X4 A3 A; w' }9 @' U9 B: J(1)新建队列消息,可以设置消息长度、队列最多消息数。队列最多消息数默认为5,也就是当消息数为5时,不会再存数据。% g. C `) H( [$ |! z
(2)发送消息。发送var变量的值。等待时间是当消息数满,是否继续等待,不等待设为0,需要等待根据实际情况设置时间。
9 @" C: D* E) X' `' ]* B(3)接收消息。接收var变量的值。
5 ^ l/ d: |6 Y1 S" r(4)中断内发送消息。是否在中断中使用?(作者现在也不是很理解,后续弄明白更新此处)# y3 M! k: H7 [( u6 L
5 _% A' [1 B% `0 a) F3 G+ A
2.2消息队列代码编写' X% f- Z! q, m0 m
本文消息队列使用程序参考官方【7.多线程使用–消息队列】。 程序主要是实现语音识别后,通过队列消息相关块,根据不同语音ID发送消息到不同线程,线程通过串口打印出来语音ID。。3 k1 M7 _% G4 Z. Y7 j
. o' ] I# V( F: H" L) o ( a q4 j0 c+ G
图2.2 消息列队示例程序9 r. q1 D# i( J- F9 @9 _
2.3消息队列代码分析
/ S1 f2 G4 a- h6 L$ q 关键注释如下图所示:
! [9 A* `8 T3 y4 P% V5 I
3 Q3 H+ E d) W! n5 h
/ a$ `, z" A" [: i. _0 y图2.3 消息列队示例程序的注释
% U6 N" k$ M/ h! }7 @4 f: \+ v5 J- G! d2.4消息队列运行测试
% Y4 b; t% O) U) s; Z* x% z. G1 f 运行测试结果如下:- M, n2 V4 {. ?& Z1 i! s
# [2 c* {9 X4 Y4 O i我:智能管家
4 D; S& ?. M4 Z/ Q( u/ G& n/ \, ?) s: K/ P+ U
ASR:我在" W- T' |* ?2 ^, w1 k8 c- }9 U* i
" Y! x z7 |/ X- T# \0 O. }4 w我:打开红灯: U. X* o7 T1 j2 O4 I9 H8 c
: b5 @9 u9 W0 D+ UASR:好的,马上打开红灯
( b7 _6 |/ W* `- X$ |* v% r
~! `1 D) i8 |. o4 y
- u& B% Q$ A" V
. z4 U( p! d J图2.4 打开红灯板子实验现象
) ]+ s% {$ Y8 Y2 @此时串口收到4。
: L. _/ t. |& ?) ]# @9 ~ 4 Q, A/ v3 d* J; L3 s
. M8 Q+ Z/ t) h8 {+ z( Q& |
图2.5 串口收到数据现象
. M+ s3 a1 a/ i我:关闭红灯
5 C* z! C( |, R# D5 B3 }( @6 H$ D6 h5 j* F1 A
* t5 S# _6 |! Z- e9 r) c
ASR:好的,马上关闭红灯 \0 M& {: p* \& A4 j0 n. C% G: ^
/ m* B" @( z) r
9 \* A; Z& a+ ^ A, @
2 u) O3 T$ N$ k
图2.6 关闭红灯板子实验现象
( P% g0 E4 G5 }此时串口收到6。如图2.5 串口收到数据现象所示。+ Y4 w! Q6 @3 Z/ o( O" X! ^; R4 Z
从测试的实验现象可以看出,打开红灯和关闭红灯会发送消息队列,通过消息队列,不同线程间可以相互共享数据。" @% L/ ^2 a& a y
8 K& {1 t; ]- n" j8 T' `' d
三、总结! K( t$ J6 ~$ y& n: {
多线程与消息队列在嵌入式操作系统中是很常用的知识。本文简单介绍了多线程与消息队列的使用,在天问Block里面有对应的程序块提供使用,当然我们在弄清楚多线程优先级、消息列队如何共享消息后,可以很好帮助我们的使用。$ U( y* a- q. r' }% k- |6 t8 q
4 ]6 V' P/ K- E1 E
) }$ a6 n5 q$ v k* `! ]9 e" V2 U0 Q6 y: K6 N7 @, [
' V" A6 f, P! w$ ?2 Y
|
|