mmihai94 Posted June 20, 2017 Share Posted June 20, 2017 Salutare. De cateva zile imi bat capul sa inteleg timerele si sistemul de intreruperi din ATSAM3X8E, dar ma cam depasesc. Vreu sa masor intarzierea intre doua semnale PWM aplicate la doua intrari diferite. Nu stiu cum sa fac asta. M-am gandit la o varianta ,folosesc un timer pe care il pornesc pe frontul crescator al unuia dintre semnale si il opresc tot pe frontul crescator al celullalt semnal. Am gasit pe net exemple care masoara frecventa, perioada, factor de umplere etc, dar toare folosesc doar o intrare pentru masura. Atasez un exemplu care masoara frecventa si care ar merge modificat cumva, dar..... A mai facut careva chestia asta? Am incercat sa modific pinul pe care se citeste frecventa, dar nici macar asta nu reusesc. Am pus PIOA->PIO_PDR = PIO_PA5A_TIOA2; PIOA->PIO_IDR = PIO_PA5A_TIOA2; in void pio_TIOA1() si nu schimba nimic. Am citit si pe aici, dar ma prind. https://forum.arduino.cc/index.php?topic=130423.120https://forum.arduino.cc/index.php?topic=386981.0https://arduino.stackexchange.com/questions/8782/how-to-use-timer1-at328mega-to-measure-the-time-between-rising-edges-of-two-inhttps://forum.arduino.cc/index.php?topic=480228.0https://forum.arduino.cc/index.php?topic=400516.0http://forum.arduino.cc/index.php?topic=80239.0 HELP!!! volatile uint32_t tmr_RA = 0; volatile uint32_t tmr_RB = 0; void setup() { Serial.begin (115200); Btmr_setup(); pio_TIOA1(); // IN, AN - 7 (max 3.3V -> keep safe !!!). } void loop() { uint32_t period = tmr_RB / 42; uint32_t duty_c = (100 * (tmr_RB - tmr_RA)) / tmr_RB; uint32_t freq = 42000000UL/ tmr_RB; Serial.print("\n\tPeriod: "); Serial.print(period, DEC); Serial.print("\tmicroseconds"); Serial.print("\n\tDuty Cycle: "); Serial.print(duty_c, DEC); Serial.print("\t%"); Serial.print("\n\tFrequency: "); Serial.print(freq, DEC); delay(1000); } void TC1_Handler(void) { if ((TC_GetStatus(T C0, 1) & TC_SR_LDRBS) == TC_SR_LDRBS) { tmr_RA = TC0->TC_CHANNEL[1].TC_RA; tmr_RB = TC0->TC_CHANNEL[1].TC_RB; } } void Btmr_setup() // Counter { pmc_enable_periph_clk (TC_INTERFACE_ID + 0 *3 + 1); TcChannel * t = &(TC0->TC_CHANNEL)[1]; t->TC_CCR = TC_CCR_CLKDIS; t->TC_IDR = 0xFFFFFFFF; t->TC_SR; t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_LDRA_RISING | TC_CMR_LDRB_FALLING | TC_CMR_ABETRG | TC_CMR_ETRGEDG_FALLING; t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; t->TC_IER = TC_IER_LDRBS; t->TC_IDR = ~TC_IER_LDRBS; NVIC_DisableIRQ(TC1_IRQn); NVIC_ClearPendingIRQ(TC1_IRQn); NVIC_SetPriority(TC1_IRQn, 0); NVIC_EnableIRQ(TC1_IRQn); } void pio_TIOA1() { PIOA->PIO_PDR = PIO_PA2A_TIOA1; PIOA->PIO_IDR = PIO_PA2A_TIOA1; } Link to comment
nico_2010 Posted June 20, 2017 Share Posted June 20, 2017 Cred ca singura solutie este sa citesti cu multa atentie asta: http://www.atmel.com/Images/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf Si chiar si asta: http://www.atmel.com/Images/Atmel-42123-SAM-Timer-Counter-%28TC%29-Driver_ApplicationNote_AT03263.pdf Stiu, are doar 1459 de pagini, insa in domeniul microcontrollere-lor cu 32 biti, cam asta este solutia .. si e dureroasa. Link to comment
mmihai94 Posted June 22, 2017 Author Share Posted June 22, 2017 Job done! Am reusit sa fac programul, in proportie de 90% e ok. Mai are o mica problema de care nu stiu cum sa scap. In momentul de fata folosesc intrarile TIOA0, TIOA1 adica AN7 si D2 de pe arduino. Am setat intreruperile sa se declanseze la incarcarea registrilor RA de pe fiecare canal TC0 si TC1. Practic, pe frontul crescator al prinului semnal se incarca in registrul RA al canalului 0 valoarea din counter la momentul aparitiei frontului. Acelasi lucru se intampla si pt celalalt semnal. Dupa care e simplu, fac diferenta intre registrii RA si obtin intarzierea dintre semnale. Calculez intarzierea la ON( cu reg. RA) si la OFF(cu reg. RB - care se incarca pe frontul descrescator). Pana aici totul bine. Vreau sa vad datele si trimit pe serial. 90% primesc datele corect, dar apar cate o data niste valori uriase. De ce se intampla chestia asta? Trebuie sa resetez vre-un registru? volatile uint32_t tmr_RA0 = 0, tmr_RA1 = 0; volatile uint32_t tmr_RB0 = 0, tmr_RB1 = 0; volatile float on_d, off_d; void setup() { Serial.begin (115200); Tmr_setup(); pio_TIOA0(); pio_TIOA1(); } void loop() { on_d = (tmr_RA1 - tmr_RA0) * 0.0238; off_d = (tmr_RB1 - tmr_RB0) * 0.0238; Serial.print("\n\nON Delay "); Serial.print(on_d); Serial.print("\nOFF Delay "); Serial.print(off_d); delay(500); } void Tmr_setup() { pmc_enable_periph_clk(ID_TC0); // configure Power Management Clock TC_Configure(TC0, 0, TC_CMR_TCCLKS_TIMER_CLOCK1 | // set timer clock to 42MHz TC_CMR_WAVSEL_UP | // ???? TC_CMR_LDRA_RISING | // set loading edge of Register A to Rising TC_CMR_LDRB_FALLING); // set loading edge of Register B to Falling pmc_enable_periph_clk(ID_TC1); TC_Configure(TC0, 1, TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_WAVSEL_UP | TC_CMR_LDRA_RISING | TC_CMR_LDRB_FALLING); TC0->TC_CHANNEL[0].TC_IER = TC_IER_LDRAS; NVIC_EnableIRQ(TC0_IRQn); TC0->TC_CHANNEL[1].TC_IER = TC_IER_LDRAS; NVIC_EnableIRQ(TC1_IRQn); TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN; TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKEN; TC0->TC_BCR = TC_BCR_SYNC; } void TC0_Handler() { uint32_t status = TC0->TC_CHANNEL[0].TC_SR; if (status & TC_SR_LDRAS) { uint32_t tm = TC0->TC_CHANNEL[0].TC_RA; // rising edge of TIOA0 happened at "tm", // do something here to deal with it... tmr_RA0 = TC0->TC_CHANNEL[0].TC_RA; tmr_RB0 = TC0->TC_CHANNEL[0].TC_RB; } } void TC1_Handler() { uint32_t status = TC0->TC_CHANNEL[1].TC_SR; if (status & TC_SR_LDRAS) { uint32_t tm = TC0->TC_CHANNEL[1].TC_RA; // rising edge of TIOA1 happened at "tm", // do something here to deal with it... tmr_RA1 = TC0->TC_CHANNEL[1].TC_RA; tmr_RB1 = TC0->TC_CHANNEL[1].TC_RB; } } void pio_TIOA1() { PIOA->PIO_PDR = PIO_PA2A_TIOA1; PIOA->PIO_IDR = PIO_PA2A_TIOA1; } void pio_TIOA0() { PIOB->PIO_PDR = PIO_PB25B_TIOA0; PIOB->PIO_IDR = PIO_PB25B_TIOA0; PIOB->PIO_ABSR |= PIO_PB25B_TIOA0; } Link to comment
mmihai94 Posted June 23, 2017 Author Share Posted June 23, 2017 Nici o idee? Daca sunt neclaritati in legatura cu finctionarea programului de mai sus, intrebati. Link to comment
nico_2010 Posted June 23, 2017 Share Posted June 23, 2017 De la STM32 citire: Frecventa cu care se produc evenimentele (pe front crescator sau/si pe front descrescator) trebuie sa fie mai mica decat frecventa semnalului de masurat (in regim de functionare Input Capture), altfel apare overflow si brusc te trezesti ca valoarea inregistrata este 65535. Cam asta cred ca ti se intampla si tie. O imagine este mai buna decat o mie de cuvinte: Link to comment
mmihai94 Posted June 23, 2017 Author Share Posted June 23, 2017 Nu cred ca asta e motivul. Frecventa timerului este MCLK/2 adica 42MHz, iar frecventa care produce acele forunturi de masurat e de maxim 5KHz. Diferenta e uriasa. Link to comment
nico_2010 Posted June 23, 2017 Share Posted June 23, 2017 Pai tocmai asta este problema. Micsoreaza frecventa timerului la 16Mhz si verifica daca fenomenul mai apare Link to comment
mmihai94 Posted June 30, 2017 Author Share Posted June 30, 2017 Tot nu merge corect. Am setat frecventa la 10.5 MHz si face la fel, daca nu apare chestia asta masoara corect.Mai mult nu pot sa scad frecventa pentru ca am nevoie de precizie. https://goo.gl/photos/wa44sL8h8Q47QeQY8 Link to comment
nico_2010 Posted June 30, 2017 Share Posted June 30, 2017 Nu stiu daca stergi flagul de intrerupere sau nu o faci in IRQ, dar cred ca ar fi bine s-o faci (cel putin asa se face la STM32 Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now