Saudações, neste artigo você aprenderá: como fazer um sensor de movimento usando um diodo IR e um receptor IR em um STM32 com uso mínimo do núcleo (ou seja, com carga máxima na periferia) nos registradores, usando temporizadores.

O artigo discute os problemas de programação com o máximo de detalhes possível. O material é projetado para o nível de treinamento de iniciante, mas também adequado para os mais experientes. Alguns dos detalhes estão escondidos sob spoilers para reduzir a carga do artigo.
Índice:
Operação de diodo IR e receptor IR
A grande imagem
Dois dispositivos são usados: um transmissor de sinal IR e um receptor de sinal IR.

O princípio geral de operação é o seguinte: um transmissor de sinal infravermelho emite um sinal na faixa de comprimento de onda infravermelho e um receptor de sinal infravermelho os recebe. Um "feixe" é formado entre esses dispositivos, a interseção do qual por qualquer objeto é fixada pelo dispositivo receptor.
TSAL6200 é usado como um diodo IR e o TSOP4856 é usado como um receptor IR.
![]() | ![]() |
Diagramas de dispositivos
.
STM32L151C8T6, 2N7002, 1 TSAL6200. .

, , ( STM32L151C8T6 25 , TSAL6200 100 ).
. 2N7002, . (Gate Threshold Voltage), , 3.3 .
, , , . 1 , 20 , 14 ( , , ). , , , -.
STM32L151C8T6, TSOP4856, 100 0.1 . .

TSAL6200 940 . 56 ( , . ). .
TSOP4856. , , , . . . .

.
. , , - .
. , - ( ) General-purpose . PB6, TIM4. PB7, TIM4.

: TIM4 56 , TIM2 TIM4, .. . TIM2 Master, TIM4 – Slave. TIM2? .

Tim_Init_Transmitter(). . , main , .
#include "main.h"
void Timer_Init_Transmitter(void);
int main(void)
{
RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable
Timer_Init_Transmitter();
while(1)
{
}
}
void Timer_Init_Transmitter(void)
{
}
RCC->ICSCR |= RCCICSCRMSIRANGE_6
- 4.194 . .
. , , ( ), . .
RCC_AHBENR. «1» GPIOBEN.

CMSIS RCC_AHBENR_GPIOBEN
, .

AHBENR :
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable
GPIOx_MODER. «10» MODER6 ( PB6).

CMSIS GPIO_MODER_MODER6_1
, .

.
MODER :
GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable
.
.

TIM4 – AF2.
, : GPIOx_AFRL 0 7 GPIOx_AFRH 8 15. , CMSIS AFR[2], «0», , «1», .
GPIOx_AFRL.

«0010» AFRL6, 0x2000000, «2» PB6, 0 5.
AFRL :
GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable
:
void Timer_Init_Transmitter (void)
{
//Settings for GPIO PB6
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable
GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1; //High speed
GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable
}
TIM4.
PSC ( ), CCR1 ( ) ARR ( ), , TIM2, Slave PB6.
GPIO.
PSC CCR1 ARR
0, .

PSC :
TIM4->PSC = 0; //Prescaler value
ARR.

ARR 4.194 ( ) 56 . 74,89, . 75. ARR:
TIM4->ARR = 75 //Auto-reload value
CCR1.

, CCR1 ARR:
TIM4->CCR1 = 37; //Capture/Compare 1 value
, CCMR1. OC1M. .


PMW mode 1, , .. «110»:
TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1
PB6
CCER CC1E «1», .

:
TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding pin
Slave

TIM4 TIM2 ITR1. TS TIMx_SMCR «001». Slave, «101» SMS. ITR1 , TIM4 , ITR1 , TIM4 .


:
TIM4->SMCR |= TIM_SMCR_TS_0; //choosing ITR1
TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode
, :
void Timer_Init_Transmitter (void)
{
//Settings for GPIO PB6
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable
GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1; //High speed
GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable
//Settings for TIM4 - Slave
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //TIM4 clock enable
TIM4->PSC = 0; //Prescaler value
TIM4->ARR = 75; //Auto-reload value
TIM4->CCR1 = 37; //Capture/Compare 1 value
TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable
TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding output pin
TIM4->SMCR |= TIM_SMCR_TS_0; //choosing ITR1
TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode
TIM4->CR1 |= TIM_CR1_CEN; //TIM4 enable
}
TIM4 , , TIM2, .
TIM2.
, PSC, CCR1 ARR, , ( TIM4) .
, TIM4.
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //TIM2 clock enable
PSC, CCR1 ARR TIM2
10 ( , ), TIM2 , TIM4.

«+1», .. PSC «9», 10 , .
TIM2->PSC = 9; //Prescaler value
CCR1: 10 , , ARR TIM4 ( , 75) 10, .. 750, , , 10, .. 750 10, 75 ( TIM4, ). CCR1 TIM2.
TIM2->CCR1 = 75; //Capture/Compare 1 value
ARR: , , «» 11.2, 2 ( , 1 4194000/1000 = 4194 , 2, 8400, 10, 840 ), 75 11.2 840, , . ARR.
TIM2->ARR = 840; //Auto-reload value
2, , . 4.
TIM2 , TIM4 - .
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable
TIM2 ( TIM4)
TIMx_CR2.


( CCR1), TIM2. OC1REF. – «100».
MMS «1» .
TIM2->CR2 |= TIM_CR2_MMS_2; //OC1REF signal is used as trigger output (TRGO)
TIM2, :
TIM2->CR1 |= TIM_CR1_CEN; //TIM2 enable
, . , , TIM2.
:
void Timer_Init_Transmitter (void)
{
//Settings for GPIO PB6
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable
GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1; //High speed
GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable
//Settings for TIM4 - Slave
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //TIM4 clock enable
TIM4->PSC = 0; //Prescaler value
TIM4->ARR = 75; //Auto-reload value
TIM4->CCR1 = 37; //Capture/Compare 1 value
TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable
TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding output pin
TIM4->SMCR &= ~TIM_SMCR_TS; //clear bits
TIM4->SMCR |= TIM_SMCR_TS_0; //choosing ITR1
TIM4->SMCR &= ~TIM_SMCR_SMS; //clear bits
TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode
TIM4->CR1 |= TIM_CR1_CEN; //TIM4 enable
//Settings for TIM2 - Master
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //TIM2 clock enable
TIM2->PSC = 9; //Prescaler value
TIM2->ARR = 840; //Auto-reload value
TIM2->CCR1 = 75; //Capture/Compare 1 value
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable
TIM2->CR2 |= TIM_CR2_MMS_2; //OC1REF signal is used as trigger output (TRGO)
TIM2->CR1 |= TIM_CR1_CEN; //TIM2 enable
}
10 , 56 , 11.2, .. 2 . , - , .. . , 2 .
, . STM32 Master Slave, Master/Slave, .. .
« » PB7 . . . TIM4.
.

, , TRGI, Trigger controller.
: , , 5 , , ARR , 5 , .. 840 * 5 = 4200. , . ARR , , 5 , , - . . TIM4.
:
#iclude "main.h"
void Timer_Init_Receiver(void);
int main(void)
{
RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable
Timer_Init_Receiver();
while(1)
{
}
}
void Timer_Init_Receiver(void)
{
}
PB7: B, , . , .
void Timer_Init_Receiver(void)
{
//Settings for GPIO PB7
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // GPIO port B clock enable
GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternative function mode enable
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speed
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // pull-up PB7
GPIOB->AFR[0] |= 0x20000000; // Pin PB7 TIM4 alternative function AF2 enable
}
, , , «2» . :
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;
TIM4.
. , CCR2. 9, TIM2 . CCR2 ARR. , 4200.
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // TIM4 clock enable
TIM4->PSC = 9; // Prescaler value
TIM4->ARR = 4200; // Auto-reload value
TIM4->CCR2 = 4200; // Capture/Compare 2 value
.
, , . TIMx_CCMR1 OC2M «000», Frozen mode. , :
TIM4->CCMR1 &= ~TIM_CCMR1_OC2M; // Frozen mode enable
, CC2S ( ), :
TIM4->CCMR1 &= ~TIM_CCMR1_CC2S; // Output mode
(. ). , PB7 TIM4, TI2FP2. TIMx_CH2 TRGI. , TIMx_SMCR TS «110». Slave: Reset mode, «100» SMS. :
TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2
TIM4->SMCR |= TIM_SMCR_SMS_2; // Reset mode
, : ( , , , ). CCER: CC2P CC2NP, , .

«1» CC2P «0» CC2NP. :
TIM4->CCER &= ~TIM_CCER_CC2NP; // This bit is used in conjunction with CC2P.
TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge
. TIMx_DIER CC2IE «1».

:
TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable
:
TIM4->CR1 |= TIM_CR1_CEN; // TIM4 enable
:
NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable
:
void Timer_Init_Receiver(void)
{
//Settings for GPIO PB7
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // GPIO port B clock enable
GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternative function mode enable
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speed
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // pull-up PB7
GPIOB->AFR[0] |= 0x20000000; // Pin PB7 TIM4 alternative function AF2 enable
//Settings for TIM4
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // TIM4 clock enable
TIM4->PSC = 9; // Prescaler value
TIM4->ARR = 4200; // Auto-reload value
TIM4->CCR2 = 4200; // Capture/Compare 2 value
TIM4->CCMR1 &= ~TIM_CCMR1_OC2M; // Frozen mode enable
TIM4->CCMR1 &= ~TIM_CCMR1_CC2S; // Output mode
TIM4->CCER &= ~TIM_CCER_CC2NP; // This bit is used in conjunction with CC2P.
TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge
TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2
TIM4->SMCR |= TIM_SMCR_SMS_2; // Reset mode
TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable
TIM4->CR1 |= TIM_CR1_CEN; // TIM4 enable
NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable
}
:
, TIMx_SR:
TIM4->SR &= ~TIM_SR_CC2IF;
, . - , . . PB15 , :
GPIOB->MODER |= GPIO_MODER_MODER15_0; // PB15 output mode
:
void TIM4_IRQHandler(void)
{
TIM4->SR &= ~TIM_SR_CC2IF;
GPIOB->ODR |= GPIO_ODR_ODR_15; // Led red on
}
! - , .
void Timer_Init_Transmitter(void);
int main(void)
{
RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable
Timer_Init_Transmitter();
while(1)
{
}
}
void Timer_Init_Transmitter(void)
{
//Settings for GPIO PB6
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable
GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1; //High speed
GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable
//Settings for TIM4 - Slave
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //TIM4 clock enable
TIM4->PSC = 0; //Prescaler value
TIM4->ARR = 75; //Auto-reload value
TIM4->CCR1 = 37; //Capture/Compare 1 value
TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable
TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding output pin
TIM4->SMCR &= ~TIM_SMCR_TS; //clear bits
TIM4->SMCR |= TIM_SMCR_TS_0; //choosing ITR1
TIM4->SMCR &= ~TIM_SMCR_SMS; //clear bits
TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode
TIM4->CR1 |= TIM_CR1_CEN; //TIM4 enable
//Settings for TIM2 - Master
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //TIM2 clock enable
TIM2->PSC = 9; //Prescaler value
TIM2->ARR = 840; //Auto-reload value
TIM2->CCR1 = 75; //Capture/Compare 1 value
TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable
TIM2->CR2 |= TIM_CR2_MMS_2; //OC1REF signal is used as trigger output (TRGO)
TIM2->CR1 |= TIM_CR1_CEN; //TIM2 enable
}
#include “main.h”
void Timer_Init_Receiver(void);
int main(void)
{
RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable
GPIOB->MODER |= GPIO_MODER_MODER15_0; // PB15 output mode
Timer_Init_Receiver();
while(1)
{
}
}
void Timer_Init_Receiver(void)
{
//Settings for GPIO PB7
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // GPIO port B clock enable
GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternative function mode enable
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speed
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // pull-up PB7
GPIOB->AFR[0] |= 0x20000000; // Pin PB7 TIM4 alternative function AF2 enable
//Settings for TIM4
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // TIM4 clock enable
TIM4->PSC = 9; // Prescaler value
TIM4->ARR = 4200; // Auto-reload value
TIM4->CCR2 = 4200; // Capture/Compare 2 value
TIM4->CCMR1 &= ~TIM_CCMR1_OC2M; // Frozen mode enable
TIM4->CCMR1 &= ~TIM_CCMR1_CC2S; // Output mode
TIM4->CCER &= ~TIM_CCER_CC2NP; // This bit is used in conjunction with CC2P.
TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge
TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2
TIM4->SMCR |= TIM_SMCR_SMS_2; // Reset mode
TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable
TIM4->CR1 |= TIM_CR1_CEN; // TIM4 enable
NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable
}
void TIM4_IRQHandler(void)
{
TIM4->SR &= ~TIM_SR_CC2IF;
GPIOB->ODR |= GPIO_ODR_ODR_15; // Led red on
}
, , , , , .
, , "" :
int StatusDiode = 0; // 0 - diode is off, 1 - diode is on
: .
, :
TIM4->DIER |= TIM_DIER_TIE; // Trigger interrupt enable
: .
, , , , , , ( ) .
, : , , , .
, , , , ( CNT), , .
:
void TIM4_IRQHandler(void)
{
if (StatusDiode == 0)
{
TIM4->SR &= ~TIM_SR_TIF;
GPIOB->ODR |= GPIO_ODR_ODR_15; // Led red on
TIM4->DIER &= ~TIM_DIER_TIE; // Trigger interrupt disable
TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable
TIM4->CNT = 0;
StatusDiode = 1;
}
else
{
TIM4->SR &= ~TIM_SR_CC2IF;
GPIOB->ODR &= ~GPIO_ODR_ODR_15; // Led red off
TIM4->DIER &= ~TIM_DIER_CC2IE; // Capture/Compare 2 interrupt disable
TIM4->DIER |= TIM_DIER_TIE; // Trigger interrupt enable
StatusDiode = 0;
}
}
#include “main.h”
void Timer_Init_Receiver(void);
int main(void)
{
RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable
GPIOB->MODER |= GPIO_MODER_MODER15_0; // PB15 output mode
Timer_Init_Receiver();
while(1)
{
}
}
void Timer_Init_Receiver(void)
{
//Settings for GPIO PB7
RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // GPIO port B clock enable
GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternative function mode enable
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speed
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // pull-up PB7
GPIOB->AFR[0] |= 0x20000000; // Pin PB7 TIM4 alternative function AF2 enable
//Settings for TIM4
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // TIM4 clock enable
TIM4->PSC = 9; // Prescaler value
TIM4->ARR = 4200; // Auto-reload value
TIM4->CCR2 = 4200; // Capture/Compare 2 value
TIM4->CCMR1 &= ~TIM_CCMR1_OC2M; // Frozen mode enable
TIM4->CCMR1 &= ~TIM_CCMR1_CC2S; // Output mode
TIM4->CCER &= ~TIM_CCER_CC2NP; // This bit is used in conjunction with CC2P.
TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge
TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2
TIM4->SMCR |= TIM_SMCR_SMS_2; // Reset mode
TIM4->DIER |= TIM_DIER_TIE; // Trigger interrupt enable
TIM4->CR1 |= TIM_CR1_CEN; // TIM4 enable
NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable
}
void TIM4_IRQHandler(void)
{
if (StatusDiode == 0)
{
TIM4->SR &= ~TIM_SR_TIF;
GPIOB->ODR |= GPIO_ODR_ODR_15; // Led red on
TIM4->DIER &= ~TIM_DIER_TIE; // Trigger interrupt disable
TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable
TIM4->CNT = 0;
StatusDiode = 1;
}
else
{
TIM4->SR &= ~TIM_SR_CC2IF;
GPIOB->ODR &= ~GPIO_ODR_ODR_15; // Led red off
TIM4->DIER &= ~TIM_DIER_CC2IE; // Capture/Compare 2 interrupt disable
TIM4->DIER |= TIM_DIER_TIE; // Trigger interrupt enable
StatusDiode = 0;
}
}
, , - . , , , . .