Raccolta sorgenti - MAPI schiano lo moriello UNINA

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
Qui raccoglieremo tutti i codici delle esercitazioni proposte nei laboratori di Mapi dal prof Schiano

Da questo link potete scaricare la cartella con il template per l'st32f401

Accensione di 4 led a seconda dell'incremento del contatore

PHP:
#include "stm32f4xx.h"
int cont = 0;
int main (void){
  RCC->AHB1ENR |= 9;   //Abilitiamo GPIOD (led) e GPIOA (bottone)
  GPIOD->MODER |= (1<<30); //configuriamo il pin 15 di tipo GP OUTPUT MODE
  GPIOD->MODER |= (1<<28);//configuriamo il pin  14 di tipo GP OUTPUT MODE
  GPIOD->MODER |= (1<<26);//configuriamo il pin  13 di tipo GP OUTPUT MODE
  GPIOD->MODER |= (1<<24);//configuriamo il pin  12 di tipo GP OUTPUT MODE
  //non configuriamo il pin  1 di tipo GP INPUT MODE, poichè è impostato di default
  while(1){
    while (!(GPIOA->IDR &= 1));  //aspetto che venga premuto un tasto
    while (GPIOA->IDR &= 1);     //aspetto che venga rilasciato
    cont ++;
    if(cont==1)                 //accendo il relativo led
      GPIOD->ODR |= 1<<15;
    if(cont==2)
      GPIOD->ODR |= 1<<14;
    if(cont==3)
      GPIOD->ODR |= 1<<13;
    if(cont==4)
      GPIOD->ODR |= 1<<12;
    if(cont==5){
      GPIOD->ODR &= 0000<<12;
      cont=0;
    }
  }
}
UNINA
 
Ultima modifica:

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
CONTATORE MODULO 4
PHP:
#include "stm32f4xx.h"
int cont = 0;
int main (void){
  RCC->AHB1ENR |= 9;   //Abilitiamo GPIOD (led) e GPIOA (bottone)
  GPIOD->MODER |= (1<<30); //configuriamo il pin 15 di tipo GP OUTPUT MODE
  GPIOD->MODER |= (1<<28);//configuriamo il pin  14 di tipo GP OUTPUT MODE
  GPIOD->MODER |= (1<<26);//configuriamo il pin  13 di tipo GP OUTPUT MODE
  GPIOD->MODER |= (1<<24);//configuriamo il pin  12 di tipo GP OUTPUT MODE
  //non configuriamo il pin  1 di tipo GP INPUT MODE, poichè è impostato di default
  while(1){
    while (!(GPIOA->IDR &= 1));  //aspetto che venga premuto un tasto
    while (GPIOA->IDR &= 1);     //aspetto che venga rilasciato
    cont ++;
    GPIOD->ODR = (cont % 16) << 12;
  } 
}
 
Ultima modifica:

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
Accendiamo i 4 led con un interrupt che si attiva alla pressione del pulsante

il processore non rimane in attesa per la pressione del pulsante
PHP:
#include "stm32f4xx.h"

//devo definire cosa fa questa routine,
//il cui prototipo è contenuto nel file di startup
void EXTI0_IRQHandler();

int main (void){
  RCC->AHB1ENR |= 0x9; //abilito il clock per portd e il pulsante 1001
  RCC->APB2ENR |= (1<<14);// abilito syscfg (per le interrupt)

  GPIOD->MODER |= (0x55<<24); //configuro i pin 12 13 14 15 in GPIO
  EXTI->IMR |= 1; //maschero il primo bit (per il pulsante)
  SYSCFG->EXTICR[0]&=!(0xF);
  EXTI->RTSR |= 1; //scelgo il fronte di salita (per il pin 0)
  NVIC->ISER[0] |= (1<<6); //devo servire la routine in posizione [0]6 dell'NVIC
  while(1);
}

void EXTI0_IRQHandler(){
    EXTI->PR |= 1; //disabilito il pending request
    GPIOD->ODR |= (0xF<<12); //1111 sul bit 12 13 14 15
}


Accendiamo i 4 led con un interrupt che si attiva cortocircuitando pb6 e pb7 (jumper)
PHP:
#include "stm32f4xx.h"

//devo definire cosa fa questa routine,
//il cui prototipo è contenuto nel file di startup
void EXTI9_5_IRQHandler();

int main (void){
  RCC->AHB1ENR |= 0x8; //abilito il clock per portD
  RCC->AHB1ENR |= 0x2; //abilito il clock per portB
  RCC->APB2ENR |= (1<<14);// abilito syscfg (per le interrupt)

  GPIOD->MODER |= (0x55<<24); //configuro i pin 12 13 14 15 in GPIO
 
  EXTI->IMR |= 1<<7; //maschero il 7 bit (per il jumper)
  SYSCFG->EXTICR[1] |= 1<<12; //indico che su exti7 voglio la linea B (pB7)
  EXTI->RTSR |= 1<<7; //scelgo il fronte di salita (per il pin 7)
  NVIC->ISER[0] |= (1<<23); //devo servire la routine in posizione [0]23 dell'NVIC
  while(1);
}

void EXTI9_5_IRQHandler(){
    EXTI->PR |= 1<<7; //disabilito il pending request
    GPIOD->ODR |= (0xF<<12); //1111 sul bit 12 13 14 15
}
 
Ultima modifica:

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
Timer
accendo e spengo il led sul pin 15 con un timer ,accendo il led 14 se viene premuto il plusante

PHP:
#include "stm32f4xx.h"

void EXTI0_IRQHandler();
void sleep(float, int);

//accensione di un led
int main (void){

  RCC->AHB1ENR |=0X9;  //Abilito porta A  e D
  RCC->APB1ENR |=1; // Abilito TIM2 da 32 bit
  RCC->APB2ENR |=1<<14 ; // Abilito syscfg per abilitare le interruzioniEXTI
  GPIOD->MODER |=0x55<<24; // Abilito le luci in output

  EXTI->IMR |= 1; // Interrupt Mask Register metto 1 in 0 perché servo EXTI0
  EXTI->RTSR |=1; // FRONTE DI SALITA EXTI0
  SYSCFG->EXTICR[0] |= 0; // EXTICR 0 vuol dire EXTI1, metto 0 per abilitare pa0
  NVIC->ISER[0] |= 1<<6; // Sceglie l'elemento dentro l NVIC da servire
   TIM2->PSC = 0;
   TIM2->ARR = 48000000;
   TIM2->CR1 |= 1;  //Abilito il timer mettendo a 1 CEN
   TIM2->CNT = 0; //inizializzo il conteggio
   while(1){
     if((TIM2->SR & 1) != 0){

        if((GPIOD->ODR & (1<<15)) == 0)
          GPIOD->ODR |= 1<<15;

        sleep(1,1);

        if((GPIOD->ODR & (1<<15)) != 0)
          GPIOD->ODR &= ~(1<<15);

        sleep(1,1);
     }

   }
}


void EXTI0_IRQHandler(){
     EXTI->PR |= 1; // Disabilito il PR per non andare in loop

     /*per controllare un registro lo metto in AND (bit a bit) con tutti 0 tranne 1 nella posizione in cui controllo */

     if((GPIOD->ODR & (1<<14)) == 0)
      GPIOD->ODR |= 1<<14;

    sleep(1,1);

    if((GPIOD->ODR & (1<<14)) != 0)
      GPIOD->ODR &= ~(1<<14);

    sleep(1,1);

}

void sleep(float mhz, int sec){
    float hz = mhz*1000000;
    float t = 1/hz;
    int i = 0;
    for(i = 0; i < (int)sec/t; i++);
}




Timer con interrupt
Gestiamo un led con un timer, il cui autoreload register si incrementa se premo il pulsante. Sia il timer che il pulsante sono gestiti con interrupt
PHP:
#include "stm32f4xx.h"
#include <stdbool.h>
//usiamo un timer per accendere e spegnere un led e un interrupt generata dal pulsante  per incrementare il prescaler

void EXTI0_IRQHandler();
void TIM2_IRQHandler();

int setPrescaler = 0;
bool isOn = 0;

int main (void){

  RCC->AHB1ENR |= 9;            //abilito portA e portD
  RCC->APB2ENR |= (1<<14);      //Syscfg en
  RCC->APB1ENR |= 1;            //abilito TIM2

  //configurazione Led
  GPIOD->MODER |= 0x55000000;   //imposto i pin 12 13 14 15 come gpOutput

  //configurazione interruzione esterna su PA0
  EXTI->IMR |= 1;               //non maschero EXTI0
  SYSCFG->EXTICR[0] &= 0;       //seleziono PA0 come sorgente di interrupt per EXTI0
  EXTI->RTSR |= 1;              //seleziono il fronte di salita per generare l'interrupt
  NVIC->ISER[0] |= (1<<6);      //seleziono la routine da servire

  //configurazione timer
  TIM2->CR1 |= (1<<2);          //no software update
  TIM2->CNT = 0;                //inizializzo il contatore a 0
  TIM2->PSC = setPrescaler;     //inizializza il prescaler
  TIM2->ARR = 36000000;         //imposta l'autoreload register
  TIM2->DIER |= 1;              //update interrupt enable
  NVIC->ISER[0] |= (1<<28);     //seleziono la routine da serviere
  TIM2->CR1 |= 1;                //counter enable


  while(1);
}


void EXTI0_IRQHandler(){
  EXTI->PR |= 1;                 //puliamo il Pending Register (da manuale si fa mettendo 1)
  setPrescaler++;                //incrementa il valore del  prescaler
  TIM2->PSC = setPrescaler;      //aggiorna il prescaler
  GPIOD->ODR |= (1<<13);         //accendiamo il led per notificare l'interrupt
}


void TIM2_IRQHandler(){
  TIM2->SR &= 0;                //abbassiamo il flag dell'interrupt
  if (!isOn){                   //ogni volta che il timer raggiunge arr controllo se il led è acceso o meno
     GPIOD->ODR |= (1<<14);
     isOn = 1;
  }else{
     GPIOD->ODR &= (0<<14);
     isOn = 0;
  }


}



Poichè non mi è chiara la frequenza con cui lavora TIM2 ho fatto altre prove e questo sembra misurare esattamente un secondo
(TIM2->ARR = (42000000/1.55); // 1 sec)

PHP:
#include "stm32f4xx.h"

//usiamo un timer per accendere e spegnere un led e un interrupt generata dal pulsante  per incrementare il prescaler

void EXTI0_IRQHandler();
void TIM2_IRQHandler();

int isOn = 0;

int main (void){
  //abilitazione dei bus
  RCC->AHB1ENR |= 0x9; //ablito portA e portD
  RCC->APB2ENR |= 1<<14;//abilito SYSGEN per le interrupt
  RCC->APB1ENR |= 1; //abilito TIM2

  //configuro le GPIO
  GPIOD->MODER |= 1<<30;

  //gestione interrupt pulsante
  EXTI->IMR |= 1; //Maschero la linea0
  EXTI->RTSR |= 1; //l'interrupt scatta sul fronte di salita
  NVIC->ISER[0] |= 1<<6; //servo l'interrupt 6 del vettore NVIC

  //settaggio timer
  TIM2->ARR = (42000000/1.55); // 1 sec
  TIM2->CNT = 0; //inizializzo il conteggio a 0
  TIM2->PSC = 0; //prescaler all'inizio vale 0 (alla frequenza impostata lampeggia ogni secondo)
  TIM2->DIER = 1; //abilito le interrupt
  NVIC->ISER[0] |= 1<<28; //servo la 28 routine nel vettore NVIC

  TIM2->CR1 |= 1; //abilito il conteggio

  while(1);





}

void EXTI0_IRQHandler(){
  EXTI->PR = 1; //pulisco il pending request
  TIM2->PSC += 1; //incremento il prescaler di  1 (dimezzando la frequenza)
}

void TIM2_IRQHandler(){
  TIM2->SR &= 0; //pulisco lo status register che si è alzato alla fine di ogni conteggio

  if(isOn == 0){
     GPIOD->ODR |= 1<<15;
     isOn = 1;
  }else if(isOn == 1){
    GPIOD->ODR &= 0<<15;
    isOn = 0;
  }
}


Prova d'esame svolta
PHP:
/*                 PROVA D'ESAME MAPI 26 GENNAIO 2015
Mettere il jumper su pa0 e pa2 e attraverso la pressione del pulsante si
scatena l interruzione di pa2 che deve contare quanto tempo passa da quando
premi a quando rilasci.. il risultato deve essere mostrato modulo 16
attraverso i led.

                            SVOLGIMENTO
Mettere il Jumper JP3 o JP4 (si trovano sul retro dello schedino) su PA0 e PA2
*/


#include "stm32f4xx.h"

void EXTI2_IRQHandler(); //routine per la gestone dell'interrupt su exti2
void TIM2_IRQHandler(); //routine per la gestione dell'interrupt su TIM2

int counter = 0;        //conta quanti secondi sono passati
int counterIsOn = 0;     //valore booleano per capire se è iniziato o meno il conteggio

int main () {
  //abiito il clock per le periferiche
  RCC->AHB1ENR |= 0x9; 
  RCC->APB2ENR |= 1<<14;
  RCC->APB1ENR |= 1;
 
  //configuro i led
  GPIOD->MODER |= 85<<24;  
 
  //configuro l'interrupt su pa2
  EXTI->IMR |= 1<<2;
  EXTI->RTSR |= 1<<2;  //la routine scatta sia sul fonte di salita che di discesa
  EXTI->FTSR |= 1<<2;  //ossia quando inizio a premere e quando rilascio il pulsante
  NVIC->ISER[0] |= 1<<8;   //servo la routine in posizione 8 dell'nvic
 
  //configuro il timer
  TIM2->ARR = (42000000/1.55); //il timer genera un interruzione ogni secondo
  TIM2->CNT = 0;
  TIM2->PSC = 0;
  TIM2->DIER |= 1;  //abilito le interruzioni
  NVIC->ISER[0] |= 1<<28;  //servo l'interrupt in posizione 28 dell'nvic
 
  while(1);
}

void EXTI2_IRQHandler(){
  EXTI->PR |= 1<<2;
  if(counterIsOn == 0){  //è l'interruzione generata per l'inizio conteggio->bottone premuto)
    TIM2->CR1 |= 1;
    counterIsOn = 1;
   
  }else if(counterIsOn == 1){//è l'interruzione generata per la fine conteggio->bottone rilasciato)
    GPIOD->ODR &= !(0xf)<<12;//spengo i led se prima erano accesi (conteggio precedente)
    TIM2->CR1 &= 0; //disabilito il conteggio
    counterIsOn = 0;
    GPIOD->ODR |= (counter%16)<<12; //mostro il valore del contatore modulo 16 sui led
    counter = 0;  //resetto il contatore
  }
 
}

void TIM2_IRQHandler(){
  TIM2->SR &=0;
  counter++;
}
 
Ultima modifica:

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
DMA
PHP:
#include "stm32f4xx.h"
#define DIM 500

#define CTCIF0 (uint32_t) 0x20
// #define CTCIF0 1<<5

int source[DIM];
int destination[DIM];

int i; //short int è a 16 bit

int main(void){
RCC->AHB1ENR |= 1<<22; //ABILITO DMA2

//SCRIVO I DATI NELLA MEMORIA

for(i=0;i<DIM;i++){
source[i]=i;
}
DMA2_Stream0->CR |= 10<<13; //IMPOSTO MSZIE A 32BIT
DMA2_Stream0->CR |= 10<<11; //IMPOSTO PSIZE A 32BIT
DMA2_Stream0->CR |= 1<<10; //ABILITO MINC
DMA2_Stream0->CR |=1<<9; //ABILITO PINC
DMA2_Stream0->CR |=10<<6; //IMPOSTO LA DIRECTION : MEM->MEM

DMA2_Stream0->PAR = (uint32_t) source; //pongo in PAR L'INDIRIZZO DELLA SORGENTE
DMA2_Stream0->M0AR = (uint32_t) destination; //PONGO IN M0AR L'INDIRIZZO DELLA DESTINAZIONE
DMA2_Stream0->NDTR =(uint32_t) DIM; //IMPOSTO IL NUMERO DI TRANSFERIMENTI

DMA2_Stream0->CR |= 1; //ABILITO LO STREAM0

while((DMA2->LISR & CTCIF0)== CTCIF0){ //SE IL TRANSFERIMENTO VIENE COMPLETATO ABBASSO IL FLAG TC
DMA2->LIFCR |= CTCIF0;
}



}
 
Ultima modifica:

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
ADC + timer
PHP:
#include "stm32f4xx.h"

//si effetuino misurazioni di tensione su PA1 campionando ogni 1 secondi
float misura = 0;


int main()
{
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  RCC->APB2ENR |= RCC_APB2ENR_ADC1EN ;
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;

  //Configuro pa1 come output analogico
  GPIOA->MODER |= (GPIO_MODER_MODER1_0|GPIO_MODER_MODER1_1);

  ADC1->CR2 |= (ADC_CR2_EXTEN_0); //TRIGGER SUL FRONTE DI SALITA
  ADC1->CR2 |= (ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_2); //TIMER2 TRG0 EVENT
  //ADC1->CR2 |= ADC_CR2_CONT ;//MODALITA' CONTINUA , non necessaria
  ADC1->SMPR2 |= (ADC_SMPR2_SMP1_0 | ADC_SMPR2_SMP1_1 |ADC_SMPR2_SMP1_2); //480 CICLI
  ADC1->SQR3 |= 1;


  //configuro il timer2
  TIM2->ARR = 42000000;
  TIM2->PSC = 0;
  TIM2->CNT = 0;
  TIM2->CR2 |= TIM_CR2_MMS_1; //Master mode selection ->output
  TIM2->CR1 |= 1;

  ADC1->CR2 |= (ADC_CR2_ADON);

  ADC1->CR2 |= (ADC_CR2_SWSTART);

  while (1){
    misura =  ADC1->DR;
  }
}


ADC - TEMPERATURA

Semplice misura continua di temperatura
PHP:
#include "stm32f4xx.h"

#define EOCS    0x00000400
#define CONT    0x00000002
#define SWSTART 0x40000000
#define EOC     0x00000002

double misura;
double temperatura = 0;

int main()
{
  RCC->APB2ENR |= 1 << 8;
  ADC->CCR |= 1 << 23;
  ADC1->CR2 |= (EOCS | CONT);
  ADC1->SMPR1 |= 0x001C0000;
  ADC1->SQR3 = 16;
  ADC1->CR2 |= 1;
  ADC1->CR2 |= SWSTART;
  while((ADC1->SR != EOC)){
  misura = ADC1->DR;                           // il valore di questa tensione è millivolt
  misura = (misura*3)/4096.0;              
                                           
  temperatura = ((misura - 0.76)/0.0025) + 25; 
  }

}

PHP:
#include "stm32f4xx.h"

//misuriamo il valore di temperatura alla pressione del tasto user (tramite interrupt)

void EXTI0_IRQHandler(void);
void ADC_IRQHandler(void);

float risultato = 0;
int risultato_dr = 0;
float temp=0;
int main (void){
  RCC->AHB1ENR |= 1; //abilito il bus su cui si trova portA
  RCC->APB2ENR |=(1<<8); //ADC1
  RCC->APB2ENR |=(1<<14); //SYSCFG

  GPIOA->MODER |= 0x3<<2;     
  EXTI->IMR |= 1;               //NON MASCHERO PA0
  EXTI->RTSR |= 1;              //TRIGGER SALITA PA0
  SYSCFG->EXTICR[0] &= ~0xF;    //seleziono pa0 nel multiplexer (predefinito)
  NVIC->ISER[0] |= 1<<6;        //ABILITO INTERRUPT SU EXT0


  ADC1->CR1 |= 1<<5;            //l'adc genera le interrupt
  ADC1->SMPR1 |= 7<<24;       //480 CICLI
  ADC1->SQR3 |= 0x10;            //IL 16 CANALE è dedicato al sensore di temp
  NVIC->ISER[0] |= 1<<18;
  ADC->CCR |= 1<<23;
  ADC1->CR2 |= 1;               //ACCENDO L'ADC

    while(1);
}

void EXTI0_IRQHandler(void){
  EXTI->PR |= 1;                //PULIRE PENDING REG
  ADC1->CR2 |= 1<<30;           //ADC START
}


void ADC_IRQHandler(void){
  //devi pulire il reg
  risultato_dr=ADC1->DR;
  risultato = (((float)risultato_dr *3) / 4096.0 );
  temp= ((risultato - 0.76)/0.0025) + 25;
}



ADC+DMA+TIMER


PHP:
DMA+TIMER

#include "stm32f4xx.h"
#define N 1000

#define CTCIF0 (uint32_t) 0x20
// #define CTCIF0 1<<5
#define CUIF (uint32_t) 0x1

short int destination[N]; //short perchè il dato della conversione è codificato su 16 bit
int i;

int main(void){
RCC->AHB1ENR |= 1<<22; //ABILITO DMA2
RCC->APB2ENR |= 1<<8; //ABILITO ADC1
RCC->APB1ENR |= 1; //ABILITO TIM2
DMA2_Stream0->CR |= 1<<13;//0x2000; //IMPOSTO MSIZE A 16BIT
DMA2_Stream0->CR |= 1<<11;//0x800; //IMPOSTO PSIZE A 16BIT
DMA2_Stream0->CR |= 1<<10; //ABILITO MINC
DMA2_Stream0->CR |= 1<<5; //Dò IL CONTROLLO DEL FLUSSO ALLA PERIFERICA
DMA2_Stream0->NDTR = N;
DMA2_Stream0->PAR = (uint32_t) (&ADC1->DR);
DMA2_Stream0->M0AR = (uint32_t)destination;

RCC->AHB1ENR |= 1; //ABILITO PORTA A
GPIOA->MODER |= 11<<2; // IMPOSTO PA1 INPUT ANALOGICO

//CONFIGURIAMO L'ADC
ADC1->CR2 |= 1<<9; //ABILITO DDS
ADC1->CR2 |= 1<<8; //ABILITO DMA
ADC1->CR2 |= 1<<28; //SCELGO IL FRONTE DI DISCESA DEL TRIGGER ESTERN
ADC1->CR2 |= 11<<25; //ABILITO TIM2 COME TRG0
ADC1->SMPR2 |=(uint32_t) 0x38; //IMPOSTO IL TEMPO DI SAMPLING A 480 CICLI
ADC1->SQR3 |= 1;
DMA2_Stream0->CR |= 1; //ABILITO LO STREAM0
ADC1->CR2 |= 1; //ACCENDO ADC

//CONFIGURO TIM2

TIM2->ARR = 420000; //ABILITO IL TIMER PER AVERE 1 CONVERSIONE OGNI 10MS
TIM2->PSC =0;
TIM2->CR2 |= 1<<5; //ABILITO L'UPDATE EVENT PER DARE IL TRIGGER DI OUTPUT
TIM2->CR1 |= 1; //FACCIO PARTIRE IL TIMER
//TIM2->CR1 |= 1<<2; NON BISOGNA DISABILITARE UDIS

while(1);

}
 
Ultima modifica:

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
SPI+GIROSCOPIO

PHP:
SPI+GIROSCOPIO

#include "stm32f4xx.h"
#define N 1000
#define SPI1RSTR 0x1000
#define CS_LO (uint16_t) 0x8

short int data=0;
short int cont=8;
short int x,y,z;

int main(void){
RCC->AHB1ENR |= 1; //ABILITO PORTA A PERCHè SPC,MISO E MOSI DI SPI1 SONO COLLEGATI A PA5,PA6,PA7
RCC->AHB1ENR |= 1<<4; //ABILITO PORTA E (PER DARE IL CH SELECT AL GIROSCOPIO)
RCC->APB2ENR |= 1<<12; //ABILITO SPI1
RCC->APB2RSTR |= SPI1RSTR; //RESETTO IL CLOCK DI SPI1
RCC->APB2RSTR &= !(SPI1RSTR); //RESETTO IL CLOCK DI SPI1

//CFG PORTA A
GPIOA->MODER |= 1<<11; //IMPOSTO PA5 COME ALTERNATE FUNCTION
GPIOA->MODER |= 1<<13; //IMPOSTO PA6 COME ALTERNATE FUNCTION
GPIOA->MODER |= 1<<15; //IMPOSTO PA7 COME ALTERNATE FUNCTION
GPIOA->AFR[0] |= 0x55500000; //SELEZIONO L'AF5 PER I PA5/6/7
GPIOA->PUPDR |= 1<<11; //IMPOSTO PULL-DOWN PER PA5
GPIOA->PUPDR |= 1<<13; //IMPOSTO PULL-DOWN PER PA6
GPIOA->PUPDR |= 1<<15; //IMPOSTO PULL-DOWN PER PA7
GPIOA->OSPEEDR |= 0xFC00; //IMPOSTO PA5/6/7 ALLA MASSIMA VELOCITà

//CFG PORTA E
GPIOE->MODER |=1<<6; //IMPOSTO PE3 COME OUTPOUT DIGITALE

//CFG SPI1
SPI1->CR1 |=1<<9; //SSM=1 -> ABILITO LA SELEZIONE DELLO SLAVE VIA SOFTWARE
SPI1->CR1 |=1<<8; //ABILITO SSI (SE METTO SSM=1 ANCHE QUESTO DEVE ESSERE 1)
SPI1->CR1 |= 0x18; //IMPOSTO IL BAUD RATE A 1/16
SPI1->CR1 |=1<<2; //ABILITO IL BIT MASTER
SPI1->CR1 |= 1<<6; //SPI ENABLE

//ESEMPIO DI COMUNICAZIONE CON IL GIROSCOPIO CON SPI

GPIOE->ODR &= !(CS_LO); //ABBASSO CH SELECT
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0x20; //"PUNTO" IL REGISTRO CTRL_REG1 DEL GIROSCOPIO IN MODALITà SCRITTURA;
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR;
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0xf; //abilito PD e i 3 assi XYZ
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //leggo il dato ricevuto (è inutile in questo caso)
GPIOE->ODR |= CS_LO; //Alzo CH SELECT


GPIOE->ODR &= !(CS_LO); //ABBASSO CH SELECT
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0xA0; //"PUNTO" IL REGISTRO CTRL_REG1 DEL GIROSCOPIO IN MODALITà LETTURA;
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //leggo il dato ricevuto (è inutile in questo caso)
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0x1; //invio un dummy
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR;
GPIOE->ODR |= CS_LO; //Alzo CH SELECT
while(1){
//VOGLIAMO LEGGERE X - Y - Z

//LETTURA DI X
GPIOE->ODR &= !(CS_LO); //ABBASSO CH SELECT
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0xA8; //"PUNTO" IL REGISTRO OUT_X_L DEL GIROSCOPIO IN MODALITà LETTURA;
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //leggo il dato ricevuto (è inutile in questo caso)
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0x1; //invio un dummy
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //RICEVO IL VALORE X_L
GPIOE->ODR |= CS_LO; //Alzo CH SELECT
x=(uint16_t)data;

GPIOE->ODR &= !(CS_LO); //ABBASSO CH SELECT
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0xA9; //"PUNTO" IL REGISTRO OUT_X_H DEL GIROSCOPIO IN MODALITà LETTURA;
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //leggo il dato ricevuto (è inutile in questo caso)
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0x1; //invio un dummy
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //RICEVO IL VALORE X_H
GPIOE->ODR |= CS_LO; //Alzo CH SELECT
x|=(uint16_t)data<<8;
//LETTURA DI Y
GPIOE->ODR &= !(CS_LO); //ABBASSO CH SELECT
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0xAA; //"PUNTO" IL REGISTRO OUT_Y_L DEL GIROSCOPIO IN MODALITà LETTURA;
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //leggo il dato ricevuto (è inutile in questo caso)
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0x1; //invio un dummy
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //RICEVO IL VALORE Y_L
GPIOE->ODR |= CS_LO; //Alzo CH SELECT
y=(uint16_t)data;

GPIOE->ODR &= !(CS_LO); //ABBASSO CH SELECT
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0xAB; //"PUNTO" IL REGISTRO OUT_Y_H DEL GIROSCOPIO IN MODALITà LETTURA;
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //leggo il dato ricevuto (è inutile in questo caso)
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0x1; //invio un dummy
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //RICEVO IL VALORE Y_H
GPIOE->ODR |= CS_LO; //Alzo CH SELECT
y|=(uint16_t)data<<8;
//LETTURA DI Z
GPIOE->ODR &= !(CS_LO); //ABBASSO CH SELECT
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0xAC; //"PUNTO" IL REGISTRO OUT_Z_L DEL GIROSCOPIO IN MODALITà LETTURA;
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //leggo il dato ricevuto (è inutile in questo caso)
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0x1; //invio un dummy
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //RICEVO IL VALORE Z_L
GPIOE->ODR |= CS_LO; //Alzo CH SELECT
z=(uint16_t)data;

GPIOE->ODR &= !(CS_LO); //ABBASSO CH SELECT
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0xAD; //"PUNTO" IL REGISTRO OUT_Z_H DEL GIROSCOPIO IN MODALITà LETTURA;
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //leggo il dato ricevuto (è inutile in questo caso)
while(((SPI1->SR)&0x2)==0); //attendo che il buffer di trasmissione sia vuoto
SPI1->DR = (uint16_t) 0x1; //invio un dummy
while(((SPI1->SR)&0x1)==0); //attendo che il buffer di ricezione sia vuoto
data = SPI1->DR; //RICEVO IL VALORE Z_H
GPIOE->ODR |= CS_LO; //Alzo CH SELECT
z|=(uint16_t)data<<8;
}


}
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
I2C+ACCELEROMETRO

PHP:
I2C+ACCELEROMETRO

#include "stm32f4xx.h"

#define BUSY 0x2
#define SB (uint16_t)0x1
#define ADDR (uint16_t)0x2
#define TxE (uint16_t) 0x80
#define BTF (uint16_t)0x4
#define TC (uint16_t)0x2
#define RxNE (uint16_t) 0x40
#define X_L (uint16_t) 0x28

short int dummy16,x,y,z;
short int data[6];

int main(void){
RCC->AHB1ENR |= 1<<1; //ABILITO PORTA B
RCC->APB1ENR |= 1<<21; //ABILITO I2C1

//CONFIG GPIOB
GPIOB->MODER |= 1<<13; //AF PER PB6
GPIOB->MODER |= 1<<19; //AF PER PB9
GPIOB->OTYPER |=1<<6;
GPIOB->OTYPER |=1<<9;
GPIOB->PUPDR |=1<<12; //PB6 OD+PU
GPIOB->PUPDR |=1<<18; //PB9 OD+PU
GPIOB->AFR[0] |=1<<26; //IMPOSTO AF4 PER PB6
GPIOB->AFR[1] |=1<<6; //IMPOSTO AF4 PER PB9

//CFG I2C
I2C1->CR2 |=1<<3; //FREQ I2C1 8MHZ
I2C1->CCR |=0x28; //28ex=40dec con 8mhz ho 125nanosecondi*40=5000ns=5ms mi serve 5ms
I2C1->CCR |=1<<15; //IMPOSTO FASTMODE
I2C1->TRISE |=0x9; //IMPOSTO LA DURATA DEL FRONTE DI SALITA A 1ms
I2C1->CR1 |=1; //ABILITO LA PERIFERICA
//I2C1->CR1 |=0;

//ESEMPIO DI COMUNICAZIONE CON L'ACCELEROMETRO CON I2C
while((I2C1->SR2&BUSY)==BUSY); //ATTENDE CHE L'I2C1 SIA LIBERO
I2C1->CR1 |= (uint16_t)0x100; //START
while(((I2C1->SR1)&SB)!=SB); //CONDIZIONE DI START
dummy16=I2C1->SR1; //leggendo lo SR lo azzero
I2C1->DR=(uint8_t)0x32; //INVIO L'INDIRIZZO DELL'ACCELEROMETRO MOD. W
while((I2C1->SR1&ADDR)!=ADDR); //ATTENDO CHE IL TRASFERIMENTO DELL'INDIRIZZO TERMINI
dummy16=I2C1->SR1; //leggendo lo SR lo azzero
dummy16=I2C1->SR2; //leggendo lo SR lo azzero
while((I2C1->SR1&TxE)!=TxE); //ATTENDO CHE IL CANALE DI TRASMISSIONE SIA VUOTO
I2C1->DR=(uint8_t)0x20; //PUNTO IL REGISTRO CTRL_REG1_A DELL'ACCELEROMETRO
while((I2C1->SR1&TxE)!=TxE); //ATTENDO CHE IL CANALE DI TRASMISSIONE SIA VUOTO
I2C1->DR=(uint8_t)0x17; //INVIO LA CONFIGURAZIONE DEL REGISTRO - ABILITO X-Y-Z(7) E POWERMODE A 1Hz
while((I2C1->SR1&(TxE|BTF))!=(TxE|BTF)); // CONTROLLO CHE IL TRANSFERIMENTO VENGA TERMINATO
I2C1->CR1 |=(uint16_t)(1<<9); //STOP


//CONTROLLO DELLA CONFIGURAZIONE
/* while((I2C1->SR2&BUSY)==BUSY); //ATTENDE CHE L'I2C1 SIA LIBERO
I2C1->CR1 |= (uint16_t) (1<<8); //START
while((I2C1->SR1&SB)!=SB); //CONDIZIONE DI START
dummy16=I2C1->SR1; //leggendo lo SR lo azzero
I2C1->DR=(uint8_t)0x32; //INVIO L'INDIRIZZO DELL'ACCELEROMETRO MOD. W
while((I2C1->SR1&ADDR)!=ADDR); //ATTENDO CHE IL TRASFERIMENTO DELL'INDIRIZZO TERMINI
dummy16=I2C1->SR1; //leggendo lo SR lo azzero
dummy16=I2C1->SR2; //leggendo lo SR lo azzero
while((I2C1->SR1&TxE)!=TxE); //ATTENDO CHE IL CANALE DI TRASMISSIONE SIA VUOTO
I2C1->DR=(uint8_t)0x20; //PUNTO IL REGISTRO CTRL_REG1_A DELL'ACCELEROMETRO
while((I2C1->SR1&(TxE|BTF))!=(TxE|BTF)); // CONTROLLO CHE IL TRANSFERIMENTO VENGA TERMINATO
I2C1->CR1 |= (uint16_t) (1<<8); //RESTART
while((I2C1->SR1&SB)!=SB); //CONDIZIONE DI START
dummy16=I2C1->SR1; //leggendo lo SR lo azzero

I2C1->DR=(uint8_t)0x33; //INVIO L'INDIRIZZO DELL'ACCELEROMETRO MOD. R
while((I2C1->SR1&ADDR)!=ADDR); //ATTENDO CHE IL TRASFERIMENTO DELL'INDIRIZZO TERMINI
dummy16=(uint16_t)I2C1->SR1; //leggendo lo SR lo azzero
dummy16=(uint16_t)I2C1->SR2; //leggendo lo SR lo azzero

while((I2C1->SR1&RxNE)!= RxNE); //ATTENDO CHE IL CANALE DI ricezione non SIA VUOTO
dummy16=I2C1->DR; //LEGGO LA CONFIG
while((I2C1->SR1&(TxE|BTF))!=(TxE|BTF)); // CONTROLLO CHE IL TRANSFERIMENTO VENGA TERMINATO
I2C1->CR1 |= (uint16_t) (1<<9); //STOP
*/
//LETTURA DELLE COORDINAE X-Y-Z

while(1){
//LETTURA DI X

while((I2C1->SR2&BUSY)==BUSY); //ATTENDE CHE L'I2C1 SIA LIBERO
I2C1->CR1 |= (uint16_t) (1<<8); //START
while((I2C1->SR1&SB)!=SB); //CONDIZIONE DI START
dummy16=I2C1->SR1; //leggendo lo SR lo azzero
I2C1->DR=(uint8_t)0x32; //INVIO L'INDIRIZZO DELL'ACCELEROMETRO MOD. W
while((I2C1->SR1&ADDR)!=ADDR); //ATTENDO CHE IL TRASFERIMENTO DELL'INDIRIZZO TERMINI
dummy16=I2C1->SR1; //leggendo lo SR lo azzero
dummy16=I2C1->SR2; //leggendo lo SR lo azzero

while((I2C1->SR1&TxE)!=TxE); //ATTENDO CHE IL CANALE DI TRASMISSIONE SIA VUOTO
I2C1->DR=(uint8_t)((0x80)|X_L); //PUNTO IL REGISTRO X_L in modalità MULTIPLA
while((I2C1->SR1&(TxE|BTF))!=(TxE|BTF)); // CONTROLLO CHE IL TRANSFERIMENTO VENGA TERMINATO
I2C1->CR1 |= (uint16_t) (1<<8); //RESTART
while((I2C1->SR1&SB)!=SB); //CONDIZIONE DI START
dummy16=I2C1->SR1; //leggendo lo SR lo azzero

I2C1->CR1 |= (uint16_t) (1<<10); // SICCOME è LETTURA MULTIPLA DEVO ABILITARE L'ACK
I2C1->DR=(uint8_t)0x33; //INVIO L'INDIRIZZO DELL'ACCELEROMETRO MOD. R
while((I2C1->SR1&ADDR)!=ADDR); //ATTENDO CHE IL TRASFERIMENTO DELL'INDIRIZZO TERMINI
dummy16=(uint16_t)I2C1->SR1; //leggendo lo SR lo azzero
dummy16=(uint16_t)I2C1->SR2; //leggendo lo SR lo azzero

for(int i=0;i<6;i++){
while((I2C1->SR1&RxNE)!= RxNE); //ATTENDO CHE IL CANALE DI ricezione non SIA VUOTO
data[i]=I2C1->DR; // RICEVO I VALORI DI X-Y-Z IN SEQUENZA
if(i==4)
I2C1->CR1 &= (uint16_t)~(1<<10); // SE I=4 VUOL DIRE CHE STO ALLA PENULTIMA RICEZIONE QUINDI DEVO INVIARE NOTACK ALLA PROSSIMA PER TERMINARE LA RICEZIONE
}
I2C1->CR1 |= (uint16_t) (1<<9); //STOP
x=((int16_t)((uint16_t)data[1]<<8)+data[0])/16; // ho messo il segno
y=((int16_t)((uint16_t)data[3]<<8)+data[2])/16;
z=((int16_t)((uint16_t)data[5]<<8)+data[4])/16;
}
}
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
USART
PHP:
USART

#include "stm32f4xx.h"

char rcv;
char tx='0';
#define TXEMP 0x80
#define RXNEMP 0x20

int main (void){

RCC->APB1ENR |= (1<<17); //ABILITO USART 2
RCC->AHB1ENR |= 1; //ABILITO PORTA A PERCHè PA3 (RX) E PA2(TX) (VEDI QUALI PIN ABILITARE DAL DATASHEET)

//CONFIGURAZIONE DEI PIN PA2 E PA3

GPIOA->MODER |= (0xA0); //IMPOSTO PA2 E PA3 COME AF
GPIOA->AFR[0] |= (0x7700); //SELEZIONO LE AF7 DI PA2 E PA3 (LO VEDI DAL DATASHEET)

//PER I CALCOLI VEDI PAG 510 RM
USART2->BRR |= ((0x2D0)|(0x9)); //IMPOSTO DIN_INT E DIV_FRAC RISPETTIVAMENTE A 45 E 9 (VEDI TAB 73 RM CON Fclock A 42MHZ)
USART2->CR1 |= ((1<<13)|(1<<3)|(1<<2)); // ABILITO USART (UE) TXE E RXE

while(1){
while(!(USART2->SR & TXEMP)); //ATTENDO CHE IL CANALE DI TX SIA VUOTO
USART2->DR = ++tx; //INVIO IL DATO
while(!(USART2->SR & RXNEMP)); //ATTENDO CHE IL CANALE DI RX SIA PIENO
rcv=USART2->DR; //RICEVO IL DATO
}

}
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
ADC
PHP:
ADC

#include "stm32f4xx.h"
#define EOC (uint32_t) 0x2

int misura;

int main (void){
misura=0;

RCC->AHB1ENR |= 1;
RCC->APB2ENR |= 1<<8; //ABILITO ADC1

GPIOA->MODER |= 11<<2; //PA1 è IMPOSTATO COME INPUT ANALOGICO

ADC1->SQR3 |= 1; //SELEZIONO CH1
ADC1->CR2 |= 1<<10; // SELEZIONO UNA CONVERSIONE

ADC1->SMPR2 |= (uint32_t) 0x38; //IMPOSTO LA VELOCITà DEL CANALE 1 A 480 CICLI

ADC1->CR2 |= 1;
ADC1->CR2 |= 1<<30;

while((ADC1->SR & EOC) == EOC){
misura=(ADC1->DR);
}
while(1);
}
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
ADC+INTERRUPT
PHP:
ADC+INTERRUPT

#include "stm32f4xx.h"
#define EOC (uint32_t) 0x2

int misura;

void ADC_IRQHandler(void);

int main (void){
misura=0;

RCC->AHB1ENR |= 1;
RCC->APB2ENR |= 1<<8; //ABILITO ADC1

GPIOA->MODER |= 11<<2; //PA1 è IMPOSTATO COME INPUT ANALOGICO

ADC1->SQR3 |= 1; //SELEZIONO CH1
ADC1->CR2 |= 1<<10; // SELEZIONO UNA CONVERSIONE

ADC1->SMPR2 |= (uint32_t) 0x38; //IMPOSTO LA VELOCITà DEL CANALE 1 A 480 CICLI

ADC1->CR1|= 1<<5; //Abilito l'interrupt al termine della conversione
RCC->APB2ENR|=1<<14;
NVIC->ISER[0]|=1<<18; //Abilito la routine di servizio per l'ADC
ADC1->CR2 |= 1;
ADC1->CR2 |= 1<<30;

/*while((ADC1->SR & EOC) == EOC){
misura=(ADC1->DR);
}*/
while(1);
}

void ADC_IRQHandler(void){
misura=(ADC1->DR);
}
 

Vectoryzed

Membro
2 Aprile 2014
4
0
1
Il codice sull'USART non funziona... l'istruzione:

PHP:
USART2->DR = ++tx; //INVIO IL DATO

non mette nulla nel registro DR dell'USART, e quindi non va avanti (perchè il bit TXE del registro USART->SR rimane sempre a 1), bloccandosi conseguentemente sul while:

PHP:
while(!(USART2->SR & RXNEMP)); //ATTENDO CHE IL CANALE DI RX SIA PIENO


A voi parte?
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
Traccia 1 svolta
PHP:
/*Configurare il convertitore AD per misurare ogni secondo (gestito con Timer2) la temperatura mediante il sensore interno.
Configurare il DMA in maniera tale da trasferire automaticamente i campioni dall'ADC a un blocco di memoria di 10 elementi gestiti in modalità buffer circolare.
Configurare il tasto USER come sorgente di interrupt. Alla prima pressione si avvia il processo di misura. Alla seconda pressione si interrompe e
si visualizzano il valore medio e l'incertezza di categoria A della temperatura. */

#include <stm32f4xx.h>
#include "math.h"

#define N 10
short int dest[N]={0};
void EXTI0_IRQHandler(void);
int flag=1;
int media=0;
float incertezzaA=0;
int i=0;

int main (void){
RCC->AHB1ENR |=1; //ABILITO PORTE A
RCC->APB2ENR |= (1<<14); //ABILITO SYSCFG
RCC->AHB1ENR |= (1<<22); //ABILITO DMA2 (da tab 28 del dma vedo che adc1 si trova in dma2 stream0)
RCC->APB2ENR |=(1<<8); //ABILITO ADC1
RCC->APB1ENR |=1; //ATTIVO TIMER2

//CONFIGURAZIONE DMA2
DMA2_Stream0->CR |= (1<<13); //MSIZE 16BIT
DMA2_Stream0->CR |= (1<<11); //PSIZE 16BIT
DMA2_Stream0->CR |= (1<<10); //MINC
//DMA2_Stream0->CR |= (1<<5); //Controllo alla periferica( non uso PINC altrimenti andrei a leggere registri al di fuori del DR dell' ADC)
DMA2_Stream0->CR |=(1<<8); //BUFFER CIRCOLARE
DMA2_Stream0->NDTR=N; //TRASFERIMENTI DA COMPIERE
DMA2_Stream0->PAR=(uint32_t)(&(ADC1->DR)); //& PER L'INDIRIZZO
DMA2_Stream0->M0AR=(uint32_t)dest;
DMA2_Stream0->CR |=1; //Abilitazione EN
//Per ora non succede nulla perchè DR è ancora vuoto

//CONFIGURAZIONE TIMER2
TIM2->CR1 |=(1<<2); //NOSWUPD
TIM2->CR2 |= (1<<5); //TRGOEN : 010: Update - The update event is selected as trigger output (TRGO).
// For instance a master timer can then be used as a prescaler for a slave timer.
TIM2->PSC=1;
TIM2->ARR =36000000;

//CONFIGURAZIONE ADC1

ADC1->SQR3 |= (1<<4); //To use the sensor: Select ADC1_IN16 or ADC1_IN18 input channel.
ADC1->SMPR2 |= (0x7)<<3; //Select a sampling time greater than the minimum sampling time specified in the datasheet.
ADC->CCR |= (1<<23); //Set the TSVREFE bit in the ADC_CCR register to wake up the temperature sensor from power down mode

ADC1->CR2 |=(1<<9); //DDS
ADC1->CR2 |=(1<<8); //DMA

ADC1->CR2 |=(1<<28); //IL TRIGGER SI DEVE ATTIVARE SOLO SUL FRONTE DI SALITA.
ADC1->CR2 |=0x6000000; //VOGLIAMO DIRE QUANDO INIZIARE LA CONVERSIONE PER IL GRUPPO DI CANALI REGOLARI.
//NEL NOSTRO CASO STIAMO USANDO TIMER2
//QUINDI VOGLIAMO TIMER2 TRGO EVENT (0110)

//CONFIGURAZIONE EXTI0
//PA0 E' IN INPUT QUINDI NON DEVO IMPOSTARE NULLA.
EXTI->IMR |= 1; //NON MASCHERO PA0
EXTI->RTSR |= 1; //TRIGGER SALITA PA0
SYSCFG->EXTICR[0] &= ~0xF; //seleziono pa0 nel multiplexer (predefinito)
NVIC->ISER[0] |= 1<<6; //ABILITO INTERRUPT SU EXT0

while(1);
}

void EXTI0_IRQHandler(void) {
if(flag) {
EXTI->PR |=1;
ADC1->CR2 |=1; //ADON
TIM2->CR1 |=1; //EN TIMER2
ADC1->CR2 |=(1<<30); //SWSTART
flag=0; }
else{
ADC1->CR2 &=~ 1; //SPENGO ADC
//media
for(i=0; i<N; i++) {
media=media+dest[i];
media=media/N;
//incertezzaA
for (i=0; i<N; i++){
incertezzaA=incertezzaA+pow(dest[i]-media,2);
incertezzaA=pow(incertezzaA/N, 0.5); }
}
flag=1; }
}
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
traccia 2 svolta
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)
}
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
traccia 3 svolta
PHP:
#include "stm32f4xx.h"
#include "stdbool.h"

//Configurare l'ADC per campionare ogni secondo due canali di ingresso selezionabili alternativamente mediante il pulsante PA0.
//In particolare, devono essere acquisiti i canali collegati al sensore di temperatura e alla batteria del microcontrollore.
//Visualizzare i valori misurati mediante il live watch, facendo in modo che il canale inattivo indichi un codice pari alla matricola del candidato.

void EXTI0_IRQHandler();


char selectChannel[1] = {'T'};
float temperatura_dr = 0.0;
float temperatura = 0.0;

//float batteria = 0;


//accensione di un led
int main (void){
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
  RCC->APB2ENR |= RCC_APB2ENR_ADC1EN ;
  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
 
  //setto l'interrupt su PA0
  EXTI->IMR |= EXTI_IMR_MR0;
  EXTI->RTSR |= EXTI_RTSR_TR0;
  NVIC->ISER[0] |= 1<<6;
 
 

  //setto l'ADC
  ADC1->CR2 |= ADC_CR2_EXTEN_0;  //TRIGGER SUL FRINTE DI SALITA
  ADC1->CR2 |= (ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_2); //TIM2 TRGO EVENT
  ADC1->SMPR1 |= (ADC_SMPR1_SMP18_0 |ADC_SMPR1_SMP18_1 | ADC_SMPR1_SMP18_2 ); //480 CICLI per il canale 18
  ADC1->SQR3 |= (ADC_SQR3_SQ1_1 | ADC_SQR3_SQ1_4); //SELEZIONO IL CANALE 18 COME PRIMO DELLA SEQUENZA
 
  ADC->CCR |= ADC_CCR_TSVREFE;
 
  ADC1->CR2 |= ADC_CR2_ADON;
 
 
 
  //setto il timer
  TIM2->ARR = 42000000;
  TIM2->PSC = 0;
  TIM2->CNT = 0;
  TIM2->CR2 |= TIM_CR2_MMS_1 ; //MASTER MODE SELECTION = UPDATE
  TIM2->CR1 |= 1;
  ADC1->CR2 |= (ADC_CR2_SWSTART);
   
 
  while(1){
      temperatura = ADC1->DR;
  }
}



void EXTI0_IRQHandler(){
  EXTI->PR = EXTI_PR_PR0;
  if(selectChannel[0] == 'B'){
   
    ADC->CCR |= ADC_CCR_VBATE; //SWITCH SULLA BATTERIA
   
    selectChannel[0] = 'T';
  }else{
    /*ABBASSANDO IL BIT SULLA BATTERIA PASSA AUTOMATICAMENTE A QUELLO DELLA TEMPERATURA
   
    */
    ADC->CCR &= !(ADC_CCR_VBATE);
   
    selectChannel[0] = 'B';
  }

}
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
//IncertezzaA
//Essa è data dalla deviazione standard, ovvero la radice quadrata positiva della varianza
for(i=0; i<N; i++)
incertezzaA = incertezzaA + pow(dest-media,2);
incertezzaA = pow(incertezzaA/N,1.2);
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
non calcola bene l'incertezza
Codice:
/*Configurare il convertitore AD per la misurazione di temperatura interna
Configurare il funzionamento con trigger (fornito da evento update di TIM2) e trasferimento dati in memoria con DMA
Configurare la seconda parte della propria matricola come intervallo di campionamento espresso in ms
Es. Matr NXX/000234 --> periodo di campionamento = 234 ms
Acquisire la temperatura per un intervallo di 10s
Visualizzare nel live watch valori acquisiti, valore medio e incertezza di categoria A */

#include "stm32f4xx.h"  
#include "math.h"
#define N 5

void TIM2_IRQHandler();

float dest[N];

float misura = 0.0;
float media = 0.0;
float incertezzaA= 0;

int status = 0;
int counter = 0;


int main (void)
{
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN ;
  RCC->APB1ENR |= (RCC_APB1ENR_TIM2EN );
  RCC->APB2ENR |=(1<<8); //ABILITO ADC1
  RCC->AHB1ENR |= (1<<22); //ABILITO DMA2
  GPIOD->MODER |= (GPIO_MODER_MODER14_0 ); //accendo un led quando termina la conversione
  //CONFIGURAZIONE DMA2
  DMA2_Stream0->CR |= (DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_1 | DMA_SxCR_MINC | DMA_SxCR_CIRC  ); 
  DMA2_Stream0->NDTR=N; //TRASFERIMENTI DA COMPIERE
  DMA2_Stream0->PAR=(uint32_t)(&(ADC1->DR)); //& PER L'INDIRIZZO
  DMA2_Stream0->M0AR=(uint32_t)dest;
  DMA2_Stream0->CR |=1; //Abilitazione EN
  //Per ora non succede nulla perchè DR è ancora vuoto
  //configuro timer2
  TIM2->ARR = (42000000/1.55)*0.292; //periodo pari alle ultime tre cifre della mia matricola - 10 sec sono 34.24 volte questo valore (10/0.292 = 34.24...)
  TIM2->DIER |=1;
  TIM2->CR2 |= (1<<5);
  NVIC->ISER[0] |= 1<<28;
  //CONFIGURAZIONE ADC1

ADC1->SQR3 |= (1<<4); //To use the sensor: Select ADC1_IN16 or ADC1_IN18 input channel.
ADC1->SMPR2 |= (0x7)<<3; //Select a sampling time greater than the minimum sampling time specified in the datasheet.
ADC->CCR |= (1<<23); //Set the TSVREFE bit in the ADC_CCR register to wake up the temperature sensor from power down mode

ADC1->CR2 |=(1<<9); //DDS
ADC1->CR2 |=(1<<8); //DMA

ADC1->CR2 |=(1<<28); //IL TRIGGER SI DEVE ATTIVARE SOLO SUL FRONTE DI SALITA.
ADC1->CR2 |=0x6000000;

ADC1->CR2 |=1; //ADON
TIM2->CR1 |=1; //EN TIMER2
ADC1->CR2 |=(1<<30); //SWSTART

  while(1);
}

void TIM2_IRQHandler(){
  TIM2->SR &= 0;
  counter++;
  if (counter == 34){ //dopo 10 secondi
    ADC1->CR2 &=0; 
    TIM2->CR1 &=0;
    ADC1->CR2 &=(0<<30);
   
    GPIOD->ODR |= 1<<14;
   
   
    for(int i=0;i<N;i++)
      media += dest[i];
       
     media /= N;
     
     //IncertezzaA
  //Essa è data dalla deviazione standard, ovvero la radice quadrata positiva della varianza
  for(int i=0; i<N; i++)
    incertezzaA = incertezzaA + pow(dest[i]-media,2);
  incertezzaA = pow(incertezzaA/N,1.2);  
   
  }
}
 

poel

Administrator
Staff Forum
Utente Premium
29 Maggio 2013
493
1
87
28
incertezza by tore
PHP:
/*
Configurare il convertitore AD per la misurazione di temperatura interna
Configurare il funzionamento con trigger (fornito da evento update di TIM2) e trasferimento dati in memoria con DMA
Configurare la seconda parte della propria matricola come intervallo di campionamento espresso in ms
Es. Matr NXX/000234 --> periodo di campionamento = 234 ms  -->N46/001471 --->471ms
Acquisire la temperatura per un intervallo di 10s
Visualizzare nel live watch valori acquisiti, valore medio e incertezza di categoria A
*/

#include "stm32f4xx.h"
#include "math.h"
#define N (uint32_t)(10/0.296)

int cont = 0;
float misura[N] = {0};
float valoreMedio = 0;
float incertezzaA = 0;

int main(void){
  /* abilito le periferiche */
  RCC->AHB1ENR |= 1<<22; // DMA2
  RCC->APB1ENR |= 1; // TIM2
  RCC->APB2ENR |= 1<<8; // ADC1
 
  /*configuro TIM2 */
  TIM2->CR2 |= 1<<5; //MMS -- event update
  TIM2->DIER |= 1; // update interrupt enable
  NVIC->ISER[0] |= 1<<28; // TIM2 global interrupt
 
  TIM2->ARR = (int)(42000000)*0.296;
  TIM2->CR1 |= 1; // CEN
 
  /*configuro ADC1 */
  ADC1->CR2 |= 6<<24; // TRGO TIM2
  ADC1->CR2 |= 1<<10; // EOCS
  ADC1->CR2 |= 1<<9; // DDS
  ADC1->CR2 |= 1<<8; // DMA
  ADC1->CR2 |= 1; // ADON
 
  /*configuro il sensore di temperatura interno */
  ADC1->SQR3 = 16; // canale 16
  ADC1->SMPR1 |= 7<<18; // 480 cicli
  ADC->CCR |= 1<<23; // TSVREFE
 
  /*configuro il DMA2 */
  DMA2_Stream0->NDTR = N; // numero trasmissioni
  DMA2_Stream0->PAR = (uint32_t)&(ADC1->DR); // source
  DMA2_Stream0->M0AR = (uint32_t)misura; // dest
 
  DMA2_Stream0->CR |= 1<<14; //MSIZE
  DMA2_Stream0->CR |= 1<<12; //PSIZE
  DMA2_Stream0->CR |= 1<<10; //MINC
  DMA2_Stream0->CR |= 1<<8; //CIRC
 
  while(cont < N){ //fino a che non ho fatto N conversioni...
 
    if(TIM2->SR & 1){ // update event
   
      TIM2->SR &= 0; // update event reset
      DMA2_Stream0->CR |= 1; // Enable DMA2 - effettuo l'i-esima trasmissione
      cont++; // passso alla successiva...
    }
 
  }
  float x = 0; // var. appoggio
 
  // Valore Medio
  for(int i = 0; i < N; i++)
    x+=misura[i];
 
  valoreMedio = x / N;
 
  // Incertezza A
  for(int i = 0; i < N; i++)
    x+=((misura[i]-valoreMedio)*(misura[i]-valoreMedio));
 
  x/=(N)*(N-1);
 
  incertezzaA = sqrt(x);
 
  return 0;
}
void TIM2_IRQHandler(){
 
  ADC1->CR2 |= 1<<30; // SWSTART avvio conversione
  TIM2->SR &= 0; // update event reset
}
 
  • Like
Reactions: crazy

Manveru9

Membro
1 Luglio 2015
10
2
3
DMA
PHP:
#include "stm32f4xx.h"
#define DIM 500

#define CTCIF0 (uint32_t) 0x20
// #define CTCIF0 1<<5

int source[DIM];
int destination[DIM];

int i; //short int è a 16 bit

int main(void){
RCC->AHB1ENR |= 1<<22; //ABILITO DMA2

//SCRIVO I DATI NELLA MEMORIA

for(i=0;i<DIM;i++){
source[i]=i;
}
DMA2_Stream0->CR |= 10<<13; //IMPOSTO MSZIE A 32BIT
DMA2_Stream0->CR |= 10<<11; //IMPOSTO PSIZE A 32BIT
DMA2_Stream0->CR |= 1<<10; //ABILITO MINC
DMA2_Stream0->CR |=1<<9; //ABILITO PINC
DMA2_Stream0->CR |=10<<6; //IMPOSTO LA DIRECTION : MEM->MEM

DMA2_Stream0->PAR = (uint32_t) source; //pongo in PAR L'INDIRIZZO DELLA SORGENTE
DMA2_Stream0->M0AR = (uint32_t) destination; //PONGO IN M0AR L'INDIRIZZO DELLA DESTINAZIONE
DMA2_Stream0->NDTR =(uint32_t) DIM; //IMPOSTO IL NUMERO DI TRANSFERIMENTI

DMA2_Stream0->CR |= 1; //ABILITO LO STREAM0

while((DMA2->LISR & CTCIF0)== CTCIF0){ //SE IL TRANSFERIMENTO VIENE COMPLETATO ABBASSO IL FLAG TC
DMA2->LIFCR |= CTCIF0;
}



}


Ragazzi buonasera, esiste un modo per verificare manualmente che una volta fatto partire lo stream in memoria si trovino i dati che abbiamo voluto trasferire?
Ho provato a cercare nella finestra Disassembly al lato, non ci ho capito molto. Qualcuno ha piu dimistichezza con l'IDE ?
GRAZIE !
 

Seguici su Facebook