|
概述 本篇文章主要介绍如何使用STM32CubeMX对红外波形进行解码,并通过串口打印。
# X- ]! R% k& a 硬件准备 首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板: + ]& J* [; j' x
& A/ F$ l2 w) S5 G& r, d* l6 B. A% r6 c5 y! T
选择芯片型号 使用STM32CUBEMX选择芯片stm32f030r8,如下所示: ! Y5 a% a" |; U: G* ]
+ l1 M3 Y! K, B 配置时钟源 HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:% J# Z' c# J7 J
7 B, K0 E; o5 i5 y
a" C5 {. f5 p H# C! \9 [ 配置时钟树 STM32F0的最高主频到48M,所以配置48即可:
& \8 z6 F7 r% }# q$ w' B
6 P( g; F' X7 d) [0 V1 {) U
8 Y L* e4 t$ ?9 W: {0 I
& Q9 e. o1 s( G* y* |9 i串口配置 本次实验使用的串口1进行串口通信,波特率配置为115200。7 M* x, `2 u( v: c6 X
- L! J; ?! a+ i" l) ]1 ~8 \! }
/ Q5 P; {5 e6 W5 [# D
定时器配置 本次使用定时器1的通道2进行检测,配置入下。
$ J# T% R9 G0 h4 d- {# B9 ]5 R8 {# V6 y$ E7 F) v: m
红外接收管 这里使用VS838的接收管,如下所示:
7 B: J# G* E9 G& x( I# O; V2 Z& @: q* ^. y' {0 X
红外编码 NEC协议载波:38khz 其逻辑1与逻辑0的表示如图所示: 7 @0 g: ~+ F6 V) W, V( A# A$ d
6 R! ~, M* P1 s# H
NEC协议格式: i* z! S: G/ ?. h
4 N- a1 s0 R% l9 \8 L" o9 g自定义红外编码 本文中数据1的低占空比设置为1120us,总时间为1.68ms,不是上图的2.25ms。 协议如下:
0 s) N3 ~3 M% |+ B9 {% S7 W* P; F/ E% ]. K
生成工程设置 注意在生产工程设置中不能出现中文,不然会报错。
" {+ y$ z# F( D* o" N
9 \2 s4 f2 o, w( ^$ s' q, ^
: k3 x4 L* J7 I9 s# G f) X代码生成设置 最后设置生成独立的初始化文件:
+ S- B2 ~2 C2 i1 z9 e: I. W
( H/ K' X. j- ]# ]0 G
3 G) k% }: S3 m3 k5 t9 C8 N
生成代码
6 \5 k; |/ E1 ]! u% b" v& A4 ]" D+ I/ N# Z, S* p3 Y- u
配置keil
2 o5 x6 v5 M" b4 b# }* g* G1 `9 n# Z& l
, I$ X" c9 n% g) J5 }: p/ F 在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。 - /* USER CODE BEGIN Includes */$ c6 M8 J9 i' t
- #include "stdio.h"0 \' X9 I- A: z. {3 x2 M- C! m
- /* USER CODE END Includes */
复制代码
3 b8 U6 G1 ^4 x3 m 红外接收口定义 。 - /* USER CODE BEGIN PTD */
/ j- [0 {' m* _, P - #define IR_IN1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_9)$ S# l: u5 b& B& L+ `
- /* USER CODE END PTD */
复制代码 " `9 C1 }7 ?$ j, {9 C" D! Z! V
函数声明和串口重定向: - /* USER CODE BEGIN PFP */, m* Q) e1 Y+ w3 H' j6 x3 D
- #ifdef __GNUC__5 V- w) t; o! i% \( v( N/ _5 W% g
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
$ O6 w+ {( ~- N5 G# \ - #else! A" y v7 c1 E" L+ v
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f): O( R! S1 Y, }. O1 @# P
- #endif /* __GNUC__ */7 `0 I) p; G' {( C% W+ v/ d2 T
- PUTCHAR_PROTOTYPE! A+ P% y1 M u
- {0 o% x/ S8 } \' d/ H
- HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
& d. m% W# ~) Q2 k# p - return ch;, g" i4 C/ N/ L/ v1 q, b% u
- } N& `6 {9 `) e9 {; ?5 L6 |7 b {
- /* USER CODE END PFP */
复制代码
5 o# q, L0 l) P' h 定时器配置: - /* USER CODE BEGIN 2 */; o; U1 J' a- J' f
- HAL_TIM_Base_Start_IT(&htim1);//启动定时器0 f/ @8 |% H6 |3 H1 ^& B
- HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_2);//函数用于使能定时器某一通道的输入捕获功能,并使能相应的中断
$ U$ x3 t5 S) f1 a a- C - printf("IR Capture !! \r\n");" [5 z* t4 ~: i1 a
- /* USER CODE END 2 *
复制代码 ' M+ p; S6 _" K3 N- m9 o, Y
红外接收代码 [4400,5000]是用于捕获4.5ms的信号 [550,700]是用于捕获560us的数据0信号 [1100,1250]是用于捕获1120us的数据1信号 [2000,2500]是用于捕获2240us的截止位信号 3 D p0 s, C5 Q u. q$ L) ]
- /* USER CODE BEGIN 4 */8 [/ U* |! x* D& c) \- E2 k. |
- // 捕获中断回调函数,每次捕获到信号就会进入这个回调函数
; t1 n" k+ [7 c( I/ x - void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)+ N9 A1 }* M: ?) }( C D4 w# ?
- {
) E) }( N6 L4 B: ~9 e: D+ c, E - uint32_t fallingCount = 0 ; // 下降沿计数4 q$ v5 m. z0 _$ A( J- t3 h: n
- uint8_t temp = 0 ;; a- P9 |! ~/ G% h; q/ S2 L
- // 判断是否是定时器1的外部捕获口2/ V) A9 S) @' s0 r
- if(htim->Instance == TIM1)
Z( W" j8 s. ^0 F7 d+ i - {
+ G3 p- N# `+ k+ L1 p - // 捕获到了上升沿3 j2 w1 e. a d: U8 Z, k: D& h8 @
- if(IR_IN1)5 U/ Y- I: l3 p7 z, x! h U# k6 W
- {
* R7 I$ j: D e* c# G" r - __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_FALLING); // 改变捕获极性为下降沿捕获
0 V L( x! x) r3 c - __HAL_TIM_SET_COUNTER(htim, 0); // 计数清零,从头开始计3 o6 C9 j) U+ H7 U+ o6 h' @
- }. L9 f* O- E6 F+ N
- else: Q- i' c' |2 E8 V- S7 r
- {
4 [8 s( m- [8 Y8 n - fallingCount = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2); // 读取捕获计数,这个时间即为上升沿持续的时间4 k. \: \/ `" L: p! p8 e' z
- __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_2, TIM_INPUTCHANNELPOLARITY_RISING); // 改变捕获极性为上升沿捕获
' B2 \/ a K# ]" e - if( ((fallingCount > 4400) && (fallingCount <5000))) % |5 c g5 w* _! n- C$ R( C
- OK = 1;/// 4.5ms引导电平
3 ^$ w$ ]! M/ V! _! a2 e: L - else if (((fallingCount > 550) && (fallingCount < 700))) : g; L O" W# Y! S4 v7 I
- {
% A ~% Z: A8 E& s/ ` - temp = 0;//560 us,数据为00 O1 C3 c9 @' }, X" j: Q0 L
- } 1 K$ B' L$ G! ~2 u
- else if (((fallingCount > 1100) && (fallingCount < 1250)))! o, N4 Y7 i5 ?' C
- {
% g4 g# D0 }+ D0 F$ f - 0 o: M- _9 Z' c! d; m! X
- temp = 1;//1120 us,数据为1' g. Q. S' T% W9 p$ r- g
- }5 B3 [. y! t! r5 [& F) N' ~
) ~) _2 j( f1 J; b. S. p @, g9 V- else if (ReadyFlag==0&& ((fallingCount > 2000) && (fallingCount < 2500))) //2.240ms截止码
) C0 R, j% @9 w: Y% Y5 a( a - {* r ~1 _: Q9 @" x+ C1 G
- ReadyFlag = 1 ;
. n* K. r W5 s* o - OK = 0;/ N) s4 t- y1 z* h
- }
w! D9 |: ]* M$ }' j - if(OK)
9 @ c9 L% T, x2 O+ Q4 P8 U+ T - {4 V/ o9 |$ n! R- e; U
- OrderData <<= 1 ;
9 i6 ~3 R4 {9 }2 C - OrderData += temp ;7 N" P$ v/ W9 A
- KeyCount = 0; // 按键次数' Q& d: ]9 ~! s% S
- }& G- x" r' d3 S( B
- }, E7 G; `1 ]3 e
- }0 [6 Y" e; W$ W5 J; y* ~1 Y
- }
- x+ U* V% d5 k+ S D4 m, t3 ` - /* USER CODE END 4 */
复制代码
+ h: L* k" X6 H/ m
. N# t3 }, _, |5 b# C 主函数。 - /* USER CODE BEGIN WHILE */
; S0 j" y0 c5 O+ i# ~6 ? - while (1)
" T9 g( m8 d% l4 m% f - {
1 X. x8 W/ k& c- H+ ~/ e! d' A - /* USER CODE END WHILE */
8 f3 k, d6 O! [3 z# Q! i; H - . f o) U+ J( o
- /* USER CODE BEGIN 3 */' A$ V$ z8 A1 h) N
- if(ReadyFlag)
) _4 B: r4 S- F. g" Q - {) l+ _- h Z) u( o
- printf("order=%08X , code=%d\r\n",OrderData,OrderData);' f4 u/ H4 Y9 M6 w: L' b/ i/ `
- OrderData = 0;
0 K( T% G" O6 Y& m6 J( x- y - OK = 0;
4 o g+ a( D9 h$ I' |& t4 w - ReadyFlag = 0;
# o; t9 y6 {' s2 s, }* m# d* w - }& o# N6 T& J- ~# w4 f
- }
复制代码 + x5 d- F1 p, W: }/ s
3 M/ }4 g2 n5 @" a" k演示效果 红外连续发送5次码值,发送分别为: 1011(11) 11 1010(58) 11 0001(49) 11 1111(63) 11 0011(51) & U/ W8 o, O4 `* f& q! c7 ?, T
分别如下所示:4 ^" U6 J" X2 ]3 q+ \: B" Y6 Z7 _
- w6 f7 c% \' o" `# H3 {* z) _; B6 }" P
转载自:记帖 - C- ]* e& q+ A! A2 y
如有侵权请联系删除
! L% r& t. W4 W3 k1 R( V
9 S, i( s2 _1 n: ^7 A. O4 F
/ ~2 v* f" @! W+ P 3 N4 G" J8 X2 g5 `8 @7 M( e: L$ F
8 X1 M+ ~0 B. J& `0 G. y
|