一、课题
4 W6 X+ h2 Q! `# I1、用 DHT11 温湿度传感器获取温湿度信息,显示到OLED屏上# O o( | h# L6 G" M* P% U" j
2、用 MQ-135 空气质量传感器获取空气质量信息,显示到OLED屏上5 N4 t& \4 w. J4 a5 C
3、设计一个报警系统,可以设置温湿度与空气质量的上限,超过这个值蜂鸣器发出声响报警
: F* p% Z6 F) B" P4 q) L$ i" }& t9 q, D" X ^+ I& c
二、准备材料
' C+ R* a+ F1 B' z* s4 x(一)、主控芯片stm32f103c8t6核心板
) E; t6 S8 B! A' P7 @1 T' z
5 t+ }" W+ h( G5 u5 o7 I# b
* L0 V5 H% z$ `4 i$ E(二)DHT11温湿度传感器
8 n& s) V% K, s9 f+ ~
7 L% v7 X X# d
8 Q2 [8 u+ f2 w+ P( u, e
1 `5 [; o# Q) b
(三)mq135空气质量传感器
7 {3 \5 w5 z- o) @* S) i& ?( A7 V9 Z
9 {# j; q5 R( b* W7 F, D
5 d- `0 S/ y) Q" _* _9 i(四)4针IIC OLED
~7 G7 V( F9 j' t0 B, _$ y U) @7 C3 {# D3 c8 f- }
6 t' p: A2 j" o$ j* x
8 {* `5 [ q% l三、原理图与PCB设计
' X. `' Q0 ~0 U! ^8 z* d" c3 ?/ p(一)原理图设计
! |' F! w2 B1 `" {& W/ S% }/ h: |- c, }- @1 _
+ E9 b' i+ @* E5 I
8 U$ z- }6 k( y0 r9 H(二)PCB设计
0 \; |) e( n. E9 K) C Y0 Q, H. X0 i4 f8 c+ B/ u9 H1 z
! }7 ]% ^8 i1 Z1 i8 C
* `+ b$ j: |+ }" w7 H6 h四、程序设计
7 A. r: f2 ]: P" a9 \(一)DHT11驱动
$ Y: G" Y% g: v* C: @DHT11.c
0 r8 |+ u7 z3 F4 r4 ~
/ k3 Q$ k- e& e, X- #include "DHT11.h") g+ l4 `4 x/ U8 h2 r
- #include "delay.h"8 H, ~1 Z+ A8 ]: E+ ?/ R
- 8 a, S1 Q L7 J( G( C
& |" [' P3 y1 S p- + h# j* ~6 Z0 S4 ^7 ^
- //???DHT11: z7 Q+ S r* G0 h3 A$ x2 y `1 `
- //??:??????(????)0 u) A+ E1 Q& R. Z
- u8 DHT11_Init()6 D' ? D/ Q$ R! l. J
- {& G* x0 y; ~$ `
- GPIO_InitTypeDef GPIO_InitStruce;
' c# C h1 l- V" Q3 H- U - RCC_APB2PeriphClockCmd(DHT11_DQ_RCC,ENABLE); //????PA0
; U; q( x* r) | N -
: |7 J* G, x: l/ B7 D - GPIO_InitStruce.GPIO_Pin = DHT11_DQ_PIN;
$ ~" l$ b& T$ ~% S6 @6 p m) ? - GPIO_InitStruce.GPIO_Mode = GPIO_Mode_Out_PP;3 J) H" L0 ?% Y+ ]" B3 ^
- GPIO_InitStruce.GPIO_Speed = GPIO_Speed_50MHz;. Z0 ^% C/ ~: ?7 }2 X- q
- GPIO_Init(DHT11_DQ_PORT,&GPIO_InitStruce);
( w3 c& {) h1 s W5 v
7 s( z* T4 O# u2 n! l1 N. F& G- DHT11_Rst();. j# b( v G6 }% N$ ^! r: _3 l
- 0 R) c. i. u& _. r1 D
- return DHT11_Check();
( N+ c8 f L& m, s6 @ - }: J; w$ m+ E9 K1 [
- G2 [" C- S" f. {- 7 |1 I5 R- @; y) T( }# I4 Z ? T, W
8 u: u. ?- ^' J' ?5 F9 ~' h
+ y. C8 N4 o( ?* M- //??DHT11/ O0 v2 N& w; y q, V
- void DHT11_Rst(void)
, t' `/ h1 U9 V$ y2 _. }# X6 l - {
; x4 X* N3 O6 B6 I; L - DHT11_IO_OUT(); //SET OUTPUT6 b# @+ w) \1 C0 v! n# l* Y7 b. q
- DHT11_DQ_OUT=0; //??DQ. I& S5 i- n6 d3 r2 \
- delay_ms(20); //????18ms
, f( m. M K! ] - DHT11_DQ_OUT=1; //DQ=1 $ u: C8 q" k0 t K
- delay_us(30); //????20~40us3 `! n" N# Y. ^- O% m. O# B
- }
- r# O1 n3 A) B. g6 ~7 {: ^ - + A% p7 K1 b. V$ A8 b
2 ` r( t/ ~' A& Z. _ G- : h! I1 C+ f4 p( f
- //??DHT11???
! g; [. s! O$ |' u2 V8 J u# A9 w - //??1:????DHT11???
9 m# d7 d1 j. _& e - //??0:??! y. a+ D. I! b- O. b- w6 H
- u8 DHT11_Check(void)
3 a: T" ]) m; t+ _ - {
! F1 i% b6 O. k! W6 g+ g/ P% H - u8 retry=0;
$ Y% J4 }+ k8 ` - DHT11_IO_IN();//SET INPUT
+ E- S n) g1 J* E- [' ], y - while (DHT11_DQ_IN&&retry<100)//DHT11???40~80us8 D# w7 B h }6 Z8 L% {) a( D
- {
3 q! t% N& G4 p. ^+ l8 x4 f( P - retry++; ' n* b% W5 ?1 Z
- delay_us(1);
% j* ~# c0 O( S' m - }; # b7 o) t" i- n9 f4 l' w- k
- if(retry>=100)return 1;) o& l. q& \; O8 U; W
- else retry=0; A, S0 S& E# t! _! v2 N! d" }+ D
- while (!DHT11_DQ_IN&&retry<100)//DHT11????????40~80us6 W. S. b& A0 B8 [
- {( I9 X# i& ]! l9 u2 N/ {. e3 R- r
- retry++; " z, c/ r$ `' r+ Z
- delay_us(1);
5 `3 b8 x9 z) m9 c - };) g, s6 T: W; D5 }
- if(retry>=100)return 1;
3 d1 G" p2 t1 n: m) l - return 0;: I( E( H6 m' e5 Y! K+ G
- }' u3 l4 K7 W% O3 T
% {+ o& z& O1 S1 N1 \
, V% I& Z' l+ Q7 k- u- //?DHT11?????
( O ~0 g b% Y- w7 e% u% d - //???:1/0
! C+ j, _$ B, w2 C - u8 DHT11_Read_Bit(void) 4 t/ H: N0 |3 L8 P; M
- {2 a; S2 b$ i( T) I
- u8 retry=0;
5 U4 a0 v$ m7 q5 J; m4 g* N - while(DHT11_DQ_IN&&retry<100)//???????1 Q$ [- u( q7 h; d; S! _8 f
- {% l3 O$ J, ]- `
- retry++;
/ k; r$ Y9 `6 ~& N3 e - delay_us(1);( Q! ?9 A/ N+ Q4 x1 p( P
- }
. `$ f6 F5 `6 i0 ]/ l7 X+ Q9 x& l - retry=0;
5 Y, S, I3 E% Q+ k - while(!DHT11_DQ_IN&&retry<100)//??????8 l7 ^, u! C6 @
- {
2 ]; O+ N& ^! a3 M8 C3 d) Y - retry++;
! L8 T" q% f1 c - delay_us(1);. C2 ~4 X( A4 H' g1 l \4 C
- }9 b3 x9 U: I' ?, v; |
- delay_us(40);//??40us7 z0 G+ T2 d/ |7 x( G& Z
- if(DHT11_DQ_IN)) Y0 s5 _' o7 L$ b# A& j7 O. g
- return 1;
( M5 R3 P1 ^' @2 u& [% x) }: T - else 3 I I# x& M3 u. d" ^- C' S$ s
- return 0;
8 B& C1 x7 G* E. J; t - }$ H/ r7 W0 S2 a
/ I% l3 A/ b1 M9 P6 D2 \
* c! J# A: K+ z4 R! u% M6 q
# `- p8 t2 n* g6 n& x' g; s# [6 J- //?DHT11??????; q! I) v! U% [, n
- //???:?????( ^& [6 W# E$ f0 w5 g# ~
- u8 DHT11_Read_Byte(void)
0 Q1 ^# B3 h; p, Z - { + e3 y" @0 `& o# x h2 j
- u8 i,dat;
" _: s I @5 A+ ` - dat=0;; D3 g# e# F% M$ s, ]" @8 |
- for (i=0;i<8;i++)
8 c: {+ [" ~- }, N v$ j% l& d" S - {
, q [1 E/ y+ l1 }8 U - dat<<=1;
; h# o2 r% L# u( u - dat|=DHT11_Read_Bit();
- |3 c+ P a3 c7 s) G* F9 y - } / R, j# n- G& k; k# j" D
- return dat;
' l4 b- Z/ d( o3 j - }
% s' H; _/ B# M$ j: U l - 5 u! f/ z) x! Y; K& T4 I
6 I8 Q/ k9 r" }8 D- * `$ ?5 g$ ?. g- M. Y+ {% b: W" C
- //?DHT11??????
4 S5 r: g" H4 |, m* G- ]9 K) T. L' L- \ - //temp:???(??:0~50? humi:???(??:20%~90%)
( a, A) q3 i. _9 n% V - //???:0,??;1,????* O+ S9 z# F) O% Z' E$ D
- u8 DHT11_Read_Data(u8 *temp,u8 *humi)
$ e/ L b( H. A; d1 { - {
5 N0 |9 `- U+ ^; I - u8 buf[5];/ H0 O6 g- }; N- B7 s
- u8 i;
: L" e; M. D- ~6 [, U- H+ o - DHT11_Rst();; ^+ x! \; i2 r8 K, {
- if(DHT11_Check()==0)
; m; E9 G% Y$ l8 x - {; n1 h1 ?2 @( h3 f
- for(i=0;i<5;i++)//??40???4 w% j- S, M6 ?' i
- {
( @. K0 f- J! e& i2 m* u* X8 z - buf<i>=DHT11_Read_Byte();
4 A3 o" X: H, v; f, ^ - }* B$ P2 ~" O. E( p# ]
- if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
+ G' Z$ _+ G, C( \% F - {, |; C& ~4 `' j+ n4 A
- *humi=buf[0];
3 j# q$ C$ w: Z% l' b - *temp=buf[2];, U# L% F6 j- _' K# Z
- }, {0 { ]6 M$ y( O) y0 k6 G4 f" C$ Y
- }else return 1;
7 G: M" c9 f& @# M5 Q - return 0;
- u! f7 \; |' \' M. |9 B" N9 I - }
1 a# W+ e$ b) ]9 h1 ` - </i>
复制代码
; k6 ]; q9 {" o) Q" ZDHT11.h u# j2 n% j& w. n8 h+ {- x
. F( W3 ^9 m4 W: t3 j- #ifndef __DHT11_H
; p& o& I' }9 B/ b# l U$ O - #define __DHT11_H
% @; r2 b9 i2 Q" |: [) [4 ? - #include "sys.h"
$ M, p6 x1 j/ @' n+ W) D' z
/ o0 q; @6 l/ d" K2 [" N- #define DHT11_IO_IN() {GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRL|=8<<20;}0 }2 {6 {9 i! O+ o
- #define DHT11_IO_OUT() {GPIOA->CRL&=0XFF0FFFFF;GPIOA->CRL|=3<<20;}
; `% n o$ r' w6 ^- p; a; p: h2 U
Z0 o/ F. \: X* t- 4 w- o, n& {+ n5 x7 Y
- #define DHT11_DQ_OUT PAout(5)
& p5 q, d, j+ e" y( A( L+ f" @ - #define DHT11_DQ_IN PAin(5) ! b( q! m) A0 S, `0 h2 I* W
- 6 p: M5 g. ]7 b
- #define DHT11_DQ_RCC RCC_APB2Periph_GPIOA
5 V; ~$ v# P3 u2 j- }0 i - #define DHT11_DQ_PIN GPIO_Pin_5
. t4 y% d5 W- C, }, N - #define DHT11_DQ_PORT GPIOA) F, e" {! L# I6 o0 g3 l
9 z9 g! A3 {2 r" e+ w- l! }- u8 DHT11_Init(void);7 o! `0 i k) C% O0 M- v6 C
- u8 DHT11_Read_Data(u8 *temp,u8 *humi);* d* T. V6 M& S* _1 x1 {9 s
- u8 DHT11_Read_Byte(void);; m% U! s! c7 H. M( d- w3 h
- u8 DHT11_Read_Bit(void);
, T. t- j- w( M% |8 T, B - void DHT11_Rst(void);
' ?1 g! T4 ~$ t. X" B/ ^) s/ I* S5 z - u8 DHT11_Check(void);
' [5 P* U( s" A - 6 { N: u3 T$ M
- #endif
复制代码 3 o" h9 ~0 p0 E# e3 {$ \8 |
(二)MQ-135驱动,由于用的是ADC,直接上ADC代码
# n, Q O: U9 z1 T* A ?6 V2 w" R9 Q& _( {
- #include "adc.h"
J6 M: C" f4 U - #include "delay.h"
* J1 [* x2 T$ t$ I8 j -
7 ^. V3 q' ~; ~: z1 m - //初始化ADC
8 n2 E6 j# R$ O- ]$ c8 H, w - //这里我们仅以规则通道为例
& H; D; t9 t9 D+ ~! B* V# M - //我们默认将开启通道0~3
4 H2 m9 O1 D5 x) z7 ]. [/ ]8 | - void Adc_Init(void)' d8 {$ R7 d: \+ s7 [
- {
/ u V; d& _4 O9 P - ADC_InitTypeDef ADC_InitStructure; L$ r( @/ Z5 j. Z- P1 K" @( P2 u
- GPIO_InitTypeDef GPIO_InitStructure;
2 i5 I( j/ V1 a# P9 f' [3 S
2 d7 y# q' ]$ d, X- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟" r' E( p, f7 I" H! U1 H
- 4 D7 T6 R8 F! W7 n
- 8 U* l: }# I9 `5 p
- RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
- q! F6 e( [; y - : Z! [' ~; {. Z* o
- //PA1 作为模拟通道输入引脚
9 @" {: {4 G1 Z - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;2 G* ~+ _* ?" I& `$ L
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
f. C* ?! M( B/ K' G, i1 H2 h& g p - GPIO_Init(GPIOA, &GPIO_InitStructure); ) ^2 K1 F$ f, h- l
- ) N# n% T( l1 c0 Q I: ^
- ADC_DeInit(ADC1); //复位ADC1
5 c) w* S1 S: N - 3 y( G; A! P" }/ g
- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
( F( \0 N5 A9 l6 W - ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式+ [ a) K+ M, R+ d
- ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
1 ]5 P U9 R$ r; l1 u8 N9 C - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
/ T; _# ? `& _( ^$ g - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐5 C5 N, x3 s& V8 u" X8 u& W
- ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
* }* i `4 t8 Z; ~6 T) N% R - ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 , T. y$ [& Z: O/ v/ C1 d
- # z" N1 J& F9 M1 I) {
$ X! C: [* n; w: q, \! C* @- f L% X$ P- ADC_Cmd(ADC1, ENABLE); //使能指定的ADC12 I( n3 B8 I* q' J6 U
-
2 B% h- d# U( O' T - ADC_ResetCalibration(ADC1); //使能复位校准
- W5 B8 W* x7 D% y - 6 I0 u+ c! ?! F8 y' c' l
- while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
! v) t) {, u7 O- s8 r0 R -
, ~0 e) r& ^$ k5 H1 [ - ADC_StartCalibration(ADC1); //开启AD校准! F0 K. D% `4 l: T& Y& G
- ( D+ ]3 d: I* y& S8 B# b
- while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
$ J# F4 L; G* t, v$ B8 h! N1 \% S) ~ - ; u% ?5 j f8 u# P8 L
- // ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能4 @9 T+ J7 ^4 k) }$ h- _
- 9 a' h. W5 Z4 C0 m E
- } & `7 U& m0 w7 Y6 Z& W% u5 S
- //获得ADC值/ v6 H i) p; K1 e4 b) S6 T/ ]
- //ch:通道值 0~3
, K1 N8 M4 G$ d$ G8 B! C. i, {: X1 m - u16 Get_Adc(u8 ch)
+ o( \1 O1 h! y: t5 n' w# n' C0 A, z1 o+ F - {
6 n7 G' ?, d" d# j2 j8 B/ z - //设置指定ADC的规则组通道,一个序列,采样时间- A# g8 \! P) c0 N, H
- ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
, ^- r# j( B# B - 8 i/ s3 Z3 l' b. z1 a/ J) H( U
- ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 $ L9 L, E; j% |
-
R3 Q' l% b4 ~- v P6 e! D6 c q - while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
6 z7 ?3 y" w8 ]- q - 4 U! A' K" U' A1 T& S2 d6 F, g
- return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果# u D5 T/ Y( C! H
- }
) X6 a% m& W! o; ^ - 9 k$ W7 {6 K8 [( {8 d6 E3 y$ x. {
- u16 Get_Adc_Average(u8 ch,u8 times)6 A- U! K% c* k$ R: ^* I4 n- [8 s
- {/ Z1 b" R, r& ]- \; V
- u32 temp_val=0;
$ d# @7 x& V7 Z - u8 t;1 }* a! ?, q+ A5 a5 s
- for(t=0;t<times;t++)
" R( ?% ~, ?& {+ v - {# t) ]# h5 k7 H; o; p/ d
- temp_val+=Get_Adc(ch);
$ b+ `7 U. p, v, f" ^1 U( ? - delay_ms(5);
* n" E v9 |4 `: G4 d/ }/ O6 h - }
. G2 A5 N1 {; t% G; G - return temp_val/times;* f# Q1 I# \ J) W. [
- }
0 w' G( l& g# q: B
复制代码
4 \1 y2 d8 \/ h(三)主程序
) F; C( g# n9 L# J# N \$ l) S/ Y; Z
R6 L+ b B0 E( C" Mmain.c部分代码
% O1 u: e$ p) i: w% X) ~- B w w1 V9 C+ z' _, F. _+ H. o: M. C1 a
- int main(void)
4 u/ e" X* N- b/ v - { ' d2 O9 B( H& g( ]/ m
- u16 key;
5 f' ^! K; q" `( H* B4 e7 n* e - int adc,cnt=0;7 ]9 K2 |: M: v3 [ r& \
- float volt;+ ^! Z' W! h2 i0 W' `
- delay_init(); " w% }: I0 k2 h* R+ O; p% m3 H
- NVIC_Configuration(); 2 r5 e5 Q: l3 m! W
- BEEP_Init();4 m- M1 _- v9 v
- OLED_Init();
2 ?! U* I$ G+ `; ^8 l/ F& H5 r - OLED_Clear();+ [1 D3 m' ?# i# @$ c% y! v
- uart_init(115200);4 y4 V5 @2 h: l( k: e% t
- printf("欢迎使用化作尘健康小工具\r\n");8 `+ N% f1 [* \5 K9 ^9 r
- KEY_Init();' H1 y( Z3 ]" B# H# X& i
- LED_Init();) o w5 r1 h. \. Z8 | G% S2 z
- TIM3_Int_Init(500-1,720-1);
: ]) B* s' z2 S, R: Y# @ -
9 |' }! w4 _% ? - DEV_Init();
. Y$ _0 I# d0 f! l, H - * q o; A" L0 Y& z( H' g5 @# D V
- 2 \4 t$ k/ i1 m- Y
- OLED_Clear();
3 v* [$ ]: d, r* R$ v* J - OLED_Dis_Menu();
- F/ v2 i h, _, E* x/ P6 Z - while(1) 1 _9 y/ _0 y: e) b( p
- { ) X2 t6 Y# M7 M
- if(cnt++ ==1000)
; s$ s K: Y/ R" V - {
( X2 i) W( K F+ V; _ u& U' C - cnt = 0;
7 r3 d! r, U7 m" J2 \& w - LED0=!LED0;
! m' O( F4 ^# Z7 M3 _8 }$ }7 o - adc = Get_Adc_Average(0,5);
7 \0 v4 z. w# o - volt = adc*3.3/4096;
B) ~. A4 o/ t - air = pow((3.4880*10*volt)/(5-volt),(1.0/0.3203));
* x- h5 `& ]3 l9 Q" k) S% w9 k+ l - printf("air :%d\r\n",air);. M* z( z [8 q% w0 _
- //获取温湿度
& h2 _5 g2 K7 r# q$ u - DHT11_Read_Data( &temp, &humi);
' @& u8 H% P/ V1 ^. d5 C& x - if(last_temp!=temp || last_humi!=humi)( E+ m$ w: k2 o; w* _
- {
" m3 U& @( h2 B9 F! M - OLED_Dis_DHT(temp,humi,air);; W: p- ~. e/ `
- }$ E9 p/ z' g3 g1 t; ~* O
- }
* D# L! k& _+ H0 J4 X - key = Key_GetValue(); //按键扫描
% [! W2 T U2 O' I - if(key)# d/ i* }+ r4 { p6 r* h0 T+ N
- DealKeyVal(key);: J3 c- n. z# r$ ~( p
- if(!KEY1_IO())3 h* z" `+ l: u" x, H" J
- {( K" W1 ?5 s4 o; e8 y
- printf("%d\r\n",GetTime());7 S" l6 v& z* Y i1 g
- }
$ R* v/ G: i3 P% B7 } - if(temp>Max_temp || humi>Max_humi || air>Max_air)
0 n) \8 W% ] D) ~# E - {
G5 ?1 r. g! d# p$ o% m& q - if(cnt<500)BEEP=1;; _1 P7 F2 J, Q" ~1 K$ n
- else if(cnt<1000)BEEP=0;: R+ R2 q& V! F7 K8 P3 g
- }else BEEP=0;
% l& d; {* r& S( J% F+ y2 u; L - 8 k8 ~ q, w4 o6 f S6 K' w! K
-
2 V# c B7 T7 o: O% i8 [ - delay_ms(1);4 |, R s6 L/ T d
- } ) A, p1 K; g8 t7 k# U
-
% C& h! q: o7 o |: g7 }. j - }
复制代码 3 }1 k0 X$ r+ s& h7 x
$ }, j. N( z$ d, [2 J
# q+ u! y9 F5 i3 m" O% H
7 i7 X+ j$ W$ ?* J; J E- `% f9 q: h7 _0 _5 ?
|