找回密码
 注册
关于网站域名变更的通知
查看: 999|回复: 1
打印 上一主题 下一主题

TWEN-ASR ONE 语音识别系列教程(2)— GPIO、ADC、PWM的使用

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-6-18 20:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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 [$ [

该用户从未签到

2#
发表于 2021-6-22 18:48 | 只看该作者
GPIO、ADC、PWM的使用
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-10-10 03:42 , Processed in 0.156250 second(s), 24 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表