Tüm projeler
07Hazır

IR Kumanda

Kızılötesi kumanda tuşlarını çöz, her tuşa bir renk ver.

Decode
01

Ne öğrenirsin

NEC protokolünü çözme: her tuş, farklı uzunlukta ışık darbelerinden oluşan 32 bitlik benzersiz bir kod gönderir. Darbe sürelerini timer ile ölçersin.

02

Gereken parçalar

03

Bağlantı

ModülKartNot
S / OUTPB2Alıcı çıkışı
+ / VCC3.3V—
- / GNDGND—
04

Kod

main.c
1#include <stdint.h>
2#include <stdbool.h>
3#include "inc/hw_memmap.h"
4#include "driverlib/sysctl.h"
5#include "driverlib/gpio.h"
6#include "driverlib/timer.h"
7 
8#define LED_ALL (GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3)
9#define IR_PORT GPIO_PORTB_BASE
10#define IR_PIN GPIO_PIN_2 // PB2
11#define PWM_STEPS 256
12 
13static void showColor(uint8_t r, uint8_t g, uint8_t b, uint32_t periods) {
14 volatile uint32_t p, i;
15 for (p = 0; p < periods; p++)
16 for (i = 0; i < PWM_STEPS; i++) {
17 uint8_t out = 0;
18 if (i < r) out |= GPIO_PIN_1;
19 if (i < g) out |= GPIO_PIN_3;
20 if (i < b) out |= GPIO_PIN_2;
21 GPIOPinWrite(GPIO_PORTF_BASE, LED_ALL, out);
22 SysCtlDelay(2);
23 }
24}
25 
26// 0..255 -> a rainbow color
27static void wheel(uint8_t pos, uint8_t *r, uint8_t *g, uint8_t *b) {
28 if (pos < 85) { *r = 255 - pos * 3; *g = pos * 3; *b = 0; }
29 else if (pos < 170) { pos -= 85; *r = 0; *g = 255 - pos * 3; *b = pos * 3; }
30 else { pos -= 170; *r = pos * 3; *g = 0; *b = 255 - pos * 3; }
31}
32 
33static int irLevel(void) { return GPIOPinRead(IR_PORT, IR_PIN) ? 1 : 0; }
34 
35// Wait while the pin stays at 'level'; return how long it stayed (us)
36static uint32_t waitWhile(int level) {
37 uint32_t start = TimerValueGet(TIMER0_BASE, TIMER_A);
38 uint32_t guard = 2000000;
39 while (irLevel() == level)
40 if (--guard == 0) break;
41 return (TimerValueGet(TIMER0_BASE, TIMER_A) - start) / 50; // 50 MHz -> us
42}
43 
44// Line has just gone LOW -> decode one NEC frame. 1 = ok.
45static int irDecode(uint32_t *out) {
46 uint32_t d, i, code = 0;
47 d = waitWhile(0); // leader burst ~9 ms
48 if (d < 7000 || d > 11000) return 0;
49 d = waitWhile(1); // space ~4.5 ms (repeat = 2.25 ms -> reject)
50 if (d < 3000 || d > 6000) return 0;
51 for (i = 0; i < 32; i++) {
52 waitWhile(0); // ~560 us burst
53 uint32_t space = waitWhile(1); // 560 us = 0, 1690 us = 1
54 code <<= 1;
55 if (space > 1000) code |= 1;
56 }
57 *out = code;
58 return 1;
59}
60 
61int main(void) {
62 uint8_t r = 0, g = 0, b = 0; // current color (starts off)
63 
64 SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL |
65 SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
66 
67 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
68 while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF)) {}
69 GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_ALL);
70 
71 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // IR output on PB2
72 while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)) {}
73 GPIOPinTypeGPIOInput(IR_PORT, IR_PIN);
74 
75 SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // free-running us timer
76 while (!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER0)) {}
77 TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);
78 TimerLoadSet(TIMER0_BASE, TIMER_A, 0xFFFFFFFF);
79 TimerEnable(TIMER0_BASE, TIMER_A);
80 
81 while (1) {
82 if (irLevel() == 0) { // a frame may be starting
83 uint32_t code;
84 if (irDecode(&code)) {
85 wheel((uint8_t)(code % 256), &r, &g, &b); // button -> color
86 }
87 }
88 showColor(r, g, b, 2); // hold color, keep polling
89 }
90}
05

Çıktı

Aşağıdaki simülasyon tarayıcında çalışır — gerçek kartın davranışını taklit eder.

tuş
—
RGB
0,0,0