我不知道如何为我的大学项目正确设置 AD 转换器。我应该使用 TRGO 来触发转换,我正在尝试使用 TIM3 来实现。每次我调用 ADC_Init 我都会得到结果,但它会根据与它无关的 PWM 信号而有所不同,我试图根据 ADC 的测量来改变 PWM 信号的 CCR。有关如何正确执行此操作的任何帮助?谢谢!
#include <stdio.h>
#include “stm32f103x6.h”
易失性 int adc_dr;
void ADC_General_Init(ADC_TypeDef * ADCx){
ADCx->CR2 |= ADC_CR2_ADON; // ukljucivanje ADC (izlazak iz rezima power-down) - ADON set
delay(20);
//kalibracija
ADCx->CR2 |= ADC_CR2_CAL;
while ((ADCx->CR2 & ADC_CR2_CAL)==ADC_CR2_CAL);
// iskljucivanje ADC dok se ne podese svi parametri (usteda energije) - ADON reset
ADCx->CR2 &= ~ADC_CR2_ADON;
ADCx->CR2 &= ~ADC_CR2_CONT; // CONT = 0: Single conversion mode - jedna konverzija
// ukljucivanje internog temperaturnog senzora i referentnog napona (strana 235)
ADCx->CR2 |= ADC_CR2_TSVREFE; // TSVREFE bit mpra biti setovan da dozvoli oba interna kanala: ADCx_IN16 (temperature sensor) and ADCx_IN17 (VREFINT) conversion.
// podesavanje konverzije jednog kanala u regularnoj grupi (strana 247)
ADCx->SQR1 &= ~ADC_SQR1_L; // setovanje bitova L[3:0]=0000: 1 konverzija, ADC_SQR1
// odredjivanje kanala 1 (Channel 1) za (prvu) konverziju u regularnoj grupi (strana 249)
ADCx->SQR3 &= ~ADC_SQR3_SQ1; // brisanje bitova
ADCx->SQR3 |= (1U << ADC_SQR3_SQ1_Pos); // setovanje bitova SQ1[4:0] u ADC_SQR3 registru - SQ1 = Channel 1; prvi kanal je u trecem registru
//"Pos" kaze da upisujem 1 (ovde) u bit (pozicija) gde pocinje SQ1 - bit 0;
//Bits 4:0 SQ1[4:0]: first conversion in regular sequence
// hardversko okidanje konverzije (strana 241)
ADCx->CR2 &= ~ADC_CR2_EXTSEL;
ADCx->CR2 |= (0b100U << ADC_CR2_EXTSEL_Pos); // EXTSEL[2:0] = 100: Timer 3 TRGO event
/*----------------ili----------------------
ADC1 -> CR2 &= ~ADC_CR2_EXTSEL;
ADC1 -> CR2 |= ADC_CR2_EXTSEL_2;
---------------------------------------------*/
ADC1 -> CR2 |= ADC_CR2_EXTTRIG; // 1: Conversion on external event enabled (strana 241)
ADCx->CR2 |= ADC_CR2_ADON;// ukljucivanje ADC
}
void ADC_GPIO_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // uključivanje takta za GPIO Port A
// strana 26 u STM32F103_Datasheet.pdf
GPIOA->CRL &= ~(GPIO_CRL_MODE1 | GPIO_CRL_CNF1); // brisanje podešavanja za PA6
GPIOA->CRL |= (GPIO_CRL_MODE1_0 | GPIO_CRL_CNF1_0); //input mode - 00: Analog mode
}
void ADC_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // ukljucivanje ADC1 clock-a
ADC_GPIO_Init();
ADC_General_Init(ADC1);
ADC1->CR1 |= ADC_CR1_EOCIE; // omogucivanje prekida (strana 240)
// postavlja se signal EOC: End of conversion
NVIC_SetPriority(ADC1_IRQn, 1); // dodela prioriteta na 1
//NVIC->ISER[0] |= NVIC_ISER_SETENA_18;
//NVIC_EnableIRQ(ADC1_2_IRQn); // drugi nacin
NVIC_EnableIRQ(ADC1_IRQn); // dozvola prekida ADC 1 & 2 - ista prekidna rutina broj 18 (strana 199)
}
void ADC1_2_IRQHandler(void) {
uint16_t statReg = (ADC1->SR & 0xFFFFU); // citanje statusnog registra
if ((statReg & ADC_SR_EOC) == ADC_SR_EOC) {
adc_dr = (ADC1 -> DR & 0xFFFFU); //cuvamo vrednost data registra u neku promenljivu
//TIM2->CCR4 = adc_dr/10; // treba menjati ovo deljenje
// delimo kako bismo dobili srazmernu promenu
delay(10);
ispisbroja(adc_dr);
delay(1000);
if(adc_dr <=1045){
TIM2->CCR4 = 999;
//ispisbroja(TIM2->CCR4);
}
else if( adc_dr >= 1084){
TIM2->CCR4 = 0;
//ispisbroja(TIM2->CCR4);
}
else{
TIM2->CCR4 = (int)999-(adc_dr-1045)*27,75;
//ispisbroja(TIM2->CCR4);
}
}
}
无效 TIM3_IRQHandler(无效){
ADC_Init();
TIM3 -> SR &= ~TIM_SR_UIF;
}
void adtim1(void){
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Enable the peripheral clock of GPIO Port A
// Hocemo da koristimo tajmer TIM3, u rezimu Toggle Output
//TIM2->CR1 &= ~TIM_CR1_CEN;
// Enable timer 2 clock
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
// Counting direction: 0 = up-counting, 1 = down-counting
//TIM2->CR1 &= ~TIM_CR1_DIR;
TIM3->CR2 &= ~TIM_CR2_MMS; // brisanje master mode selection bitova
TIM3->CR2 |= TIM_CR2_MMS_2; // setovanje OC1REF as trigger output TRGO (OC1REF=100)
// Clock prescaler (16 bits, up to 65,535)
TIM3->PSC = 7999;
//Auto-reload: up-counting (0-->ARR), down-counting (ARR-->e
TIM3->ARR = 2000;
//Upisujemo vrednost u Capture/Compare Register 1 i time podesavamo sirinu impulsa,
// tj. izlaz ce biti 1, dok je vrednost brojaca manja od vrednosti u CCR4
TIM3->CCR2 = 50;
//TIM2->CCR3 = 90;
// Output compare se podešava u registru TIMx_CCMR1 - Capture/Compare Mode Register (za kanale 1 i 2), ili TIMx_CCMR2 (za kanale 3 i 4)
// Polje OC3M[2:0], 011: Toggle - OC4REF toggles when TIMx_CNT=TIMx_CCR4.
TIM3->CCMR1 &= ~TIM_CCMR1_OC2M; // Prvo brisemo bitove za to polje
TIM3->CCMR1 |= (0b110 << TIM_CCMR1_OC2M_Pos); // Upisujemo vrednost 011 od pozicije na kojoj pocinje polje TIM_CCMR2_OC4M
//TIM3->CCMR1 |= 0b01 << TIM_CCMR1_CC2S_Pos;
//TIM3->CCMR2 &= ~TIM_CCMR2_OC4PE;
// Select output polarity: 0 = active high, 1 = active Low
TIM3->CCER &= ~TIM_CCER_CC2P; //OC4 active high
TIM3->CCER |= TIM_CCER_CC2P;
// Enable output for channel 1 , CC4E: Capture/Compare 1 output enable
TIM3->CCER |= TIM_CCER_CC2E; // 1: On - OC4 signal is output on the corresponding output pin.
//TIM3->SMCR |= 0b110 << TIM_SMCR_SMS_Pos;
//TIM3->SMCR |= 0b110 << TIM_SMCR_TS_Pos;
/* TIM2->CCMR2 &= ~TIM_CCMR2_OC3M; // 卡纳尔 3
TIM2->CCMR2 |= (0b011 << TIM_CCMR2_OC3M_Pos); // Upisujemo vrednost 011 od pozicije na kojoj pocinje polje TIM_CCMR2_OC4M
TIM2->CCMR2 &= ~TIM_CCMR2_OC3PE;
// Select output polarity: 0 = active high, 1 = active Low
TIM2->CCER &= ~TIM_CCER_CC3P; //OC4 active high
// Enable output for channel 1 , CC4E: Capture/Compare 1 output enable
TIM2->CCER |= TIM_CCER_CC3E; // 1: On - OC4 signal is output on the corresponding output pin. KANAL 3
*/
// Enable timer 2
//TIM2->CR1 |= (0b01 << TIM_CR1_CMS_Pos);
TIM3->CR1 &= ~TIM_CR1_ARPE;
TIM3->CR1 |= TIM_CR1_CEN;
TIM3->DIER |=TIM_DIER_UIE; //Update Interrupt Enable
TIM3 -> SR &= ~TIM_SR_UIF; //Update Interrupt Flag
//TIM3->DIER |=TIM_DIER_TIE; //Update Interrupt Enable
//TIM3 -> SR &= ~TIM_SR_TIF; //Update Interrupt Flag
NVIC_EnableIRQ(TIM3_IRQn); //Interrupt Set-Enable Register
__enable_irq(); //Enable Interrupt
}