概述: {# j7 M" B6 C( `- z
本篇文章主要介绍如何使用STM32CubeMX对红外波形进行解码,并通过串口打印。
7 y& E4 b- P# i" u# X5 g7 ^/ j
7 Z: W* c0 l. R" h硬件准备
% D/ h0 ^& B# Y5 m, \/ b. L4 M% B首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:/ C0 z7 q( n( S5 z
+ u, {" }& Q& h0 I O. k% K
; o X3 o/ b: _
( Y9 e; a: J% P选择芯片型号5 L- Y. s& w8 G$ X1 `' ?
. M. {: k5 j/ l$ J l" x
- F1 {( r8 g* ^" D6 H, J
6 D, f, V% G: _* l+ f; \% N
配置时钟源+ E: M7 E) n" {& `% o( v# _
HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示: A1 n& p0 x7 v. c' D. E$ D
" J( B6 j7 }6 ~. R
" X# n7 O, R) A( {
( m- C' ?8 [. G% k
配置时钟树
. O4 I+ b0 j6 f- |& s6 uSTM32F0的最高主频到48M,所以配置48即可:, d; [! Q; O8 T5 e8 _
: _ H) l2 S* L+ K. T% Q
) z$ {* u2 j b6 N. D& A, \5 l' ?% y6 ]6 X
串口配置- z8 V( S, e5 }+ ~/ }9 E
本次实验使用的串口1进行串口通信,波特率配置为115200。
& B4 L0 ^% D+ W! ]( k9 e$ f% w8 D0 p* N& ]# g) @$ Q
+ J5 w! t) i- I) v3 Z" W' F) I
; p$ t9 t6 k6 m6 U" a1 L
定时器配置
: U6 h- y5 I9 V: y" M( W本次使用定时器1的通道2进行检测,配置入下。( v3 I+ z: c; b: K) O( b% f
4 K f% y* A% b1 m- }
4 e# a; l" V4 B! l! F; t1 J" M( C+ a# Q3 v0 B0 o
红外接收管
; f% Y6 q8 I( z7 y g7 I这里使用VS838的接收管,如下所示:5 U, `6 \% p: V) y
; z( f/ e; B$ k% _- Y
. B" ^, E; O2 g' P
% H. Q5 Y/ Z+ |8 D红外编码( d1 Y H, y+ J3 |, P( J
NEC协议载波:38khz2 A5 @9 A9 u8 t" ^7 R
其逻辑1与逻辑0的表示如图所示:
( |* R; a& V1 n! h. k( z4 N0 `' y# A Y+ { a- V
# O6 Z9 K( p* x' `# ?4 J# w% U) r- i4 k& P
NEC协议格式:$ g2 f# o% S$ V1 U w
9 F6 f4 N' w! ]/ W1 S
+ z0 U6 @+ u# W0 ?, b8 H; F
6 O R: l7 w1 w) J1 o- T/ w" F4 `2 {# m
自定义红外编码5 j, ~/ N, S6 l+ q7 o
协议如下:, E) o3 b6 F7 R$ M- }: E' W
, z7 Z- V( [" I1 A; v/ i
3 t! W& p: p: {0 N5 W6 G' f3 r/ _. ?. m4 U; m
代码
, A, t9 E$ B- H) N$ Q5 H% G. I3 a在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。" j" ~. |. p4 u) I! v' L) b) I
% r/ I# }% i1 t8 G2 E* ~1 T
- /* USER CODE BEGIN Includes */
# V5 X3 c {$ F- c+ U - #include "stdio.h"
& H6 v- Z' h: X% T - /* USER CODE END Includes */
复制代码
# \* i4 x/ t6 _4 ~红外接收口定义. v% H1 B: v# [; L# h. W
9 T9 E4 t9 @4 U# b. S0 C& d3 \8 F r- /* USER CODE BEGIN PTD */' S) j, Q. i" b. u* j: S, Z1 q1 z" q
- #define IR_IN1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)% v+ u) N! }/ p1 L3 H0 I
- /* USER CODE END PTD */
复制代码 8 T. I5 Q: D5 C
函数声明和串口重定向:
3 F2 j3 ?9 @$ L2 z; x- V
% m1 ^3 z) M, O3 z2 P6 Q/ z k {, R3 T- /* USER CODE BEGIN PFP */5 g9 A; g! f0 z7 k+ e# ^
- #ifdef __GNUC__' }4 m- @0 y* |$ a0 v5 M9 V& u
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)/ H& c7 W" J9 q5 N
- #else
% p# l2 E: [. a3 M/ l6 v: ?4 P5 I3 N5 y" t - #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)5 B* W) Q' x% I
- #endif /* __GNUC__ */1 Z3 n# j; O* j2 v1 y5 E! t7 I
- PUTCHAR_PROTOTYPE' x0 K6 R! A' q& Q/ } p1 w. C
- {
; t+ B' K U* I - HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);) d0 y C) J0 v* l" t- W$ y$ r
- return ch;
# {3 n3 y0 H4 b# A e: b - } V+ n2 a3 B: d7 y
- /* USER CODE END PFP */
复制代码- /* USER CODE BEGIN 0 */
5 t/ c, t4 |7 T9 F - uint32_t OrderData = 0;
7 C' P+ J7 C) a4 Q/ }% w5 a - uint8_t ReadyFlag = 0;
4 s: U; d0 k3 U5 w/ J; J - uint8_t OK = 0;
3 c& ]. n$ s4 X8 | - /* USER CODE END 0 */
复制代码 ) {2 m; G# D r/ |* h: v( G
定时器配置6 w& A. g$ b6 g x: Z) G9 V: p+ R$ @4 c
: W6 s; L8 w/ \
- /* USER CODE BEGIN 2 */7 L2 {1 P1 z5 `6 `' D$ R6 @
- HAL_TIM_Base_Start_IT(&htim1);//启动定时器! p+ a% }9 d' T! t5 u
- HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);//函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断
% {9 w2 W; u( b8 Z+ I# v - printf("IR Capture !! \r\n");
( s7 d5 _" I* \, O% O! r4 ~' t2 Y; w - /* USER CODE END 2 *
复制代码 2 A$ R8 r( _* _1 \
红外接收代码
& ^6 D/ Y$ p) P" C0 q& n3 Q1 Z
H3 S+ ]; I$ o# k$ g) x2 B% I[4400,5000]是用于捕获4.5ms的信号" e; x8 [4 ~6 ]7 Y% _3 i
[550,700]是用于捕获560us的数据0信号+ H# y1 L, W% j u4 F* N9 H
[1100,1250]是用于捕获1120us的数据1信号% ^& K& L% X5 Q5 m
[2000,2500]是用于捕获2240us的截止位信号4 }- Q9 y' ?6 I) I, d9 U
- /* USER CODE BEGIN 4 */
, O3 i! z/ ^4 T6 u2 E - // 捕获中断回调函数,每次捕获到信号就会进入这个回调函数
6 k0 ~! ^5 l ]& X - void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
0 y" y; I9 M8 [/ B8 O* \ B& o: Y3 @ - { x3 `* R3 N! P! m) R8 I; j8 l
- uint32_t fallingCount = 0 ; // 下降沿计数% p+ d* B* y2 p1 I) I4 o
- uint8_t temp = 0 ;
. }* }- K' I; O - // 判断是否是定时器1的外部捕获口2
; e& [3 M; ]! Y4 ?! t! {% w - if(htim->Instance == TIM1)
2 ^! e/ B8 U* x$ W. K1 w - {& {+ {) D* }$ D* z. [* F! \! n" w
- // 捕获到了上升沿
0 w% l( X8 p: f/ K - if(IR_IN1). ^+ d' \& H/ e+ c# ]0 D% ]% X
- {
: L, i; F w( O - __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极性为下降沿捕获6 U) ?0 v R* }4 W: q0 @& y6 Z% ~
- __HAL_TIM_SET_COUNTER(htim, 0); // 计数清零,从头开始计0 |* O* K' m9 a# h
- }$ |' J* C# m+ {6 I8 l2 W f
- else3 ]4 w: t; d; B
- {
3 x4 n3 e+ ?; e o7 O7 q - fallingCount = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2); // 读取捕获计数,这个时间即为上升沿持续的时间3 J$ U2 C4 `' b N# {# \# r* K
- __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极性为上升沿捕获
( D! h$ x. }; T' `2 V - if( ((fallingCount > 4400) && (fallingCount <5000)))
2 Z* S b( v) D! s0 B( X - OK = 1;/// 4.5ms引导电平
, }) w$ i% r5 C% x& d6 K- j! [ - else if (((fallingCount > 550) && (fallingCount < 700))) : T3 j- _6 J. g
- {) A# P4 y! g$ W2 D/ d
- temp = 0;//560 us,数据为0
& @9 p8 u) ?7 W - }
+ c$ }# b! C9 u/ Z& b+ J3 p - else if (((fallingCount > 1100) && (fallingCount < 1250)))
3 m9 P* D- L; s* M1 _0 ?: a; \ - {
4 |5 |8 ~) e P% n - ) H, c% i4 o8 U8 C6 u* V5 h/ |
- temp = 1;//1120 us,数据为1
& A u' y; u* C - }
0 H4 A9 w3 |* ^: }' b - 1 g! n3 e4 I) o4 D& ?8 I
- else if (ReadyFlag==0&& ((fallingCount > 2000) && (fallingCount < 2500))) //2.240ms截止码" W: q( V8 ~6 ]6 P
- {
" {( u. s, C X& V) Y - ReadyFlag = 1 ;7 l+ }+ L Q8 l5 K7 G4 W
- OK = 0;
' q& |7 ?9 c8 T' \ - }9 q p1 P' B' Q7 P/ w. U3 u
- if(OK): ~4 c% k& X/ _' g1 z# Y4 g
- {, m5 N8 N5 P2 w: g) X
- OrderData <<= 1 ;" }. e/ ]' G7 R. y9 B* x
- OrderData += temp ;* f6 u7 P) n3 n1 s3 F( q& @4 m) L
- KeyCount = 0; // 按键次数
8 e3 s7 h4 p e - }% C& I/ T) _" R
- }. {1 T9 ` ^' ]7 q# G5 \$ b
- }
, Q& g; H; ]) m$ D/ k: N" e - }
2 Y" P2 j: j# B6 u - /* USER CODE END 4 */
复制代码
8 E% \' W0 K9 K% ?8 G* \主函数+ S5 g' I& [1 O+ w* l0 E
4 S" g) Z1 i& O, B2 f
- /* USER CODE BEGIN WHILE */1 @4 ?" H% J* E: J
- while (1)
1 X- }! }2 G: V9 u( z2 f2 o - {
" U3 s$ m* @! p! p0 @" @) ] - /* USER CODE END WHILE */
9 `4 E0 u2 @ L3 ^) c+ g: U D
5 O1 p- K5 o8 g; |5 c. a9 t- /* USER CODE BEGIN 3 */
3 [# ?5 s& O Y - if(ReadyFlag)! e. w7 l9 h0 M
- {
/ a& J6 \, h) u; [ - printf("order=%08X , code=%d\r\n",OrderData,OrderData);& ?7 \- c( t: m5 _. p4 Z5 |1 V. D& a
- OrderData = 0;
: h( n) n# A1 X; C& e8 f& G' K - OK = 0;
& p' j1 p0 c' E. D/ i# G' j) j - ReadyFlag = 0; 5 l2 C/ _1 U# D0 W A& }! n0 D
- }
. t5 V: R% g% u% {4 y( U - }
) D) m/ @% y5 S3 S: P I5 C - /* USER CODE END 3 */
复制代码 $ x7 j6 O$ s w# B1 R8 m
! l8 O! T& ?+ [: t$ A结果演示
; Z6 u% P6 y0 _0 `5 }红外连续发送5次码值,发送分别为
2 ?" Q J; E1 n0 ^; p+ i( a
" P) z' b; d0 f, E' Q2 _9 _/ o1011(11), i: G7 n$ K- W8 ^' a
11 1010(58)9 Q& K6 b i# G" M
11 0001(49)7 R) q- B! C' A. j7 M
11 1111(63)4 d* C/ j. g" w* @& ^/ `
11 0011(51)
$ E. d9 _* Z# ?2 D分别如下所示:* F& k; [$ b. y1 k& X
h$ [; t+ n8 F- D" n/ @/ I1 o2 g
! I4 X3 A' B' ^/ Y, g" I
|