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

No tak pekne dakujem :slight_smile:
Tak este prikladam konecnu verziu aj s vypisom v ASM. Pravoverni ASM by este videli moznost optimalizovat kod pri plneni ukazatela nie z RAM ale z registrov, ale to su uz len marginalne opatrenia. Pod 0.6us na periodu sa myslim vyrazne nedostanu (>10%). Ale mozno to tu niekto predvedie, tesim sa :slight_smile:

samotny program slucky trva 0.6us a pri prednastaveni hodnot (jeden krat za periodu) 0.7us.

Hodnoty v poliach si musis prepocitat na 25vzoriek a na pozadovanu amplitudu ucitelom.

perioda sinusu je od 23.7 do 23.9us, tak ze priemer je 23.74us
(pocitane z desiatich period v simulatore).
Jedna vzorka sa napni za 1us, po niekolkych vzorkach za 0.8us tak, ze priemer je tych 0.9496us na vzorku aby na periodu bolo tych 23.74us.
Frekvencia je od pozadovanej o 1% vyssia, to by nemalo vadit. Vhodnejsie hodnoty som skusmo nenasiel.

Perioda trojuholnika je od 20,00us do 20,10us. Priemer z desiatich period je 20.00us.
Jedna vzorka sa naplni vzdy pravidelne za 0.8us.

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>


#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT)))
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT)))

#define TRUE 0x00
#define FALSE 0xff
#define SINUS TRUE
#define TROJUHOLNIK FALSE
#define PREDVOLBA_CZ_SINUS 18 // 41.67kHz predv.18,vz25=42.12kHz, predv.18,vz26=40.48kHz, predv.17/vz26=42.74kHz, predv.17,vz27=41.15kHz
#define PREDVOLBA_CZ_TROJUHOLNIK 15 // 50kHz: predvolba 15,vz.25  

// pri rovnakom pocte vzoriek 25 a predvolbe 15 je vystupna frekvencia signalu 50kHz
// pri rovnakom pocte vzoriek 25 a predvolbe 18 je vystupna frekvencia signalu 42.12kHz, co je o 1% vyssia frekvencia aka bola pozadovana


#define POCET_VZORIEK 25

#define PORT_PRE_DA PORTB
#define SMER_PORT_PRE_DA DDRB

uint8_t generuj_signal = SINUS;
uint8_t stav_tlacitka_new,  stav_tlacitka_old, i;

uint8_t sinu  [POCET_VZORIEK] = {127,138,149,160,171,182,193,205,      //127-205
                     205,193,182,171,160,149,138,127,      //205-127
                     127,116,105,94,83,72,61,49,         //127-49
                     49,61,72,83,94,105,116,127};      //49-127

// trojuholnik s rovnakym poctom prvkov ako SINUS. 
uint8_t troj2  [POCET_VZORIEK] = {0,10,20,30,40,50,60,70,
                     80,90,100,110,120,130,140,150,  
                     160,150,140,130,120,110,100,90,    
                     80,70,60,50,40,30,20,10};   


volatile uint8_t *p_bajt_pom;

int main(void)
{
	register uint8_t i, j;
	register uint8_t *p_bajt;

	p_bajt_pom = (uint8_t *)sinu;
	p_bajt = (uint8_t *)p_bajt_pom;
		
//	predvolba = MAX_VZORKY_SINUS;
//	i = predvolba;
	i = POCET_VZORIEK;
	SMER_PORT_PRE_DA = 0xff;

   OCR2 = PREDVOLBA_CZ_SINUS;
   SET(TCCR2,WGM21);
   SET(TCCR2,CS20); // delicka 1

	while(1) {
		j = TIFR;
		if (TST(j, OCF2)) {
		   TIFR = j;
	      i--;
   		if (i == 0) {
				i = POCET_VZORIEK; 
				p_bajt = (uint8_t *)p_bajt_pom;
	      }
		   PORT_PRE_DA = *p_bajt;
    		p_bajt++;
		}
	}
}

// nech je tlacitko pripojene na pin s INT0 a dobre osetrene proti zakmitom
// frekvencia sa bude menit zmenou hodnoty v OCR2
ISR (INT0_vect) { 
	if (p_bajt_pom == (uint8_t *)sinu) {
		 p_bajt_pom = (uint8_t *)troj2;
       OCR2 = PREDVOLBA_CZ_SINUS;
	}	 
	else {
		p_bajt_pom = (uint8_t *)sinu;
      OCR2 = PREDVOLBA_CZ_TROJUHOLNIK;
	}
	return;   
}  

vypis strojoveho kodu z prekladaca.

43:       {
+0000002F:   E6E0        LDI       R30,0x60       Load immediate
+00000030:   E0F0        LDI       R31,0x00       Load immediate
+00000031:   93F00094    STS       0x0094,R31     Store direct to data space
+00000033:   93E00093    STS       0x0093,R30     Store direct to data space
53:       	SMER_PORT_PRE_DA = 0xff;
+00000035:   EF8F        SER       R24            Set Register
+00000036:   BB87        OUT       0x17,R24       Out to I/O location
55:          OCR2 = PREDVOLBA_CZ_SINUS;
+00000037:   E182        LDI       R24,0x12       Load immediate
+00000038:   BD83        OUT       0x23,R24       Out to I/O location
56:          SET(TCCR2,WGM21);
+00000039:   B585        IN        R24,0x25       In from I/O location
+0000003A:   6088        ORI       R24,0x08       Logical OR with immediate
+0000003B:   BD85        OUT       0x25,R24       Out to I/O location
57:          SET(TCCR2,CS20); // delicka 1
+0000003C:   B585        IN        R24,0x25       In from I/O location
+0000003D:   6081        ORI       R24,0x01       Logical OR with immediate
+0000003E:   BD85        OUT       0x25,R24       Out to I/O location
52:       	i = POCET_VZORIEK;
+0000003F:   E199        LDI       R25,0x19       Load immediate
62:       		j = TIFR;
+00000040:   B788        IN        R24,0x38       In from I/O location
63:       		if (TST(j, OCF2)) {
+00000041:   FF87        SBRS      R24,7          Skip if bit in register set
+00000042:   CFFD        RJMP      PC-0x0002      Relative jump
64:       		   TIFR = j;
+00000043:   BF88        OUT       0x38,R24       Out to I/O location
65:       	      i--;
+00000044:   5091        SUBI      R25,0x01       Subtract immediate
67:          		if (i == 0) {
+00000045:   F419        BRNE      PC+0x04        Branch if not equal
69:       				p_bajt = (uint8_t *)p_bajt_pom;
+00000046:   E6E0        LDI       R30,0x60       Load immediate
+00000047:   E0F0        LDI       R31,0x00       Load immediate
68:       				i = POCET_VZORIEK; 
+00000048:   E199        LDI       R25,0x19       Load immediate
71:       		   PORT_PRE_DA = *p_bajt;
+00000049:   9181        LD        R24,Z+         Load indirect and postincrement
+0000004A:   BB88        OUT       0x18,R24       Out to I/O location
+0000004B:   CFF4        RJMP      PC-0x000B      Relative jump
@0000004C: __vector_1
79:       ISR (INT0_vect) { 
+0000004C:   921F        PUSH      R1             Push register on stack
+0000004D:   920F        PUSH      R0             Push register on stack
+0000004E:   B60F        IN        R0,0x3F        In from I/O location
+0000004F:   920F        PUSH      R0             Push register on stack
+00000050:   2411        CLR       R1             Clear Register
+00000051:   932F        PUSH      R18            Push register on stack
+00000052:   938F        PUSH      R24            Push register on stack
+00000053:   939F        PUSH      R25            Push register on stack
80:       	if (p_bajt_pom == (uint8_t *)sinu) {
+00000054:   91800093    LDS       R24,0x0093     Load direct from data space
+00000056:   91900094    LDS       R25,0x0094     Load direct from data space
+00000058:   E020        LDI       R18,0x00       Load immediate
+00000059:   3680        CPI       R24,0x60       Compare with immediate
+0000005A:   0792        CPC       R25,R18        Compare with carry
+0000005B:   F081        BREQ      PC+0x11        Branch if equal
85:       		p_bajt_pom = (uint8_t *)sinu;
+0000005C:   E680        LDI       R24,0x60       Load immediate
+0000005D:   E090        LDI       R25,0x00       Load immediate
+0000005E:   93900094    STS       0x0094,R25     Store direct to data space
+00000060:   93800093    STS       0x0093,R24     Store direct to data space
86:             OCR2 = PREDVOLBA_CZ_TROJUHOLNIK;
+00000062:   E08F        LDI       R24,0x0F       Load immediate
+00000063:   BD83        OUT       0x23,R24       Out to I/O location
89:       }  
+00000064:   919F        POP       R25            Pop register from stack
+00000065:   918F        POP       R24            Pop register from stack
+00000066:   912F        POP       R18            Pop register from stack
+00000067:   900F        POP       R0             Pop register from stack
+00000068:   BE0F        OUT       0x3F,R0        Out to I/O location
+00000069:   900F        POP       R0             Pop register from stack
+0000006A:   901F        POP       R1             Pop register from stack
+0000006B:   9518        RETI                     Interrupt return
81:       		 p_bajt_pom = (uint8_t *)troj2;
+0000006C:   E789        LDI       R24,0x79       Load immediate
+0000006D:   E090        LDI       R25,0x00       Load immediate
+0000006E:   93900094    STS       0x0094,R25     Store direct to data space
+00000070:   93800093    STS       0x0093,R24     Store direct to data space
82:              OCR2 = PREDVOLBA_CZ_SINUS;
+00000072:   E182        LDI       R24,0x12       Load immediate
+00000073:   BD83        OUT       0x23,R24       Out to I/O location
89:       }  
+00000074:   919F        POP       R25            Pop register from stack
+00000075:   918F        POP       R24            Pop register from stack
+00000076:   912F        POP       R18            Pop register from stack
+00000077:   900F        POP       R0             Pop register from stack
+00000078:   BE0F        OUT       0x3F,R0        Out to I/O location
+00000079:   900F        POP       R0             Pop register from stack
+0000007A:   901F        POP       R1             Pop register from stack
+0000007B:   9518        RETI                     Interrupt return
89:       } 

Rozhodenie signalu pocas spracovanie interuptu od tlacitka nevidim ako problem, lebo aj tak chcem menit typ signalu, tak na tych par mikrosekundach rozhodenia casovaca aj tak nezalezi.

Tot vsjo, drzim Ti palce :slight_smile:

Takto jsem to zkusil ja. Myslite ze je to OK?

[code]#define F_CPU 20000000UL
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT))) //nastav!
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT))) //je nastaven?

#define OCR_SINUS 19 //2441670=1000000;20000000/(11000000)-1=19
#define OCR_TROJUHELNIK 19 //2050000=1000000;20000000/(11000000)-1=19

#define DA_SMER_PORT DDRB //DA na porte B
#define DA_PORT PORTB //DA na porte B

#define TLACITKO_SMER_PORT DDRD //tlacitko na porte D
#define TLACITKO_PORT PIND //tlacitko na porte D
#define TLACITKO_BIT 2 //tlacitko PD2

#define VZORKY_SINUS 24 //pocet vzorku
#define VZORKY_TROJUHELNIK 20 //pocet vzorku

uint8_t signal = SINUS;
uint8_t i=0;

unsigned char sinu [VZORKY_SINUS] =
{};
unsigned char troj [VZORKY_TROJUHELNIK] =
{};

int main(void)
{
//========= inicializace ===========
sei(); //globalni preruseni
SET(GIMSK,INT0); //preruseni od INT0
SET(MCUCR, ISC01); // preruseni na dobezne hrane
OCR0A = OCR_SINUS;
SET(TCCR0A,WGM01); //CTC
SET(TCCR0B,CS00); //preddelicka: f/1
SET(TLACITKO_SMER_PORT,TLACITKO_BIT); //tlacitko na PD2
DA_SMER_PORT = 0xFF; //vystup pro DA

//==================================
while(1)
{
	if (TST(TIFR,OCF0A))	//je nastaven OCF0A?
	{
		SET(TIFR,OCF0A);	//vynuluj TIFR
		//========= generovani vzorku ============
		if (signal == SINUS)
		{
			DA_PORT = sinu*;
			i++;
			if (i >= VZORKY_SINUS)
			{
				i = 0;
			}
		}
		else
		{
			DA_PORT = troj*;
			i++;
			if (i >= VZORKY_TROJUHELNIK)
			{
				i = 0;
			}
		}
		//=======================================
	}
}

}
ISR (INT0_vect)
{
if (signal == sinu)
{
signal = troj;
OCR0A = OCR_TROJUHELNIK;
}
else
{
signal = sinu;
OCR0A = OCR_SINUS;
}
return;
}[/code]

Jen si jeste nejsem jist tim RETURN; Myslim zde:

ISR (INT0_vect) { if (signal == sinu) { signal = troj; OCR0A = OCR_TROJUHELNIK; } else { signal = sinu; OCR0A = OCR_SINUS; } return; }
Jakou presne funkci to plni?**

navrat z podprogramu.
Ak vracias aj nejaku hodnotu tak tam byt musi, ak vracias hodnotu void, teda ziadnu a do zdrojaku slovo return nenapises, prekladac ho tam doplni sam. No stabna kultura je stabna kultura. :slight_smile:
Aspon pri zlozitejsich podprogramoch s viacerymi vystupnymi bodmi vidis, kde sa funkcia vlastne konci.

Dekuji za odpoved. A co rikas na program, ktery jsem sem poustnul?

Co Ti povedali testy v simulatore?

Vidno, ze si to neskusal ani len prelozit. Ty nas skusas? To nerob, mohlo by nas to tu prestat bavit :slight_smile:

  1. Nemas zadefinovanu konstatnu SINUS.
  2. Priradujes premennej ukazatel a nie premennu. Konkretne
signal = troj;
...
signal = sinu;

Zmena jednej vzorky Ti trva priemerne 1.12us. Ak si s tymto spokony, potom je vsetko OK (samozrejme po odstraneni chyb ktore som uviedol)
1.12us pri 20 vzorkach na trojuholniku Ti neda 50kHz. 17-18 vzoriek uz ano.

kod bez chyb:
ATtiny2313, -O3,

[code]
#define F_CPU 20000000UL
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

#define SET(BAJT,BIT) ((BAJT) |= (1<<(BIT))) //nastav!
#define TST(BAJT,BIT) ((BAJT) & (1<<(BIT))) //je nastaven?
#define SINUS 0xff
#define TROJUHOLNIK 0x00
#define OCR_SINUS 19 //2441670=1000000;20000000/(11000000)-1=19
#define OCR_TROJUHELNIK 19 //2050000=1000000;20000000/(11000000)-1=19

#define DA_SMER_PORT DDRB //DA na porte B
#define DA_PORT PORTB //DA na porte B

#define TLACITKO_SMER_PORT DDRD //tlacitko na porte D
#define TLACITKO_PORT PIND //tlacitko na porte D
#define TLACITKO_BIT 2 //tlacitko PD2

#define VZORKY_SINUS 24 //pocet vzorku
#define VZORKY_TROJUHELNIK 20 //pocet vzorku

uint8_t signal = SINUS;
uint8_t i=0;

unsigned char sinu [VZORKY_SINUS] =
{};
unsigned char troj [VZORKY_TROJUHELNIK] =
{};

int main(void)
{
//========= inicializace ===========
sei(); //globalni preruseni
SET(GIMSK,INT0); //preruseni od INT0
SET(MCUCR, ISC01); // preruseni na dobezne hrane
OCR0A = OCR_SINUS;
SET(TCCR0A,WGM01); //CTC
SET(TCCR0B,CS00); //preddelicka: f/1
SET(TLACITKO_SMER_PORT,TLACITKO_BIT); //tlacitko na PD2
DA_SMER_PORT = 0xFF; //vystup pro DA

//==================================
while(1)
{
if (TST(TIFR,OCF0A)) //je nastaven OCF0A?
{
SET(TIFR,OCF0A); //vynuluj TIFR
//========= generovani vzorku ============
if (signal == SINUS)
{
DA_PORT = sinu*;
i++;
if (i >= VZORKY_SINUS)
{
i = 0;
}
}
else
{
DA_PORT = troj*;
i++;
if (i >= VZORKY_TROJUHELNIK)
{
i = 0;
}
}
//=======================================
}
}
}
ISR (INT0_vect)
{
if (signal == sinu)
{
signal = TROJUHOLNIK;
OCR0A = OCR_TROJUHELNIK;
}
else
{
signal = SINUS;
OCR0A = OCR_SINUS;
}
return;
}
[/code]**

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: