|
STM32CUBEME--自定义红外NEC解码,定时器TIM捕获方式 概述 本篇文章主要介绍如何使用STM32CubeMX对红外波形进行解码,并通过串口打印。$ i+ q5 V: S; M/ f2 q, }
& z8 Z8 X% m6 Z5 B0 m5 [
$ Z5 P0 L @1 U% H硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:
6 L' x' b/ i! z% i$ L F选择芯片型号 使用STM32CUBEMX选择芯片stm32f030r8,如下所示:* \) C' a9 ^4 t" H$ K0 X- u
配置时钟源 HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:; ^& Q, J+ [: A+ I$ Z* @
配置时钟树 STM32F0的最高主频到48M,所以配置48即可:
# f k8 `4 W+ p- h/ j$ q串口配置 本次实验使用的串口1进行串口通信,波特率配置为115200。
, D; ?, {* t; e' j定时器配置 本次使用定时器1的通道2进行检测,配置入下。. h6 v p1 Q# j, P* h7 h0 z! p2 ?
红外接收管 这里使用VS838的接收管,如下所示:8 [# X" e+ M; d. d. y" q1 T
红外编码 这里使用VS838的接收管,如下所示:$ C" |0 z* y. J4 V7 J7 V! e
NEC协议载波:38khz. S& `. H( z3 ^, Z+ c' ~
& |) o' y% k8 W* j/ P- l; d
A/ l3 M- d. v$ O自定义红外编码 本文中数据1的低占空比设置为1120us,总时间为1.68ms,不是上图的2.25ms。1 V$ l1 {# Y9 I! K# h& K
协议如下:
$ K. G' h4 F9 m0 m生成工程设置 注意在生产工程设置中不能出现中文,不然会报错。
1 g1 K* Z% T6 [) y8 Q# s代码生成设置 最后设置生成独立的初始化文件:0 R! p/ e/ i3 D: _, i
生成代码 配置keil 在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。5 H, f/ Q" Q ~2 W
6 ^4 O. ]+ f8 V$ h/ U3 b- /* USER CODE BEGIN Includes */9 P) X2 Z) U1 _, W- ]! p i
- #include "stdio.h"
# m( \7 U' z! K3 U( _ - /* USER CODE END Includes */
复制代码 红外接收口定义 。$ L: o" F/ I, @
- 6 y/ O3 P% z4 r7 K* n1 c
- /* USER CODE BEGIN PTD */: I T& E$ t, v3 Z7 F) \% H# @
- #define IR_IN1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)- M# \& z0 ? M: Z
- /* USER CODE END PTD */
复制代码 函数声明和串口重定向:, c. `% o4 [$ o8 O
2 {5 H, t" |# Q: o- /* USER CODE BEGIN PFP */
b' j' ^4 ?0 x& {6 s) D - #ifdef __GNUC__
9 P( t8 H% ]6 k$ ^( B, O - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)" q" g& l: p6 B
- #else% l/ P) k T; D. K3 O' ]
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
/ o; {3 k! A$ T) a" Z - #endif /* __GNUC__ */
9 m' |# ^9 d7 W6 x' B, Q - PUTCHAR_PROTOTYPE
W$ G3 m. T8 h% z2 A! J - {: N& i5 d* G" A) s$ N
- HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
. w1 W# z. h% i1 n! S - return ch;' E8 E2 o8 L& x$ d5 z7 i4 n
- }2 [2 A1 d9 B: T3 m6 N) U: L( ]
- /* USER CODE END PFP */
复制代码 定时器配置:" w# V; x! O/ R9 `9 ?
- /* USER CODE BEGIN 2 */, O# a# q0 T) z! d. ] _+ b- f
- HAL_TIM_Base_Start_IT(&htim1);//启动定时器) I2 x* k5 C& Q2 F
- HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);//函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断
" m! G$ a2 c; L0 d- ?$ } - printf("IR Capture !! \r\n");0 I1 h( C+ H8 B2 d4 E3 q0 Y3 |
- /* USER CODE END 2 *
复制代码 红外接收代码
" r4 P( g7 M" f+ h* V/ s$ g |0 o5 W
. @' S Z+ Y9 Z' `5 q4 y* @$ `* S" a[4400,5000]是用于捕获4.5ms的信号! q! k0 A6 b( Y5 e9 I
1 ?& T# P/ m# k2 i
; a; b+ Q$ l: |( \2 `3 z2 K
[550,700]是用于捕获560us的数据0信号8 \; j: ?+ m% ?# j c* L
7 V6 [) p* b, r1 ?2 U4 V. U: V; x; W2 w# o- |6 N
[1100,1250]是用于捕获1120us的数据1信号3 S/ s7 F, F* B# N; _$ [
% B; ]# K4 C" J- F$ }& a
5 L1 O2 T9 s( c8 Y) [3 G# I$ _, i
[2000,2500]是用于捕获2240us的截止位信号
7 _. {' o3 v+ t; T" v2 _
2 ^# C* c/ s8 {6 H* \' ~' w& j1 H- /* USER CODE BEGIN 4 */
) x: _: N* h% J8 d' Z - // 捕获中断回调函数,每次捕获到信号就会进入这个回调函数/ t' Y& I x% p3 L. I3 f- x/ z
- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)9 U5 m2 j! X. k+ t" G
- {2 N- v- I% L1 [
- uint32_t fallingCount = 0 ; // 下降沿计数
$ k9 e2 l( k* E8 q; D$ U - uint8_t temp = 0 ;) y9 g) J: H& X' F2 p; B; \, w
- // 判断是否是定时器1的外部捕获口2
/ Z9 ?( ]# p5 d$ r1 f3 S0 ?5 Z - if(htim->Instance == TIM1)( M7 Y+ R0 d8 v0 h4 ~( i
- {/ F" j8 P x% o; M9 N
- // 捕获到了上升沿
- Z! Z7 u, F& { p- E: o - if(IR_IN1)7 M i; P3 N3 ?6 c6 L& o8 U
- {0 C1 k& p6 a S
- __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极性为下降沿捕获0 h( Z$ q! ^$ s* k) C
- __HAL_TIM_SET_COUNTER(htim, 0); // 计数清零,从头开始计
% g7 Y. c. P. P9 K& G7 q - }- ^/ i( f) H* O8 J/ U: {9 e
- else6 Q& G- N' j. {6 t
- {
" ^3 @ X9 E3 q. s - fallingCount = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2); // 读取捕获计数,这个时间即为上升沿持续的时间
# [2 }. a* H9 K - __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极性为上升沿捕获
$ D% h, z! ?3 v3 x1 u - if( ((fallingCount > 4400) && (fallingCount <5000)))
9 X4 h, ?; z4 j3 q - OK = 1;/// 4.5ms引导电平' c0 v: {7 C& t
- else if (((fallingCount > 550) && (fallingCount < 700)))
( N S, y) t2 r M, p - {
" F6 X8 [$ c5 o" x( V: D3 ? W - temp = 0;//560 us,数据为0
8 V7 h3 y4 l, A- B - } ! N( ~0 x5 o* e
- else if (((fallingCount > 1100) && (fallingCount < 1250)))
; W; k% ?( T( U5 O! f1 } - {- m ~1 Y+ g& ~+ D
- 4 K! p4 y4 F. ?; S. Q% ?( Q6 `2 ~
- temp = 1;//1120 us,数据为19 u% x: p+ _+ ~% T! p- ], q
- }. t5 Q# v) `: y9 k
+ C' t4 i' [, F5 r( U- else if (ReadyFlag==0&& ((fallingCount > 2000) && (fallingCount < 2500))) //2.240ms截止码
; r M2 F/ a2 o3 U0 F - {6 X+ x$ a& G, j5 i0 h% r
- ReadyFlag = 1 ;
: Z( G" d4 H3 Q* P" M - OK = 0;
9 h' k$ k5 P: J* ^: K4 v0 U - }; B1 B7 p4 j9 d( ?$ O0 U
- if(OK)1 n+ a- e I3 C9 {+ u$ {9 h
- {! g" Q) c; Z3 W* o7 p
- OrderData <<= 1 ;- H2 Y; b1 i$ J' ^3 _7 ?! a
- OrderData += temp ;+ Y) f. N7 L) u9 B
- KeyCount = 0; // 按键次数 f0 ]+ W' k* V# h; W1 P( k
- }
; S! c5 o: w) z I4 m0 f3 z1 G - }
2 M7 v' v, }$ U8 s+ n! u - }
, }& k! ~1 ~: {) i$ n5 z9 w - }
" O" m0 R) x$ G2 N" j - /* USER CODE END 4 */
复制代码 主函数。- w" `+ f1 n- \
- /* USER CODE BEGIN WHILE */
2 Z t$ W' ~5 P4 { - while (1)) m7 l# i7 P, R0 g% ~4 M0 T: j
- {
! D `) I& v7 }& c' [8 J4 O+ L - /* USER CODE END WHILE */
' F, `4 L5 j3 h' Y+ t3 p
6 l! D3 D0 D, l' L) A- s6 }3 A/ P- /* USER CODE BEGIN 3 */) |7 i. q& J$ v; V( n
- if(ReadyFlag)2 c; n5 L& s, \! N$ v: ~
- {, H4 B# ~ Z- c& ?
- printf("order=%08X , code=%d\r\n",OrderData,OrderData);0 f% p5 U- \) N3 c0 S+ P
- OrderData = 0;
- p9 k2 }/ L1 L0 P - OK = 0;! H: \0 x0 {( p% M; J/ t8 I% {
- ReadyFlag = 0;
. D" j0 _# t% c - }
1 k4 M6 _8 ^& n7 @3 W7 b - }
复制代码演示效果 红外连续发送5次码值,发送分别为:
* [% }% [9 z& p- j+ E4 t( T# z' ?- I5 V7 u; z
$ t& h( I+ ^0 ]4 X" C1011(11)
! ^' M6 ^) e4 x5 H# L1 @11 1010(58)
6 }! K3 _& n8 H1 |11 0001(49)6 k* x5 Y( d W7 O) a) m: ` q
11 1111(63)6 U2 s6 J5 _/ Y( Y* P, h6 n2 O6 x
11 0011(51)
- q2 `8 f: y$ p0 N# G 分别如下所示:& ]2 U8 Y, p% i# f" U! _& H# M
$ U1 t: \ q$ d% s( q4 m9 w# [
; B0 p$ y1 p: v+ E3 C
2 ]6 p' D8 |0 L8 v) x9 z! ]/ Q5 ^
1 Y9 t+ z) x% i! F; o/ n, F# U! a6 h, Y( ^- E3 |8 p9 @
|