No tak pekne dakujem
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
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