Timer0 v rezime CTC (Bascom-ATMEGA644P)

Zdravim Vas, potreboval by som generovat prerusenie kazdu 1us co sa mi pri Fcpu 16Mhz a 8bit casovaci v normalnom rezime nedari, nakolko najnizsiu hodnotu ktoru mozem dosiahnut je 16us(1/Fcpu*2^8). Viem ze existuje moznost kde dokazem nastavit do registra OCR0A hodnotu pri ktorej by sa vyvolalo prerusenie, co by v mojom pripade bola hodnota 16 a vtedy by som mal prerusenie kazdu 1us no nedari sa mi nastavit T0 do rezimu CTC. Vedel by niekto pomoct ako to v bascome nastavit? Samozrejme datasheet som pozeral, viem ze registre maju byt nastavene na WGM01=1, WGM00=0 a ze musim zapisat hodnotu OCR0A = 16 ale aj tak sa mi nedari rozbehnut to. V normalnom rezime mi to na tych 16tich us chodi bezproblemov, no potrebujem kratsi cas. Dakujem

musis mat povolene prerusenie OCIE0A v registri TIMSK0, a napisat pre toto prerusenie obsluhu.
V Bascome nerobim, ale snad som poradil.

Přerušení 1us v BASCOM při 16 MHz? Zbláznil ses? To nemůžeš dosáhnout. :slight_smile: I v assembleru bys měl co dělat, abys do toho času vecpal pár instrukcí, a na hlavní program by ani nezbyl čas.

A aky najkratsi cas by bolo podla teba mozne dosiahnut? Nikdy som s tak kratkym casom nerobil tak neviem co ma caka

Těch 16us je pro BASCOM asi tak minimum času na obsluhu přerušení. To je průměrně asi 200 strojových instrukcí. Ale i tak je třeba hlavní smyčku i obsluhu přerušení psát dost úspornou a přerušení bude procesor dost zatěžovat (např. 100 instrukcí na přerušení a 100 na hlavní smyčku).

V preruseni len inkrementujem premenne a na zaklade ich hodnoty potom v hlavnej slucke vyhodnocujem co dalej. Ide mi o to ze potrebujen generovat kratke impulzy (podla potreby 8-10-12…20us) pre spinanie tyristorov a chcel som az sa tato hodnota da nastavit co mozno najpresnejsie(neskor softverovo). Teraz to mam vyriesene pomocou waitov(delay) ale sam vies ze to nieje dobre a uz vobec nie pokial pracujem s tak kratkymi casmi. V niektorych aplikaciach bude 16us v pohode, inde uz to bude velmi dlha doba

No nevím, já bych řekl, že je to naopak. Dlouhé waity v hlavním programu nemají být.
Ale těch pár mikrosekund by většinou nemělo vadit.

No ale mne v hlavnej slucke bezi komparator ktory porovnava pilu s nejakym referencnym napatim a na zaklade toho v akom stave tento komparator je ja hadzem impulzy a teda sa obcas stane ze mi ten impulz ‘‘uleti’’ o tych ± 20us :slight_smile:

Udělej přerušení pro komparátor a v něm pošli ten impuls.

Aj tak by to islo, no rozmyslam ze asi skor zacnem uvazovat na nejakou Xmegou. Sice som o nich zatial len cital no vyzeraju pouzitelne. Vdaka dvojnasobnej Fcpu by som mohol s casom ist teoreticky az na 8us co by mi celkom vyhovovalo no a ako dalsie plus je tam rychlejsi AD prevod a zabudovany DA prevodnik. Co hovorite na tieto procesory?

Generuj pulsy raději hardwarově, výstupem z čítače přímo na port. Je to mnohem přesnější a umožní i krátké časy.

Moc som nepochopil ako si to myslel s tym generovanim pulzov, mohol by si mi to prosim upresnit? Ja ale celkovo budem musiet najst iny MCU nakolko by som velmi rad generoval aj vystupny pilovity signal ktory by som vyrabal z obdlznikoveho. S tymto MCU som to robil cez PWM a dostal som sa na max frekvenciu okolo 1,2kHz kedy sa este signal podobal na pilu. Tieto Xmegy co som pozeral tak umoznuju aj vyssi vypoctovy vykon a maju v sebe aj DA prevodnik s ktorym by som sa mozno dostal aj na vyssiu frekvenciu. Treba to asi jedine vyskusat, ked nic ine tak aspon nazbieram skusenosti s tymto svabom

Vykon Xmegy (32MHz) by som v sucasnosti uz ani nebral za relevantny. To za oproti 20MHz pre ATmega nie je take terno, aby sa oplatilo ucit pracu s novym prostredim, atd, atd.
Za cenu nizsiu su k dispozicii STM32F05x (48MHz), STM32F2xx (120MHz), … Ak uz chces prejst na nieco nove tak potom ta namaha za trochu dlhsi cas pre nastudovanie 32b technologie urcite stoji za to a vydrzis s tym do dochodku urcite. A na 32b technologii nemusis samo o sebe nic studovat, Vsetko za Teba aj tak poriesi prekladac C-cka. Jedine co musis nastudovat, je ako pracuju periferie. Ale to je pri kazdej zmene procesora.

Inak pre generovanie pily kludne pouzi ATmega s 8b paralelnym DA prevodnikom. Rychlost dosiahnes daleko vyssiu. Nepises co potrebujes prakticky dosiahnut.

Ak potrebujes generovat pilu, da sa to aj tak, ze si spravis zdroj prudu (jeden OZ, jedna BSS123 a par pasivnych elementov). Referencne napatie mozes generovat tym PWM, ale od jevo velkosti bude zavisiet velkost prudu na vystupe toho prevodnika napatie/prud. No a ked tym prudom budes nabijat kondenzator, tak na nom bude prakticky pekna hrana s uhlom sklonu podla velkosti toho prudu. Po dosiahnuti nejakej zelanej hranice kondenzator kratkym pulzom skratni a dej sa Ti bude opakovat. A mas generator pily s premenlivou frekvenciou ako vysity. Ked pouzijes DA, aj tak sa nejakym dalsim suciastkam nevyhnes ako je urcite OZ a par dalsich pasivnych elementov. Toto je o nieco komplikovanejsie, ale fakt ze len o nieco.

Nevím, co všechno potřebuješ, protože z diskuze nejsem úplně moudrej. Napsal jsem Ti příklad, jak generovat pulzy pomocí časovače. Jen mám trošku obavu, jestli dokážeš dosahnout takovouhle přesnost v BASCOMu.

;==============================================================================
; Generování impulzu pro tyristory
; Délka impulzu 1-128 us
; Odchylka délky pulzu max. +4 takty MCU v případě,
; že nebude použito žádné jiné přerušení
; Fmcu = 16 MHz 
;==============================================================================

#include <m644def.inc>

;------------------------------------------------------------------------------
; Definice registrových proměnných

.def Temp=R16				; Pomocná proměnná
.def Temp2=R17				; Pomocná proměnná pro přerušení


;------------------------------------------------------------------------------
; Definice konstant

#define Tyristor_PORT portb
#define Tyristor0 0
#define Tyristor1 1
#define Tyristor2 2
#define Tyristor3 3
#define Tyristor4 4
#define Tyristor5 5
#define Tyristor6 6
#define Tyristor7 7

#define Delka_Pulzu_us 1	; Požadovaná délka impulzu v us (1-128)

;------------------------------------------------------------------------------
; Definice paměťových proměnných

.dseg
SRAM_Tyristory: .byte 1		; Sem se ukládá, které tyristory se mají zapnout
SRAM_Delka_Pulzu: .byte 1	; Sem se ukládá vypočtená hodnota pro požadovanou délku impulzu



;------------------------------------------------------------------------------
; Tabulka skoků

.cseg
.org 0

	rjmp RESET		; Reset Handler
	rjmp INT0_INT		; External Interrupt Request 0
	rjmp INT1_INT		; External Interrupt Request 1
	rjmp INT2_INT		; External Interrupt Request 2
	rjmp PCINT0_INT		; Pin Change Interrupt Request 0
	rjmp PCINT1_INT		; Pin Change Interrupt Request 1
	rjmp PCINT2_INT		; Pin Change Interrupt Request 2
	rjmp PCINT3_INT		; Pin Change Interrupt Request 3
	rjmp WDT_INT		; Watchdog Time-out Interrupt
	rjmp TIMER2_COMPA	; Timer/Counter2 Compare Match A
	rjmp TIMER2_COMPB	; Timer/Counter2 Compare Match B
	rjmp TIMER2_OVF		; Timer/Counter2 Overflow
	rjmp TIMER1_CAPT	; Timer/Counter1 Capture Event
	rjmp TIMER1_COMPA	; Timer/Counter1 Compare Match A
	rjmp TIMER1_COMPB	; Timer/Counter1 Compare Match B
	rjmp TIMER1_OVF		; Timer/Counter1 Overflow
	rjmp TIMER0_COMPA	; Timer/Counter0 Compare Match A
	rjmp TIMER0_COMPB	; Timer/Counter0 Compare match B
	rjmp TIMER0_OVF		; Timer/Counter0 Overflow
	rjmp SPI_STC		; SPI Serial Transfer Complete
	rjmp USART0_RX		; USART0 Rx Complete
	rjmp USART0_UDRE	; USART0 Data Register Empty
	rjmp USART0_TX		; USART0 Tx Complete
	rjmp ANALOG_COMP	; Analog Comparator
	rjmp ADC_INT		; ADC Conversion Complete
	rjmp EE_READY		; EEPROM Ready
	rjmp TWI_INT		; two-wire Serial Interface
	rjmp SPM_READY		; Store Program Memory Ready
	rjmp USART1_RX		; USART1 Rx Complete
	rjmp USART1_UDRE	; USART1 Data Register Empty
	rjmp USART1_TX		; USART1 Tx Complete
	rjmp TIMER3_CAPT	; Timer/Counter3 Capture Event
	rjmp TIMER3_COMPA	; Timer/Counter3 Compare Match A
	rjmp TIMER3_COMPB	; Timer/Counter3 Compare Match B
	rjmp TIMER3_OVF		; Timer/Counter3 Overflow

;------------------------------------------------------------------------------
; Rutiny obsluhy přerušení

TIMER3_COMPA:				; Timer/Counter3 Compare Match A
; Z nějakého záhadného důvodu v simulátoru AVR Studia skáče Timer 0 Compare Match A
; na adresu Timer 3 Compare Match A
; Proto je tu i tento jinak nepoužitý vektor přerušení, který má pouze MCU ATmega1284.
; MCU na vyzkoušení nemám.

TIMER0_COMPA:				; Timer/Counter0 Compare Match A
	ldi Temp2, 0
	out Tyristor_PORT, Temp2	; Vypnout všechny tyristory
	out TCCR0B, Temp2	; Zastavit čítač
	out TCNT0, Temp2	; Vynulovat čítač
	reti

;------------------------------------------------------------------------------
; Nepoužité vektory přerušení

INT0_INT:					; External Interrupt Request 0
INT1_INT:					; External Interrupt Request 1
INT2_INT:					; External Interrupt Request 2
PCINT0_INT:					; Pin Change Interrupt Request 0
PCINT1_INT:					; Pin Change Interrupt Request 1
PCINT2_INT:					; Pin Change Interrupt Request 2
PCINT3_INT:					; Pin Change Interrupt Request 3
WDT_INT:					; Watchdog Time-out Interrupt
TIMER2_COMPA:				; Timer/Counter2 Compare Match A
TIMER2_COMPB:				; Timer/Counter2 Compare Match B
TIMER2_OVF:					; Timer/Counter2 Overflow
TIMER1_CAPT:				; Timer/Counter1 Capture Event
TIMER1_COMPA:				; Timer/Counter1 Compare Match A
TIMER1_COMPB:				; Timer/Counter1 Compare Match B
TIMER1_OVF:					; Timer/Counter1 Overflow

TIMER0_COMPB:				; Timer/Counter0 Compare match B
TIMER0_OVF:					; Timer/Counter0 Overflow
SPI_STC:					; SPI Serial Transfer Complete
USART0_RX:					; USART0 Rx Complete
USART0_UDRE:				; USART0 Data Register Empty
USART0_TX:					; USART0 Tx Complete
ANALOG_COMP:				; Analog Comparator
ADC_INT:					; ADC Conversion Complete
EE_READY:					; EEPROM Ready
TWI_INT:					; two-wire Serial Interface
SPM_READY:					; Store Program Memory Ready
USART1_RX:					; USART1 Rx Complete
USART1_UDRE:				; USART1 Data Register Empty
USART1_TX:					; USART1 Tx Complete
TIMER3_CAPT:				; Timer/Counter3 Capture Event
TIMER3_COMPB:				; Timer/Counter3 Compare Match B
TIMER3_OVF:					; Timer/Counter3 Overflow

            reti

;------------------------------------------------------------------------------
; Hlavní program - inicializace MCU

RESET:  
	ldi Temp,high(RAMEND)
	out SPH,Temp
	ldi Temp,low(RAMEND)
	out SPL,Temp


	ldi XH, high(SRAM_SIZE)
	ldi XL, low(SRAM_SIZE)
	ldi YH, high(SRAM_START)
	ldi YL, low(SRAM_START)
	clr temp
Init_RAM:
	st Y+, temp
	sbiw XL, 1
	brne Init_RAM

	clr r0
	clr r1
	clr r2
	clr r3
	clr r4
	clr r5
	clr r6
	clr r7
	clr r8
	clr r9
	clr r10
	clr r11
	clr r12
	clr r13
	clr r14
	clr r15
	clr r16
	clr r17
	clr r18
	clr r19
	clr r20
	clr r21
	clr r22
	clr r23
	clr r24
	clr r25
	clr r26
	clr r27
	clr r28
	clr r29
	clr r30
	clr r31
	out SREG, r0

; Hlavní program - konec inicializace MCU

;------------------------------------------------------------------------------
; Hlavní program

	rcall Inicializace_Citace_A_Portu
	sei								; Povolit přerušení

	Temp, (1<<Tyristor0)|(1<<Tyristor3) ; Zapnout tyristory 1 a 3
	sts SRAM_Tyristory, Temp		; Sem se ukládá, které tyristory se mají zapnout


	ldi Temp, Delka_Pulzu_us*2-1	; Vypočítat hodnotu OCIE0A pro požadovanou délku impulzu
	sts SRAM_Delka_Pulzu, Temp		; Sem se ukládá hodnota OCIE0A pro požadovanou délku impulzu

	rcall Start_Impulzu

Hlavni_Smycka:

	rjmp Hlavni_Smycka

;------------------------------------------------------------------------------
Inicializace_Citace_A_Portu:
	ldi Temp, 0
	out TCNT0, Temp				; Vynulovat čítač
	out TCCR0A, Temp			; Nastavit normální režim čítače
	out TCCR0B, Temp			; Nastavit normální režim čítače, NESPOUŠTĚT ČÍTAČ
	ldi Temp, 255
	out TIFR0, Temp				; Pro jistotu vynulovat všechny příznaky přerušení
	ldi Temp, (1<<OCIE0A)
	sts TIMSK0, Temp			; Povolit přerušení při překročení hodnoty v OCIE0A
	ldi Temp, 0
	out Tyristor_PORT, Temp		; Vynulovat port (pokud jsou tyristory zapínané log. 1)
	ldi Temp, 255
	out ddrb, Temp				; Nastavit port jako výstupní
	ret

;------------------------------------------------------------------------------
Start_Impulzu:
	lds Temp, SRAM_Delka_Pulzu	; Načíst z RAM délku impulzu
	out OCR0A, Temp
	ldi Temp, (1<<CS01)
	out TCCR0B, Temp			; Spustit čítač - Prescaler=8

; Počkat 4 takty mcu kvůli synchronizaci
	nop
	nop
	nop
	nop

	lds Temp, SRAM_Tyristory	; Načíst z RAM které tyristory se mají zapnout
	out Tyristor_PORT, Temp		; Zapnout tyristory
	ret
;------------------------------------------------------------------------------

Prográmek je psaný v AVR Studiu.

Před dalším zapnutím jiného nebo jiných tyristorů musíš počkat, než dojde k vypnutí těch zapnutých - neboli než se ukončí cyklus. U délky pulzu 1 us to není až takový problém, protože od zapnutí do vypnutí procesor vykoná max. 16 instrukcí (včetně instrukce ret a části přerušovacího vektoru do vypnutí tyristorů), takže času na ostatní věci je opravdu minimum, ale u delších impulzů by bylo potřeba tohle ještě ošetřit.

Šlo by to třeba takhle :[code]
Start_Impulzu:
in Temp, Tyristor_PORT ; Načíst stav portu tyristorů
tst Temp ; Test na nulu
brne Start_Impulzu ; Není-li port nulový, opakovat

     lds Temp, SRAM_Delka_Pulzu   ; Načíst z RAM délku impulzu
     out OCR0A, Temp
     ldi Temp, (1<<CS01)
     out TCCR0B, Temp         ; Spustit čítač - Prescaler=8

; Počkat 4 takty mcu kvůli synchronizaci
nop
nop
nop
nop

     lds Temp, SRAM_Tyristory   ; Načíst z RAM které tyristory se mají zapnout
     out Tyristor_PORT, Temp      ; Zapnout tyristory
     ret

;------------------------------------------------------------------------------ [/code]

Zavoláš rutinu pro spuštění pulzu a ta čeká, dokud je některý z tyristorů zapnutý.

V Ccku nerobim, ale ako vidim tak coskoro budem musiet na to prejst lebo sem tam sa vyskytne zapojenie ako teraz kde uz Basic nestaci. Samozrejme ale dakujem za kod a skusim si ho vecer prejst a pokusit sa pochopit ako si to myslel. Konkretne ide o riadenie tyristoroveho striedaca, tzn budem potrebovat generovat dva impulzy s urcitou dlzkou(10-25us) a samozrejme s urcitou frekvenciou. Ono je to na dlhe pisanie a takto cez net sa to ani poriadne neda vysvetlit co vsetko tam vlastne bude a hlavne ako to ma fungovat lebo je tam toho viacero aj ked viem ze zasa pre Vas je tazko mi radit ked neviete o co ide. V podstate 80% si dokazem spravit aj sam, akurat toto generovanie casu mi robi problem + generovanie piloveho signalu ale skusim to s tym operakom a prudovym zdrojom, to znie ako velmi dobry napad no treba si to vyskusat. Ale aj tu xmegu by som si rad skusil, hlavne tie DA prevodniky, s tym som este nemal tu cest pracovat a ked nic ine tak aspon sa zasa cosi naucim, na skodu to urcite nebude

Jenom drobnost - to není Cčko, ale Assembler …

Cčko má podobný problém jako BASCOM. Nevíš přesně, co všechno tam kompiler přihodí za bižuterii, takže je hodně těžké udělat tak přesné časování jako právě v Assembleru, kde co napíšeš, to se zkompiluje a nic se k tomu nepřilepí.

No jasne, somar :smiley: pozrel som si zaciatok kde bolo include a define a to viem ze sa pouziva aj v Ccku, takze sa ospravedlnujem :slight_smile:…na asm si zatial veru netrufam, ale raz mozno…no nic skusim este cosi vymysliet, skusim tu xmegu, pripadne nejaky 32b no a uvidi sa co dalej. Zatial Vam vsetkym velmi pekne dakujem za cas a ochotu, no a ked sa posuniem niekde dalej tak sa urcite ozvem

Tak po dlhsej dobe som opat spat, akurat som skusil na moju M644ku pripojit DA prevodnik TLC7226 a generovat s nim pilu. Pri vyske pily cca. 3,5V som sa dostal na f=2kHz co oproti PWMke nieje ziadna vyhra, snad jedine plus je ze nemusim pri zmene frekvencie menit RC clen a nemusim mat zapojeny vybijaci tranzistor paralelne s kapacitou :slight_smile:

Obecně řečeno - na některé úlohy programově ani poměrně rychlé MCU nestačí a řeší se to integrovaným HW případně externím HW (PLD, CPLD, FPGA) jako jsou pole čítačů/komparátorů + DMA a podobně.
Z diskuze jsem nijak zvlášť nepochopil co je cílem Tvého snažení, ale někdo Ti tu radil rodinu ARM STM32F/L ( z osmibitů je ještě celkem schopná rodina 80C51F) tak si prostuduj a napasuj svoje požadavky na vhodný MCU :wink: