|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 Heaven_1 于 2021-6-21 09:33 编辑
1 t1 j O4 V F3 l
" F* C% M) `; t" l' Y4 | WTWEN-ASR ONE 语音识别系列教程(2)— GPIO、ADC、PWM的使用
9 m+ m; c# c3 {. i& Y- j7 n提示:作者使用 TWEN-ASR ONE V1.0开发板进行开发学习。
# R7 ^% e8 m9 J
+ Y8 E) v* o6 P& ^- ~文章目录
: L6 w9 Z7 }# g# p$ o: J
8 j, s) _# d+ ?. ?9 `3 k6 W前言8 o2 W. r: m1 T$ ]
一、TWEN-ASR ONE GPIO读写操作+ s0 A9 P% ?% d" _
1.1 GPIO 使用说明 d# M# l" M9 h8 q4 G# K/ X& R$ D0 G
1.2 GPIO 代码编写1 H/ I8 H0 l% U' n }
1.3 GPIO 代码分析1.4 GPIO 运行测试4 a' w6 S6 S5 ?2 e; {% s- f9 y
1.5 GPIO 使用小结
# M& ?: a5 [& e$ F5 [; s二、TWEN-ASR ONE ADC读取操作
7 l( u8 H5 @6 {9 r0 g2.1 ADC 使用说明( O$ R/ r5 J7 A2 V, C
2.2 ADC 代码编写
2 R k, R+ z' r# E, [6 H0 R2.3 ADC 代码分析. B& |, n) x+ Q5 R5 k2 _# }
2.4 ADC 运行测试
( U- [! l% E4 E$ l8 P; m2.5 ADC 使用小结" P. [+ D/ F9 J7 W
三、TWEN-ASR ONE PWM使用8 d! z, ^- a- Y2 K. p; |
3.1 PWM 使用说明
& Y, J, N4 a& i9 g G/ \3.2 PWM 代码编写1 H; k P! D# X1 N! R
3.3 PWM 代码分析
) u7 L3 [3 a7 Q+ Z- i# K8 s3.4 PWM 运行测试& z4 L9 G) P9 Z) m. ?% N
3.5 PWM 使用小结
0 v! m0 H8 h$ R四、总结
8 Z& D0 C% n+ D+ u+ m. M" n# |前言
' q P! M2 a# m. \- S' ^6 s0 L1 N4 G& K
通过《TWEN-ASR 语音识别系列教程(1)—运行第一个程序》文章,我们学习了如何编写一个TWEN-ASR程序、下载程序、调试程序。从上文可知,TWEN-ASR ONE开发板引脚丰富,引脚主要功能有GPIO、ADC、PWM、 UART、IIC、SPI。本文将介绍TWEN-ASR ONE的GPIO、ADC、PWM使用。 主要内容有:" b+ U- y" @% v @4 h& S: N V8 B
, ^% Y \* }: g5 y# J0 H {9 K6 HTWEN-ASR GPIO读写操作;# w5 ?; O% p% M; g/ p: q
TWEN-ASR ADC获取当前电压值;" d; \+ F2 J- ]5 h6 S
TWEN-ASR 根据ADC的值,使用PWM调节红灯的亮度。
2 P8 C# o, L. c) P$ `4 K8 E8 @一、TWEN-ASR ONE GPIO读写操作
' f# q+ d8 n7 Y0 ?' c" _
& g4 M2 t! S( y8 }' ?( h* k1.1 GPIO 使用说明
0 r9 v: R- y. C" A- b
0 V$ a3 Z8 Q8 n. y2 U9 H 了解GPIO使用前,先了解TWEN-ASR ONE芯片的一些信息,如下图所示芯片引脚信息图。
' o" w& P; m% S) `7 f
' l1 r* S1 o3 a5 h
2 K! C/ o/ v( J" L- q- T图1.1 TWEN-ASR ONE 引脚信息图! l. Z- M4 P2 O; g, n) F2 B- v
TWEN-ASR GPIO可支持27个GPIO口(IO功能复用)、每个GPIO口可配置中断功能、支持两路带滤波功能外部中断。因为IO功能复用,所以GPIO工作前需要选择引脚功能。当然如果使用默认的话,可以不设置。 例如P0_0引脚功能[1]如下图1.2 引脚功能描述图所示:
# ~1 @) P! ~ y( p1 |( B7 C# l9 j3 C3 t- z 1 N3 l9 P2 c y1 m
; @% ?" w' z+ q3 X$ D& J图1.2 引脚功能描述图. r, {" e4 d$ ]. C( F
从上图1.2可以看出,P0_0是芯片的第4引脚,IO口有4mA的驱动能力。默认是输入模式。T+D表示三态下拉。具体的状态定义如下表1.1所示。: ^" [* M. f2 e! U* E5 V
4 a% g6 ?( H% Q, j1 q& w6 d# o表1.1 状态定义表7 W: Q$ c+ B, w6 U- O
( l/ r. l& {7 C5 E7 C7 y
" g. F( G x2 B2 M8 ]6 Y) s0 o1.2 GPIO 代码编写
1 I) v' K# d! t X6 \1 \* K8 S4 O+ ~, J% m
根据前面的分析,如果我们使用P0_0为GPIO的输入输出引脚,需要设定为第一功能引脚。同时根据使用需求,设置为输入或输出模式。
: Z7 m( M. ~0 s: {! b4 x/ i (1)P0_0输出模式测试程序。 实现程序主要是通过P0_0输出高低电平,控制灯的亮灭。电路原理图如下:. _) o* _; W: k$ p' n' {: A
8 ]- i# e7 |( `7 g) p( ~ p
9 |* @4 F1 I1 J图1.3 P0_0外接扩展电路图
1 q' a- k# a" S, B) r其中,高电平红灯灭,低电平红灯亮。 这与官方的板载RGB灯恰好相反。具体代码编写如下:
' Z( i! j. |: d2 |$ y/ x$ X1 l6 H# i8 w0 m* o0 ^
图形代码:# w% A5 G5 f4 b# G1 E, F7 P
( J6 H# g$ \0 B- w* R6 s
( v3 U) \6 v, L) N8 \2 C
图1.4 P0_0输出模式测试程序图
- B$ t# g# w/ [8 W: {字符代码:$ H6 [2 S. c0 p0 z
#include "asr.h"
3 @6 b) Z: i9 }- ~- x+ X* @ S#include "setup.h"% s6 F* ^% f4 m0 l" j7 @- R! s
+ x( H" l4 u: s X2 h6 d/ Z5 _uint32_t snid;! \* v) D$ V) E/ S4 y( A
void ASR_CODE();
: a% n2 o9 s$ b: O$ [; ~' p* i* |" c0 e3 X2 j( \& G6 F2 ^6 @
//{ID:250,keyword:"命令词",ASR:"最大音量",ASRTO:"音量调整到最大"}+ B! o' K* p- \8 K) |
//{ID:251,keyword:"命令词",ASR:"中等音量",ASRTO:"音量调整到中等"}- N: o& Q2 n1 I# ]6 A1 U
//{ID:252,keyword:"命令词",ASR:"最小音量",ASRTO:"音量调整到最小"}
e! G3 ~/ Y7 i) s- l rvoid app(){
X6 z* f4 Y. \: G% c while (1) {
$ t2 Z2 E) m8 L- n digitalWrite(0,1);
2 r* c$ w& G0 O delay(1000);! `/ R2 o0 x; M; l. [0 D5 \4 v& Z
digitalWrite(0,0);
, K& I4 j0 W. k, F6 Z4 U delay(1000);
2 Z% E. c1 i$ [9 A" s, W }- y7 E8 V4 a K N: V* F0 G
vTaskDelete(NULL);
) b" S7 x) U$ u/ c/ ?; ^; i9 g1 k}
8 p* i3 ?/ \4 q3 U% f& c9 S# z/*描述该功能...5 J, D6 y; U1 y+ \- x
*/' ~, F* X3 r7 e: B0 G1 g
void ASR_CODE(){! O' e5 s: T. E, |* F
if((snid) == 4){
2 u, X, Z- E E$ i digitalWrite(13,1);; p/ P, g& {2 x: U% H
}! ~5 n" d% ~0 Q
if((snid) == 6){4 {( \- {: R$ F+ D
digitalWrite(13,0);* J: s; j0 l/ \6 Z0 O
} o' ?4 d( z3 {7 w/ _2 o+ t# `5 R
}! s4 r5 Y4 C9 x8 `/ k8 Q) Q
$ Y, k* D' \+ I; R2 X
void setup()
: R: ?% L" I! f{
6 ]3 n) K& W. d& E- X* S5 w //{speak:小蝶-清新女声,vol:10,speed:10}& c$ ?2 D$ E( ?4 h/ z; g9 @* p
//{playid:10001,voice:欢迎使用智能管家,用智能管家唤醒我。}
, t' C: F+ P4 Z% `; y //{playid:10002,voice:我退下了,用智能管家唤醒我}+ }2 S7 F9 w7 w; Y# M1 V
//{ID:2,keyword:"唤醒词",ASR:"智能管家",ASRTO:"我在"}
6 t9 S" }8 t3 F) G2 Q9 D //{ID:4,keyword:"命令词",ASR:"打开红灯",ASRTO:"好的,马上打开红灯"}
, o d) I$ v" U9 L$ H3 O4 } //{ID:6,keyword:"命令词",ASR:"关闭红灯",ASRTO:"好的,马上关闭红灯"}0 b. [6 {5 I7 O4 i$ t6 h% ^6 f/ b2 N
setPinFun(0,FIRST_FUNCTION);, \0 b D+ K9 n
pinMode(0,output);
7 N6 @( [9 {! h6 y$ z1 X$ M xTaskCreate(app,"app",128,NULL,4,NULL);
0 W' o+ l* M1 i* O0 F2 `1 W ^( t- n% |
, M! R1 R3 `. G4 \: w9 l& @) j}4 ]( l3 b8 T6 e' [ m' i! ^
( C+ O3 Y! s& w4 r
(2)P0_0输入模式。 实现程序主要是按键按下,P0_0获取到高电平;按键松开,P0_0获取到低电平。 电路原理图如下:3 j2 q3 k" [( i, q
* G' Q) r8 ~& e5 R8 H/ y- v
8 o% Q8 N& Y% a1 x N- {$ l
图1.5 P0_0 按键输入接线图
' D1 A: a; {0 `2 g. Y$ p5 v- [$ G也许有人会疑问为什么KEY1 1引脚接3.3V。因为P0_0默认T+D(三态下拉),即默认P0_0悬空的情况下,读取到的是低电平。 所以KEY1 1引脚接3.3V,当按键KEY1按下时,P0_0读取到高电平,松开按键KEY1读取到低电平。& X9 {) {, K% p9 {$ M
: Z5 a: m5 E& z
图形代码:# E% P/ Y8 {7 B- _0 n
# _& X0 H9 }( I* o9 p& {; Q& ]! F4 U/ R
图1.6 P0_0输入模式程序图4 u; \2 O4 n* B8 I, x
字符代码:) R; a; K" e: W3 W
#include "asr.h": \6 K$ ^& G$ X% s0 }# G
#include "setup.h"$ }: \+ k& I/ Y5 z( c
#include "HardwareSerial.h"2 b( d7 u6 e; D9 z u) I
# b9 {" ?% M6 a4 h$ a
uint32_t snid;1 a& E" X0 M, K5 @
void ASR_CODE();) L, m& b! J7 _6 i
% @" m' e' U# N//{ID:250,keyword:"命令词",ASR:"最大音量",ASRTO:"音量调整到最大"}
4 o- O) k& _- Z- v0 l& _2 B( {//{ID:251,keyword:"命令词",ASR:"中等音量",ASRTO:"音量调整到中等"}& n! z" k- }, g. b a: k1 H
//{ID:252,keyword:"命令词",ASR:"最小音量",ASRTO:"音量调整到最小"}
. d9 U( t* ?- R2 U5 I' U! X4 _& a" Kvoid app(){
8 p% g4 l x5 o: {- o) H" U9 { while (1) {$ P, T4 J: J- Q0 f8 @9 r
Serial.println((digitalRead(0)));
+ K% h- P# ]5 E$ R7 P; q- T delay(1000);
4 X% b A1 z% d/ R) j" [& }% y }* x$ W, l" \6 H
vTaskDelete(NULL);
9 ?2 f- z3 y% r2 }" g}& G* n+ ^' [2 i* U+ Y" _' c( Y" _
/*描述该功能...; Z, b0 n, }2 a
*/
# G* A7 j# s# z' I( |, `4 C7 \void ASR_CODE(){9 ^4 n5 C6 `+ X3 S) o
if((snid) == 4){
1 N+ |5 k2 `( v5 X0 |6 f digitalWrite(13,1);
7 X8 ~6 v, P5 v# _' X! L0 o2 D7 ] }
* L. V" v( r3 A* v L- J. P6 O if((snid) == 6){
2 q1 Z$ I9 E* X1 k; b digitalWrite(13,0);4 C" w& _4 {2 }5 H$ D) D
}
( x" {/ P9 n: z& n4 [# t6 K}
# z4 x6 h- d9 z- C8 s: i4 j" k* n3 Z$ Y5 a3 V( D) j
void setup()8 r; f0 b- F4 p' E) k8 [2 k
{% q! C2 t3 l$ f! I& ~) e- p5 W
Serial.begin(9600);
" p! U% [ m9 l- I //{speak:小蝶-清新女声,vol:10,speed:10}( D. z7 I4 s4 q( W( W8 _
//{playid:10001,voice:欢迎使用智能管家,用智能管家唤醒我。}
* p- Y% o. u% [/ L! c //{playid:10002,voice:我退下了,用智能管家唤醒我}
" K; I' g) F% E7 w //{ID:2,keyword:"唤醒词",ASR:"智能管家",ASRTO:"我在"}
9 E. y9 P1 K- G2 N8 ? //{ID:4,keyword:"命令词",ASR:"打开红灯",ASRTO:"好的,马上打开红灯"}
! _. m, W& Q3 A$ z; Y //{ID:6,keyword:"命令词",ASR:"关闭红灯",ASRTO:"好的,马上关闭红灯"}- v+ ^+ r- S8 w
setPinFun(0,FIRST_FUNCTION);' J. C& O. ?, W/ F4 H u
pinMode(0,input);
( h i3 z% T3 G. N1 r xTaskCreate(app,"app",128,NULL,4,NULL);/ J/ T& {9 `; z, s+ g: l
5 ?! Z5 C4 Y* }. L}- x+ L( z% P. d$ J( C$ i+ P% L
- D- M+ c. L' I1.3 GPIO 代码分析# b* V0 ~! R0 m- z% P& p
' A& H; W1 {0 j7 p* e$ h 如果上面的代码含义明白可以跳过【1.3节代码分析】。不太清楚,可以参考下面的代码分析。# J% u6 K3 `" C3 I+ E
5 i) U. B5 Z7 j- P1 E (1)P0_0输出模式测试程序分析。; T) w( f7 Z2 W: A
; }' e: P& ^+ d2 m4 V初始化:6 m: z. D1 j7 _& c2 [
设置引脚功能为第一引脚功能;
. O, ^# X Y( f: ^设置输出模式。
8 f- @9 y. M) K6 D线程中写操作: C# R6 d: {/ O" [
使用写引脚块,可设置为高,低电平。
/ x: H9 H/ F- T7 y# }3 J: K在线程中,重复执行P0_0高电平,低电平。中间延时一秒钟。关键代码注释如下:+ r4 C. ~( m+ ]
. T3 n! I& F' ~) b! A4 C. i" K
( y8 }3 G9 t& l% i% ]% b
, D4 S' `- o9 E
图1.7 P0_0输出模式程序注释图
1 a: ?* y- y7 U }8 Y7 s (2)P0_0输入模式测试程序分析。3 h0 b6 H$ a' K; a$ N P+ b
\; n! T! T4 ^* M
初始化:! E7 @' E8 r+ |
; Q- h" [) {( N* L; D设置串口0波特率为9600;
7 ?) u+ X( P. t$ m: o2 R设置引脚功能为第一引脚功能;
5 l8 q6 S6 x' a0 u设置输入模式。
' ]; }& g& c6 x2 F3 h线程中读操作:$ Q) x9 o7 r3 \
$ G% ?7 C2 D# a. H% Y, o使用读引脚块,读取的内容通过串口打印出来。
: ]1 \; |9 d+ k. T在线程中,每秒钟读取P0_0状态,并通过串口打印出来。关键代码注释如下:. v0 l$ j8 S/ S
( e- r& h' ?) |' C+ G3 g
, J3 k, T/ l* L- C6 G b- M图1.8 P0_0输入模式程序注释图" N1 {9 R- r0 k+ B Y- {
1.4 GPIO 运行测试
& u. g& I+ R+ A& E% m# a6 R0 D! B; {$ U" ?9 Z$ D
(1)P0_0输出模式程序运行测试。 红灯闪烁,红灯每间隔一秒亮或灭。输出高电平红灯灭,输出高电平红灯亮。! b8 i8 z% ^3 w8 q
" ?) ~5 ?, i' v% P: F5 \; V) z* l. t2 P
图1.9 P0_0输出高电平红灯灭3 Q# s: H" J8 q: a& E. x
7 F( L! i8 j9 \% f
6 E" V/ A0 _4 [图1.10 P0_0输出低电平红灯亮
7 q6 _4 O; c/ @6 o( p& G* R (2)P0_0输入模式程序运行测试。 当松开按键读取到低电平,当按键按下时,P0_0读取到高电平。具体测试结果如下图所示。1 ~; d' F+ ]4 Z
' }$ w$ e, _) F1 {7 a3 P
) N/ I7 X l) e U* l
图1.11 P0_0输入模式松开按键6 F; |* f0 X8 z. [- {8 h/ m
4 z* b% t& E) I3 i 6 k* J; Y9 ~& m/ E, |, K
图1.12 P0_0输入模式按下按键& V; m0 A0 f) l- T
1.5 GPIO 使用小结 C4 a, x; v! S; v+ D2 a0 L3 h
0 z; N' M2 V! B, K7 k GPIO的使用,一般需要设置功能引脚,设置输入输出模式,输入模式对应读取引脚状态,输出模式对应输出高或低电平。实际使用设置功能引脚需要查看芯片引脚功能描述。而输入或输出模式则需要根据实际使用情况设置。* n/ m/ {/ X& l% v6 w, X* V
) Q( L) Y, y8 h3 |( b+ d二、TWEN-ASR ONE ADC读取操作& N+ e S& H- h) x( Z
& V1 c. G5 M8 ` ?7 ~5 h3 ^
2.1 ADC 使用说明: r/ B$ {: u6 a" f; y/ L
" N6 p7 @* `5 B+ M- ]: r* d TWEN-ASR ONE ADC拥有4路12bit SAR ADC输入通道。 ADC IO可与数字GPIO进行功能复用。从图1.1 TWEN-ASR ONE 引脚信息图,可知ADC 引脚分别是AIN0~AIN3,对应是P0_0 ~P0_3。因为IO复用特别需要注意功能引脚设置。而ADC是默认的功能。所以使用ADC无需另外设置功能引脚。
/ m7 u U" L0 A8 z. a
" y7 g* A4 e) q1 k2 d8 c$ n2.2 ADC 代码编写) w4 I: H/ `; T8 M6 z
: s1 U' L1 g( o, N% O" g 实现程序主要是读取AIN0数值,并进行电压换算,最后用串口打印电压值。 关于电压的换算,由于TWEN-ASR是12位的ADC,那么读取的范围0 ~(212 - 1),即0 ~ 4095。0对应电压为0V,4095对应3.3V(参考电压)。读取数值和电压是线性关系,换算公式1如下:4 }# t: s ?- S: m) G6 y/ H
; @9 n+ ~! ?" h8 H H( U% _
U = V a l 4095 ∗ 3.3 v U=\frac{Val}{4095}*3.3v
1 S" \) y) ^) cU=
) G7 Y. W y! A4095' M+ v, S0 e$ B$ {4 r5 U i' X, o
Val
8 i7 C0 o4 o4 A7 O/ c1 z" U' Y" K* b
m7 ^: k, h4 `, P# }+ ^ g∗3.3v
1 q. x6 V& z2 C- `( n; M3 ~% _2 [: \
--- 公式1) f* I2 z" r% X, r
! i- q" \3 G. H2 u' B: e
其中, V a l Val Val是读取的ADC值, U U U是换算出来的电压值。测试ADC将会使用滑动电位器, 测试电路原理如下图2.1所示:' v2 ~ b( Z# s. |
" G6 H" j2 j- X+ u. M1 y
+ } m5 |, g0 l1 D" X0 U" a图2.1 ADC测试接线图
! m) b5 ^. R' ?8 T6 X- o6 G8 m其中,P0_0对应AIN0,滑到最左边电压为3.3V,滑到最右边电压为0V。" h8 q# y% N) Y/ }5 n$ d7 g
- q" R0 R4 @' D; ~/ p4 ^图形代码:" V' t! y2 J1 A; ?7 ~$ F! U
. n; L; w# Y4 A4 n7 i& }0 @7 g5 V8 e& f: i) o) F- P/ N4 m5 D6 ?
图2.2 ADC测试程序图
! {2 g( p( d! Z字符代码:, }6 S6 Z$ V" t" J0 B% ~# S
#include "asr.h"
7 [+ N( K: v! |5 a/ T+ j#include "setup.h"
# |8 E# m7 ?+ h- f# Q9 q#include "HardwareSerial.h"4 Y7 S4 ]/ Y5 J% v
7 z5 v0 M: P) ^0 s" xuint32_t snid;
7 L6 P4 H$ u& E$ Kfloat res = 0;
3 |4 h% H4 L4 Q% t; ovoid ASR_CODE();; G/ k, c/ p/ [- I) p
4 f( i; o% }* N& `) M//{ID:250,keyword:"命令词",ASR:"最大音量",ASRTO:"音量调整到最大"}8 a5 I5 [& m9 l' V$ V' D% w
//{ID:251,keyword:"命令词",ASR:"中等音量",ASRTO:"音量调整到中等"}% k1 \- w) y& ]8 @0 U
//{ID:252,keyword:"命令词",ASR:"最小音量",ASRTO:"音量调整到最小"}/ U/ S2 S* f# Q* D; I* M: l9 G6 i
void app(){! P {- |& Y% l0 I* s0 l K$ U
while (1) {
$ K' U& D( s1 D! O* R& O1 _. z Serial.print("U=");
1 g! w9 v1 x. I* U4 { Serial.print(((adc_read(0) / 4096.0) * 3.3));
( O* y9 T& d9 T4 @6 I8 X! A2 C Serial.println("V");/ w" M7 T" U6 ?5 o! t
delay(1000);
3 E. u2 f6 B4 [& t" c: E2 q: A }
: i3 s% w1 L2 v+ Q4 jvTaskDelete(NULL);
$ M {$ o& B8 b1 x}
* I* M' l! e. Z) z: \, X( k* K/*描述该功能...
/ l1 L' h2 E( l1 \# P0 ^" X*/
, g' {' C# P$ `void ASR_CODE(){
# I4 R+ p% s6 _! F! X; P% w8 P switch (snid) {
3 h- v; x) I4 W, F8 O' R5 T0 y case 4:" o6 ?/ v& q. p( G$ ?5 N1 e K
digitalWrite(13,1);
* e# b4 ?7 V3 E' N' L5 L+ Y. h break;( V( a- [$ K( ? w' T* x( G5 ^
case 6:
s5 f- _5 o$ H( B7 ~ digitalWrite(13,0);& c0 w7 Z: |- C7 u. H
break;
; y/ B3 a' Y7 W0 c& o1 t9 Q }
! ^5 p, I* C$ D9 @# G% w}
! ~9 D3 Q" U$ }' ~# ]5 ]3 i: K1 [' f( K/ H1 \% w! ^- d
void setup()" v, d/ u1 g& b: a3 o
{+ R) y7 W- L. ]7 b$ ^- J4 P+ l
Serial.begin(9600);, Y D0 `- x4 @9 b
//{speak:小蝶-清新女声,vol:10,speed:10}" e8 T0 X: @; y" Q7 P' q' t
//{playid:10001,voice:欢迎使用智能管家,用智能管家唤醒我。}' {; y+ s# G: ?" |
//{playid:10002,voice:我退下了,用智能管家唤醒我}( h7 c; ?2 k. u# W9 Q
//{ID:2,keyword:"唤醒词",ASR:"智能管家",ASRTO:"我在"}* ?4 n9 Z: U% y6 i: _* t
//{ID:4,keyword:"命令词",ASR:"打开红灯",ASRTO:"好的,马上打开红灯"}
1 p: j' \+ N, `- z- o/ F //{ID:6,keyword:"命令词",ASR:"关闭红灯",ASRTO:"好的,马上关闭红灯"}
: i1 b; |' w8 i. y4 x G- r) s xTaskCreate(app,"app",128,NULL,4,NULL);4 A1 B9 ]: T4 I% T" X$ j$ |
: w1 h- `6 R' C9 e}( y. H& V4 ]* g; U# i
; }5 B, M! }- i3 P
8 h! u& Y, a6 t+ |- a+ [
2.3 ADC 代码分析$ }! N% `3 j5 }
' ^" g- _" I& G; X
如果上面的代码含义明白可以跳过【2.3 ADC 代码分析】。不太清楚,可以参考下面的代码分析。0 }$ r; c& K! |; w% ~
P0_0引脚默认是ADC功能引脚,所以不需要设置功能引脚。 在线程app里面,"读入ADC值AN0"就是读取AIN0的值,并根据公式1进行电压换算。
9 t+ c! q% h$ }3 z S! a7 [ 7 c x3 m+ a" \
# p, G3 T( L$ f' f3 q$ x
图2.3 ADC测试程序注释图. X. o* B' n2 A, N% k+ U J
2.4 ADC 运行测试4 p9 E) t/ A3 L0 @/ |" C
# _, I: Y3 ?7 t: a9 g
程序下载完后,打开串口监视器。9 G( a" w$ f N1 a3 t# H4 p
. e4 q& H% U* ?2 ]图2.4 万用表与串口打印数据比较(1)图
( y& B# o1 J* I" h9 ]* |由上图可知,串口打印出U=3.3 V,而实际万用表测出来是3.608V,误差有0.308V左右。因为参考电压选用了3.3V,而实际是3.608V。当我再次测量ASR-ONE 3.3V引脚时,实测电压为3.637V。所以修改程序为:
) m/ n1 E( _% Q: Q2 L( h4 [. ~ - J E6 W% B) k9 E9 f" S( |
! g, b9 ]* {3 I3 n图2.5 根据实测3.3V引脚电压,修改程序图
8 X# H7 ?1 A, K' |1 n调节滑动电位器,到最左端。万用表实测电压为3.640V,串口输出为3.63V或3.64V。可见经过修改参考值后,数据与万用表接近。
% x2 F' y4 U: j* [( Y- I
# X8 c# ~3 D7 f: P" h E2 w# z4 ~+ p- N* o& @8 e( q" \/ m
图2.6 万用表与串口打印数据比较(2)图+ }. u: b: W) I. @6 u( h
再次调节滑动电位器。万用表实测电压为2.275V,串口输出为2.27、2.28、2.29V。可见数据与万用表接近。误差还是很小的,在接受范围内。5 V0 U8 g) h. Q% A* x. }
. i. p9 S# j0 o+ \$ F: v
+ y5 h: E* T4 E$ g1 ?5 I
图2.7 万用表与串口打印数据比较(3)图
- _0 h+ t& U: w% o _; ^' K2.5 ADC 使用小结, [2 s' x: h# l5 d; N
* z/ E: E7 Q' f ~% Z' @
ADC 使用不需要设置功能引脚,因为默认就是ADC功能。ADC 引脚分别是AIN0~AIN3,对应是P0_0 ~P0_3。本文使用P0_0进行测试,可见ADC使用,需要对参考电压的修正,才能准确测量出电压值。当然如果使用稳压管的电压作为参考电压,这样就不用修正。或者ASR-ONE是否有内部的基准电压可用。想要用好ASR-ONE的ADC还需要对芯片更多的了解。4 r! W4 B! s, [& B
p" h! p1 t! k K三、TWEN-ASR ONE PWM使用
, R: G+ D7 D/ U' S9 U
2 O9 H% Z3 Y6 M$ S. v& u3.1 PWM 使用说明
9 T! s& S) u/ K7 `0 L
4 e! g$ V+ ^ O/ ] WM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%[2]。# z* H& O/ Q5 v# L+ J4 Y1 l( P2 e
/ Z1 v7 O: \) W
! w9 ]" J) P* M8 |) \& x图3.1 PWM占空比示意图
* u; V+ N$ M) [# ^# N6 F* o. H 在天问Block软件中,有两个PWM相关的块。使用PWM只需要进行PWM初始化,设置占空比、初始值、调整占空比。$ h# e# `" o& j! P
: V' o7 }" G- Z6 o# f6 `" [- z
) D* r' T) ~3 R# x' C
图3.2 天问Block PWM相关块; S( w* z D6 I
3.2 PWM 代码编写# t- L/ A/ R" {3 s% [
& _- J8 Y6 {! r% T. ]8 O
实现程序主要是读取AIN0数值,根据读到的数值,调节板载RGB灯的绿灯的亮度,值越大亮度越大,反之,亮度越小。 RGB灯的电路原理图如下所示:; E. Z$ q4 }! O$ ^& F' q7 z
8 x& n$ }" X' D% j 5 t2 z0 r: G# i. }, R
图3.3 RGB灯电路原理图* D! I$ v- c* L2 d& t3 E
其中,PWM5是控制绿灯。. Q( E) @/ ~' E+ m) E, i
8 v& ], A7 z7 W6 \+ C
图形代码:
3 h; V6 s' m. g
6 {( u0 l1 }& x, Y0 S* \2 l# H+ m图3.4 PWM测试程序图 n! C8 `, h; y" j/ t
字符代码:4 r" Q. {, \- X" x/ R/ w* p0 I
#include "asr.h"
2 B! z, G5 ]1 p! n#include "setup.h"; G6 F; _: ^. D( ~4 C, I
: P4 ?7 M0 z) G" e1 f) P
uint32_t snid;
2 y Q& Z' ~, p8 J7 W4 ^void ASR_CODE();
0 F% I% ~9 G3 ~, L" i( g; }- S3 Q$ i
//{ID:250,keyword:"命令词",ASR:"最大音量",ASRTO:"音量调整到最大"}3 ^/ K; g3 t) c
//{ID:251,keyword:"命令词",ASR:"中等音量",ASRTO:"音量调整到中等"}5 ~% H' i4 k4 K! x
//{ID:252,keyword:"命令词",ASR:"最小音量",ASRTO:"音量调整到最小"}
9 c4 k9 }+ s8 F1 {5 ~6 f) avoid app(){
8 m, J/ X q. h) I4 J while (1) {' Z+ }7 j0 f2 W
pwm_set_duty(PWM5,adc_read(0),0x1000);
' ^/ ?! O+ a: l$ o1 U4 ~, m delay(50); t/ A; Z( s( A& K& W9 M
}& G$ ~* K" \5 ~7 S6 v
vTaskDelete(NULL);
* k( \$ C" s) E* |% G3 u}/ K; ^/ m2 X9 o1 C1 P6 W
/*描述该功能...6 W) K; D/ b7 D6 n& k% B$ I
*/ U6 n8 |9 Z% ^
void ASR_CODE(){8 W4 V# p0 T2 {& P. A6 o
if((snid) == 4){
, u/ T5 e' e# I1 @7 x: x digitalWrite(13,1);
$ Y! ?- f- X2 G: A& I }
3 B9 s3 n. \4 d' J1 r, [ if((snid) == 6){
6 q6 Y7 [+ Z! j t( ` digitalWrite(13,0);
2 v& b, r4 l* [5 p }6 |6 ^. u- k3 Y# X7 I
}% g# i. `( ^) l
0 k% ~0 ]1 ?* V' Y+ r1 Kvoid setup()1 E6 ?* Y* x6 C) a6 F+ g; y H" N* S
{1 T- z( M& N" ]* }- _( A* o, N
//{speak:小蝶-清新女声,vol:10,speed:10}2 t6 C1 r9 r7 k9 W5 |
//{playid:10001,voice:欢迎使用智能管家,用智能管家唤醒我。}( o9 R# [& Q% K7 Z ^% @
//{playid:10002,voice:我退下了,用智能管家唤醒我}
2 H$ E$ y R' u6 L //{ID:2,keyword:"唤醒词",ASR:"智能管家",ASRTO:"我在"}
6 K1 u( G! l, z! {+ f7 R //{ID:4,keyword:"命令词",ASR:"打开红灯",ASRTO:"好的,马上打开红灯"}1 c) J0 X0 \% d! Z8 Q
//{ID:6,keyword:"命令词",ASR:"关闭红灯",ASRTO:"好的,马上关闭红灯"}) c4 r: h! L& j1 V7 D
setPinFun(14,SECOND_FUNCTION);
9 u* J5 W3 y% s/ @/ K PWM_enble(PWM5,1000,0x1000,0x000);4 H$ a9 x: c+ M5 B: ]
pwm_set_duty(PWM5,adc_read(0),0x1000);4 w' X* f' r" w2 E* j) ]; ~
xTaskCreate(app,"app",128,NULL,4,NULL);( P) j- D5 \& f3 V4 b u
: D9 w$ ^. X2 U& H6 J t5 \
}" ^/ s T7 O: F9 s ~' y) D. E
* w6 W7 ~( R, r1 B' w9 y
3.3 PWM 代码分析
# I' `2 p! y+ R. n
& i( s3 w2 |1 A 如果上面的代码含义明白可以跳过【3.3 PWM 代码分析】。不太清楚,可以参考下面的代码分析。
( E! e- l v! [( ~. E% N% ]4 [PWM 频率设置为1000,最大占空比为0x1000。这么设置是因为ADC最大值为0xFFF。
# C. f. Y3 c% t
. |+ |7 L6 }0 y s6 O& k. A4 g: U* }8 F! v# m- ?
图3.5 PWM测试程序注释图
# v. B( n6 B" G S/ n6 n" J1 G3.4 PWM 运行测试
p6 @% `) B" c* H5 p: ~/ u+ j% m
/ ~" z: q: _- `2 W8 |+ K C0 k7 s 调节电位器的大小。AIN0读到值大时,灯会比较亮。如下图所示:; F& ?+ C, S! R3 y$ `
* n W5 `7 r# G4 l
7 |( n" [' R% U图3.6 ADC数值较大时
0 I; R: o. S! y AIN0读到值小时,灯会比较暗。如下图所示:- M- G6 ^# H" g2 S; m
0 q2 M! |( f" h- H" U
' k: e' |0 S: [# i- a' B
2 t& v& Y9 T. [" j0 c; \+ [图3.7 ADC数值较小时
8 H) Q! N$ O* J改变PWM占空比,相当于改变PWM5引脚的电压值,从而达到调节亮度的目的。4 m8 v. h! [7 }4 d/ J; e; k) I
6 l$ J" }* z O. g8 {0 C- E8 M3.5 PWM 使用小结
- F1 f% C, c+ P# m# |: P
" i6 v. q5 `% m" J6 B2 l |9 x/ C 在天问Block软件里面,PWM使用非常便捷,设置频率,设置占空比。PWM块有PWM0~PWM5可以使用。PWM在控制直流电机速度、LED灯亮度等等场合应用比较多,使用ASR-ONE可以快速的实现想要的效果。$ t8 e7 g! o8 d+ o/ n X
0 }9 z& E' c' u8 E- T
四、总结
3 Y* i8 i8 d% [3 J- e
/ d+ `( o3 H8 _' J 本文介绍TWEN-ASR ONE的GPIO、ADC、PWM使用。GPIO使用,设置功能引脚,设置为输入输出模式。ADC使用,需要注意参考电压,12位ADC的数值范围为0~4095。PWM使用,设置频率,占空比。TWEN-ASR-ONE总体来说,不管GPIO、ADC、PWM编程实现非常方便,有很多块可以使用。+ \8 r2 v+ _" X3 K( ~
———————————————— `8 q7 [, v! k1 |/ g3 e% x
/ @/ e4 o# ?9 S5 [$ [
|
|