概述
" M' t! _+ {! f( A9 b! u本篇文章主要介绍如何使用STM32CubeMX对红外波形进行解码,并通过串口打印。. @! Z; \1 l4 f) d0 H* a0 F
" e! Y; k- }9 x3 l& l+ c' z硬件准备
" i7 u- h6 j7 i3 {6 g3 G: l首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:( i6 l, B" @! i$ a$ H
, R5 t j8 r A' Q% c4 H9 j
' ?0 G' d1 C; _ i$ I
0 V( K6 M v4 G- `7 G选择芯片型号4 V) B& h* S; Y6 N. \
& u, I) S5 t `7 `7 ~
' n2 Y) d. p3 r" Q" n9 B3 h
, ?2 n5 c( h. s( P, t
配置时钟源, {$ ~7 Z) \; V5 H: s% e7 X
HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:! f" \0 o6 G/ a" G4 q' n% A
" G* t( P2 ]; ^# Y5 N
0 R6 _( K! u' z6 Z* j3 t3 A+ I! j* L$ i1 ]! e9 Y) p
配置时钟树
n7 y. R& G4 p9 t4 l. R9 hSTM32F0的最高主频到48M,所以配置48即可:' Z G, m! b7 P4 }+ b, H2 H# o
7 d# [" m9 Y+ m/ ?# N
$ ~6 C* G5 G- I* e3 s
* M' i( Q4 S9 d3 u. Z7 i3 y# n
串口配置$ D& |0 `7 c+ V% u# c
本次实验使用的串口1进行串口通信,波特率配置为115200。
a8 L K2 o" E4 m6 w
3 {/ u7 g, r$ D& a8 K0 j+ A) U6 t
7 @$ I" ^& O0 Q+ D9 O% L
& I; l, R7 O- m9 i" |! F( j8 E7 l定时器配置
) C9 j: }. c4 g本次使用定时器1的通道2进行检测,配置入下。4 U7 E; c# Q9 Q9 |# f
* a, t8 y& J, z3 `
+ t: P. |' |% f) `3 a, _6 M( ^+ j: L$ o* q& E
红外接收管: E: d3 R; S/ p0 q
这里使用VS838的接收管,如下所示:, d3 Q, \& X. b2 L& x8 e0 h
$ O2 L0 z6 q! e% c u4 G3 `5 O" x
! D6 j& _- o" s! i% A# a9 e6 q9 w% X
红外编码
1 D' V; x: l# F& N1 aNEC协议载波:38khz
9 @8 U8 J F" h/ {, V& ^" v/ R其逻辑1与逻辑0的表示如图所示:
- O1 H' q9 T1 n: n. h" A* K. C8 r, d5 L
6 e R# y. Y7 x+ {2 D$ Z/ t9 D
0 e6 g8 }2 ?1 g: {+ d" iNEC协议格式:
( H b3 u- q& ~% W4 t2 G9 D" j+ c" K; f: Y# w# L
6 q9 [ l: w, }' i
3 Y" b/ `5 U4 D自定义红外编码
! Q9 \: C) n3 i7 K# w! d6 d8 B1 A协议如下:
( `/ g7 E( y, `
0 t$ n' N% ]7 ?
1 d* U& {; A: P2 i6 {2 h
1 d/ A( W0 P6 j1 c1 D6 u( {6 d代码; M4 {9 x3 ]8 s" u
在main.c中,添加头文件,若不添加会出现 identifier “FILE” is undefined报错。
0 J3 b l9 M; s+ b9 r4 M) |7 J+ Y' d0 b1 r( \# i
- /* USER CODE BEGIN Includes */7 e% A- q2 i# @6 a
- #include "stdio.h"
9 U5 @5 p {6 l: |- d - /* USER CODE END Includes */
复制代码
0 ` a9 K& v) u3 I H2 D红外接收口定义) r3 O" Q) K5 X+ S& P" |
( I* U* o% s5 k- P9 H/ I5 B1 ?- /* USER CODE BEGIN PTD */) s( k5 Z' N2 e( }& y. d- I
- #define IR_IN1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)
6 G9 j9 g) r5 X - /* USER CODE END PTD */
复制代码 3 \3 r' j, \* H
函数声明和串口重定向:
! q! b# Z) Z: s% E( {
7 t$ [$ h' v7 D# Q1 n0 [: [+ H$ {) ^- /* USER CODE BEGIN PFP */
* U j5 h1 N5 L- D0 j - #ifdef __GNUC__9 s1 G) A' ~) ^) ~ r2 m
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)- Y/ D* [; E+ d5 K
- #else
3 W% n& w. a0 L% P5 `, k( M l - #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)" Y2 f9 e1 c4 N' F M* {
- #endif /* __GNUC__ */
+ L$ }6 y& ~& _: Y7 S4 i' f - PUTCHAR_PROTOTYPE
2 z- z- x" ~% Q; B$ @ - {, x* o, s7 x# W5 {- b
- HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
& T' |, V. y. }6 ~3 V6 w( [ - return ch;0 x" j* K& `& ^0 m; P! S5 c; C4 X
- }
. `9 n' s2 o( S% y5 y' l4 B, S' ? - /* USER CODE END PFP */
复制代码- /* USER CODE BEGIN 0 */% o& m" ]0 Z% Y: k1 L' y
- uint32_t OrderData = 0;; b/ @6 P8 L; ^& s4 a! V% J
- uint8_t ReadyFlag = 0;9 m( H2 L* ?* V* Q" t# I
- uint8_t OK = 0;
7 i5 ?! T, g# u/ y& ^3 i k3 G4 Q - /* USER CODE END 0 */
复制代码 # d1 K. \5 ^* p; W9 ?
定时器配置9 y I2 y2 L* j2 B- h7 O( R
+ |; w2 B+ e/ o S e. R- /* USER CODE BEGIN 2 */% e0 }( G; p4 u& Q
- HAL_TIM_Base_Start_IT(&htim1);//启动定时器: N/ }. F- N7 R! G; J6 u9 {: y+ r
- HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);//函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断
$ l! a; Q" D( c/ L - printf("IR Capture !! \r\n");
* H" B' Y/ W- z9 o* Q - /* USER CODE END 2 *
复制代码 & {3 _' v9 v. V# ~# n% w
红外接收代码
3 V9 F# F& h9 {& ^2 o7 ~: @! `
( J' V0 d- T6 Y: Q2 K* h[4400,5000]是用于捕获4.5ms的信号* f: ]+ Q% C8 r, S% v
[550,700]是用于捕获560us的数据0信号
$ y7 r: o6 S* m' S[1100,1250]是用于捕获1120us的数据1信号
# C, w" [5 |% v- ?. Q[2000,2500]是用于捕获2240us的截止位信号
# R# j7 ^1 X7 y1 W$ V8 B4 L7 G/* USER CODE BEGIN 4 */
6 N/ M- B! t% k// 捕获中断回调函数,每次捕获到信号就会进入这个回调函数
+ E; |' S8 H8 e5 a# V( x; g5 P- ]- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
. E, R8 a- {! w2 ]! g* X) v) q - {8 {: q6 k5 S c L, u) {
- uint32_t fallingCount = 0 ; // 下降沿计数1 l7 d& ^8 x+ `1 g# C, a" `
- uint8_t temp = 0 ;) R7 Q: x. _4 J9 \
- // 判断是否是定时器1的外部捕获口2
" `7 ?+ ~/ _, z3 ]! P+ D4 y - if(htim->Instance == TIM1)
1 K3 }; d$ s+ R, I1 N+ ~$ t - {
- y3 M; \7 O0 ~6 h5 C: t2 _ - // 捕获到了上升沿( M8 H- j" A- C
- if(IR_IN1)
- Y$ e. i2 B+ B6 w7 o1 W - {
( U& }. y3 C, n( w3 p& D# d% ^ - __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极性为下降沿捕获
" l J/ R: c/ B- B% M9 q& C! r2 s - __HAL_TIM_SET_COUNTER(htim, 0); // 计数清零,从头开始计, m" w0 J- n# j) ?4 K6 ]4 c1 s6 ~0 N
- }
' G6 j$ C3 j6 X$ R5 I* ] - else4 ^; [+ E" m( h
- {, a& R$ k& l( V
- fallingCount = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2); // 读取捕获计数,这个时间即为上升沿持续的时间
4 H2 d# u! G. G# f9 D" x* N8 {" }4 V - __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极性为上升沿捕获
# r- i" F' Y+ R+ R" Y - if( ((fallingCount > 4400) && (fallingCount <5000))) & W% h! l0 z; f5 o( k0 X( q5 M. O
- OK = 1;/// 4.5ms引导电平
2 u+ E6 w% u3 n& v* L - else if (((fallingCount > 550) && (fallingCount < 700))) + y# o8 m/ Q$ H; ^( T# w) E" j
- {1 i: X" }# e$ v! l
- temp = 0;//560 us,数据为0& u; p* A/ p, L4 L! C0 Y7 N
- } ; j; W) p q& C1 X
- else if (((fallingCount > 1100) && (fallingCount < 1250)))
( `6 h$ t0 G7 a. J6 I7 m& z - {2 \' L" {" c& _ q. ]0 B9 ^- p* J
-
" G% u! Q2 {% i* `' d - temp = 1;//1120 us,数据为1! O- \6 x& s+ t8 |/ \1 j) I( i
- }# y: T3 E7 t4 f( Q
-
# t3 j& q9 c' o - else if (ReadyFlag==0&& ((fallingCount > 2000) && (fallingCount < 2500))) //2.240ms截止码
0 w4 |4 t! J6 ` - {
O* x/ O! Z) r4 x - ReadyFlag = 1 ;4 e) f. g3 ^ f8 d& P9 B
- OK = 0;
; j. M( i4 l q: m" I* o - }6 g* Y$ b6 e! @& M O1 |7 N
- if(OK)4 N; x$ F6 ?( ~% f- V7 Y" {
- {# }- Z4 m) O. u; h: [
- OrderData <<= 1 ;' C. Q' [$ z" T, s/ \1 i9 i; v
- OrderData += temp ;0 e: ?( ^7 e b3 D2 D" g) W
- KeyCount = 0; // 按键次数& | q3 A$ V( H3 K# h
- }
- b" y8 N1 M) o' L - }) T# _" \5 Q8 U; j6 v* E! |2 d
- }5 _9 D/ \8 ^7 w* v% C8 P% O' q9 C
- } _$ b5 V) q, l* `5 {' y# j
- /* USER CODE END 4 */
复制代码
$ d3 p% J, ]0 H主函数( m5 T. f/ f5 ^% Q3 x: l x
# P2 t4 Z; s2 Y% @+ ]1 i7 c! U
- /* USER CODE BEGIN WHILE */2 J U) G: P) {7 n. L2 F
- while (1)
% p# |: ?" f6 { - {
' E9 F7 U' J/ {9 l4 ^' Y2 G0 A - /* USER CODE END WHILE */
; { ^8 @+ D: I1 d3 v" ~
( Q6 A$ Y! M& l: S$ L) M W- /* USER CODE BEGIN 3 */
) b! z2 L& U" ^3 P1 W - if(ReadyFlag)3 I) W8 A+ e- I) h8 u
- {; d' G6 A! x7 V; i0 q& X+ F& `( |+ p
- printf("order=%08X , code=%d\r\n",OrderData,OrderData);/ S# R) N% R q: ~
- OrderData = 0;
$ j, f R' Y8 e" t - OK = 0;; [$ u/ k# j* O1 p4 r
- ReadyFlag = 0; : \: e" F( X5 n) Q& o
- }% A: K1 N1 @+ B0 x
- }
0 z% Z# ^! l& ~/ Q - /* USER CODE END 3 */
复制代码 / g2 W5 P" x! t/ `% |
结果演示
5 b% Y- P* h, {, e红外连续发送5次码值,发送分别为
c. p. L, ~) i8 q K/ G
% J0 g: s, C1 h/ i- P; L' V2 R1011(11)) d5 K) A3 y' T$ {( E* H
11 1010(58)' C$ |+ }. z7 H. P' h( [% k! J' e P
11 0001(49)
# X3 x9 |' E) O o. _3 w7 m11 1111(63)+ U5 ?/ ~7 T& M! o6 z
11 0011(51)
& ^" S7 X+ I# C$ g1 ]% T分别如下所示:
! D" M H) a. I( ?4 e4 V2 C
* M! \' ]2 |& [4 C0 w, K( L1 w; V
5 \' q9 f% \& n0 Q9 v8 y' O/ U
0 }- n0 z" N) C. @8 g: |, y
6 n# }: g; S4 V3 Y6 l8 K |