Generátor: Generovaní sinusového a trojúhelníkového průběhu

JZS ja sem takovej kreten :smiley: Ja to prave jeste poupravoval, nez sem to sem poslal, takze ano nebylo to odzkousene :smiley: Ale dekuji za upozorneni

A to, ze zmena jednoho vzorku trva 1,12us, je zpusobeno spatnym vypoctem v OCR nebo je smicka prilis dlouha a hodnoty se nestaci tak rychle posilat?

Dekuji.

Ked si das ten kod do simulatora zistis, ze pod 1.1us sa bez ohladu na hodnotu v OCR medzi vzorkami a pod 1.4us na konci periody s tymto kodom nedostanes.

A myslis ze treba zkraceni z:

if (i >= VZORKY_TROJUHELNIK) { i = 0; }
na:

 if (i >= VZORKY_TROJUHELNIK) i = 0;

usetri nejak strojovy cas? Nebo to usetrim jen radky?

Diky.

Ved si preloz kod do simulatora v AVR studiu a tam zistis, aka zmena nastala v kode ak v nom nieco zmenis.

To co si uviedol, na vysledny kod nema absolutne ziadny vplyv. Pouzi moj kod, nechaj si ho prelozit a uvidis rozdiely v case behu jednotlivych casti.
Nauc sa pouzivat simulator.

Zkusil jsem si jen tak na zkoušku udělat to v assembleru - 2 takty na vzorek, tj. 0.1us, tedy vzorkovací kmitočet je 10 MHz. Pro sinusovku to je 240 vzorků (aby se dosáhlo frekvence výstupu 41,67 kHz), pro pilu to je 200 vzorků (frekvence pily 50 kHz).

U sinusovky se testuje přepnutí tlačítkem během vrcholu, využívá že vzorky se po pár taktů nemění a proto mohou být nahrazené pár jinými instrukcemi. U pily se tlačítko testuje na začátku pomalé vzestupné hrany, trochu tam vznikne zoubek (chybí 2 vzorky).

Přerušení od tlačítka pro zjednodušení neřeší zákmity, to by tam mělo být, nebo alespoň přidat k tlačítku kondenzátor pár nF. Obsluha jenom invertuje registr obsahující příznak typu signálu. Přerušení neuchovává stavový registr, protože se v programu nevyužívá.

Není to vyzkoušeno, možná tam jsou chyby a není to funkční, nevím.

[code]; ===== Generator sinusovky a pily
; Sinusovka: Um=4V, f=41,67 kHz
; Trojuhelnik: Um=3V, f=50 kHz, vrchol v 3/4 T
; Vystup na port B, 8-bitovy D/A prevodnik TLC7524C
; Tlacitko na vstupu PD2 prepina vystupni signal.

.nolist
#include <avr/io.h>
.list

; ------------- registry

	.equ	tmp,24			; pracovni registr
	.equ	sin,25			; priznak: 1=sinus, 0=trojuhelnik

; ------------- makra - vystup sinusovky

.macro OUT1 d1 ; vystup 1 bajtu na D/A prevodnik
; [2 takty = 0.1us]
ldi tmp,\d1 ; [1 takt] hodnota bajtu
out _SFR_IO_ADDR(PORTB),tmp ; [1 takt] vystup bajtu
.endm

.macro OUT10 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 ; vystup 10 bajtu na D/A prevodnik
OUT1 \d1 ; kazdy vzorek 2 takty
OUT1 \d2
OUT1 \d3
OUT1 \d4
OUT1 \d5
OUT1 \d6
OUT1 \d7
OUT1 \d8
OUT1 \d9
OUT1 \d10
.endm

; ------------- makra - vystup trojuhelniku

.macro OUTU1 ; vystup 1 bajtu s inkrementaci o 1
; [2 takty = 0.1us]
inc tmp ; [1 takt] zvyseni hodnoty vzorku
out _SFR_IO_ADDR(PORTB),tmp ; [1 takt] vystup bajtu
.endm

.macro OUTU10 ; vystup 10 bajtu s inkrementaci o 1
OUTU1 ; kazdy vzorek 2 takty
OUTU1
OUTU1
OUTU1
OUTU1
OUTU1
OUTU1
OUTU1
OUTU1
OUTU1
.endm

.macro OUTD1 ; vystup 1 bajtu s dekrementaci o 3
; [2 takty = 0.1us]
subi tmp,3 ; [1 takt] snizeni hodnoty vzorku
out _SFR_IO_ADDR(PORTB),tmp ; [1 takt] vystup bajtu
.endm

.macro OUTD10 ; vystup 10 bajtu s dekrementaci o 3
OUTD1 ; kazdy vzorek 2 takty
OUTD1
OUTD1
OUTD1
OUTD1
OUTD1
OUTD1
OUTD1
OUTD1
OUTD1
.endm

; ------------- tabulka vektoru

	.text
	.org	0

	rjmp	Reset			; 0x0000: (1) RESET
	rjmp	Int0			; 0x0001: (2) INT0

; ------------- inicializace registru

	.global	Reset

Reset: eor sin,sin ; sin ← 0 (vystup trojuhelnik)
out _SFR_IO_ADDR(SREG),sin ; nulovani status registru
ldi tmp,RAMEND ; konec RAM
out _SFR_IO_ADDR(SPL),tmp ; ukazatel zasobniku

; ------------- inicializace vystupniho D/A portu

	ldi	tmp,0xff		; vsechny bity vystup
	out	_SFR_IO_ADDR(DDRB),tmp	; nastaveni portu B na vystup

; ------------- zapnuti pull-up pro vstup z tlacitka

	out	_SFR_IO_ADDR(PORTD),tmp	; zapnuti pull-up bitu portu D

; ------------- inicializace preruseni od tlacitka (INT0, vstup PD2)

	ldi	tmp,1<<INT0		; preruseni od INT0
	out	_SFR_IO_ADDR(GIMSK),tmp	; povoleno preruseni od INT0
	ldi	tmp,1<<ISC01		; preruseni sestupnou hranou INT0
	out	_SFR_IO_ADDR(MCUCR),tmp	; nastaveni preruseni
	sei				; povoleni globalniho preruseni

; ------------- vystup sinusovky (2 takty na vzorek, pro 41,67 kHz celkem 240 vzorku,
; pro napeti max. 4V je stred 2V, rozsah hodnot 0 az 204, stred 102)

Sinus:
OUT10 204 204 204 204 203 203 203 202 202 201 ; 0…9
OUT10 201 200 199 198 197 196 195 194 193 192 ; 10…19
OUT10 190 189 188 186 185 183 181 180 178 176 ; 20…29
OUT10 174 172 170 168 166 164 162 160 158 155 ; 30…39
OUT10 153 151 148 146 143 141 139 136 134 131 ; 40…49
OUT10 128 126 123 121 118 115 113 110 107 105 ; 50…59
OUT10 102 99 97 94 91 89 86 83 81 78 ; 60…69
OUT10 76 73 70 68 65 63 61 58 56 53 ; 70…79
OUT10 51 49 46 44 42 40 38 36 34 32 ; 80…89
OUT10 30 28 26 24 23 21 19 18 16 15 ; 90…99
OUT10 14 12 11 10 9 8 7 6 5 4 ; 100…109
OUT10 3 3 2 2 1 1 1 0 0 0 ; 110…119
OUT10 0 0 0 0 1 1 1 2 2 3 ; 120…129
OUT10 3 4 5 6 7 8 9 10 11 12 ; 130…139
OUT10 14 15 16 18 19 21 23 24 26 28 ; 140…149
OUT10 30 32 34 36 38 40 42 44 46 49 ; 150…159
OUT10 51 53 56 58 61 63 65 68 70 73 ; 160…169
OUT10 76 78 81 83 86 89 91 94 97 99 ; 170…179
OUT10 102 105 107 110 113 115 118 121 123 126 ; 180…189
OUT10 128 131 134 136 139 141 143 146 148 151 ; 190…199
OUT10 153 155 158 160 162 164 166 168 170 172 ; 200…209
OUT10 174 176 178 180 181 183 185 186 188 189 ; 210…219
OUT10 190 192 193 194 195 196 197 198 199 200 ; 220…229
;OUT10 201 201 202 202 203 203 203 204 204 204 ; 230…239
OUT1 201 ; 230
OUT1 201 ; 231
OUT1 202 ; 232
OUT1 202 ; 233
OUT1 203 ; 234
OUT1 203 ; 235
OUT1 203 ; 236
OUT1 204 ; 237
;OUT1 204 ; 238 [2 takty]
;OUT1 204 ; 239 [2 takty]
nop ; [1 takt] pro casovani
sbrc sin,0 ; [1/2 takty] je sinusovka?
rjmp Sinus ; [2 takty] je sinusovka

; ------------- vystup trojuhelniku (2 takty na vzorek, pro 50 kHz celkem 200 vzorku,
; tj. pro 3/4 T je to 150 + 50 vzorku, pro napeti 3V je rozsah hodnot 0 az 150)

Trian:
;OUT1 1 ; 1
;OUT1 2 ; 2
OUT1 3 ; 3
OUT1 4 ; 4
OUT1 5 ; 5
OUT1 6 ; 6
OUT1 7 ; 7
OUT1 8 ; 8
OUT1 9 ; 9
OUT1 10 ; 10, inicializace vzorku
OUTU10 ; 11…20
OUTU10 ; 21…30
OUTU10 ; 31…40
OUTU10 ; 41…50
OUTU10 ; 51…60
OUTU10 ; 61…70
OUTU10 ; 71…80
OUTU10 ; 81…90
OUTU10 ; 91…100
OUTU10 ; 101…110
OUTU10 ; 111…120
OUTU10 ; 121…130
OUTU10 ; 131…140
OUTU10 ; 141…150

	OUTD10		; 147..120
	OUTD10		; 117..90
	OUTD10		; 87..60
	OUTD10		; 57..30
	OUTD10		; 27..0

	nop		; [1 takt] pro casovani
	sbrs	sin,0	; [1/2 takty] je sinusovka?
	rjmp	Trian	; [2 takty] je trojuhelnik

	rjmp	Sinus	; je sinusovka

; ------------- obsluha preruseni od tlacitka (INT0)
; Pozor, neuchovava stavovy registr SREG !

Int0: com sin ; inverze priznaku signalu
reti[/code]
generator.zip (12.2 KB)

To je velmi sikovne :slight_smile:
Ten kod nefunguje, respektive sa mi ho ani len nepodarilo prelozit.

Překlad - to je divné, přeložit mi to jde. Používám WinAVR-20100110.

Tak ted uz jsem snad pochopil vse co jsem potreboval. Jen jeste posledni problem. Ja kdyz v simulatoru meril cas,za ktery se zapise vzorek, tak mi vyslo 1,3us misto 1,12.

To Martin:
Takze kdo z nas dvou udelal chybu? :wink: :smiley:
Asi ja, ale zajimalo by me cim to je.
Mohl by jsi to jeste jednou promerit prosim?

Diky.

To sa divim,

direktiva na vlozenie suboru v ASM nie je #include ale .include
.text toto asembler nepozna, ale pozna toto .CSEG

Okrem toho WinAVR je prekladac C-cka, tak to mi uz nejde vobec.

Nepises s akou optimalizaciou si to prekladal, nepises ako mas nastaveny simulator. Ak nenastavis spravne v simulatore procesor, vysledky byvaju vseliake. Moj cas je 1.1us a pri konci periody 1.4us
Stredny cas ako priemer zo vsetkych vzoriek z periody je

tpriem = (X*1.1 + 1.4)/(X + 1)

pre X = 14 to je 1.12us, pre X = 4 to je 1.16us a tak dalej. Takze rozny pocet vzoriek bude viest k roznemu priemernemu casu. Okrem toho este zavisi , aky mas konkretne prekladac.

Ja pouzivam AVR studio 4.19 build 730 a asi
avr-toolchain-installer-3.3.0.710

Takze pripad od pripadu mozes mat trochu rozdiel v kode. Prave preto som k mojmu zdrojaku prilozil aj preklad do ASM. To je uplne presne kopia strojaku a v tom pripade casy 100% sedia.

breakpoint mam na riadku

SET(TIFR,OCF0A); //vynuluj TIFR

Panda38:
Nejde přeložit protože chybí main.

Toto funguje

[code] .text
.org 0

  .global main

main:
rjmp Reset ; 0x0000: (1) RESET
rjmp Int0 ; 0x0001: (2) INT0

; ------------- inicializace registru

Reset:
eor sin,sin ; sin <- 0 (vystup trojuhelnik)
out _SFR_IO_ADDR(SREG),sin ; nulovani status registru

[/code]

Koncovka asm souboru má být velké S (generator.S)
aby se nepletl se souborem který vytvoří překladač (generator.s).

Ještě musím doplnit:
Co jsem napsal výše, platí pro automaticky generovaný makefile,
což se asi používá nejčastěji.
S tvým makefile překlad proběhl dobře.

Martin: gcc má bezkonkurenční inline assembler (dobré propojení s C pomocí parametrů) a tak si někdy ani neuvědomím že někdo používá něco jiného. Používám ho pro C i assembler samotný.

AB: Jo, překládat se musí s tím makefile co tam je (např. musí být vypnuté standardní knihovny -nostdlib, které by používaly vlastní startup a chtěly main, to by nefungovalo). Jen jsem to zkoušel kolik se z toho dá vytáhnout v assembleru (makefile je z jiného projektu, není na míru), není to připravené pro jiná prostředí. gcc používám už dnes výhradně z příkazového řádku, s vlastním makefile, bez nějakých gui (nakonec se vždy ukazuje, že u MCU jsou spíš zátěží než přínosem).

Clovek sa ma furt co ucit :slight_smile:

Dakujem za pekny priklad vratane jeho spracovania pod Winavr.

Uz mi to samozrejme ide a je to velmi pekne 240 vzoriek na sinus, to uz teda bude velmi slusny sinus.
Zaroven je vidiet, ako sa da s AVR-ka vytlacit maximum

gratulujem :slight_smile:

Zdravim. Tak jsem tu zase zpet. Posledni dobou jsem nemel moc cas toto resit, ale uz jsem pochopil snad vse, co se tyka problematiky DAC… Jediny problem mi dela vypocet vzorku sinusovky :frowning: Marťo nevis jak na to? Ja kdyz to zkousel na osciloskopu, tak mi to delalo krasny trojuhelniky :smiley: Staci mi jen vzorecek :stuck_out_tongue: Predem diky.

Ja by som si vzorky pocital na zaklade nasledujuce vztahu, samozrejme najpr v Excely a potom by som vysledky vlozil do zdrojaku v AVR studiu.
Vysledok je pre 8bit DA.

hodnota_vzorky(n) = 127 + 127 * sin(360°*n/P);

P celkovy pocet vzoriek
n aktualny index vzorky v rozmedzi 0 az (P-1)

pre P=240 sa bude n pohybovat v rozmedzi 0 az 239

Vysledna hodnota bude nadobudat hodnoty od 0 do 254. Stredna hodnota bude 127.

Super :smiley: Ty vis proste vsechno :stuck_out_tongue:

Ví, mohu potvrdit. :wink:

Ale pani, privadzate ma do rozpakov, este sa zacnem cervenat :slight_smile:
Ak mozem, rad pomozem a tak isto aj ja sa mam stale co ucit. Takze je to cele dobra zabava :slight_smile: