Traccia mapi 09/06/2015

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
la traccia per l'STM32F4: utilizzando l' SPI, configurare il giroscopio per avere un fondo scala di +-500 dp, una banda passante di 25 Hz e un'output data rate di 190 Hz. Dopo aver configurato il giroscopio con questi parametri, leggere i dati relativi all'asse x del giroscopio, con un periodo di campionamento di 50 mss,e inserire i valori letti in un buffer circolare di 100 elementi.
 

megone

Membro
Utente Premium
13 Aprile 2015
34
19
15
l'altra traccia era uguale ma con parametri diversi:
fondo scala +- 2000 dps
ODR 760 Hz e Cut Off 50 Hz
periodo di campionamento 10 ms
Leggere dall'asse z.
 
  • Like
Reactions: poel

chris92

Membro
16 Febbraio 2014
1
1
3
Questa è la traccia che è uscita a me che ho sostenuto l'esame proprio l'8 giugno. Il dispositivo utilizzato è l'F4. Ovviamente ho testato il programma e sembra funzionare. Ecco il procedimento :D

PHP:
/*
Configurare il giroscopio per misurare la velocità angolare del solo asse Z, con fondo scala +-(2000) dps.
Utilizzare un output data rate a 760 Hz e una frequenza di cut-off a 50 Hz.
Acquisire un campione ogni 10 ms, e utilizzare un buffer circolare per la memorizzazione. Esprimere il valore in dps (°C/s).
Raccogliere 100 campioni.
Visualizzare tale buffer nel Live Watch.
*/

#include "stm32f4xx.h"

#define MS_COUNT 42000
#define PERIOD_MS 10
#define N 100

#define GPIOAEN                         1
#define GPIOEEN                         1 << 4
#define TIM2EN                          1
#define SPI1EN                          1 << 12

#define GPIOA_PA5_AF                    1 << 11
#define GPIOA_PA6_AF                    1 << 13
#define GPIOA_PA7_AF                    1 << 15
#define GPIOA_PA5_OSPEED_MAX            0x3 << 10
#define GPIOA_PA6_OSPEED_MAX            0x3 << 12
#define GPIOA_PA7_OSPEED_MAX            0x3 << 14
#define GPIOA_PA5_SPI1_SCK              0x5 << 20
#define GPIOA_PA6_SPI1_MISO             0x5 << 24
#define GPIOA_PA7_SPI1_MOSI             0x5 << 28
#define GPIOA_PA5_PD                    1 << 11
#define GPIOA_PA6_PD                    1 << 13
#define GPIOA_PA7_PD                    1 << 15

#define GPIOE_PE3_OUT                   1 << 6

#define SPI1_SSM                        1 << 9
#define SPI1_SSI                        1 << 8
#define SPI1_SPE                        1 << 6
#define SPI1_BR                         0x3 << 3
#define SPI1_MSTR                       1 << 2
#define SPI1_TXE                        1 << 1
#define SPI1_RXNE                       1

#define TIM2_ARR                        (MS_COUNT * PERIOD_MS) - 1
#define TIM2_PSC                        0
#define TIM2_UIE                        1
#define TIM2_CEN                        1
#define TIM2_UIF                        0
#define TIM2_INT                        1 << 28

#define PE3_CHS                         1 << 3
#define CTRL_REG1_ADDR                  0x20
#define CTRL_REG1_CONF                  0xED
#define CTRL_REG4_ADDR                  0x23
#define CTRL_REG4_CONF                  0x30
#define OUT_Z_L_ADDR                    0x2C
#define RD                              1 << 7
#define DUMMY                           0x00
#define COMP_8BIT_MAX                   256
#define SENSITIVITY                     70

short int data = 0;
short int z_l = 0;
short int z_h = 0;
short int z = 0;
short int buffer[N] = {0};
int cnt = 0;

int main( )
{
  RCC->AHB1ENR |= (GPIOAEN | GPIOEEN); // abilito le due porte (A ed E)
  RCC->APB1ENR |= TIM2EN; // abilito il timer TIM2
  RCC->APB2ENR |= SPI1EN; // abilito SPI1
  GPIOA->MODER |= (GPIOA_PA5_AF | GPIOA_PA6_AF | GPIOA_PA7_AF); // PA5, PA6 E PA7 con Alternate Functions
  GPIOA->OSPEEDR |= (GPIOA_PA5_OSPEED_MAX | GPIOA_PA6_OSPEED_MAX | GPIOA_PA7_OSPEED_MAX); // PA5, PA6 e PA7 con velocità di output massime
  GPIOA->AFR[0] |= (GPIOA_PA5_SPI1_SCK | GPIOA_PA6_SPI1_MISO | GPIOA_PA7_SPI1_MOSI); // PA5, PA6 e PA7 come SPI1_SCK, SPI1_MISO e SPI1_MOSI
  GPIOA->PUPDR |= (GPIOA_PA5_PD | GPIOA_PA6_PD | GPIOA_PA7_PD); // PA5, PA6 e PA7 in pull-down
  GPIOE->MODER |= GPIOE_PE3_OUT; // PE3 come output (Chip Select)
  SPI1->CR1 |= (SPI1_SSM | SPI1_SSI | SPI1_BR | SPI1_MSTR); // SSM = no pin NSS; SSI = sostituisce il pin NSS; BR = Baud Rate; MSTR = Master
  TIM2->ARR = TIM2_ARR; // viene generato un Update Event ogni (TIM_ARR + 1) conteggi
  TIM2->PSC = TIM2_PSC; // Prescaler
  TIM2->DIER |= TIM2_UIE; // viene generata una interrupt per ogni Update Event
  SPI1->CR1 |= SPI1_SPE; // abilito la comunicazione con il giroscopio

  // Configurazione CTRL_REG1
  GPIOE->ODR &= !(PE3_CHS); // abbasso il Chip Select
  while (!(SPI1->SR & SPI1_TXE) & SPI1_TXE); // attendo che il buffer di trasmissione sia libero (!empty)
  SPI1->DR = CTRL_REG1_ADDR; // punto il registro CTRL_REG1 in modalità scrittura
  while (!(SPI1->SR & SPI1_RXNE) & SPI1_RXNE); // attendo che il buffer di ricezione sia non vuoto (!notEmpty)
  data = SPI1->DR; // serve solo a resettare i bit dello SR
  while (!(SPI1->SR & SPI1_TXE) & SPI1_TXE); // attendo che il buffer di trasmissione sia libero (!empty)
  SPI1->DR = CTRL_REG1_CONF; // scrivo la configurazione in CTRL_REG1 impostando l'output data rate e la banda passante richiesti (vedi man. Giroscopio)
                             // abilito anche l'asse Z
  while (!(SPI1->SR & SPI1_RXNE) & SPI1_RXNE); // attendo che il buffer di ricezione sia non vuoto (!notEmpty)
  data = SPI1->DR; // serve solo a resettare i bit dello SR
  GPIOE->ODR |= PE3_CHS; // alzo il Chip Select
  // Configurazione CTRL_REG4
  GPIOE->ODR &= !(PE3_CHS); // abbasso il Chip Select
  while (!(SPI1->SR & SPI1_TXE) & SPI1_TXE); // attendo che il buffer di trasmissione sia libero (!empty)
  SPI1->DR = CTRL_REG4_ADDR; // punto il registro CTRL_REG4 in modalità scrittura
  while (!(SPI1->SR & SPI1_RXNE) & SPI1_RXNE); // attendo che il buffer di ricezione sia non vuoto (!notEmpty)
  data = SPI1->DR; // serve solo a resettare i bit dello SR
  while (!(SPI1->SR & SPI1_TXE) & SPI1_TXE); // attendo che il buffer di trasmissione sia libero (!empty)
  SPI1->DR = CTRL_REG4_CONF; // scrivo la configurazione in CTRL_REG4 impostando il fondo scala specificato
  while (!(SPI1->SR & SPI1_RXNE) & SPI1_RXNE); // attendo che il buffer di ricezione sia non vuoto (!notEmpty)
  data = SPI1->DR; // serve solo a resettare i bit dello SR
  GPIOE->ODR |= PE3_CHS; // alzo il Chip Select
  NVIC->ISER[0] |= TIM2_INT; // abilito la routine di servizio per le interrupt generate da TIM2
  TIM2->CR1 |= TIM2_CEN; // abilito il conteggio del timer TIM2
  while (1);
}

void TIM2_IRQHandler( )
{
  TIM2->SR &= TIM2_UIF; // abbasso il flag Update Interrupt
  // Lettura della velocità angolare dall'asse Z
  GPIOE->ODR &= !(PE3_CHS); // abbasso il Chip Select
  while (!(SPI1->SR & SPI1_TXE) & SPI1_TXE); // attendo che il buffer di trasmissione sia libero (!empty)
  SPI1->DR = (OUT_Z_L_ADDR | RD); // punto il registro OUT_Z_L in modalità lettura
  while (!(SPI1->SR & SPI1_RXNE) & SPI1_RXNE); // attendo che il buffer di ricezione sia non vuoto (!notEmpty)
  data = SPI1->DR; // serve solo a resettare i bit dello SR
  while (!(SPI1->SR & SPI1_TXE) & SPI1_TXE); // attendo che il buffer di trasmissione sia libero (!empty)
  SPI1->DR = DUMMY; // invio un DUMMY, autorizzando il giroscopio a inviare i dati
  while (!(SPI1->SR & SPI1_RXNE) & SPI1_RXNE); // attendo che il buffer di ricezione sia non vuoto (!notEmpty)
  z_l = SPI1->DR; // prelevo i primi 8 bit di Z (sono i meno significativi)
  while (!(SPI1->SR & SPI1_TXE) & SPI1_TXE); // attendo che il buffer di trasmissione sia libero (!empty)
  SPI1->DR = DUMMY; // invio un DUMMY, autorizzando il giroscopio a inviare i dati
  while (!(SPI1->SR & SPI1_RXNE) & SPI1_RXNE); // attendo che il buffer di ricezione sia non vuoto (!notEmpty)
  z_h = SPI1->DR; // prelevo gli ultimi 8 bit di Z (sono i più significativi)
  GPIOE->ODR |= PE3_CHS; // alzo il Chip Select
  z_l = (z_l > COMP_8BIT_MAX - 1 ? -(COMP_8BIT_MAX - z_l) : z_l); // z_l è in complemento a 2
  z_h = (z_h > COMP_8BIT_MAX - 1 ? -(COMP_8BIT_MAX - z_h) : z_h); // z_h è in complemento a 2
  z = ((z_l + (z_h << 8)) * SENSITIVITY) / 1000; // il parametro So (sensitivity) è riportato nel manuale del Giroscopio, e varia in base al fondo scala (FS)
                                                 // inoltre, la grandezza è espressa in milligradi/secondo (noi la vogliamo in gradi/secondo)
  buffer[cnt++] = z; // memorizzo il campione raccolto nel buffer
  cnt %= N; // per la memorizzazione circolare (quando cnt diventa N, si azzera, e si ricomincia da capo)
}
 
Ultima modifica da un moderatore:
  • Like
Reactions: poel

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
Questa invece è la traccia della seconda data di giugno:
Misurare l'intervallo di tempo in cui viene premuto pulsante user e usare tale intervallo di tempo come periodo di campionamento con cui acquisire misure di temperatura in un buffer circolare di 10 elementi in cui va calcolato valore medio e incertezza a degli ultimi 10 elementi
 

Seguici su Facebook