Salutations, dans cet article, vous apprendrez: comment créer un capteur de mouvement à l'aide d'une diode IR et d'un récepteur IR sur un STM32 avec une utilisation minimale du noyau (c'est-à-dire avec une charge maximale sur la périphérie) sur les registres, à l'aide de minuteries.
L'article traite des problèmes de programmation avec autant de détails que possible. Le matériel est conçu pour le niveau d'entraînement débutant, mais convient également aux plus expérimentés. Certains détails sont cachés sous des spoilers pour réduire la charge sur l'article.
Table des matières:
Fonctionnement de la diode IR et du récepteur IR
La grande image
Deux appareils sont utilisés: un émetteur de signal IR et un récepteur de signal IR.
Le principe général de fonctionnement est le suivant: un émetteur de signal IR émet un signal dans la gamme de longueurs d'onde infrarouge, et un récepteur de signal IR les reçoit. Un "faisceau" est formé entre ces dispositifs dont l'intersection par tout objet est fixée par le dispositif récepteur.
TSAL6200 est utilisé comme diode IR et TSOP4856 comme récepteur IR.
Diagrammes d'appareils
.
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;
}
}
, , - . , , , . .