/*
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
SOLUZIONE ADOTTATA: si configura il TIM2 per contare a una frequenza di 1 MHz quindi con risoluzione di 1 us.
(considerando come Clock di base HSI a 16MHz e settando Prescaler a 15). Ad ogni numero di
millisecondi corrispondente alla matricola (nell'esempio 234 ms) il Counter raggiunge il valore di ARR e genera un trigger TRGO
che viene recepito come segnale di start dall'ADC1. Ogni volta che si resetta il counter viene incrementato un indice che serve
per contare i 10 secondi (questo per evitare l'uso di un altro timer da sincronizzare).
A quel punto spengo il timer e faccio i calcoli richiesti.
ALTERNATIVA: il conto degli N cicli per raggiungere i 10 secondi, invece che con 2 while può essere gestito in una routine TIM2_IRQHandler
che viene eseguita ad ogni evento di update, quindi ogni volta che viene generato il trigger.
*/
#include "stm32f4xx.h"
#define MATRICOLA 234
#define N 10000/MATRICOLA //contando in ms, 10 sec = 10000 ms, che si raggiungono dopo N misurazioni
int media;
int i=0;
int incertezza;
short int buffer[N];
int main (void){
//N=(10000/MATRICOLA)
//ATTIVAZIONE PERIFERICHE
RCC->APB2ENR |= 1<<8; //ADC1
RCC->APB1ENR |= 1; //TIM2
RCC->AHB1ENR |= 1<<21; //DMA1
//CONFIG DMA1
DMA1_Stream0->CR |= 1<<13; //MSIZE a 16bit
DMA1_Stream0->CR |= 1<<11; //PSIZE a 16bit
DMA1_Stream0->CR |= 1<<10; //MINC
DMA1_Stream0->CR |= 1<<5; //controllo del DMA affidato alla periferica (in questo caso TIM2)
DMA1_Stream0->NDTR = N;
DMA1_Stream0->PAR = (uint32_t)(&ADC1->DR);
DMA1_Stream0->M0AR = (uint32_t) buffer;
//CONFIG ADC1
ADC1->CR2 |= 6<<24; //seleziono Trigger TRGO di TIM2
ADC1->CR2 |= 1<<28; //attivo su fronte di salita
ADC1->SQR3 |= 0x10; // canale 16 (o 18) - 1° in sequenza
ADC1->CR2 |= 1<<8; //DMA
ADC1->CR2 |= 1<<9; //DDS
DMA2_Stream0->CR |= 1; //ABILITO LO STREAM0
ADC1->CR2 |= 1; //Accendo ADC
ADC->CCR |= 1<<23; //Accendo Sens Temp.
//CONFIG TIM2
TIM2->PSC =0xF; //Timer clock a 1MHz (16/(15+1))
TIM2->ARR = MATRICOLA*1000; //visto che a 1 MHz ogni ciclo dura 1 us, moltiplico per 1000 per contare in ms
TIM2->CR2 |= 1<<5; //Trigger TRGO in corrispondenza di Update
TIM2->CR1 |= 1; //Inizia il conteggio
while (i!=N){
//si conta ogni volta che il Counter viene azzerato
while (TIM2->CNT != 0){} //finchè non si raggiunge il numero di misurazioni
//che si contano in 10 secondi (10000/MATRICOLA)
i++;
}
TIM2->CR1 |= 0; //spengo il timer
//media
for(i=0; i<N; i++) {
media=media+buffer[i];
media=media/N;
}
//incertezzaA
for (i=0; i<N; i++){
incertezza=incertezza+pow(buffer[i]-media,2);
incertezza=pow(incertezza/N, 0.5);
}
while(1);
}
L'ho testato e il programma in sé funziona e condivido il ragionamento, ma dopo le acquisizioni i valori di media e incertezza mi sembrano sballati. O forse sono io impedito, sia chiaro!Ho provato a svolgere la seconda traccia. Non avendo fisicamente lo schedino non posso testarla quindi non assicuro la correttezza. C'è qualcuno disposto a fare delle prove? Magari date un vostro parere in merito.
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 SOLUZIONE ADOTTATA: si configura il TIM2 per contare a una frequenza di 1 MHz quindi con risoluzione di 1 us. (considerando come Clock di base HSI a 16MHz e settando Prescaler a 15). Ad ogni numero di millisecondi corrispondente alla matricola (nell'esempio 234 ms) il Counter raggiunge il valore di ARR e genera un trigger TRGO che viene recepito come segnale di start dall'ADC1. Ogni volta che si resetta il counter viene incrementato un indice che serve per contare i 10 secondi (questo per evitare l'uso di un altro timer da sincronizzare). A quel punto spengo il timer e faccio i calcoli richiesti. ALTERNATIVA: il conto degli N cicli per raggiungere i 10 secondi, invece che con 2 while può essere gestito in una routine TIM2_IRQHandler che viene eseguita ad ogni evento di update, quindi ogni volta che viene generato il trigger. */ #include "stm32f4xx.h" #define MATRICOLA 234 #define N 10000/MATRICOLA //contando in ms, 10 sec = 10000 ms, che si raggiungono dopo N misurazioni int media; int i=0; int incertezza; short int buffer[N]; int main (void){ //N=(10000/MATRICOLA) //ATTIVAZIONE PERIFERICHE RCC->APB2ENR |= 1<<8; //ADC1 RCC->APB1ENR |= 1; //TIM2 RCC->AHB1ENR |= 1<<21; //DMA1 //CONFIG DMA1 DMA1_Stream0->CR |= 1<<13; //MSIZE a 16bit DMA1_Stream0->CR |= 1<<11; //PSIZE a 16bit DMA1_Stream0->CR |= 1<<10; //MINC DMA1_Stream0->CR |= 1<<5; //controllo del DMA affidato alla periferica (in questo caso TIM2) DMA1_Stream0->NDTR = N; DMA1_Stream0->PAR = (uint32_t)(&ADC1->DR); DMA1_Stream0->M0AR = (uint32_t) buffer; //CONFIG ADC1 ADC1->CR2 |= 6<<24; //seleziono Trigger TRGO di TIM2 ADC1->CR2 |= 1<<28; //attivo su fronte di salita ADC1->SQR3 |= 0x10; // canale 16 (o 18) - 1° in sequenza ADC1->CR2 |= 1<<8; //DMA ADC1->CR2 |= 1<<9; //DDS DMA2_Stream0->CR |= 1; //ABILITO LO STREAM0 ADC1->CR2 |= 1; //Accendo ADC ADC->CCR |= 1<<23; //Accendo Sens Temp. //CONFIG TIM2 TIM2->PSC =0xF; //Timer clock a 1MHz (16/(15+1)) TIM2->ARR = MATRICOLA*1000; //visto che a 1 MHz ogni ciclo dura 1 us, moltiplico per 1000 per contare in ms TIM2->CR2 |= 1<<5; //Trigger TRGO in corrispondenza di Update TIM2->CR1 |= 1; //Inizia il conteggio while (i!=N){ //si conta ogni volta che il Counter viene azzerato while (TIM2->CNT != 0){} //finchè non si raggiunge il numero di misurazioni //che si contano in 10 secondi (10000/MATRICOLA) i++; } TIM2->CR1 |= 0; //spengo il timer //media for(i=0; i<N; i++) { media=media+buffer[i]; media=media/N; } //incertezzaA for (i=0; i<N; i++){ incertezza=incertezza+pow(buffer[i]-media,2); incertezza=pow(incertezza/N, 0.5); } while(1); }