一. 简介) E7 ?8 l# Q+ J$ T5 O
最近在做项目的过程中,由于使用的是核心板,没有按键,尝试通过串口进行数据发送,进行控制,但是太麻烦了。于是想到了通过红外遥控进行控制。经济又实惠,还可以隔空远程操作,且只有一个数据线,YYDS。1 c' H5 v) `. _. m: v x% [
& C- |6 g- f' V, b& E1 {
二. 红外遥控数据传输协议3 x" C- x9 j. v* P- ]) ^: Q
不做过多的理论知识的简介,主要是为了教大家怎么使用。传输过程如下. R9 I' n3 x7 b$ W; U
/ R. t& ]/ J* g4 k6 V4 T
1.空闲态 为 高电平
# b/ A+ O6 N1 n, T0 f% x2.引导码 : 9ms的低电平 和 4.5ms的高电平
1 v& m% C2 o& }( ? v5 W5 j3.数据码: 数据码包括四个部分依次是用户码、用户反码、键码和键码反码,每个8位,共32位,560us的低电平加560us的高电平表示数据0,560us的低电平加1.68ms的高电平表示数据11 H$ i9 |/ M& M+ S
4.停止位:可以忽略,软件中可以不用管% m, [/ ]0 H' k3 Y
依次按照对应的时间来检测就可以。, F/ F0 K9 s6 k( [4 H: R2 _
5 @3 m- C3 W$ A1 Z# Q本次设计通过外部IO中断来进行红外数据的读取,低电平触发(空闲为高电平)。; Q; h) J1 ^; T6 Z; z. a# ~" f0 }
- {1 C' c, @) y- X$ T
三. 程序设计& Y- I/ F/ z: h0 `$ i* N/ o
1.定义好相关变量,RCC和GPIO
( n. l0 m8 b& }/ ]! x% W) N- //红外遥控控制 m/ R0 e% T& t# e9 S& f$ t, R5 S# |
- #define InfraredGPIOPort GPIOB
; G! M$ I' ~; F' } - #define InfraredGPIOPin GPIO_Pin_0 $ ?% S3 Q# {- Z" _' J- j8 j ?
- #define InfraredRCC_APB RCC_APB2Periph_GPIOB
复制代码 ) s9 Z6 R$ l b3 e# {- ~
2.GPIO初始化
' A+ I2 v1 n: M, P$ N- void InfraredGPIOInit(void)//GPIO口初始化- K. C/ z8 N9 i# G7 [7 H# M5 o
- {
- o$ ^8 P9 X1 p. S6 J u3 T - GPIO_InitTypeDef GPIOInitStruct;
6 _' ]7 r* C- i! v - RCC_APB2PeriphClockCmd(InfraredRCC_APB | RCC_APB2Periph_AFIO ,ENABLE); //开启时钟 RCC_APB2Periph_AFIO& P) c5 O: s% |$ E
- GPIOInitStruct.GPIO_Pin = InfraredGPIOPin;8 L1 R% ^, A6 ]5 M" f" _5 |; F
- GPIOInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
* ^5 L0 j' \* Z1 V - GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;
1 t$ j0 t. \0 S- i) l5 S - GPIO_Init(InfraredGPIOPort,&GPIOInitStruct);
! l2 n9 O( W1 p" [% I+ d2 J6 k$ _ - }
复制代码 0 t. H; h+ ]& s- r- g
3.开启中断2 g2 w8 v0 i5 r. }: A: ^
中断控制线可以根据自己的Pin来确定,如果是GPIO_Pin_8,那么这里就是EXTI_Line8.
5 `" X! } {, G9 [- void InfraredEXTIInit(void)//中断初始化& k6 p# h8 t8 R7 Y" d. w% a) p
- {
% C1 ^3 |2 B' @9 u) h - EXTI_InitTypeDef EXTI_InitStructure;% ?" F J9 l& Y8 j \# L
- NVIC_InitTypeDef NVIC_InitStructure;//定义中断结构体变量) ?* m1 i) j6 E/ U" N0 {8 L4 @
- ! Q2 K; l7 }4 v: |" Y
- //中断配置8 h+ x/ V- ~- r, z b2 ^
- EXTI_ClearITPendingBit(EXTI_Line0);
1 x( s8 [# w9 z" s9 u4 ^( B+ k - GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0); ; Q+ {4 z Y8 y. U4 L" m; I* K# x
- ' R) |+ L2 M6 L! x l
- EXTI_InitStructure.EXTI_Line = EXTI_Line0;
* G1 [, d0 n' t6 e5 \ d' L! Y - EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;8 u. E, s& r$ U3 V4 d
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; - Q; F4 c3 O# Q/ q6 B
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;. z2 _1 m) K6 ]' A
- EXTI_Init(&EXTI_InitStructure); O4 I. f5 F z; m' q( A* K
- - w A, I2 h! a+ k, w
- NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//EXTI0中断通道
0 Z% b9 b6 ]! i, T' K - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级3 F6 y" ^" S" I, C6 ~
- NVIC_InitStructure.NVIC_IRQChannelSubPriority =1; //子优先级
! h1 ~. P/ `$ v* j: I - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能
& m5 X( D# U" C - NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
复制代码 2 T4 f( R3 a7 J* b4 y% I
4.电平持续时间计数
) S! L6 n0 F0 p, {/ Q' G$ u0 W这里主要是对电平的出现时间进行一个计数9 i# y; q- A* ?
- //计算低电平的持续时间/ o* }* u6 R) p2 G
- uint16_t InfraredRecvLowTime(void)
4 ]+ k/ {/ H4 D; Q* r A - {
# |# c* j2 [3 I7 t( a: l - uint16_t time = 0;
5 w- k' c* y* h- M+ r; E; N% b7 _ - while(GPIO_ReadInputDataBit(InfraredGPIOPort,GPIO_Pin_0) == 0)7 r; _ G( ~+ }( ]5 a
- {
' g; g* ]+ ?* {+ ?/ Z% Q4 P0 l - if(time >= 500)
; K* R1 b \5 w - break;
5 Q+ z7 `3 m# B# R$ g3 \# N" u! A - time +=1;4 z+ ?* J! i* X
- delay_us(17);
8 C8 O0 m. U* E6 c( O$ V4 B8 k9 V - }
- I9 ?1 r9 x8 ^: b& c; Z0 F - return time;
' I6 h2 A& ^8 K# e - }
( {# |3 R' t! A. u - //计算高电平的持续时间5 N/ w) [* e! j. `7 A
- uint16_t InfraredRecvHighTime(void)
( }& Q+ _* v! P - {
+ k2 F) R ]8 ~9 H8 w7 P9 q - uint16_t time = 0;
N5 V! H& k' R) n& ? - while(GPIO_ReadInputDataBit(InfraredGPIOPort,GPIO_Pin_0) == 1)+ k3 N& {5 Y, `1 ~( e
- {
V6 h6 S0 E: J! F1 \/ U0 O9 q - if(time >= 250)8 Z' P3 \7 E1 C! L2 c5 }7 D
- break;
: m' R+ @) |: p. o( l2 V z3 i* s - time +=1;: [9 I, H% j% J1 [; E
- delay_us(17);8 r7 |- Z9 R! B: N+ M3 r$ H
- }' j2 F- S4 ~4 k6 F; Y: H
- return time;
' ?0 k. V0 i$ Q/ q0 {7 L - }
; |3 e0 g4 j W, I, I6 G - ) q9 s- V& v, s
复制代码 & n: X0 u4 a% f/ k" a! y! x
5.编写中断控制函数. o4 ]+ b! u9 q: I
通过数据的参数过程进行判断,就可以了。持续时间需要在一个范围内,可以自己测试后设置。
: U" r' |; K4 j; n8 u
: S6 Q" A* j: F% i$ c! l% N- uint8_t InfraredDataRecv() //获取红外遥控数据
5 P6 O3 ~2 X' P3 N9 G0 O6 J( {. V) @ - {
( p2 A& Z9 S9 u4 z% E - uint16_t time;
$ P. K. @4 T5 M/ t4 ] d) W - uint8_t i,j;
# Q( e' w/ x' _3 S4 K - uint8_t data[4] = {0};
- O: g" \ P B( ^/ U/ b4 S$ Q( a$ U - //获取引导码: r5 @8 `! p" [( R) _! m* X
- time = InfraredRecvLowTime();3 v! z: t- w/ m" o
- if(time < 400 || time >= 500)
$ U; S7 z# N8 B. i+ A - return 0x00;9 N5 T1 I; T* G9 s) o6 n! d
- time = InfraredRecvHighTime();
' G6 F$ q& E* s- H - if(time < 150 || time > 250)8 M1 l- w; {! u2 `- p: u% A
- return 0x00;
8 s! _. V7 U$ ?+ S) R - //获取数据
# k8 V6 Y2 O3 I4 Y) D - for(i = 0; i < 4 ; i++). C% I& P+ w/ f4 _
- {
1 z1 W6 s; i, H2 Y' c. A - for(j = 0 ; j < 8 ;j ++)
; \ |, L/ G6 W3 h - {
$ e3 E' G3 S0 S7 ]" G2 I - time = InfraredRecvLowTime();6 ^# x7 D. M5 h/ |
- if(time < 20 || time > 35)
1 Z( D, i- G- n- [ Z8 {9 `2 ~ - return 0x00;
: X, X: _# T1 t" ? - time = InfraredRecvHighTime(); //通过高电平的时间长短来判断数据0,17 x: }# p+ m9 T* e8 w: h5 E' |
- if(time < 35) //数据0
. |% c% p ~/ T( j% K - {
. ?# r7 @ a0 c: ~' ~) V% \ - data<i> <<= 1;! O( c0 z+ E7 z1 S0 V0 _& Q
- data<i> |=0x0;
( T8 M6 g8 O B, M' F( M - }
1 n5 R) r, q& x7 p5 d - else
: P: E2 q% ~/ o4 G( q - {2 G n" O, y( a
- data<i> <<= 1;
: o; `- K; A( L6 c1 ~2 g+ g - data<i> |= 0x1;0 J0 w4 O, M4 z5 ]9 q+ _
- }
( y3 B/ ?2 U. Z- S# x) k. v, T - }0 t9 I1 g, z3 F8 k( B+ w
- }+ e8 b% ^8 B- U' @
- return data[2];& q2 X1 H+ n8 s$ e' L
- }% y) e, X# x3 U2 l" K2 m
- void EXTI0_IRQHandler(void)5 H( m: o8 x& T8 c/ `: H
- {
- Q; } d Z+ B: M - if(EXTI_GetITStatus(EXTI_Line0) != RESET)" E8 t$ T' P5 F; n$ G
- {
7 r+ W1 ~) M( Q - uint8_t data;
' ^: Y/ \; Z$ K; y3 E. d - data = InfraredDataRecv();+ M7 }& C' i. G6 h
- if(data == InfraredLeft)
8 \4 G- l( V% `- ?( M - KEYState = KEYLEFT;- _9 C0 {: |! J
- else if(data == InfraredRight)
- @. A1 m7 O6 K: E2 Q8 f" S - KEYState = KEYRIGHT;
& ^% M* b1 X3 z( Z2 r* } - else if(data == InfraredUp)# _1 i' t% j1 D, X' i) |& _
- KEYState = KEYUP;
' N9 I, F- B5 _9 `5 ] - else if(data == InfraredDown)
* \2 x, s& y, e' y. m - KEYState = KEYDOWN;
4 W" d9 T8 J2 n0 b+ `! s - else if(data == InfraredReturn)
& K N5 R7 o% F0 v/ } - KEYState = KEYRETURN;5 p C; g. ?0 W+ s; ]! S8 M$ k" i
- delay_ms(10);
* b/ B6 X/ w2 _ G$ v - /*清除标志位 */
5 ~+ j B; C n5 B$ ]5 M( X9 a) i - EXTI_ClearITPendingBit(EXTI_Line0);% h P! X; U* B# d2 g/ `
- }, Y8 K: ~6 a' p1 A$ F
: S' U L8 s8 V, U- }
3 Q8 Z/ E3 D9 f - + {/ Y6 o. K9 ?0 n
- , w5 J+ ~6 b& j2 M, [/ @& T
- </i></i></i></i>
复制代码
- Y1 f9 v7 V9 r; ?7 t% O
# [) a" N/ p5 o4 D( x9 W/ H% O; f K |