TODOPIC

Mecatrónica => DMX512 - Diseños y Proyectos => Mensaje iniciado por: esteban_k en 29 de Julio de 2015, 17:39:29

Título: Invertir pwm en Atmega 8515 asembler
Publicado por: esteban_k en 29 de Julio de 2015, 17:39:29
Hola como andan, quiero ver si me pueden dar una mano, de programación se muy poco , solo hago retoques y nada mas.. digamos que casi nada..
,Quiero invertir la fase del pwm del codigo que adjunto, mi problema es que si uso un mosfet canal n me queda al revés en la consola dmx  (cuando el potenciometro esta al maximo el pwm esta en 0, y cuando el potenciometro esta al minimo el pwm esta en valos 255) , lo soluciones agregando un CD4069, pero bueno se que se puede invertir, estoy buscando información pero mayormente es en lenguaje C....  si me pueden ayudar muchas gracias... igual sigo buscando...

Saludos

Código: [Seleccionar]
include "m8515def.inc"

;Register and Pin definitions

.def tempL = r16
.def tempH = r17
.def Flags = r18
.def DMXstate = r19
.def null = r2
.def status = r21
.def ind_count = r3
.def blink = r4
.def PwmCnt = r20
.def SREGbuf = r5
.def ChaseFine = r6
.def ChaseRes = r7

.equ StrobeFreqH = 0x80
.equ StrobeFreqL = 0x81
.equ StrobeBuf = 0x82

.equ OldStepH = 0x83
.equ OldStepL = 0x84
.equ NewStepH = 0x85
.equ NewStepL = 0x86
.equ StepCnt = 0x87
.equ ChaseCnt = 0x88
.equ ChaseSeed = 0x89

.equ LED1= PD7
.equ LED2= PE0
.equ BIT9= PE2

.equ DMX_FIELD=      0x60 ;SRAM-Beginn
.equ DMX_CHANNELS=   5
.equ PWM_FIELD=      0x70
.equ F_OSC=          8000
.equ FLASH_DURATION= 400
.equ IND_OFFSET=     12 ;Offset für indicator-Timer (14Hz)

#define CHS_SPD (0x600)
#define RATE         (0x500)
#define PAT0 (0x400)
#define PAT1         (PAT0 +0xA)
#define PAT2 (PAT1 +0xA)
#define PAT3 (PAT2 +0xA)
#define PAT4 (PAT3 +0xA)
#define PAT5         (PAT4 +0xA)
#define PAT6         (PAT5 +0xA)
#define PAT7         (PAT6 +0xA)


;***** special Flags

#define  VALID_DMX     (0)
#define  SIGNAL_COMING  (1)

#define  doIND (5)
#define  BLACK_OUT (6)
#define  DATA_REFRESHED (7)


;interrupt vectors
.org 0
rjmp init ;reset vector address
reti ;External Interrupt0 Vector Address
reti ;External Interrupt1 Vector Address
reti ;Input Capture1 Interrupt Vector Address
rjmp strobe ;Output Compare1A Interrupt Vector Address
reti ;Output Compare1B Interrupt Vector Address
reti ;Overflow1 Interrupt Vector Address
rjmp pwm ;Overflow0 Interrupt Vector Address
reti ;SPI Interrupt Vector Address
rjmp get_byte ;UART Receive Complete Interrupt Vector Address
reti ;UART Data Register Empty Interrupt Vector Address
reti ;UART Transmit Complete Interrupt Vector Address
reti ;Analog Comparator Interrupt Vector Address
reti ;External Interrupt2 Vector Address
reti ;Output Compare0 Interrupt Vector Address
reti ; EEPROM Interrupt Vector Address
reti ; SPM complete Interrupt Vector Address
reti ; SPM complete Interrupt Vector Address

; INIT

init:

; Stack
ldi tempH,high(RAMEND)
ldi tempL,low(RAMEND)
out SPH,tempH
out SPL,tempL

; WATCHDOG
wdr
ldi tempL, (1<<WDE)|(1<<WDCE)
out WDTCR, tempL
ldi tempL, (1<<WDE)|(1<<WDCE)|(1<<WDP2)|(1<<WDP1)
out WDTCR, tempL
wdr ;set prescaler @0,5s

; PortA
ser tempL
out DDRA, tempL
clr tempL
out PortA, tempL ;low Outputs

; PortB
ldi tempL, 0b00000011
out DDRB, tempL
ldi tempL, 0b11110100
out PortB, tempL

; PortD
ldi tempL, 0b10000100
out DDRD, tempL
ldi tempL, 0b01111000
out PortD, tempL ;DMX & Spare , LED1 on

; PortE
ldi tempL, 0b00000001
out DDRE, tempL
ser tempL
out PortE, tempL ;LED2 off, BIT9 & OPTION Pullup

; Timers
ldi tempL, (1<<CS01) ;set counter0 @clock/8 frequency
out TCCR0, tempL
clr tempL
out TCCR1A, tempL
ldi tempL, (1<<CS12)|(1<<WGM12) ;set counter1 @clock/256 frequency, CTCmode
out TCCR1B, tempL
ldi tempL, (1<<TOIE0) ;aktivate overflow interrupt
out TIMSK, tempL

rcall init_dmx


; set Register
clr null
clr blink
com blink
mov ChaseFine, blink
ldi tempL, IND_OFFSET
mov ind_count, tempL
ldi PwmCnt, 0xFF
ldi Flags, 0 ;clear Flags

sts StepCnt, null
sts NewStepH, null
sts NewStepL, null
ldi tempL, 1
sts ChaseCnt, tempL
sts ChaseSeed, tempL
mov ChaseRes, tempL

wdr
sei

main: sbrc Flags, doIND
rcall indicate

rcall   eval_strobe_freq
;rcall chase
rjmp main



;****************************** LED INDICATOR ***********************************
indicate:
cbr Flags, (1<<doIND) ;clear flag
rcall chase
dec ind_count
breq ind_a
ret
     
  ind_a:
wdr ;reset Watchdog
;working LED
sbrc Flags, DATA_REFRESHED ;should flash?
rjmp data_flash
sbi PortE, LED2 ; LED off

Error_LED:
sbrc  blink, 0 ;wenn erstes bit HI
rjmp  on
sbi    PortD, LED1
rjmp  ind_tst
on:
cbi  PortD, LED1

     ind_tst:
    lsr    blink
ldi tempL, 1
cp blink, tempL
brne no_ind

;wenn durchrotiert (blink = 0)
ldi tempL, 0b10000000
sbrs Flags, VALID_DMX
ldi tempL, 0b10001010
sbrs Flags, SIGNAL_COMING
ldi tempL, 0b10000010
mov  blink, tempL

cbr Flags, (1<<VALID_DMX)|(1<<SIGNAL_COMING)

no_ind:
ldi tempL, IND_OFFSET
mov ind_count, tempL ;plant prescaler
ret
data_flash:
cbr Flags, (1<<DATA_REFRESHED)
    sbis PortE,LED2 ;blinken grün
rjmp off
cbi PortE,LED2
rjmp Error_LED
off:
sbi PortE,LED2
rjmp Error_LED




;****************************** strobe frequency ***********************************
eval_strobe_freq:
lds tempL, DMX_FIELD ;get 1st DMX ch
cpi tempL, 246
brlo esf_1
ldi tempL, 245
       esf_1:
lds tempH, StrobeBuf
cp tempL, tempH
brne esf_2 ;only eval if changed
ret
esf_2:
sts StrobeBuf, tempL
cpi tempL, 30
brlo esf_no_strobe
cpi tempL, 245
brsh esf_sync

subi tempL, 30 ;0-200 allowed
ldi ZL, low(RATE*2) ;get freq from table
ldi ZH, high(RATE*2)
add ZL, tempL
adc ZH, null
add ZL, tempL
adc ZH, null
lpm tempL, Z+
lpm tempH, Z
cli
sts StrobeFreqL, tempL ;atomic store
sts StrobeFreqH, tempH

in tempL, TIMSK
sbr tempL, (1<<OCIE1A) ;enable irq
out TIMSK, tempL
in tempL, TIFR
sbr tempL, (1<<OCF1A) ;enable irq
out TIFR, tempL
reti


esf_no_strobe:
in tempL, TIMSK
cbr tempL, (1<<OCIE1A) ;disable irq
out TIMSK, tempL
cbr Flags, (1<<BLACK_OUT) ;enable pwm
ret

esf_sync:
in tempL, TIMSK
sbrs tempL, OCIE1A ;only when strobing
ret
cli
sbr Flags, (1<<BLACK_OUT) ;blank!
lds ZH, StrobeFreqH
lds ZL, StrobeFreqL
out OCR1AH, ZH
out OCR1AL, ZL
sbiw ZH:ZL, 20
out TCNT1H, ZH
out TCNT1L, ZL
reti


;****************************** manual chaser mode ***********************************
chase: ;called by indicator
sbis PinE, PE1
rjmp chs_a
sbic UCSRB,RXEN
ret ;enable DMX reception
sbi UCSRB, RXEN
clr DMXstate
ret

chs_exit:
sts ChaseCnt, tempH
ret

    chs_a:
cbi UCSRB,RXEN ;disable DMX
sbr Flags, (1<<VALID_DMX)|(1<<SIGNAL_COMING)
lds tempH, ChaseCnt ;load prescaler
dec tempH
brne chs_exit
lds tempL, ChaseSeed ;reseed prescaler
sts ChaseCnt, tempL

add ChaseFine, ChaseRes ;up-fade val
adc tempH, null ;(tempH was 0)
mov tempL, ChaseFine
com tempL ;down-fade val

tst tempH
brne chs_step
  chs_step_ret:
ldi XL, low(DMX_FIELD +1)
ldi XH, high(DMX_FIELD)
ldi ZL, 1
   chase_fade: ;ch1..8
clr tempH
lds ZH, OldStepL
and ZH, ZL
breq cf_no_old
mov tempH, tempL
   cf_no_old:
    lds ZH, NewStepL
and ZH, ZL
breq cf_no_new
        add tempH, ChaseFine
       cf_no_new:
    st X+, tempH
lsl ZL
brne chase_fade

clr tempH ;9th ch
lds ZH, OldStepH
sbrc ZH, 0
mov tempH, tempL
lds ZH, NewStepH
sbrc ZH, 0
add tempH, ChaseFine
st X, tempH

ret


chs_step:
sbr Flags, (1<<DATA_REFRESHED)
clr ChaseFine ;reset fader
ser tempL

lds tempH, NewStepL ;change steps
sts OldStepL, tempH
lds tempH, NewStepH
sts OldStepH, tempH

ldi ZH, high(CHS_SPD*2) ;get speed
in ZL, PinC
com ZL
swap ZL
andi ZL, 0b00001111 ;isolate pattern
lpm ZH, Z
ldi tempH, 1

cpi ZL, 5 ;switch between resolution and prescale
brsh chs_decres
mov ChaseRes, tempH
sts ChaseSeed, ZH
rjmp chs_strb
       chs_decres:
    mov ChaseRes, ZH
sts ChaseSeed, tempH
   chs_strb:

clr ZH ;add strobe
sbis PinE, PE2
ldi ZH,  220
sts DMX_FIELD, ZH

ldi ZH, high(PAT0*2) ;get next step
lds tempH, StepCnt
mov ZL, tempH
lsl ZL
inc tempH
sts StepCnt, tempH
lpm tempH, Z+
sts NewStepL, tempH
lpm tempH, Z
sts NewStepH, tempH

sbrs tempH, 1 ;reset pattern?
rjmp chs_step_ret

in ZL, PinC
com ZL
andi ZL, 0b00000111 ;isolate pattern
ldi tempH, 10
mul ZL, tempH
sts StepCnt, r0 ;save pattern

rjmp chs_step_ret






; ***************************9ch 8bitpwm-Ausgabe ****************************************
pwm:
in      SREGbuf, SREG
push tempL

  sbrc Flags, BLACK_OUT ;blanked by strobe?
rjmp pwm_bo_exit

lds tempL, PWM_FIELD
cp tempL, PwmCnt
ror status
 
  lds tempL, (PWM_FIELD+1)
cp tempL, PwmCnt
ror status

lds tempL, (PWM_FIELD+2)
cp tempL, PwmCnt
ror status

lds tempL, (PWM_FIELD+3)
cp tempL, PwmCnt
ror status

lds tempL, (PWM_FIELD+4)
cp tempL, PwmCnt
ror status

  lds tempL, (PWM_FIELD+5)
cp tempL, PwmCnt
ror status
 
lds tempL, (PWM_FIELD+6)
cp tempL, PwmCnt
ror status

  lds tempL, (PWM_FIELD+7)
cp tempL, PwmCnt
ror status
    ;9th bit
    sbis PinD, PD4 ;invert option
  rjmp pwm9_pos ; no invert

lds tempL, (PWM_FIELD+8)
sbi PortB, 0
cp tempL, PwmCnt
brlo pwm_exit
cbi PortB, 0
rjmp pwm_exit

   pwm9_pos:
    com status
  lds tempL, (PWM_FIELD+8)
cbi PortB, 0
cp tempL, PwmCnt
brlo pwm_exit
sbi PortB, 0
rjmp pwm_exit

pwm_bo_exit:
sbis PinD, PD4 ;invert option
  rjmp pwm_bo_pos ; no invert
ser status ;all ch off (inverted)
sbi PortB, 0
rjmp pwm_exit
   pwm_bo_pos:
    clr status ;all ch off
cbi PortB, 0

pwm_exit:
out PortA, status ;output
mov tempL, PwmCnt ;set next compare time
lsr tempL
lsr tempL
lsr tempL
ldi status, 250
sub status, tempL
out TCNT0, status

inc PwmCnt
tst PwmCnt
brne pwm_no_reload
lds tempL, (DMX_FIELD+1) ;refresh channels
sts PWM_FIELD, tempL
lds tempL, (DMX_FIELD+2)
sts (PWM_FIELD+1), tempL
lds tempL, (DMX_FIELD+3)
sts (PWM_FIELD+2), tempL
lds tempL, (DMX_FIELD+4)
sts (PWM_FIELD+3), tempL
lds tempL, (DMX_FIELD+5)
sts (PWM_FIELD+4), tempL
lds tempL, (DMX_FIELD+6)
sts (PWM_FIELD+5), tempL
lds tempL, (DMX_FIELD+7)
sts (PWM_FIELD+6), tempL
lds tempL, (DMX_FIELD+8)
sts (PWM_FIELD+7), tempL
lds tempL, (DMX_FIELD+9)
sts (PWM_FIELD+8), tempL
ldi PwmCnt, 1 ;reseed counter
sbr Flags, (1<<doIND) ;indicate in main
 
  pwm_no_reload:
  pop tempL
out     SREG, SREGbuf
reti



; ***************************Strobo function ****************************************
strobe:
in      SREGbuf, SREG
push tempL
push tempH

sbrs Flags, BLACK_OUT
rjmp str_blank
cbr Flags, (1<<BLACK_OUT) ;enable pwm
ldi tempL,  low(FLASH_DURATION) ;load flash time
ldi tempH, high(FLASH_DURATION)
rjmp str_exit

str_blank:
sbr Flags, (1<<BLACK_OUT)
lds tempL, StrobeFreqL
lds tempH, StrobeFreqH

str_exit:
out OCR1AH, tempH
out OCR1AL, tempL
pop tempH
pop tempL
out     SREG, SREGbuf
reti


.include "lib_dmx_in.asm"

nix: rjmp nix

// Strobo frequency table (damped logarithmic)
.org RATE
.dw 65532, 60407, 56368, 53017, 50170, 47708, 45546, 43626, 41904, 40345, 38925, 37623, 36423, 35311, 34277, 33311
.dw 32406, 31555, 30753, 29996, 29278, 28596, 27948, 27331, 26741, 26177, 25637, 25120, 24623, 24145, 23685, 23242
.dw 22814, 22402, 22003, 21617, 21244, 20882, 20531, 20191, 19861, 19540, 19228, 18924, 18629, 18341, 18061, 17788
.dw 17521, 17261, 17007, 16760, 16517, 16281, 16049, 15823, 15601, 15384, 15172, 14964, 14760, 14560, 14364, 14172
.dw 13983, 13798, 13617, 13438, 13263, 13091, 12922, 12756, 12593, 12432, 12274, 12119, 11966, 11815, 11667, 11522
.dw 11378, 11237, 11098, 10960, 10825, 10692, 10561, 10431, 10304, 10178, 10054, 9931,  9811,  9691,  9574,  9458
.dw 9343,  9230,  9119,  9008,  8899,  8792,  8686,  8581,  8477,  8375,  8273,  8173,  8074,  7976,  7880,  7784
.dw 7690,  7596,  7504,  7412,  7322,  7232,  7144,  7056,  6969,  6884,  6799,  6715,  6631,  6549,  6467,  6387
.dw 6307,  6227,  6149,  6071,  5994,  5918,  5843,  5768,  5694,  5620,  5548,  5475,  5404,  5333,  5263,  5193
.dw 5125,  5056,  4988,  4921,  4855,  4789,  4723,  4658,  4594,  4530,  4466,  4404,  4341,  4279,  4218,  4157
.dw 4097,  4037,  3978,  3919,  3860,  3802,  3744,  3687,  3631,  3574,  3518,  3463,  3408,  3353,  3299,  3245
.dw 3191,  3138,  3085,  3033,  2981,  2929,  2878,  2827,  2777,  2726,  2677,  2627,  2578,  2529,  2480,  2432
.dw 2384,  2337,  2289,  2242,  2196,  2149,  2103,  2057,  2012,  1967,  1922,  1877,  1833,  1789,  1745,  1701
.dw 1658,  1615,  1572,  1530,  1488,  1446,  1350,  1250,  1100,  1050,  1000,  950,   900,   850,   800,   750
.dw 700,   650,   600,   550,   500,   450,   400,   350,   300,   250,   200,   150


.org PAT0 ;on
.dw 0b0111111111
.dw 0b1111111111

.org PAT1 ;Lauflicht
.dw 0b0000000001
.dw 0b0000000010
.dw 0b0000000100
.dw 0b0000001000
.dw 0b0000010000
.dw 0b0000100000
.dw 0b0001000000
.dw 0b0010000000
.dw 0b1100000000

.org PAT2 ;ping pong
.dw 0b0000010000
.dw 0b0000100000
.dw 0b0000001000
.dw 0b0001000000
.dw 0b0000000100
.dw 0b0010000000
.dw 0b0000000010
.dw 0b0100000000
.dw 0b1000000001

.org PAT3 ;ping pong
.dw 0b0000011000
.dw 0b0000100100
.dw 0b0001000010
.dw 0b1010000001

.org PAT4 ;pfeil
.dw 0b0000011000
.dw 0b0000111100
.dw 0b0001111110
.dw 0b0011111111
.dw 0b0011100111
.dw 0b0011000011
.dw 0b1010000001

.org PAT5 ;RGB
.dw 0b0001001001
.dw 0b0011011011
.dw 0b0010010010
.dw 0b0110110110
.dw 0b0100100100
.dw 0b1101101101

.org PAT6 ;RGB spread
.dw 0b0100010001
.dw 0b0101110011
.dw 0b0001100010
.dw 0b0011101110
.dw 0b0010001100
.dw 0b1110011101

.org PAT7
.dw 0b0001001001 ;RGB single change
.dw 0b0001001011
.dw 0b0001011011
.dw 0b0011011011
.dw 0b0011011010
.dw 0b0011010010
.dw 0b0010010010
.dw 0b0010010110
.dw 0b0010110110
.dw 0b0110110110
.dw 0b0110110100
.dw 0b0110100100
.dw 0b0100100100
.dw 0b0100100101
.dw 0b0100101101
.dw 0b0101101101
.dw 0b0101101001
.dw 0b1101001001


.org CHS_SPD
.db 25, 10, 3, 2, 1, 2, 3, 5, 8, 12, 17, 22, 27, 35, 40, 48



 
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 30 de Julio de 2015, 01:44:10
Es un PWM por software, no trabaje nunca con micros de Atmel, pero el ASM es parecido en todo, solo cambia la forma de los nombres y la arquitectura, se me ocurren 4 cosas a probar:

1-
Parece que ya tiene incorporado algo para invertirlo, supuestamente el pin D4 sirve para invertir la señal de salida. Podrias probarlo, para empezar.

2-
Tal ves la mas compleja por que requiere tener en cuenta varias cosas, y sea mucho mas facil la otra opcion

Cambiar el formato del PWM, en ves de incrementar la variable que la reste, pero esto requiere el cambio de 3 lineas de codigo.
Lo bueno de este metodo es que no se agregan instrucciones ni ciclos. Las instrucciones a cambiar son:

Código: ASM
  1. inc      PwmCnt
  2. ldi PwmCnt, 0xFF
  3. ldi      PwmCnt, 1                     ;reseed counter


3-
La opcion mas simple (ya que se encuentra confinado en un bloque y no en diversas partes del codigo) y no creo que afecte demasiado el cambio.
Ya esto deberias de agregar un par de instrucciones mas, en ves de contar a la inversa, deberias invertir lo guardado, en ves de modificar el index. simplemente haces el complemento y deberias cambiar:

Código: ASM
  1. lds      tempL, (DMX_FIELD+1)            ;refresh channels
  2.       sts      PWM_FIELD, tempL
  3.       lds      tempL, (DMX_FIELD+2)
  4.       sts      (PWM_FIELD+1), tempL
  5.       lds      tempL, (DMX_FIELD+3)
  6.       sts      (PWM_FIELD+2), tempL
  7.       lds      tempL, (DMX_FIELD+4)
  8.       sts      (PWM_FIELD+3), tempL
  9.       lds      tempL, (DMX_FIELD+5)
  10.       sts      (PWM_FIELD+4), tempL
  11.       lds      tempL, (DMX_FIELD+6)
  12.       sts      (PWM_FIELD+5), tempL
  13.       lds      tempL, (DMX_FIELD+7)
  14.       sts      (PWM_FIELD+6), tempL
  15.       lds      tempL, (DMX_FIELD+8)
  16.       sts      (PWM_FIELD+7), tempL
  17.       lds      tempL, (DMX_FIELD+9)
  18.       sts      (PWM_FIELD+8), tempL

Por:

Código: ASM
  1. lds      tempL, (DMX_FIELD+1)            ;refresh channels
  2.       com      tempL
  3.       sts      PWM_FIELD, tempL
  4.       lds      tempL, (DMX_FIELD+2)
  5.       com      tempL
  6.       sts      (PWM_FIELD+1), tempL
  7.       lds      tempL, (DMX_FIELD+3)
  8.       com      tempL
  9.       sts      (PWM_FIELD+2), tempL
  10.       lds      tempL, (DMX_FIELD+4)
  11.       com      tempL
  12.       sts      (PWM_FIELD+3), tempL
  13.       lds      tempL, (DMX_FIELD+5)
  14.       com      tempL
  15.       sts      (PWM_FIELD+4), tempL
  16.       lds      tempL, (DMX_FIELD+6)
  17.       com      tempL
  18.       sts      (PWM_FIELD+5), tempL
  19.       lds      tempL, (DMX_FIELD+7)
  20.       com      tempL
  21.       sts      (PWM_FIELD+6), tempL
  22.       lds      tempL, (DMX_FIELD+8)
  23.       com      tempL
  24.       sts      (PWM_FIELD+7), tempL
  25.       lds      tempL, (DMX_FIELD+9)
  26.       com      tempL
  27.       sts      (PWM_FIELD+8), tempL


De esa forma cuando lo llegado del DMX le indique que es de 250, lo que luego se compara es con 255 - 250 = 5, es decir 5, cuando tu potenciometro este en 205, tu pwm va a usar el valor de 50.
Es decir ahi estarias invirtiendolo, no se si lo que recibe ya lo invierte y lo guarda en DMX_FIELD, pero con este caso, lo estariamos invirtiendo de nuevo.
De todas formas no tuve en cuenta el tiempo, pero solo llevaria mas tiempo el momento en que comienze en 0 pwmCnt ya que necesitaria recargar, y en tiempo me refiero a 8 ciclos mas de reloj.

4-
Buscar donde cambia el valor del puerto e invertirlo antes, es decir esto:

Código: ASM
  1. pwm_exit:
  2.       out      PortA, status                  ;output

Por

Código: ASM
  1. pwm_exit:
  2.       com     status
  3.       out      PortA, status                  ;output
  4.       com     status

Agregando 2 instrucciones, Y todo lo demas internamente funcionaria de la misma forma, es decir solo toco lo que va al puerto. invierto e invierto nuevamente por que luego se hace uso de "status" entonces debe mantener el valor sin invertir.
Sino habria que revisar todo el programa. Si solo quisiera invertirlo una ves


------------------------

De recomendar te recomiendo la primera opcion, luego la 4ta, luego la 3era y luego la 2da.

PD: Esto sin conocer los atmega ya que nunca trabaje con ellos, solo mire su set de intrucciones.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: esteban_k en 30 de Julio de 2015, 12:01:52
Buenas....
Te comento que use la Opción nº 4 y anduvo perfecto!!!!!!..

Muchas gracias por la información, soy muy duro para esto de la programación...

Mil Gracias!!!!..
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 31 de Julio de 2015, 19:23:52
hola
Es un PWM por software, no trabaje nunca con micros de Atmel, pero el ASM es parecido en todo, solo cambia la forma de los nombres y la arquitectura, se me ocurren 4 cosas a probar:

1-
Parece que ya tiene incorporado algo para invertirlo, supuestamente el pin D4 sirve para invertir la señal de salida. Podrias probarlo, para empezar.

2-
Tal ves la mas compleja por que requiere tener en cuenta varias cosas, y sea mucho mas facil la otra opcion

Cambiar el formato del PWM, en ves de incrementar la variable que la reste, pero esto requiere el cambio de 3 lineas de codigo.
Lo bueno de este metodo es que no se agregan instrucciones ni ciclos. Las instrucciones a cambiar son:

Código: ASM
  1. inc      PwmCnt
  2. ldi PwmCnt, 0xFF
  3. ldi      PwmCnt, 1                     ;reseed counter


3-
La opcion mas simple (ya que se encuentra confinado en un bloque y no en diversas partes del codigo) y no creo que afecte demasiado el cambio.
Ya esto deberias de agregar un par de instrucciones mas, en ves de contar a la inversa, deberias invertir lo guardado, en ves de modificar el index. simplemente haces el complemento y deberias cambiar:

Código: ASM
  1. lds      tempL, (DMX_FIELD+1)            ;refresh channels
  2.       sts      PWM_FIELD, tempL
  3.       lds      tempL, (DMX_FIELD+2)
  4.       sts      (PWM_FIELD+1), tempL
  5.       lds      tempL, (DMX_FIELD+3)
  6.       sts      (PWM_FIELD+2), tempL
  7.       lds      tempL, (DMX_FIELD+4)
  8.       sts      (PWM_FIELD+3), tempL
  9.       lds      tempL, (DMX_FIELD+5)
  10.       sts      (PWM_FIELD+4), tempL
  11.       lds      tempL, (DMX_FIELD+6)
  12.       sts      (PWM_FIELD+5), tempL
  13.       lds      tempL, (DMX_FIELD+7)
  14.       sts      (PWM_FIELD+6), tempL
  15.       lds      tempL, (DMX_FIELD+8)
  16.       sts      (PWM_FIELD+7), tempL
  17.       lds      tempL, (DMX_FIELD+9)
  18.       sts      (PWM_FIELD+8), tempL

Por:

Código: ASM
  1. lds      tempL, (DMX_FIELD+1)            ;refresh channels
  2.       com      tempL
  3.       sts      PWM_FIELD, tempL
  4.       lds      tempL, (DMX_FIELD+2)
  5.       com      tempL
  6.       sts      (PWM_FIELD+1), tempL
  7.       lds      tempL, (DMX_FIELD+3)
  8.       com      tempL
  9.       sts      (PWM_FIELD+2), tempL
  10.       lds      tempL, (DMX_FIELD+4)
  11.       com      tempL
  12.       sts      (PWM_FIELD+3), tempL
  13.       lds      tempL, (DMX_FIELD+5)
  14.       com      tempL
  15.       sts      (PWM_FIELD+4), tempL
  16.       lds      tempL, (DMX_FIELD+6)
  17.       com      tempL
  18.       sts      (PWM_FIELD+5), tempL
  19.       lds      tempL, (DMX_FIELD+7)
  20.       com      tempL
  21.       sts      (PWM_FIELD+6), tempL
  22.       lds      tempL, (DMX_FIELD+8)
  23.       com      tempL
  24.       sts      (PWM_FIELD+7), tempL
  25.       lds      tempL, (DMX_FIELD+9)
  26.       com      tempL
  27.       sts      (PWM_FIELD+8), tempL


De esa forma cuando lo llegado del DMX le indique que es de 250, lo que luego se compara es con 255 - 250 = 5, es decir 5, cuando tu potenciometro este en 205, tu pwm va a usar el valor de 50.
Es decir ahi estarias invirtiendolo, no se si lo que recibe ya lo invierte y lo guarda en DMX_FIELD, pero con este caso, lo estariamos invirtiendo de nuevo.
De todas formas no tuve en cuenta el tiempo, pero solo llevaria mas tiempo el momento en que comienze en 0 pwmCnt ya que necesitaria recargar, y en tiempo me refiero a 8 ciclos mas de reloj.

4-
Buscar donde cambia el valor del puerto e invertirlo antes, es decir esto:

Código: ASM
  1. pwm_exit:
  2.       out      PortA, status                  ;output

Por

Código: ASM
  1. pwm_exit:
  2.       com     status
  3.       out      PortA, status                  ;output
  4.       com     status

Agregando 2 instrucciones, Y todo lo demas internamente funcionaria de la misma forma, es decir solo toco lo que va al puerto. invierto e invierto nuevamente por que luego se hace uso de "status" entonces debe mantener el valor sin invertir.
Sino habria que revisar todo el programa. Si solo quisiera invertirlo una ves


------------------------

De recomendar te recomiendo la primera opcion, luego la 4ta, luego la 3era y luego la 2da.

PD: Esto sin conocer los atmega ya que nunca trabaje con ellos, solo mire su set de intrucciones.
bueno yo use ese codigo tal cual esta ., y no tube problemas de invercion en la consola
 
pero eso si ., segui la sujerencias del autor ., para conectar los led y use de 5W (que talvez alli este el problema del amigo )
 
yo lo que siempre intente ., pero no pude lograrlo es copiar o pasr las funciones de FADING o RAIMBON  a C en AVRstuduo (sin DMX)
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 01 de Agosto de 2015, 00:06:58
Citar
yo lo que siempre intente ., pero no pude lograrlo es copiar o pasr las funciones de FADING o RAIMBON  a C en AVRstuduo (sin DMX)

Realmente yo jamas trabaje con un atmel (ni en C ni en ASM), asi que mi codigo solo fue por curiosidad de ver como era el ASM de los atmega. Debido a que todos los ASM manejan binario no fue dificil entenderlo
Tampoco trabaje con DMX para saber que es o cuales son las funciones FADING y RAIMBON ( o RAINBOW?) como para intentar decirte como pasarlo, lo que si veo es que los efectos parecen estar programados al final del codigo.

Si pasas el codigo en ASM e indicas cual es la parte se podria pasar tranquilamente creo.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 02 de Agosto de 2015, 16:06:44
hola  ., y desde ya muchas gracias por enseñar
Si pasas el codigo en ASM e indicas cual es la parte se podria pasar tranquilamente creo.
bueno aca te paso el codigo de ASM que probe (el anterior ya tambien esta probado y funcionan los dos perfectamente )
esta parte esta solamente los efectos FADING y RAINBOW(corregido su  escritura gracias ) pero todo esto sin DMX
tambien habria que aclarar que las funciones  de FADING de la libreria anterior funcionan si se coloca la llave minidips numero 10 en ON (conectada) adjunto foto del montaje fisico por si tiene dudas
de esa manera desabilita la funcion DMX y queda en modo programado
este codigo que pongo solo es para tres (3) led o sea RGB ., el anterior es para nueve (9) divididos en RGB (8 del puerto A y 1 del puerto B )
y vuelvo a repetir., he probado los dos codigos originales .,  el anterior y el simplificado (este) !!!! y funciona los dos perfectamente ¡¡¡
(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=44207.0;attach=23382;image)
este es la configuracion que uso (montaje )
Código: [Seleccionar]
; ***********************************************************************************************
; * RGB atenuador + mix colores + stroboscopico + luz discoteca-intermitente *
; * *
; * para ATMega 8515 *
; * *
; * Versión 3.0 - 22/03/2008 *
; * LED en el interruptor MOSFET al puerto B *
; * *
; * *
; * PortB0 = Rojo, PortB1 = Verde, PortB2 = Azul  *
; ***********************************************************************************************

.include "m8515def.inc"

; ------------------------------------------------------------------------------------------------
;           Definir los registros, etc.
; ------------------------------------------------------------------------------------------------

.def temp0 = R16 ;Definir registro
.def temp1 = R17
.def temp2 = R18
.def temp_ZL = R1
.def temp_ZH = R2
.def temp_Sreg = R3
.def Speed = R19
.def R  = R20
.def V  = R21
.def A  = R22
.def R_Out = R4
.def V_Out  = R5
.def A_Out = R6
.def PWM_Count = R23

.equ XTAL = 8000000 ; Sólo para información

; ------------------------------------------------------------------------------------------------
;            Tabla de vectores de interrupción Mega8515
; ------------------------------------------------------------------------------------------------

.CSEG

.org 0x0000

rjmp    Inicio  ; Restablecer controlador
reti ; Interrupción externa Solicitud 0
reti ; Interrupción externa Solicitud 1
reti ; Temporizador / Captura de Counter1
reti ; Timer / Counter1 Comparar Partido A
reti ; Timer / Counter1 Comparar Partido B
reti ; Timer / Counter1 desbordamiento (overflow)
rjmp    ISR_PWM ; Timer / Counter0 desbordamiento (Overflow) -> rutina PWM
reti ; Transferencia serial completa
reti ; Rx completa
reti ; Registro de datos vacía
reti ; Tx completa
reti ; Comparador analógico
reti ; Interrupción externa Solicitud 2
reti ; Timer / Counter0 Comparar Partido (match)
reti ; EEPROM Ready
reti ; almacenado memoria Ready Programa

; ------------------------------------------------------------------------------------------------
;                Puntero de pila , puertos establecidos
; ------------------------------------------------------------------------------------------------

Inicio:

ldi temp0, LOW(RAMEND);Byte bajo de dirección superior RAM BAJA
out SPL, temp0
ldi temp0, HIGH(RAMEND);Byte alto de dirección superior RAM ALTA
out SPH, temp0

ldi     temp0, 0b00000001;Conjunto CS00: 1 divisor
out     TCCR0, temp0

ldi     temp0, (1<<TOIE0);TOIE0: interrumpir el desbordamiento del temporizador
out     TIMSK, temp0

sei          ;Habilitar las interrupciones

ldi temp0, 0
out DDRC, temp0 ;Puerto C en la entrada (interruptor DIP)

ldi temp0, 0b00000001
out DDRE, temp0 ;PortE0 en la salida (LED), 1 y 2 en la entrada
sbi PORTE, 1 ;Pull-up resistencias
sbi PORTE, 2         ;Pull-up resistencias

ldi temp0, 0xff
out DDRB, temp0 ;PortA para establecer la salida (salida PWM)
out PORTC, temp0 ;Habilitar resistencias pull-up en PORTC

sbi DDRD, 7 ;PortD7 en la salida ("On" LED)

; ------------------------------------------------------------------------------------------------
; "Estado fundamental" - Colores y Strobo, ajustables mediante interruptores DIP switch
; ------------------------------------------------------------------------------------------------

Interruptor_Loop:    ;Comprobar el interruptor DIP

sbis PINC, 6   ;El interruptor 7 está apagado, más
rcall RGB_Fader  ;Cambie a -> RGB atenuador

sbis PINC, 5   ;El interruptor 6 está apagado, más
rcall Disco   ;Cambie a -> Indicador de Disco

cbi PORTE, 0  ;LED de estado encendido

sbic PINC, 3   ;Comprobar el interruptor 4 (medio Verde / corrección de color rosa)
rjmp Mixcolores   ;No se requiere corrección, "lo más normal"

in temp1, PINC ;Comprobar dip switch
andi temp1, 0b00000111 ;Caso especial "blanco"
brne Mixcolores   ;no todos los interruptores (no blanco), por lo que otros colores

ldi R, 220   ;menos rojo porque ajustado a rosa rebelde
ldi V, 255
ldi A, 255
rcall Dimmercurva ;Corrección y de salida Brillo

rjmp Strobo ;Saltarse la configuración del color, además Strobo

Mixcolores:

ldi R, 255 ;encendido de rojo
sbic PINC, 0 ;Comprobar el interruptor 1 (Rojo)
ldi R, 0 ;El interruptor está apagado,apagado de rojo

ldi V, 0 ;apagado de verde
sbic PINC, 1 ;Comprobar el interruptor 2 (Verde)
rjmp azul ;El interruptor está apagado, más
ldi V, 255 ;encendido de verde
sbis PINC, 3 ;Comprobar el interruptor 4 (media Verde / corrección de color de rosa)
ldi V, 128 ;si el interruptor encendido , la mitad verde

azul:

ldi A, 255 ;encendido de Azul
sbic PINC, 2 ;Comprobar el interruptor 3 (azul)
ldi A, 0 ;El interruptor está apagado, apagado de azul

rcall Dimmercurva ;Corrección y de salida Brillo

Strobo:

sbic PINC, 4 ;Revise el interruptor 5 (estroboscópico)
rjmp Interruptor_Loop ;no Apagar, 

;// ------------------------------------------------------------------------------------------------//
;              Strobo - estroboscópica
;// ------------------------------------------------------------------------------------------------//
ldi Speed, 255 ;Strobo velocidad básica

sbic PINC, 7 ;Interruptor 8 chequea (Rojo / Azul Strobe)
rjmp Strobo_normal ;interuptor apagado, Strobo normales

ldi R, 255 ;Rojo
ldi V, 0    ;verde
ldi A, 0    ;azul
rcall Dimmercurva ;Corrección y de salida Brillo

cbi PORTE, 0 ;LED de estado encendido

ldi temp1, 2 ;durante 2 ciclos rojo

Strobo_rojo:

rcall esperar

dec temp1
brne Strobo_rojo


ldi R, 0 ;rojo apagado
ldi v, 0    ;verde apagado
ldi A, 0    ;azul apagado
rcall Dimmercurva ;Corrección y de salida Brillo

sbi PORTE, 0 ;LED de estado apagado

ldi temp1, 10 ;y 10 ciclos de apagado

Strobo_rojo_desde:

rcall esperar

dec temp1
brne Strobo_rojo_desde

ldi R, 0 ;rojo apagado
ldi V, 0    ;verde apagado
ldi A, 255  ;azul encendido
rcall Dimmercurva ;Corrección y de salida Brillo

cbi PORTE, 0 ;LED de estado encendido

ldi temp1, 2 ;durante 2 ciclos azul

Strobo_azul:

rcall esperar

dec temp1
brne Strobo_azul

ldi R, 0 ;rojo apagado
ldi V, 0    ;verde apagado
ldi A, 0    ;azul apagado
rcall Dimmercurva ;Corrección y de salida Brillo

sbi PORTE, 0 ;LED de estado apagado

ldi temp1, 10 ;y 10 ciclos de apagado

Strobo_azul_desde:

rcall esperar

dec temp1
brne Strobo_azul_desde

rjmp Interruptor_Loop

Strobo_normal:

ldi temp1, 2 ;durante 2 ciclos

Strobo_a:

rcall esperar

dec temp1
brne Strobo_a


ldi R, 0 ;rojo apagado
ldi V, 0    ;verde apagado
ldi A, 0    ;azul apagado
rcall Dimmercurva ;Corrección y de salida Brillo

sbi PORTE, 0 ;LED de estado apagado

ldi temp1, 10 ;y 10 ciclos de apagado

Strobo_desde:

rcall esperar

dec temp1
brne Strobo_desde

rjmp Interruptor_Loop

; ------------------------------------------------------------------------------------------------
;      Atenuacion o Fader General sin cambiar el valor del brillo(fading) rutina 1
; ------------------------------------------------------------------------------------------------

RGB_Fader:

ldi Speed, 127 ;Velocidad del módo básico en espera

RGB_Loop:

ldi R, 255 ;rojo encendido
ldi V, 0    ;verde apagado
ldi A, 0    ;azul apagado
rcall Dimmercurva ;Corrección y de salida Brillo

cbi PORTE, 0 ;LED de estado encendido

rojo_amarillo: ;verde apagado -> pasa a amarillo

sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador

sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambie a seguir el programa 2

rcall esperar

sbi PORTE,0 ;LED de estado apagado

inc V
rcall Dimmercurva ;Corrección y de salida Brillo
cpi V, 255
brlo rojo_amarillo

cbi PORTE, 0 ;LED de estado encendido

amarillo_verde: ;amarillo apagado -> pasa a Verde

sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador

sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambie a seguir el programa 2

rcall esperar

sbi PORTE,0    ;LED de estado apagado

dec R
rcall Dimmercurva ;Corrección y de salida Brillo
brne amarillo_verde

cbi PORTE, 0 ;LED de estado encendido

verde_cyan: ;verde apagado -> pasa a Cyan

sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador

sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambio, a seguir el programa 2

rcall esperar

sbi PORTE,0 ;LED de estado apagado

inc A
rcall Dimmercurva ;Corrección y de salida Brillo
cpi A, 255
brlo verde_cyan

cbi PORTE, 0     ;LED de estado encendido

cyan_azul: ;cyan apagado -> pasa a Azul

sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador

sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambio a seguir el programa 2

rcall esperar

sbi PORTE,0 ;LED de estado apagado

dec V
rcall Dimmercurva ;Corrección y de salida Brillo
brne cyan_azul

cbi PORTE, 0     ;LED de estado en

azul_magenta: ;azul apagado -> pasar a Magenta

sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador

sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ; Cambio , a seguir el programa 2

rcall esperar

sbi PORTE,0 ;LED de estado apagado

inc R
rcall Dimmercurva ;Corrección y de salida Brillo
cpi R, 255
brlo azul_magenta

cbi PORTE, 0 ;LED de estado en

magenta_rojo: ;magenta apagado -> pasa a rojo

sbic PINC, 6 ;Interruptor 7 encendido continuar con Fader
rjmp RGB_fin ;interuptor apagado -> Detener RGB atenuador

sbis PINC, 7 ;Revise el interruptor 8 ("Fader 2")?
rcall Rainbow_Fader ;Cambio , a seguir el programa 2

rcall esperar

sbi PORTE,0 ;LED de estado apagado

dec A
rcall Dimmercurva ;Corrección y de salida Brillo
brne magenta_rojo

rjmp RGB_Loop ;Fader-ciclo repetitivo desde el principio

RGB_fin:

ret

; ------------------------------------------------------------------------------------------------
;           Rainbow-Fader 2 -- "funcion Rainbow" atenuador 2
; ------------------------------------------------------------------------------------------------

Rainbow_Fader:

mov temp0, R  ;definicion de Colores fijos para diferentes atenuaciones
mov temp1, V  ;definicion de Colores fijos para diferentes atenuaciones
mov temp2, A  ;definicion de Colores fijos para diferentes atenuaciones

ldi Speed, 254 ;Velocidad del módo básico en espera

Rainbow_Loop:

ldi R, 255 ;primero ,tiempo del colr rojo encendido
ldi V, 0        ;tiempo de verde CERO
ldi A, 0        ;tiempo de azul CERO
rcall Dimmercurva ;Corrección y de salida Brillo

cbi PORTE, 0 ;LED de estado encendido

rojo_verde: ;Ocultar Rojo, Mostrar Verde

sbic PINC, 7 ;Interruptor 8 está encendido, continúe con el fader 2
rjmp Rainbow_fin ;Switch -> volver a RGB-faders 1

rcall esperar

sbi PORTE,0 ;LED de estado apagado

dec R
inc V
rcall Dimmercurva ;Corrección y de salida Brillo
cpi V, 255
brlo rojo_verde

cbi PORTE, 0 ;LED de estado encendido

verde_azul: ;Ocultar Verde, mostrar Azul

sbic PINC, 7 ;Interruptor 8 está encendido, continúe con el fader 2
rjmp Rainbow_fin ;interuptor apagado -> volver a RGB-faders 1

rcall esperar

sbi PORTE,0 ;LED de estado apagado

dec V
inc A
rcall Dimmercurva ;Corrección y de salida Brillo
cpi A, 255
brlo verde_azul

cbi PORTE, 0 ;LED de estado encendido

azul_rojo:              ;Ocultar Azul, Mostrar Rojo

sbic PINC, 7 ;Interruptor 8 está encendido, continúe con el fader 2
rjmp Rainbow_fin ;iteruptor apagado -> volver a faders RGB 1

rcall esperar

sbi PORTE,0 ;LED de estado apagado

dec A
inc R
rcall Dimmercurva ;Corrección y de salida Brillo
cpi R, 255
brlo azul_rojo

cbi PORTE, 0   ;LED de estado encendido

rjmp Rainbow_Loop  ;LED de Estado encendido

Rainbow_fin:

mov R, temp0 ;Restaurar colores para diferentes atenuaciones
mov V, temp1    ;Restaurar colores para diferentes atenuaciones
mov A, temp2    ;Restaurar colores para diferentes atenuaciones

ret

; ------------------------------------------------------------------------------------------------
;         "Disco-Blink"-Routine -- Rutina "Disco Blink"
; ------------------------------------------------------------------------------------------------

Disco:

in temp1, PINC ;Comprobar el interruptor DIP-swch
andi temp1, 0b00000011 ;sólo está interesado en los dos primeros, PC0 y PC1
mov temp2, temp1 ;lamado ,para ver si el interruptor cambió su estado

cpi temp1, 0b00000011 ;Programa 1
brne Disco_P2
ldi     ZL, LOW(Disco_Mixcolores_1*2) ;Z-puntero, Cargar programa 1
        ldi     ZH, HIGH(Disco_Mixcolores_1*2)
rjmp Disco_Loop

Disco_P2:

cpi temp1, 0b00000001 ;Programa 2
brne Disco_P3
ldi     ZL, LOW(Disco_Mixcolores_2*2) ;Z-puntero, Cargar programa 2
        ldi     ZH, HIGH(Disco_Mixcolores_2*2)
rjmp Disco_Loop

Disco_P3:

cpi temp1, 0b00000010 ;Programa 3
brne Disco_P4
ldi     ZL, LOW(Disco_Mixcolores_3*2) ;Z-puntero, Cargar programa 3
        ldi     ZH, HIGH(Disco_Mixcolores_3*2)
rjmp Disco_Loop

Disco_P4:

ldi     ZL, LOW(Disco_Mixcolores_4*2) ;Cargar programa Z-puntero 4
        ldi     ZH, HIGH(Disco_Mixcolores_4*2)

Disco_Loop:

lpm Speed, Z+ ;Compruebe la velocidad / "bandera final"
tst Speed ;Se ha llegado al final de la muestra de la mesa?
breq Disco ;Sí, empezar de nuevo

in temp1, PINC ;Comprobar el interruptor DIP
andi temp1, 0b00000011 ;sólo está interesado en los dos primeros
cp temp2, temp1 ;Si cambia el interruptor DIP?
brne Disco ;Sí, reiniciar con un nuevo programa

cbi PORTE, 0 ;LED de estado encendido

lpm R, Z+ ;Elija los colores de la tabla
lpm V, Z+
lpm A, Z+
rcall Dimmercurva ;Corrección de brillo

ldi temp0, 64 ;tiempo de la funcion Discoteca Básica intermitente

Disco_esperar:

sbic PINC, 5 ;El interruptor 6 está encendido, continúe con funcion "disco"
ret ;interuptor apagado -> Detener Disco

rcall esperar

sbi PORTE,0 ;LED de estado apagado

dec temp0
brne Disco_esperar

rjmp Disco_Loop ;Color siguiente

; ------------------------------------------------------------------------------------------------
; Las tablas de colores para los colores del indicador Disco
; Byte primero = velocidad / extremo (255), los bytes 2-4 = R, G, B
; ------------------------------------------------------------------------------------------------

Disco_Mixcolores_1:

.db 128,255,0,0 ;Rojo
.db 128,0,255,0 ;Verde
.db 128,0,0,255 ;Azul
.db 128,255,0,0 ;Rojo
.db 128,0,255,0 ;Verde
.db 128,0,0,255 ;Azul
.db 64,255,0,0 ;Rojo
.db 64,0,255,0 ;Verde
.db 64,0,0,255 ;Azul
.db 64,255,0,0 ;Rojo
.db 64,0,255,0 ;Verde
.db 64,0,0,255 ;Azul
.db 128,0,255,255 ;Cyan
.db 128,255,0,255 ;Magenta
.db 128,255,255,0 ;Amarillo
.db 128,0,255,255 ;Cyan
.db 128,255,0,255 ;Magenta
.db 128,255,255,0 ;Amarillo
.db 64,0,255,255 ;Cyan
.db 64,255,0,255 ;Magenta
.db 64,255,255,0 ;Amarillo
.db 64,0,255,255 ;Cyan
.db 64,255,0,255 ;Magenta
.db 64,255,255,0 ;Amarillo
.db 0,0 ;Fin de la Tabla

Disco_Mixcolores_2:

.db 128,255,0,0 ;Rojo
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 64,255,0,0 ;Rojo
.db 64,0,0,255 ;Azul
.db 64,210,255,255 ;Blanco
.db 64,255,0,0 ;Rojo
.db 64,0,0,255 ;Azul
.db 64,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 64,255,0,0 ;Rojo
.db 64,0,0,255 ;Azul
.db 64,210,255,255 ;Blanco
.db 64,255,0,0 ;Rojo
.db 64,0,0,255 ;Azul
.db 64,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,210,255,255 ;Blanco
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 128,255,0,0 ;Rojo
.db 128,210,255,255 ;Blanco
.db 128,0,0,255 ;Azul
.db 128,210,255,255 ;Blanco
.db 0,0 ;Fin de la Tabla

Disco_Mixcolores_3:

.db 255,255,90,0 ;Naranja
.db 255,0,0,255 ;Azul
.db 255,255,128,0 ;Naranja
.db 255,0,255,255 ;Cyan
.db 255,255,128,0 ;Naranja
.db 255,0,255,0 ;Verde
.db 255,255,128,0 ;Naranja
.db 255,255,0,255 ;Magenta
.db 255,0,0,255 ;Azul
.db 255,255,0,255 ;Magenta
.db 255,0,255,255 ;Cyan
.db 255,255,0,255 ;Magenta
.db 255,255,255,0 ;Amarillo
.db 255,0,255,0 ;Verde
.db 0,0 ;Fin de la Tabla

Disco_Mixcolores_4:

.db 64,255,0,0 ;Rojo
.db 64,0,0,0 ;empieza
.db 64,0,255,255 ;Cyan
.db 64,0,0,0 ;empieza
.db 64,255,128,0 ;Naranja
.db 64,0,0,0 ;empieza
.db 64,0,255,0 ;Verde
.db 64,0,0,0 ;empieza
.db 64,255,0,255 ;Magenta
.db 64,0,0,0 ;empieza
.db 64,255,255,0 ;Amarillo
.db 64,0,0,0 ;empieza
.db 64,0,0,255 ;Azul
.db 64,0,0,0 ;empieza
.db 64,255,255,0 ;Amarillo
.db 64,0,0,0 ;empieza
.db 0,0 ;Fin de la Tabla

; ------------------------------------------------------------------------------------------------
;              ISR para PWM por software
; ------------------------------------------------------------------------------------------------

ISR_PWM:    ;Salida PWM
 
        push temp0
        in    temp0, SREG
        push temp0

        ldi     temp0, 0b00000111 ;Estado fundamental 1 = LED encendido, 0 = LED apagado (porque FET)

inc     PWM_Count         ;el contador de PWM de 0 a ++++
 
 
        cp      PWM_Count, R_Out  ;Si se alcanza el límite para el rojo?
        brlo    PWM_V   ;no, pase a verde
        andi    temp0, 0b00000110 ;sí, LED rojo apagado

PWM_V:
 
        cp      PWM_Count, V_Out  ;Si se alcanza el límite para el verde?
        brlo    PWM_A   ;no, pase a azul
        andi    temp0, 0b00000101 ;Sí, LED verde apagado

PWM_A:

        cp      PWM_Count, A_Out  ;Si se alcanza el límite para el azul?
        brlo    PWM_edicion   ;Si no es así, seguir emitiendo
        andi    temp0, 0b00000011 ;sí, LED azul desde
 
PWM_edicion:                    ;Emisión de nueva asignación de bits

        out     PORTB, temp0
 
pop temp0
        out SREG, temp0 ;Restaurar el registro de estado + temp0
pop temp0

reti

; ------------------------------------------------------------------------------------------------
;                 Conversión dimmer transferencia curva en el registro PWM
; ------------------------------------------------------------------------------------------------

Dimmercurva:

push temp0
in temp0, SREG ;Guardar registros
push temp0
mov temp_ZL, ZL
mov temp_ZH, ZH

ldi     ZL, LOW(DC_Data*2) ;Carga Z-puntero empezar valores dimmer bajo
        ldi     ZH, HIGH(DC_Data*2)  ;Carga Z-puntero empezar valores dimmer alto

add     ZL, R ;Añadir valor de rojo, de 16 bit+
    ldi     temp0,0                   
    adc     ZH,temp0

lpm R_Out, Z ;Obtener el valor de la tabla

ldi     ZL, LOW(DC_Data*2) ;Carga Z-puntero empezar valores dimmer bajo
        ldi     ZH, HIGH(DC_Data*2) ;Carga Z-puntero empezar valores dimmer alto

add     ZL, V ;Añadir valor verde, 16 bits
    ldi     temp0,0                   
    adc     ZH,temp0

lpm V_Out, Z ;Obtener el valor de la tabla

ldi     ZL, LOW(DC_Data*2) ;Carga Z-puntero empezar valores dimmer bajo
        ldi     ZH, HIGH(DC_Data*2) ;Carga Z-puntero empezar valores dimmer alto

add     ZL, A ;Añadir valor azul, 16 bit
    ldi     temp0,0                   
    adc     ZH,temp0

lpm A_Out, Z ;Obtener el valor de la tabla

pop temp0
out SREG, temp0 ;Restaurar registro
pop temp0
mov ZL, temp_ZL
mov ZH, temp_ZH

ret

; ------------------------------------------------------------------------------------------------
;       Los datos para la curva de dimmer -DIMERCURVA
; ------------------------------------------------------------------------------------------------

DC_Data:

.db     0,   0,   1,   1,   1,   1,   1,   2
.db     2,   2,   2,   3,   3,   3,   4,   4
.db     4,   5,   5,   5,   6,   6,   7,   7
.db     8,   8,   9,   9,  10,  10,  11,  11
.db    12,  12,  13,  13,  14,  14,  15,  15
.db    16,  16,  17,  17,  18,  18,  19,  19
.db    20,  20,  21,  21,  22,  22,  23,  23
.db    24,  24,  25,  25,  26,  27,  28,  29
.db    30,  30,  31,  32,  33,  34,  35,  36
.db    36,  37,  38,  39,  40,  41,  42,  43
.db    43,  44,  45,  46,  47,  48,  49,  50
.db    51,  52,  52,  53,  54,  55,  56,  57
.db    58,  59,  60,  61,  62,  63,  64,  65
.db    66,  67,  68,  69,  70,  71,  72,  73
.db    74,  75,  76,  77,  78,  79,  80,  81
.db    82,  83,  84,  85,  86,  88,  89,  90
.db    91,  92,  93,  94,  95,  96,  97,  98
.db    99, 100, 102, 103, 104, 105, 106, 107
.db   108, 109, 110, 112, 113, 114, 115, 116
.db   117, 119, 120, 121, 122, 123, 124, 126
.db   127, 128, 129, 130, 132, 133, 134, 135
.db   136, 138, 139, 140, 141, 142, 144, 145
.db   146, 147, 149, 150, 151, 152, 154, 155
.db   156, 158, 159, 160, 161, 162, 164, 165
.db   167, 168, 169, 171, 172, 173, 174, 176
.db   177, 178, 180, 181, 182, 184, 185, 187
.db   188, 189, 191, 192, 193, 195, 196, 197
.db   199, 200, 202, 203, 204, 206, 207, 208
.db   210, 211, 213, 214, 216, 217, 218, 220
.db   221, 223, 224, 226, 227, 228, 230, 231
.db   233, 234, 236, 237, 239, 240, 242, 243
.db   245, 246, 248, 249, 251, 252, 254, 255

; ------------------------------------------------------------------------------------------------
;          Bucle de temporisacion de espera (delay)
; ------------------------------------------------------------------------------------------------

esperar:    ;3 loops de espera (delay)

        push temp2 ;Registro de estado Temp + asegurar
        push temp1
        push temp0
in    temp0, SREG
        push temp0

mov temp0, Speed ;Velocidad de registro "Speed"

loop0:

ldi temp1, 255 ;255 repeticiones
sbis PINE, 2 ;Dip en 9? -> Duración maxima
ldi temp1, 64

loop1:

ldi temp2, 2 ;2 repeticiones
sbis PINE, 1 ;Dip en 10? -> Duracion Medio tiempo
ldi temp2, 1

loop2:                         

dec     temp2
brne    loop2

dec     temp1
brne    loop1

dec     temp0
brne    loop0

        pop temp0
out SREG, temp0 ;Estado del registro + Restaurar Temporizador
        pop temp0
pop temp1
pop temp2

ret

; ------------------------------------------------------------------------------------------------
;               ternminacion de programa y Cierre
; ------------------------------------------------------------------------------------------------

fin: rjmp fin

 
las funciones que tiene con las llaves son
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 02 de Agosto de 2015, 19:18:23
No pase todo a C solo, la parte del fading y rainbow_fading, tampoco pase la parte del PWM por software, ya que eso es hacerlo con una interrupcion cada X tiempo ( dado por el valor que se le carga al timer ) y ahi usar V_out,R_out y A_out, para comparar con el PWM por soft


un poco burdo el programa y seguro que se puede mejorar mas:
Código: C
  1. const short int arraydimmer[256]={0,0,1,1,......,251,252,254,255};  // Lo que aparece como DC_Data
  2. Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
  3.  
  4.  
  5.  
  6. void main() {
  7.  
  8.         if(!PINC6){ fading();}
  9.         if(!PINC5){ disco();}
  10.         /*
  11.         Aca mas codigo que realmente no influye en nada
  12.         */
  13. }
  14.  
  15.  
  16.  
  17. void fading() {
  18.  
  19.         Velocidad = 127;
  20.  
  21.         while(!PINC6)
  22.         {
  23.                 Rojo = 255;
  24.                 Verde = 0;
  25.                 Azul = 0;
  26.  
  27.                 DimmerCurva()
  28.                 PORTE0 = 0;
  29.  
  30.         //rojo_amarillo
  31.                 while(Verde!=255 && !PINC6)
  32.                 {
  33.                         if(PINC7) { rainbow_fader();}
  34.                         delay(velocidad);
  35.                         PORTE0 = 1;
  36.                         Verde++;
  37.                         DimmerCurva();
  38.                 }
  39.                 PORTE0 = 0;
  40.  
  41.         //amarillo_verde
  42.                 while(Rojo && !PINC6)
  43.                 {
  44.                         if(PINC7) { rainbow_fader();}
  45.                         delay(velocidad);  //esperar
  46.                         PORTE0 = 1;
  47.                         Rojo--;
  48.                         DimmerCurva();
  49.                 }
  50.                 PORTE0 = 0;
  51.  
  52.         //verde_cyan
  53.                 while(Azul!=255 && !PINC6)
  54.                 {
  55.                         if(PINC7) { rainbow_fader();}
  56.                         delay(velocidad);  //esperar
  57.                         PORTE0 = 1;
  58.                         Azul++;
  59.                         DimmerCurva();
  60.                 }
  61.                 PORTE0 = 0;
  62.  
  63.         //cyan_azul
  64.                 while(Verde && !PINC6)
  65.                 {
  66.                         if(PINC7) { rainbow_fader();}
  67.                         delay(velocidad);  //esperar
  68.                         PORTE0 = 1;
  69.                         Verde--;
  70.                         DimmerCurva();
  71.                 }
  72.                 PORTE0 = 0;
  73.  
  74.         //azul_magenta
  75.                 while(Rojo!=255 && !PINC6)
  76.                 {
  77.                         if(PINC7) { rainbow_fader();}
  78.                         delay(velocidad);  //esperar
  79.                         PORTE0 = 1;
  80.                         Rojo++;
  81.                         DimmerCurva();
  82.                 }
  83.                 PORTE0 = 0;
  84.        
  85.         //magenta_rojo
  86.                 while(Azul && !PINC6)
  87.                 {
  88.                         if(PINC7) { rainbow_fader();}
  89.                         delay(velocidad);  //esperar
  90.                         PORTE0 = 1;
  91.                         Azul--;
  92.                         DimmerCurva();
  93.                 }
  94.                 PORTE0 = 0;
  95.         }
  96. }
  97.  
  98. void delay(int velocidad) {
  99.  
  100.         delay_ciclos();  // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
  101.                          // Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
  102.  
  103. //temp2 = 1  si PINE1 = 0 sino temp2=2
  104. //temp1 = 64 si PINE2 = 0 sino temp1=255
  105.  
  106. /*
  107.  
  108. Ciclos a esperar
  109.  
  110. temp2=1 temp1=255
  111. 11445 * (velocidad-1) +28
  112.  
  113. temp2=1 temp1=64
  114. 2895 * (velocidad -1) +28
  115.  
  116. temp2=2 temp1=255
  117. 18303 * (velocidad-1) +28
  118.  
  119. temp2=2 temp1=64
  120. 4551 * (velocidad-1) +28
  121. */
  122. }
  123.  
  124.  
  125. void rainbow_fader(){
  126.  
  127.         int Temp_R,Temp_A,Temp_V;
  128.         Velocidad = 254;
  129.         Temp_R = Rojo;
  130.         Temp_A = Azul;
  131.         Temp_V = Verde;
  132.  
  133.         while(PINC7)
  134.         {
  135.                 Rojo = 255;
  136.                 Verde = 0;
  137.                 Azul = 0;
  138.                 DimmerCurva();
  139.                 PORTE0 = 0;
  140.  
  141.         //rojo_verde
  142.                 while(Verde!=255 && PINC7)
  143.                 {
  144.                         delay(velocidad);
  145.                         PORTE=1;
  146.                         Rojo--;
  147.                         Verde++;
  148.                         DimmerCurva();
  149.                 }
  150.                 PORTE0=0;
  151.  
  152.         //verde_azul
  153.                 while(Azul!=255 && PINC7)
  154.                 {
  155.                         delay(velocidad);
  156.                         PORTE=1;
  157.                         Verde--;
  158.                         Azul++;
  159.                         DimmerCurva();
  160.                 }
  161.                 PORTE0=0;
  162.  
  163.         //azul_rojo
  164.                 while(Rojo!=255 && PINC7)
  165.                 {
  166.                         delay(velocidad);
  167.                         PORTE=1;
  168.                         Azul--;
  169.                         Rojo++;
  170.                         DimmerCurva();
  171.                 }
  172.                 PORTE0=0;
  173.         }
  174.  
  175.         Rojo = Temp_R;
  176.         Azul = Temp_A;
  177.         Verde = Temp_V;
  178.  
  179. }
  180.  
  181. void DimmerCurva(){
  182.  
  183.         R_out=arraydimmer[Rojo];
  184.         V_out=arraydimmer[Verde];
  185.         A_out=arraydimmer[Azul];
  186.  
  187. }

Si observas ahi donde puse el delay, eso depende de las llaves, el cual van a cambiar el valor de temp1 y temp2, si no me equivoque eso son los ciclos que requieren segun cada caso.

Código: ASM
  1. esperar:                ;3 loops de espera (delay)
  2.  
  3.                 push    temp2           ; 3 ciclos rcall
  4.                 push    temp1
  5.                 push    temp0
  6.                 in      temp0, SREG
  7.                 push    temp0
  8.  
  9.                 mov     temp0, Speed    ; 10 ciclos
  10.  
  11. loop0:
  12.  
  13.                 ldi     temp1, 255      ; 3 ciclos
  14.                 sbis    PINE, 2         ;
  15.                 ldi     temp1, 64
  16.  
  17. loop1:
  18.  
  19.                 ldi     temp2, 2        ; 3 ciclos
  20.                 sbis    PINE, 1         ;
  21.                 ldi     temp2, 1
  22.  
  23. loop2:                          
  24.  
  25.                 dec     temp2           ; (temp2-1)*3+2
  26.                 brne    loop2
  27.  
  28.                 dec     temp1           ; (temp1-1)*3+2 ( acumulado esto multiplicado por lo de temp2)
  29.                 brne    loop1
  30.  
  31.                 dec     temp0           ; (temp0-1)*3+2
  32.                 brne    loop0
  33.  
  34.                 pop     temp0
  35.                 out     SREG, temp0     ; 9 ciclos
  36.                 pop     temp0
  37.                 pop     temp1
  38.                 pop     temp2
  39.  
  40.                 ret                     ; 4 ciclos

Hacer una formula para eso se llenaria de parentesis, asi que no la pongo.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 04 de Agosto de 2015, 01:04:04
 hola y gracias
No pase todo a C solo, la parte del fading y rainbow_fading, tampoco pase la parte del PWM por software, ya que eso es hacerlo con una interrupcion cada X tiempo ( dado por el valor que se le carga al timer ) y ahi usar V_out,R_out y A_out, para comparar con el PWM por soft
un poco burdo el programa y seguro que se puede mejorar mas:
Código: C
  1. const short int arraydimmer[256]={0,0,1,1,......,251,252,254,255};  // Lo que aparece como DC_Data
  2. Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
  3.  
  4.  
  5.  
  6. void main() {
  7.  
  8.         if(!PINC6){ fading();}
  9.         if(!PINC5){ disco();}
  10.         /*
  11.         Aca mas codigo que realmente no influye en nada
  12.         */
  13. }
  14.  
  15.  
  16.  
  17. void fading() {
  18.  
  19.         Velocidad = 127;
  20.  
  21.         while(!PINC6)
  22.         {
  23.                 Rojo = 255;
  24.                 Verde = 0;
  25.                 Azul = 0;
  26.  
  27.                 DimmerCurva()
  28.                 PORTE0 = 0;
  29.  
  30.         //rojo_amarillo
  31.                 while(Verde!=255 && !PINC6)
  32.                 {
  33.                         if(PINC7) { rainbow_fader();}
  34.                         delay(velocidad);
  35.                         PORTE0 = 1;
  36.                         Verde++;
  37.                         DimmerCurva();
  38.                 }
  39.                 PORTE0 = 0;
  40.  
  41.         //amarillo_verde
  42.                 while(Rojo && !PINC6)
  43.                 {
  44.                         if(PINC7) { rainbow_fader();}
  45.                         delay(velocidad);  //esperar
  46.                         PORTE0 = 1;
  47.                         Rojo--;
  48.                         DimmerCurva();
  49.                 }
  50.                 PORTE0 = 0;
  51.  
  52.         //verde_cyan
  53.                 while(Azul!=255 && !PINC6)
  54.                 {
  55.                         if(PINC7) { rainbow_fader();}
  56.                         delay(velocidad);  //esperar
  57.                         PORTE0 = 1;
  58.                         Azul++;
  59.                         DimmerCurva();
  60.                 }
  61.                 PORTE0 = 0;
  62.  
  63.         //cyan_azul
  64.                 while(Verde && !PINC6)
  65.                 {
  66.                         if(PINC7) { rainbow_fader();}
  67.                         delay(velocidad);  //esperar
  68.                         PORTE0 = 1;
  69.                         Verde--;
  70.                         DimmerCurva();
  71.                 }
  72.                 PORTE0 = 0;
  73.  
  74.         //azul_magenta
  75.                 while(Rojo!=255 && !PINC6)
  76.                 {
  77.                         if(PINC7) { rainbow_fader();}
  78.                         delay(velocidad);  //esperar
  79.                         PORTE0 = 1;
  80.                         Rojo++;
  81.                         DimmerCurva();
  82.                 }
  83.                 PORTE0 = 0;
  84.        
  85.         //magenta_rojo
  86.                 while(Azul && !PINC6)
  87.                 {
  88.                         if(PINC7) { rainbow_fader();}
  89.                         delay(velocidad);  //esperar
  90.                         PORTE0 = 1;
  91.                         Azul--;
  92.                         DimmerCurva();
  93.                 }
  94.                 PORTE0 = 0;
  95.         }
  96. }
  97.  
  98. void delay(int velocidad) {
  99.  
  100.         delay_ciclos();  // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
  101.                          // Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
  102.  
  103. //temp2 = 1  si PINE1 = 0 sino temp2=2
  104. //temp1 = 64 si PINE2 = 0 sino temp1=255
  105.  
  106. /*
  107.  
  108. Ciclos a esperar
  109.  
  110. temp2=1 temp1=255
  111. 11445 * (velocidad-1) +28
  112.  
  113. temp2=1 temp1=64
  114. 2895 * (velocidad -1) +28
  115.  
  116. temp2=2 temp1=255
  117. 18303 * (velocidad-1) +28
  118.  
  119. temp2=2 temp1=64
  120. 4551 * (velocidad-1) +28
  121. */
  122. }
  123.  
  124.  
  125. void rainbow_fader(){
  126.  
  127.         int Temp_R,Temp_A,Temp_V;
  128.         Velocidad = 254;
  129.         Temp_R = Rojo;
  130.         Temp_A = Azul;
  131.         Temp_V = Verde;
  132.  
  133.         while(PINC7)
  134.         {
  135.                 Rojo = 255;
  136.                 Verde = 0;
  137.                 Azul = 0;
  138.                 DimmerCurva();
  139.                 PORTE0 = 0;
  140.  
  141.         //rojo_verde
  142.                 while(Verde!=255 && PINC7)
  143.                 {
  144.                         delay(velocidad);
  145.                         PORTE=1;
  146.                         Rojo--;
  147.                         Verde++;
  148.                         DimmerCurva();
  149.                 }
  150.                 PORTE0=0;
  151.  
  152.         //verde_azul
  153.                 while(Azul!=255 && PINC7)
  154.                 {
  155.                         delay(velocidad);
  156.                         PORTE=1;
  157.                         Verde--;
  158.                         Azul++;
  159.                         DimmerCurva();
  160.                 }
  161.                 PORTE0=0;
  162.  
  163.         //azul_rojo
  164.                 while(Rojo!=255 && PINC7)
  165.                 {
  166.                         delay(velocidad);
  167.                         PORTE=1;
  168.                         Azul--;
  169.                         Rojo++;
  170.                         DimmerCurva();
  171.                 }
  172.                 PORTE0=0;
  173.         }
  174.  
  175.         Rojo = Temp_R;
  176.         Azul = Temp_A;
  177.         Verde = Temp_V;
  178.  
  179. }
  180.  
  181. void DimmerCurva(){
  182.  
  183.         R_out=arraydimmer[Rojo];
  184.         V_out=arraydimmer[Verde];
  185.         A_out=arraydimmer[Azul];
  186.  
  187. }

Si observas ahi donde puse el delay, eso depende de las llaves, el cual van a cambiar el valor de temp1 y temp2, si no me equivoque eso son los ciclos que requieren segun cada caso.
Hacer una formula para eso se llenaria de parentesis, asi que no la pongo.
Bueno amigo tome tu codigo y le agrege lo que me parece que falta ., y aclaro que la parte fisica esta armada
solo armar esta libreria ., para que compile y probar ., yo uso el wachdog por que si te fijas el esquematico no esta conectado el "reset"
aca te muestro para que veas y revices si esta bien 
Código: [Seleccionar]
#define F_CPU 8000000
#include<util\delay.h>

#include<stdio.h>
#include<stdlib.h>

#include <avr/wdt.h>
 //*********************************//
const short int arraydimmer[256]={0,0,0.0.0.0.0.0.0.0.0.1.1.1.1.1.1.1.1.1,1,1,1,1,2.2,2,2,3,3,3,4,4.4,5,5,5,6,6,7,7.8,8,9,9,10,10,11,11.12,12,13,13,14,14,15,15.16,16,17,17,18,18,19,19.20,20,21,21,22,22,23,23.24,24,25,25,26,27,28,29.30,30,31,32,33,34,35,36.36,37,38,39,40,41,42,43.43,44,45,46,47,48,49,50.51,52,52,53,54,55,56,57.58,59,60,61,62,63,64,65.66,67,68,69,70,71,72,73.74,75,76,77,78,79,80,81.82,83,84,85,86,88,89,90.91,92,93,94,95,96,97,98.99,100,102,103,104,105,106,107.108,109,110,112,113,114,115,116,117,119,120,121,122,123,124,126.127,128,129,130,132,133,134,135.136,138,139,140,141,142,144,145.146,147,149,150,151,152,154,155.156,158,159,160,161,162,164,165.167,168,169,171,172,173,174,176.177,178,180,181,182,184,185,187.188,189,191,192,193,195,196,197.199,200,202,203,204,206,207,208.210,211,213,214,216,217,218,220.221,223,224,226,227,228,230,231.233,234,236,237,239,240,242,243.245,246,248,249,251,252,254,255 }; // Lo que aparece como DC_Data
                                   
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
//************* Inicialización pines / port *****************//
void init_pinouts(){                   
    //#ifdef USE_DIP
 
    DDRC  = 0; // establecer DIPs
    PORTC  = 0xFF;
    DDRE  &= ~((1<<PE2)|(1<<PE1));
    PORTE |=   (1<<PE2)|(1<<PE1);
 
  //  #endif
   
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB= 0;
DDRE  |= (1<<PE0); //LED2 azul indicador
    PORTE |= (1<<PE0);
    }     
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción

}     
     
    void main()
     {
 //***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
   
sei();     // habilitar las interupciones globales  ???
int PWM_timer;  // inicializar el timer PWM

      for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado
{
    if(!PINC6){ fading();}
    if(!PINC5){ disco();}
    /*
    Aca mas codigo que realmente no influye en nada
    */
    }
     
     
     
    void fading() {
     
    Velocidad = 127;
     
    while(!PINC6)
    {
    Rojo = 255;
    Verde = 0;
    Azul = 0;
     
    DimmerCurva()
    PORTE0 = 0;
     
    //rojo_amarillo
    while(Verde!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);
    PORTE0 = 1;
    Verde++;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //amarillo_verde
    while(Rojo && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Rojo--;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //verde_cyan
    while(Azul!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Azul++;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //cyan_azul
    while(Verde && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Verde--;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //azul_magenta
    while(Rojo!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Rojo++;
    DimmerCurva();
    }
    PORTE0 = 0;
   
    //magenta_rojo
    while(Azul && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Azul--;
    DimmerCurva();
    }
    PORTE0 = 0;
    }
    }
     
    void delay(int velocidad) {
     
    delay_ciclos();  // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
    // Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
     
    //temp2 = 1  si PINE1 = 0 sino temp2=2
    //temp1 = 64 si PINE2 = 0 sino temp1=255
     
    /*
     
    Ciclos a esperar
     
    temp2=1 temp1=255
    11445 * (velocidad-1) +28
     
    temp2=1 temp1=64
    2895 * (velocidad -1) +28
     
    temp2=2 temp1=255
    18303 * (velocidad-1) +28
     
    temp2=2 temp1=64
    4551 * (velocidad-1) +28
    */
    }
     
     
    void rainbow_fader(){
     
    int Temp_R,Temp_A,Temp_V;
    Velocidad = 254;
    Temp_R = Rojo;
    Temp_A = Azul;
    Temp_V = Verde;
     
    while(PINC7)
    {
    Rojo = 255;
    Verde = 0;
    Azul = 0;
    DimmerCurva();
    PORTE0 = 0;
     
    //rojo_verde
    while(Verde!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Rojo--;
    Verde++;
    DimmerCurva();
    }
    PORTE0=0;
     
    //verde_azul
    while(Azul!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Verde--;
    Azul++;
    DimmerCurva();
    }
    PORTE0=0;
     
    //azul_rojo
    while(Rojo!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Azul--;
    Rojo++;
    DimmerCurva();
    }
    PORTE0=0;
    }
     
    Rojo = Temp_R;
    Azul = Temp_A;
    Verde = Temp_V;
     
    }
     
    void DimmerCurva(){
     
    R_out=arraydimmer[Rojo];
    V_out=arraydimmer[Verde];
    A_out=arraydimmer[Azul];
     
    }
te vuelvo a agradecer y espero tus comentarios
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 04 de Agosto de 2015, 04:54:05
Ojo que faltan cosas...

Cosas que imagino que van a fallar:

1-

PINC6
PINC7
PORTE0

PINC6 es en ASM, pero en C tal ves debas hacer un (PINC & (1<<6)) , que es lo mismo que PINC & 0x20
De la misma forma que si quiero cambiar el bit 0 del PORTE:

Para ponerlo a 0
PORTE &= 0xFE;
PORTE &= ~(1<<0);

Para ponerlo a 1
PORTE |= 0x01;
PORTE |= (1<<0);

Para hacer un toggle
PORTE ^= 0x01;
PORTE ^= (1<<0);

No se si C tiene acceso directo a esos pines como para llamarlos PINC6 y PORTE0, recorda que yo no se del entorno de programacion de los ATmega.

2-
Este estoy seguro que va a fallar
En mi codigo "faltaron" unas cosas

if(!PINC5){ disco();}

Esa parte deberia quitarse, solo lo hice por que asi era el ASM, pero no hice la funcion disco() ya que me dijiste de las otras 2 funciones nomas.

3-
La funcion delay() esta incompleta, yo ahi di las formulas para sacar cuantos ciclos de espera son segun las opciones y la velocidad. No se si hay uan libreria que permita hacer un delay de ciclos en ves de tiempo. Por eso mismo no la escribi.
Sino vas a tener que pasar esos ciclos a tiempos y seguir usando la formula.

4-
El array posee puntos ( . ) en ves  de comas ( , ) en algunos valores

5-
Falta el PWM por software el cual pense que ya estaba implementado, pero que eso se puede buscar en cualquier otro lado.
Jusatmente en la interrupcion del timer se cambia los valores del los puertos segun V_out,R_out y A_out.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 05 de Agosto de 2015, 06:53:39
hola amigo ¡¡¡¡¡ muchisimas gracias por enceñarme!!!!!
Ojo que faltan cosas...

Cosas que imagino que van a fallar:

1-

PINC6
PINC7
PORTE0

PINC6 es en ASM, pero en C tal ves debas hacer un (PINC & (1<<6)) , que es lo mismo que PINC & 0x20
De la misma forma que si quiero cambiar el bit 0 del PORTE:

Para ponerlo a 0
PORTE &= 0xFE;
PORTE &= ~(1<<0);

Para ponerlo a 1
PORTE |= 0x01;
PORTE |= (1<<0);

Para hacer un toggle
PORTE ^= 0x01;
PORTE ^= (1<<0);

No se si C tiene acceso directo a esos pines como para llamarlos PINC6 y PORTE0, recorda que yo no se del entorno de programacion de los ATmega.

2-
Este estoy seguro que va a fallar
En mi codigo "faltaron" unas cosas

if(!PINC5){ disco();}

Esa parte deberia quitarse, solo lo hice por que asi era el ASM, pero no hice la funcion disco() ya que me dijiste de las otras 2 funciones nomas.

3-
La funcion delay() esta incompleta, yo ahi di las formulas para sacar cuantos ciclos de espera son segun las opciones y la velocidad. No se si hay uan libreria que permita hacer un delay de ciclos en ves de tiempo. Por eso mismo no la escribi.
Sino vas a tener que pasar esos ciclos a tiempos y seguir usando la formula.

4-
El array posee puntos ( . ) en ves  de comas ( , ) en algunos valores

5-
Falta el PWM por software el cual pense que ya estaba implementado, pero que eso se puede buscar en cualquier otro lado.
Jusatmente en la interrupcion del timer se cambia los valores del los puertos segun V_out,R_out y A_out.
bueno amigo ., yo arme esto pero todavia no compile., porque se que hay muchos errores
bueno muchos de ellos son los que tu amablemente me señalas
pero tranquilo ., el C para atmega no difiere mucho del C para pic ., basicamente son los cambio de nombres par las sentencias
Código: [Seleccionar]
//************* Inicialización pines / port *****************//
void init_pinouts(){                   
    //#ifdef USE_DIP
 
    DDRC  = 0; // establecer DIPs
    PORTC  = 0xFF;
    DDRE  &= ~((1<<PE2)|(1<<PE1));
    PORTE |=   (1<<PE2)|(1<<PE1);
 
  //  #endif
a tener en cuenta que la sentencia USE_DIP la comente y asi la desbilite bueno en mis compilaciones se puede llamar ala lectura de los MINI-DIPS con esta sentencia get_dips();
de esa manera podemos leer todas las llaves de los 10 puertos (los 8 de C y los  de E ., tal cual esta en la compilacion de ASM
eso tendrias que fiajarte si es correto a tu modo de ver

Código: [Seleccionar]
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
y tambien un PWM por sofware
Código: [Seleccionar]
int PWM_timer;  // inicializar el timer PWM for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado
pero obiamente no lo implemente en la compilacion ., ademas ya tiene  los pin de salidas declarados del puerto B y el LED  del puero E

Código: [Seleccionar]
       ldi     temp0, 0b00000001;     Conjunto CS00: 1 divisor
out     TCCR0, temp0
      
o sea tendria que ser  CS00 y yo lo cabie por CS02., porque habia un pequeño "parpadeo" en los led., en las compilaciones que yo usaba antes en C ., y con esta configuracion CS02.,  casi no se nota
yo no se como cambiar esa sentencia o sea  "0b00000001" en binario para aplicarla por la que yo cambie CS02 ., y probarla en ASM
y vuelvo a repetir.,  muchas gracias por tu tiempo y tus ganas de enseñarme ., espero tus comentarios 


Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 05 de Agosto de 2015, 07:49:50
Como te habia adelantado jamas programe en C/ASM ni un ATmega, ni un arduino, por lo cual estoy un poco perdido.

No sabia que hacer:

variable = (PINC & (1<<6));

era equivalente a

variable = PINC6;

Y cuando habia que cambiar o leer unicamente un pin, pense que podria haber problemas, por eso lo nombre.

-----------------------------------

Con respecto a los delays, ahi vi que usas esa libreria y que posee 2 funciones

_delay_ms();
_delay_us();

Tomando la tabla que deje donde se cuentan los ciclos, y tomando en consideracion que 1 ciclo es justamente 1 / Fosc, entonces el ciclo de reloj es de 0.125us (Para 8 Mhz)
teniendo en cuenta eso

Citar
PINE1 => temp2  , si 0 temp2=1 , si 1 temp2=2
PINE2 => temp1  , si 0 temp1=64 si 1 temp2=255

    temp2=1 temp1=255
    11445 * (velocidad-1) +28
    
    temp2=1 temp1=64
    2895 * (velocidad -1) +28
    
    temp2=2 temp1=255
    18303 * (velocidad-1) +28
    
    temp2=2 temp1=64
    4551 * (velocidad-1) +28

Podemos hacer la funcion de espera (o delay como habia puesto):

Código: C
  1. void espera(short int velocidad){
  2.         int tiempo;
  3.         switch((PINE&0x06))
  4.         {
  5.         case 0x00:
  6.                 tiempo=((362 * (velocidad-1)+3)/1000);
  7.                 _delay_ms(tiempo);
  8.                 break;
  9.         case 0x02:
  10.                 tiempo=((568 * (velocidad-1)+3)/1000);
  11.                 _delay_ms(tiempo);
  12.                 break;
  13.         case 0x04:
  14.                 tiempo=((1430 * (velocidad-1)+3)/1000);
  15.                 _delay_ms(tiempo);
  16.                 break;
  17.         case 0x06:
  18.                 tiempo=((2287 * (velocidad-1)+3)/1000);
  19.                 _delay_ms(tiempo);
  20.                 break;
  21.         default:
  22.                 break;
  23.         }
  24. }

Citar
6° : en la compilacion actual yo implemente el timerO asi TCCR0|= (1<<CS02) ; ahora en la compilacion ASM esta asi

La traduccion directa del ASM al C de esas intrucciones que me pasaste es:

TCCR0 = 0x01;

Pero supongamos que no queres afectar a los otros bits, entonces mejor un:
TCCR0 &= 0x7;  // Para limpiar si habia otro valor
TCCR0 |=0x1;   // Escribimos el bit CS0

o directamente:

TCCR0 = ((TCCR0 & 0x7) | 0x01);

Lo que me parece raro. Por que como esta significa que el Timer no posee preescaler y por eso mismo se va a producir la interrupcion mas rapido, es decir los ultimos 3 bits del TCCR0 corresponden a CSn2:0, estos indican que preescaler va encima. Y esto va afectar al PWM por software, Mientras mas rapido, quiere decir que es mas rapida la frecuencia del PWM, por lo que no deberias notar nunca un parpadeo, Haber si me explico..
Tu PWM por soft usa una interrupcion, en esa interrupcion incrementa el valor del PWM en 1 hasta llegar a 255 y volver a comenzar de 0. entonces cuando pasa 255, es decir 255 interrupciones la señal subio y bajo. es decir hizo un ciclo completo.
Si vos agrandas el preescaler (dividis mas la señal del clock) quiere decir que va a contar mucho mas lento, por lo tanto mas tiempo para la interrupcion y en consecuencia va a estar mucho mas tiempo encendido y tambien apagado la salida.

Segun el datasheet con un valor de 001b de esos bits la frecuencia del reloj entra directamente al timer. Mientras que si pones un 100b como vos queres la frecuencia del reloj se encuentra disminuida por 256.

De todas formas si queres poner el preescaler asi:
TCCR0|= (1<<CS02)

es equivalente a
TCCR0 &= 0x7; // Limpio los bits por si otra instruccion antes los cambio, esto detiene el timer
TCCR0 |= 0x4;  // Activo el bit CS02 el cual le da reloj al timer con un preescaler de 1/256

Citar
y tambien un PWM por sofware
Citar
int PWM_timer;  // inicializar el timer PWM   for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado

Eso no es un PWM por software y esta mal realizado. No deberias tener nunca un for ahi. Ni si quiera en la interrupcion, solamente en la interrupcion deberia quedarte algo asi:

Código: C
  1. // *************** Soft PWM ****************
  2. ISR (TIMER0_OVF_vect)
  3. {
  4.         salida=0x7;
  5.         if (R_out>=PWM_timer) { salida &= 0x06; }   // Esta es la traduccion directa del ASM , por eso lo puse asi.
  6.         if (V_out>=PWM_timer) { salida &= 0x05; }
  7.         if (A_out>=PWM_timer) { salida &= 0x03; }
  8.         PORTB = salida;
  9. }

Y tu main como dije no deberia tener el for, sino que simplente el while y estar continuamente llamando a las funciones que debe.

El por que no deberias tener un for actuando de PWM en el main, es por que tenes delays involucrados. esto hace que cada cuenta del PWM_timer (PWMCnt en el ASM) sea distinto, y la idea es que cada seccion de las 256 secciones ( al contar de 0 a 255 ) tengan el mismo tiempo, asi tener una buena definicion de duty cicle
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 09 de Agosto de 2015, 17:32:33
¡¡¡¡¡¡ MUCHISIMAS GRACIAS !!!!!!
Como te habia adelantado jamas programe en C/ASM ni un ATmega, ni un arduino, por lo cual estoy un poco perdido.

No sabia que hacer:

variable = (PINC & (1<<6));

era equivalente a

variable = PINC6;

Y cuando habia que cambiar o leer unicamente un pin, pense que podria haber problemas, por eso lo nombre.

-----------------------------------

Con respecto a los delays, ahi vi que usas esa libreria y que posee 2 funciones

_delay_ms();
_delay_us();

Tomando la tabla que deje donde se cuentan los ciclos, y tomando en consideracion que 1 ciclo es justamente 1 / Fosc, entonces el ciclo de reloj es de 0.125us (Para 8 Mhz)
teniendo en cuenta eso

Citar
PINE1 => temp2  , si 0 temp2=1 , si 1 temp2=2
PINE2 => temp1  , si 0 temp1=64 si 1 temp2=255

    temp2=1 temp1=255
    11445 * (velocidad-1) +28
     
    temp2=1 temp1=64
    2895 * (velocidad -1) +28
     
    temp2=2 temp1=255
    18303 * (velocidad-1) +28
     
    temp2=2 temp1=64
    4551 * (velocidad-1) +28

Podemos hacer la funcion de espera (o delay como habia puesto):

Código: C
  1. void espera(short int velocidad){
  2.         int tiempo;
  3.         switch((PINE&0x06))
  4.         {
  5.         case 0x00:
  6.                 tiempo=((362 * (velocidad-1)+3)/1000);
  7.                 _delay_ms(tiempo);
  8.                 break;
  9.         case 0x02:
  10.                 tiempo=((568 * (velocidad-1)+3)/1000);
  11.                 _delay_ms(tiempo);
  12.                 break;
  13.         case 0x04:
  14.                 tiempo=((1430 * (velocidad-1)+3)/1000);
  15.                 _delay_ms(tiempo);
  16.                 break;
  17.         case 0x06:
  18.                 tiempo=((2287 * (velocidad-1)+3)/1000);
  19.                 _delay_ms(tiempo);
  20.                 break;
  21.         default:
  22.                 break;
  23.         }
  24. }

Citar
6° : en la compilacion actual yo implemente el timerO asi TCCR0|= (1<<CS02) ; ahora en la compilacion ASM esta asi

La traduccion directa del ASM al C de esas intrucciones que me pasaste es:

TCCR0 = 0x01;

Pero supongamos que no queres afectar a los otros bits, entonces mejor un:
TCCR0 &= 0x7;  // Para limpiar si habia otro valor
TCCR0 |=0x1;   // Escribimos el bit CS0

o directamente:

TCCR0 = ((TCCR0 & 0x7) | 0x01);

Lo que me parece raro. Por que como esta significa que el Timer no posee preescaler y por eso mismo se va a producir la interrupcion mas rapido, es decir los ultimos 3 bits del TCCR0 corresponden a CSn2:0, estos indican que preescaler va encima. Y esto va afectar al PWM por software, Mientras mas rapido, quiere decir que es mas rapida la frecuencia del PWM, por lo que no deberias notar nunca un parpadeo, Haber si me explico..
Tu PWM por soft usa una interrupcion, en esa interrupcion incrementa el valor del PWM en 1 hasta llegar a 255 y volver a comenzar de 0. entonces cuando pasa 255, es decir 255 interrupciones la señal subio y bajo. es decir hizo un ciclo completo.
Si vos agrandas el preescaler (dividis mas la señal del clock) quiere decir que va a contar mucho mas lento, por lo tanto mas tiempo para la interrupcion y en consecuencia va a estar mucho mas tiempo encendido y tambien apagado la salida.

Segun el datasheet con un valor de 001b de esos bits la frecuencia del reloj entra directamente al timer. Mientras que si pones un 100b como vos queres la frecuencia del reloj se encuentra disminuida por 256.

De todas formas si queres poner el preescaler asi:
TCCR0|= (1<<CS02)

es equivalente a
TCCR0 &= 0x7; // Limpio los bits por si otra instruccion antes los cambio, esto detiene el timer
TCCR0 |= 0x4;  // Activo el bit CS02 el cual le da reloj al timer con un preescaler de 1/256

Citar
y tambien un PWM por sofware
Citar
int PWM_timer;  // inicializar el timer PWM   for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado

Eso no es un PWM por software y esta mal realizado. No deberias tener nunca un for ahi. Ni si quiera en la interrupcion, solamente en la interrupcion deberia quedarte algo asi:

Código: C
  1. // *************** Soft PWM ****************
  2. ISR (TIMER0_OVF_vect)
  3. {
  4.         salida=0x7;
  5.         if (R_out>=PWM_timer) { salida &= 0x06; }   // Esta es la traduccion directa del ASM , por eso lo puse asi.
  6.         if (V_out>=PWM_timer) { salida &= 0x05; }
  7.         if (A_out>=PWM_timer) { salida &= 0x03; }
  8.         PORTB = salida;
  9. }

Y tu main como dije no deberia tener el for, sino que simplente el while y estar continuamente llamando a las funciones que debe.

El por que no deberias tener un for actuando de PWM en el main, es por que tenes delays involucrados. esto hace que cada cuenta del PWM_timer (PWMCnt en el ASM) sea distinto, y la idea es que cada seccion de las 256 secciones ( al contar de 0 a 255 ) tengan el mismo tiempo, asi tener una buena definicion de duty cicle
bueno amigaso ., por empezar., aunque parezca que se mucho ., no se engañe ., NO es asi
Y viendo eso ., esperando que no lo tome a mal ., " lo declaro mi  maestro " ., soy una persona que por cuestiones de la vida ., no pudo ir ala escuela.,
el aprender aleer y escribir ., aun mas el manejo de la informatica ., lo aprendi solo y por mis propios medios
yo empece con los micros a mediados del 2013 ., y al contrario de la mayoria ., directamente con atmega
intente aprender ASM .,(y puse mucho empeño ) ., tengo tres tutoriales traducidos al español por mi ., pero no hay caso no entiendo muchisimas cosas
En cambio con C (aunque todavia hay cosas que me confunden ) me llevo mejor ., es mas entendible ( para mi )
esto lo cuento par que sepa que tipo de persona "esta" ., enfrente
bueno como a mi me encanta el DMX ., "juego" con los led y motorcitos PAP 
Vi y acepte que en estos casos para tener multifunciones ., se debe implementar el PWM por sotfware., y no por hardware
pues el PWM ., se puede usar en mas de una funcion ( ¿¿¿ o estoy equivocado ??? ) ., igual menra que la IRS
por el simple hecho ., que por lo general se controlan todas las salidas de un PORT
como en este caso que tengo 3 PORT ( portb ) .,  para los led y me quedan 5 libres ( que podria colocar un motor tranquilamente y que funcione con otro timer )
por eso uso el PWM asi
en la compilacion DMX., que indique mas arriba ., funciona con las dos configuraciones de timer ( TCCR0|= (1<<CS00 )  y  TCCR0|= (1<<CS02) )
L e pido mil perdones , por no entenderlo ., pero se me hace dificil comprender cuando usa definiciones asi
Código: [Seleccionar]
int tiempo;
switch((PINE&0x06))
{
case 0x00:
tiempo=((362 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x02:
tiempo=((568 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x04:
tiempo=((1430 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
case 0x06:
tiempo=((2287 * (velocidad-1)+3)/1000);
_delay_ms(tiempo);
break;
concretamente cuando usa por ejemplo: "" case 0x04:" ., la definicion CASE si la entiendo pero 0x04 ., no
bueno aca le publico lo que mas o menos arme ( no esta compilado todavia ) solo el bosquejo
tambien prepare las llaves MINI-DIPS para poder poner alli las escala de tiempos y demas
con la llave N° 10 ( PINE=1) en ON tendriamos funcionamiento ., en OFF apagado
de alli nos pasa a otra funcion (PINE=2) ., en ON es fading y en OFF es rainbow
aparte en las que quedan (PINC=0 a PINC=7) se puede agregar las velocidades u otra funcion que nesesites ., ( por ahora esta definido los valores DMX ) ., pero eso se puede cambiar y tenes 8 posisciones.,  que tambien se suman
el valor de la suma o resultado lo puede alojar en ADRRESTEMP
tambien esta la posibilidad que nesesitas otra funcion de las MINI-DIPS la numero 10 (PINE=1) en OFF ., tenga otras funciones a definir  .,
bueno aca te pongo lo que arme y vamos viendo
Código: [Seleccionar]
#define F_CPU 8000000
#include<util\delay.h>

#include<stdio.h>
#include<stdlib.h>

#include <avr/wdt.h>
 // *** establecer valor de WHILE  ***//
enum {FALSE=0, TRUE=1};   //*********************************//
uint8_t count= 1; // contador del soft PWM
enum {FADING,RAINBOW_FADER,} mode;
 //*********************************//
const short int arraydimmer[256]={0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1.1,1,1,1,1,1,1,2.2,2,2,3,3,3,4,4.4,5,5,5,6,6,7,7,8,8,9,9,10,10,11,11.12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19.20,20,21,21,22,22,23,23.24,24,25,25,26,27,28,29.30,30,31,32,33,34,35,36.36,37,38,39,40,41,42,43,43,44,45,46,47,48,49,50,51,52,52,53,54,55,56,57,58,59,60,61,62,63,64,65.66,67,68,69,70,71,72,73.74,75,76,77,78,79,80,81,82,83,84,85,86,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,112,113,114,115,116,117,119,120,121,122,123,124,126,127,128,129,130,132,133,134,135.136,138,139,140,141,142,144,145,146,147,149,150,151,152,154,155.156,158,159,160,161,162,164,165,167,168,169,171,172,173,174,176,177,178,180,181,182,184,185,187,188,189,191,192,193,195,196,197,199,200,202,203,204,206,207,208,210,211,213,214,216,217,218,220,221,223,224,226,227,228,230,231,233,234,236,237,239,240,242,243,245,246,248,249,251,252,254,255 }; // Lo que aparece como DC_Data
                                   
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;
//************* Inicialización pines / port *****************//
void init_pinouts(){                   
    #ifdef USE_DIP
 
    DDRC  = 0; // establecer DIPs
    PORTC  = 0xFF;
    DDRE  &= ~((1<<PE2)|(1<<PE1));
    PORTE |=   (1<<PE2)|(1<<PE1);
 
    #endif
   
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB= 0;
DDRE  |= (1<<PE0); //LED2 azul indicador
    PORTE |= (1<<PE0);
    }     
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
 // ****** Temporizador de inicialización para evitar efecto estroboscópico *****//
#define OV_COUNT 14 // 161 , 7  = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
 // ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
 
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp=   // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
Address= Temp;
if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
     {
mode= FADING;
}else{
mode= RAINBOW_FADER;

     }
return;
}
//mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
//Temp=
// (!(PINC &(1<<PC0)) *1) +
// (!(PINC &(1<<PC1)) *2) +
// (!(PINC &(1<<PC2)) *4) +
// (!(PINC &(1<<PC3)) *8) +
// (!(PINC &(1<<PC4)) *16) +
// (!(PINC &(1<<PC5)) *32) +
// (!(PINC &(1<<PC6)) *64) +
// (!(PINC &(1<<PC7)) *128) +
// (!(PINE &(1<<PE2)) *256);
 
 
//if (Temp != 0)
// {
// Address= Temp;

// }
 
#endif
}
         
   int main(void)
     {
 //***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
   
sei();     // habilitar las interupciones globales  ???
int PWM_timer;  // inicializar el timer PWM
  while(1) // bucle principal (LOOP)
    {

        get_dips(); // Comprobar dip-switch y habilitar la funcion

      for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado
{

// if(!PINC6){ fading();}
    // if(!PINC5){ disco();}
    /*
    Aca mas codigo que realmente no influye en nada
    */
    }
     
     
     
    void fading() {
     
    Velocidad = 127;
     
    while(!PINC6)
    {
    Rojo = 255;
    Verde = 0;
    Azul = 0;
     
    DimmerCurva()
    PORTE0 = 0;
     
    //rojo_amarillo
    while(Verde!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);
    PORTE0 = 1;
    Verde++;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //amarillo_verde
    while(Rojo && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Rojo--;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //verde_cyan
    while(Azul!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Azul++;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //cyan_azul
    while(Verde && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Verde--;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //azul_magenta
    while(Rojo!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Rojo++;
    DimmerCurva();
    }
    PORTE0 = 0;
   
    //magenta_rojo
    while(Azul && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Azul--;
    DimmerCurva();
    }
    PORTE0 = 0;
    }
    }
     
    void delay(int velocidad) {
     
    delay_ciclos();  // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
    // Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
     
    //temp2 = 1  si PINE1 = 0 sino temp2=2
    //temp1 = 64 si PINE2 = 0 sino temp1=255
     
    /*
     
    Ciclos a esperar
     
    temp2=1 temp1=255
    11445 * (velocidad-1) +28
     
    temp2=1 temp1=64
    2895 * (velocidad -1) +28
     
    temp2=2 temp1=255
    18303 * (velocidad-1) +28
     
    temp2=2 temp1=64
    4551 * (velocidad-1) +28
    */
    }
     
     
    void rainbow_fader(){
     
    int Temp_R,Temp_A,Temp_V;
    Velocidad = 254;
    Temp_R = Rojo;
    Temp_A = Azul;
    Temp_V = Verde;
     
    while(PINC7)
    {
    Rojo = 255;
    Verde = 0;
    Azul = 0;
    DimmerCurva();
    PORTE0 = 0;
     
    //rojo_verde
    while(Verde!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Rojo--;
    Verde++;
    DimmerCurva();
    }
    PORTE0=0;
     
    //verde_azul
    while(Azul!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Verde--;
    Azul++;
    DimmerCurva();
    }
    PORTE0=0;
     
    //azul_rojo
    while(Rojo!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Azul--;
    Rojo++;
    DimmerCurva();
    }
    PORTE0=0;
    }
     
    Rojo = Temp_R;
    Azul = Temp_A;
    Verde = Temp_V;
     
    }
     
    void DimmerCurva(){
     
    R_out=arraydimmer[Rojo];
    V_out=arraydimmer[Verde];
    A_out=arraydimmer[Azul];
     }
     if (count == 0xFF)
   { // Llamado con 122Hz
   count= 1;
   
   }
      else count++;
       }
}
 }
 //***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER:
count = OV_COUNT + Address;
break;
case FADING :
count = OV_COUNT + Address * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;

if (mode==FADING){

}
 
}else{ timer_counter++; }

{

}


bueno espero tus comentarios tan educativos para mi ., aunque no lo creas ., eres la primer persona que me explica ., algo de C ., que no usa ese lenguaje ( partiendo del conosimiento del ASM )., y para colmo no usa atmega., y eso es muy destacable ., infinitas  gracias
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 09 de Agosto de 2015, 18:48:09
Citar
directamente con atmega intente aprender ASM .,(y puse mucho empeño )
Tenes 2 caminos concretamente:

Usar un lenguaje de alto nivel como C, el cual te abstrae un poco del hardware y sus funciones, hace que programar sea mas facil.
Por otro lado tenes el ASM que es ideal en tema del provecho que le podes sacar al micro, pero que te ocupa mucho tiempo para hacer algo simple. Lo que si te lleva a aprender bien el manejar el binario y saber bien como se maneja por dentro el microcontrolador asi de esa forma luego cuando pasas a C podes aprovecharlo mas.

Citar
Vi y acepte que en estos casos para tener multifunciones ., se debe implementar el PWM por sotfware., y no por hardware

Las principales razones de por que se usa un PWM por software y no uno por hardware son varias.

Si es de elegir se prefiere siempre un PWM por Hardware y no uno por software, por que de esa forma el micro se encuentra libre ejecutando otras instrucciones mientras que el Hardware solo genera el PWM.

Aunque esto tiene algunos problemas segun el micro que sea. Uno de estos por la cantidad de salidas. Por cada pin se requiriria el Hardware para el mismo, entonces por ahi no se tienen 8 salidas con PWM por hardware. Entonces te fuerza a usar un PWM por Software.

Otra de las razones es que algunos PWM por Hardware no son lo suficientemente lentos. Tal ves el maximo periodo es de 1ms y vos necesitas un periodo de 20ms, entonces no queda otra que usar uno por Software a pesar que significa que el micro tenga que ponerse a hacer el PWM y no solo el programa en cuestion.

Citar
concretamente cuando usa por ejemplo: "" case 0x04:" ., la definicion CASE si la entiendo pero 0x04

Hay distintas formas de expresar los numeros, ya sea binario, decimal, hexadecimal, octal(realmente nunca lo use), esto va a depender a veces del compilador usado, algunos formatos que eh visto:

Binario (8bits):
0b00100101
b'00100101'

Decimal
30
.30
30d

Hexadecimal
0x20
20h


Lo interesante del Hexadecimal y el binario es que tienen una forma facil de pasar de uno a otro
              0      4
0x04 = 0000 0100 = 4 decimal
0x2A = 0010 1010 = 42 decimal
              2      A

Si observas al numero binario de 8 bits lo separe en 4 bit, y cada 4 bits es representado por un solo valor en hexadecimal. En esa parte hago:

 (PINE&0x06)

es igual a ( separo los bits para que sea mas legible nada mas )

 PINE & 0000 0110

entonces eso me va a dejar los bits de los pines 1 y 2.

Segun el valor que salga de ahi, el resultado de esa AND, va a ser donde entre el case. Si por ejemplo tengo que
PINE = 0101 1101

Entonces tendria ->  PINE & 0000 0110 -> 0101 1101 & 0000 0110 -> 0000 0100
Eso en hexadecimal seria 0x04

Citar
bueno espero tus comentarios tan educativos para mi ., aunque no lo creas ., eres la primer persona que me explica ., algo de C ., que no usa ese lenguaje ( partiendo del conosimiento del ASM )., y para colmo no usa atmega., y eso es muy destacable ., infinitas  gracias

El lenguaje C es igual en todos los micros, sea de microchip / atmel / renesas / ti / nxp, etc. Lo unico que cambian son los registros a configurar, y modulos. Y eso es lo bueno de C. Una funcion en un micro puede ser usada en otro, siempre y cuando no modifique registros, ya que vas a tener que buscar equivalentes entre los micros. Si haces:

tiempo=((568 * (velocidad-1)+3)/1000);

En cualquier micro eso va a servir. Esto no pasa con ASM ya que el manejo de memoria es distinto, las instrucciones son distintas incluso de cada marca de microcontrolador y vas a tener que aprender todo de ese micro nuevamente.

Y una ves que viste algunos microcontroladores, vas a notar que TODOS son casi iguales, si usas un timer, tenes que buscar los registros a modificar y listo, llenas esos registros y tenes andando tu timer sea cual sea tu micro.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 09 de Agosto de 2015, 22:55:44
bueno amigaso ., a vuelto a responder magistralmente
 ((:-))  ((:-))  ((:-))  ((:-))
muchisimas gracias ., por el tiempo y la voluntad puesta de manifiesto
espero que tenga tiempo (y ganas de leer el bosquejo de programacion que hice
viendo de esa manera mis posibles "horrores"
aca subo varios tutos ., de ASM par atmega., (incluida la hoja de datos resumida del 8515 traducida
si algun moderador considera que tienen que publicarce en otro lugar que lo corrija  (gracias )
quedo ala espera de su comentario ., muchas gracias
NOTA AL MODERADOR : quedaron sin subir 4 archivos con los tutos traducidos ., por el limite de tamaño
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: stk500 en 10 de Agosto de 2015, 02:43:11
Por lo que leo, veo que estais saliendo del Tema DMX512 y tutoriando de Lenguaje , para este caso seria mejor abrir el tema en el Subforo de Atmel.
Querido amigo Locodelafonola, quizas te ha pasado por el Subforo de Atmel, pues alli hay muchos tutoriales de todos los lenguaje de programacion y de Assemble mas aun. por favor respectar el orden de los Subforo , asi se facilita a la hora de buscar Informaciones. para esto esta el foro Clasificado, no siendo asi seria dificil para Usuarios que usen el Buscador encontrar la Info que busquen.

Saludos
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 10 de Agosto de 2015, 03:00:09
stk vos fuiste quien trajiste el post a este lugar. Estaba en el subforo de Atmel, te dejo el link para que le veas


http://www.todopic.com.ar/foros/index.php?topic=44884.0
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: stk500 en 10 de Agosto de 2015, 08:41:27
stk vos fuiste quien trajiste el post a este lugar. Estaba en el subforo de Atmel, te dejo el link para que le veas


http://www.todopic.com.ar/foros/index.php?topic=44884.0
Si lo se, pero el Tema al principio trataba sobre DMX512, por eso lo pase para aca,
lo que aconsejaria al Amigo Locodelafonola que abra un tema en el Subforo de Atmel,
Saludos

Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 10 de Agosto de 2015, 17:19:55
hola
stk vos fuiste quien trajiste el post a este lugar. Estaba en el subforo de Atmel, te dejo el link para que le veas


http://www.todopic.com.ar/foros/index.php?topic=44884.0

Si lo se, pero el Tema al principio trataba sobre DMX512, por eso lo pase para aca,
lo que aconsejaria al Amigo Locodelafonola que abra un tema en el Subforo de Atmel,
Saludos


gracias a los dos ., basicamente espero poder compilar y que funcione
luego pasrlo a DMX ., en mi libreria base que funciona
En los comandos de recepcion y accionamiento no tengo problema ., por que basicamente trabajamos con valores de 0 a 255
Voy a aclarar un poco la cuestion ., esta funcion que quiero implementar (aprenderla mas que todo )., esta en los equipos DMX profecionales 
ya sea que tenga el comando DMX ., o cuando funcionan en manual o audioritmico .,  si se fijan el esquematico de mi montaje  !!!!! es DMX ¡¡¡¡¡ 
igual que las funciones de la libreria que dio origen a este hilo., no se desvirtua (al menos eso creo) 
asi que no creo que alla problemas ., mientras pueda lograr algo y se comparta ., no importa el lugar ., gracias a los dos 
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 19 de Agosto de 2015, 11:59:15
Disculpa que por la falta de tiempo solo me limite a contestar algunas preguntas rapidas. Si podes poner los errores que te dan es mas facil solucionarlo.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 19 de Agosto de 2015, 20:36:09
ok amigo y muchas gracias
Disculpa que por la falta de tiempo solo me limite a contestar algunas preguntas rapidas. Si podes poner los errores que te dan es mas facil solucionarlo.
bueno aqui va ., aclaro que lo que arme es pensando usar esta finciones de fading y rainbow.,  en dmx y standalone (que seria esta) 
es reparado los errores del armado  ., de la compilacion hasta donde yo se ., y como veras los errores que me larga son del agregado de estas funiones .,
Código: [Seleccionar]
//#define F_CPU 8000000
#include<util\delay.h>

#include<stdio.h>
#include<stdlib.h>

#include <avr/wdt.h>
 // *** establecer valor de WHILE  ***//
enum {FALSE=0, TRUE=1};
//*********************************//  
uint8_t count= 1; // contador del soft PWM
enum {FADING,RAINBOW_FADER,} mode; //funciones de muestr                                                                                                                                                                                                                                                                                                                                                                                                                                                           
Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out; //
 //*********************************//
const short int arraydimmer[256]={0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1.1,1,1,1,1,1,1,2.2,2,2,3,3,3,4,4.4,5,5,5,6,6,7,7,8,8,9,9,10,10,11,11.12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19.20,20,21,21,22,22,23,23.24,24,25,25,26,27,28,29.30,30,31,32,33,34,35,36.36,37,38,39,40,41,42,43,43,44,45,46,47,48,49,50,51,52,52,53,54,55,56,57,58,59,60,61,62,63,64,65.66,67,68,69,70,71,72,73.74,75,76,77,78,79,80,81,82,83,84,85,86,88,89,90,91,92,93,94,95,96,97,98,99,100,102,103,104,105,106,107,108,109,110,112,113,114,115,116,117,119,120,121,122,123,124,126,127,128,129,130,132,133,134,135.136,138,139,140,141,142,144,145,146,147,149,150,151,152,154,155.156,158,159,160,161,162,164,165,167,168,169,171,172,173,174,176,177,178,180,181,182,184,185,187,188,189,191,192,193,195,196,197,199,200,202,203,204,206,207,208,210,211,213,214,216,217,218,220,221,223,224,226,227,228,230,231,233,234,236,237,239,240,242,243,245,246,248,249,251,252,254,255 }; // Lo que aparece como DC_Data
                                   
 // ****** Temporizador de inicialización para evitar efecto estroboscópico *****//
#define OV_COUNT 14 // 161 , 7  = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
//************* Inicialización pines / port *****************//
void init_pinouts(){                   
    #ifdef USE_DIP
 
    DDRC  = 0; // establecer DIPs
    PORTC  = 0xFF;
    DDRE  &= ~((1<<PE2)|(1<<PE1));
    PORTE |=   (1<<PE2)|(1<<PE1);
 
    #endif
   
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB= 0;
DDRE  |= (1<<PE0); //LED2 azul indicador
    PORTE |= (1<<PE0);
    }     
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}

 // ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
 
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp=   // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
Address= Temp;
if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
     {
mode= FADING;
}else{
mode= RAINBOW_FADER;

     }
return;
}
//mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
//Temp=
// (!(PINC &(1<<PC0)) *1) +
// (!(PINC &(1<<PC1)) *2) +
// (!(PINC &(1<<PC2)) *4) +
// (!(PINC &(1<<PC3)) *8) +
// (!(PINC &(1<<PC4)) *16) +
// (!(PINC &(1<<PC5)) *32) +
// (!(PINC &(1<<PC6)) *64) +
// (!(PINC &(1<<PC7)) *128) +
// (!(PINE &(1<<PE2)) *256);
 
 
//if (Temp != 0)
// {
// Address= Temp;

// }
 
#endif
}
         
   int main(void)
     {
 //***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
   
sei();     // habilitar las interupciones globales  ???
int PWM_timer;  // inicializar el timer PWM
  while(1) // bucle principal (LOOP)
    {

        get_dips(); // Comprobar dip-switch y habilitar la funcion

      for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado
{

// if(!PINC6){ fading();}
    // if(!PINC5){ disco();}
    /*
    Aca mas codigo que realmente no influye en nada
    */
    }
     
     
     
    void fading() {
     
    Velocidad = 127;
     
    while(!PINC6)
    {
    Rojo = 255;
    Verde = 0;
    Azul = 0;
     
    DimmerCurva()
    PORTE0 = 0;
     
    //rojo_amarillo
    while(Verde!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);
    PORTE0 = 1;
    Verde++;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //amarillo_verde
    while(Rojo && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Rojo--;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //verde_cyan
    while(Azul!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Azul++;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //cyan_azul
    while(Verde && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Verde--;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //azul_magenta
    while(Rojo!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Rojo++;
    DimmerCurva();
    }
    PORTE0 = 0;
   
    //magenta_rojo
    while(Azul && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Azul--;
    DimmerCurva();
    }
    PORTE0 = 0;
    }
    }
     
    void delay(int velocidad) {
     
    delay_ciclos();  // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
    // Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
     
    //temp2 = 1  si PINE1 = 0 sino temp2=2
    //temp1 = 64 si PINE2 = 0 sino temp1=255
     
    /*
     
    Ciclos a esperar
     
    temp2=1 temp1=255
    11445 * (velocidad-1) +28
     
    temp2=1 temp1=64
    2895 * (velocidad -1) +28
     
    temp2=2 temp1=255
    18303 * (velocidad-1) +28
     
    temp2=2 temp1=64
    4551 * (velocidad-1) +28
    */
    }
     
     
    void rainbow_fader(){
     
    int Temp_R,Temp_A,Temp_V;
    Velocidad = 254;
    Temp_R = Rojo;
    Temp_A = Azul;
    Temp_V = Verde;
     
    while(PINC7)
    {
    Rojo = 255;
    Verde = 0;
    Azul = 0;
    DimmerCurva();
    PORTE0 = 0;
     
    //rojo_verde
    while(Verde!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Rojo--;
    Verde++;
    DimmerCurva();
    }
    PORTE0=0;
     
    //verde_azul
    while(Azul!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Verde--;
    Azul++;
    DimmerCurva();
    }
    PORTE0=0;
     
    //azul_rojo
    while(Rojo!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Azul--;
    Rojo++;
    DimmerCurva();
    }
    PORTE0=0;
    }
     
    Rojo = Temp_R;
    Azul = Temp_A;
    Verde = Temp_V;
     
    }
     
    void DimmerCurva(){
     
    R_out=arraydimmer[Rojo];
    V_out=arraydimmer[Verde];
    A_out=arraydimmer[Azul];
     }
     if (count == 0xFF)
   { // Llamado con 122Hz
   count= 1;
   
   }
      else count++;
       }
}

 //***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER:
count = OV_COUNT + Address;
break;
case FADING :
count = OV_COUNT + Address * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;

if (mode==FADING){

}
 
}else{ timer_counter++; }

{

}
}
los errores que me larga el compilador son estos
Código: [Seleccionar]
Build started 19.8.2015 at 20:21:43
avr-gcc.exe  -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99   -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT fading_raibow.o -MF dep/fading_raibow.o.d  -c  ../fading_raibow.c
../fading_raibow.c:1:1: warning: "F_CPU" redefined
<command-line>: warning: this is the location of the previous definition
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c: In function 'main':
../fading_raibow.c:97: warning: implicit declaration of function 'cli'
../fading_raibow.c:101: warning: implicit declaration of function 'sei'
../fading_raibow.c: In function 'fading':
../fading_raibow.c:122: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:122: error: (Each undeclared identifier is reported only once
../fading_raibow.c:122: error: for each function it appears in.)
../fading_raibow.c:126: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:127: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:128: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:130: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:131: error: expected ';' before numeric constant
../fading_raibow.c:136: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c:137: warning: implicit declaration of function 'delay'
../fading_raibow.c:137: error: 'velocidad' undeclared (first use in this function)
../fading_raibow.c:138: error: lvalue required as left operand of assignment
../fading_raibow.c:142: error: lvalue required as left operand of assignment
../fading_raibow.c:149: error: lvalue required as left operand of assignment
../fading_raibow.c:153: error: lvalue required as left operand of assignment
../fading_raibow.c:160: error: lvalue required as left operand of assignment
../fading_raibow.c:164: error: lvalue required as left operand of assignment
../fading_raibow.c:171: error: lvalue required as left operand of assignment
../fading_raibow.c:175: error: lvalue required as left operand of assignment
../fading_raibow.c:182: error: lvalue required as left operand of assignment
../fading_raibow.c:186: error: lvalue required as left operand of assignment
../fading_raibow.c:193: error: lvalue required as left operand of assignment
../fading_raibow.c:197: error: lvalue required as left operand of assignment
../fading_raibow.c: In function 'delay':
../fading_raibow.c:203: warning: implicit declaration of function 'delay_ciclos'
../fading_raibow.c: In function 'rainbow_fader':
../fading_raibow.c:231: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:232: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:233: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:234: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:242: error: lvalue required as left operand of assignment
../fading_raibow.c:247: error: 'velocidad' undeclared (first use in this function)
../fading_raibow.c:253: error: lvalue required as left operand of assignment
../fading_raibow.c:264: error: lvalue required as left operand of assignment
../fading_raibow.c:275: error: lvalue required as left operand of assignment
../fading_raibow.c: In function 'DimmerCurva':
../fading_raibow.c:286: error: 'R_out' undeclared (first use in this function)
../fading_raibow.c:286: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:287: error: 'V_out' undeclared (first use in this function)
../fading_raibow.c:287: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:288: error: 'A_out' undeclared (first use in this function)
../fading_raibow.c:288: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c: At top level:
../fading_raibow.c:300: warning: return type defaults to 'int'
../fading_raibow.c: In function 'ISR':
../fading_raibow.c:300: warning: type of '__vector_7' defaults to 'int'
../fading_raibow.c:304: error: 'Address' undeclared (first use in this function)
make: *** [fading_raibow.o] Error 1
Build failed with 36 errors and 20 warnings...
con los "WARNINGS" no hay problema .,  si no son graves .,  compila igual.,  pero son solo advertencias de forma.,  nada mas
he tratado de hacerlo solo.,  pero sinceramente me confudi mas ., son los "ERROR" ., los que hay que tener en cuenta ( pero me parece que falta definir las funciones o funcion de cad cosa
gracias y perdona la molestia
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 20 de Agosto de 2015, 08:43:13
Voy a hacer un resumen, disculpa si no me explayo mucho en la explicacion:


Citar
../fading_raibow.c:1:1: warning: "F_CPU" redefined

Esto es por que tenias el #define F_CPU y en otro lado tenes escrito lo mismo, es decir solo necesitas ponerlo 1 sola ves

Citar
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')
../fading_raibow.c:14: warning: excess elements in array initializer
../fading_raibow.c:14: warning: (near initialization for 'arraydimmer')

Esto es por que el arraydimmer tiene cerca de 270 y algo mas valores y vos intenta ponerlo en un array de 256 valores, aca hay valores de mas, si observas el archivo ASM ni siquiera hay tantos ceros.

Citar
../fading_raibow.c:97: warning: implicit declaration of function 'cli'
../fading_raibow.c:101: warning: implicit declaration of function 'sei'

Mas claro que nunca, basicamente esas funciones no existen, no se si tenes que agregar algun archivo para usarlas. Creo que es:

#include <avr/interrupt.h>   

Citar
../fading_raibow.c:122: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:122: error: (Each undeclared identifier is reported only once
../fading_raibow.c:122: error: for each function it appears in.)
../fading_raibow.c:126: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:127: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:128: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:231: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:232: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:233: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:234: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:247: error: 'velocidad' undeclared (first use in this function)
../fading_raibow.c:286: error: 'R_out' undeclared (first use in this function)
../fading_raibow.c:286: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:287: error: 'V_out' undeclared (first use in this function)
../fading_raibow.c:287: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:288: error: 'A_out' undeclared (first use in this function)
../fading_raibow.c:288: error: 'Azul' undeclared (first use in this function)

Otro error muy simple... una cosa a notar que existe la variable "velocidad" y Velocidad" intenta hacer que sea una u otra y no ambas. es decir poneles a todos "Velocidad" o todos "velocidad"
Luego hay que declararlas. Aunque las veo declaradas:

Short int Velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;

Citar
../fading_raibow.c:138: error: lvalue required as left operand of assignment
../fading_raibow.c:142: error: lvalue required as left operand of assignment
../fading_raibow.c:149: error: lvalue required as left operand of assignment
../fading_raibow.c:153: error: lvalue required as left operand of assignment
../fading_raibow.c:160: error: lvalue required as left operand of assignment
../fading_raibow.c:164: error: lvalue required as left operand of assignment
../fading_raibow.c:171: error: lvalue required as left operand of assignment
../fading_raibow.c:175: error: lvalue required as left operand of assignment
../fading_raibow.c:182: error: lvalue required as left operand of assignment
../fading_raibow.c:186: error: lvalue required as left operand of assignment
../fading_raibow.c:193: error: lvalue required as left operand of assignment
../fading_raibow.c:197: error: lvalue required as left operand of assignment

Corresponde a estas lineas:

PORTE0 = 0;
PORTE0 = 1;

Tal ves no se modifican asi, es como que no reconociera el PORTE0, asi que lo mas seguro es que tengas que reemplazarlo por un PORTE |= 0x01 ( Para ponerlo en 1 ) y un PORTE &=0xFE ( Para ponerlo en 0 ).

Citar
../fading_raibow.c:130: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:131: error: expected ';' before numeric constant
../fading_raibow.c:136: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c:137: warning: implicit declaration of function 'delay'
../fading_raibow.c:203: warning: implicit declaration of function 'delay_ciclos'

Los mensajes es por que no se crearon los prototipos de las funciones, y el error es por que falta un punto y coma en el codigo
Tambien notar que en un lado usamos el nombre "delay" y en otro lado "delay_ciclos", Cuando solo deberia haber el "delay" que es la funcion que nosotros creamos

Citar
../fading_raibow.c:300: warning: return type defaults to 'int'
../fading_raibow.c:300: warning: type of '__vector_7' defaults to 'int'

Por que no se declaro el tipo de funcion

Código: C
  1. ISR(TIMER0_OVF_vect){
  2.                          ....
  3. }

por

Código: C
  1. void ISR(TIMER0_OVF_vect){
  2.                        ......
  3. }


Citar
../fading_raibow.c:304: error: 'Address' undeclared (first use in this function)

Obviamente no definio esa variable tampoco, esta usada en la interrupcion, asi que por eso el error.


-------------

Solucionado todo esto deberia compilar o salir nuevos errores
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 20 de Agosto de 2015, 17:04:35
Bueno amigo ., esto va por muy buen camino.,  gracias a usted ¡¡¡¡ infinitas Gracias !!!!
bueno alli acomode un poco las cosas
Agregue la libreria #include"fading_raibow.h" ., repare lo del ocilador ( estaba definido 2 veces en la optimizacion de codigo)., y el potE0 ., yo creo que va a funcionar.,  como estaba.,  desde un pricipio ., tenia mal dedinido el port en "pinouts" ., por eso largaba error
Bueno lo que larga ahora., creo que son errores de forma., no de funcionamiento
yo creo que para mi ver., son la formas que estan escritas las funciones nada mas que eso
por ejemplo :
Código: [Seleccionar]
while(Verde && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
Bien yo esa funcion la defini en el array de llaves PINE2., ahora la duda que tengo es que al parecer ., PINC6 y PINC7 ., trabajen en conjunto o separadamente .,  no lo defini ni cambie para confirmar eso
Tal vez.,  no presto atencion.,  a lo que yo arme (!!! ojo ¡¡¡¡ puede estar mal )  ., porque ya esta definido la funcion de la llave OFF/ON ., que lee GET_DIPS() ., en cada ciclo del While
Por eso digo ., que talvez entendi mal el funcionamiento
En el array de llaves esta con valores de  DMX ., pero alli se pueden poner valores del delay (esta armado par que se sumen las llaves.,  y tome el total en DMXADRRDES = Temp
Como lo que esta puesto aca :
Código: [Seleccionar]
//temp2 = 1  si PINE1 = 0 sino temp2=2
    //temp1 = 64 si PINE2 = 0 sino temp1=255
     
    /*
     
    Ciclos a esperar
     
    temp2=1 temp1=255
    11445 * (velocidad-1) +28
     
    temp2=1 temp1=64
    2895 * (velocidad -1) +28
     
    temp2=2 temp1=255
    18303 * (velocidad-1) +28
     
    temp2=2 temp1=64
    4551 * (velocidad-1) +28
    */
Otra cosa que hice fue ., declarar las salidas de los LED R,G,B   
Ahora lo que no se ., es que valor toma de la compilacion para el PWM ., como tampoco entiendo como se ejecuta la salida en la compilacion ASM
Esto como dije .,  aparte de aprender como funciona un fading por software ., quiero aplicarlo al DMX
En la configuracion fisica.,  que tengo armada ., solo usa los tres puertos  de B y tengo los puertos libres de A
Yo pesaba agregar mas llaves en  puertos A ( las que sean necesarias) y que trabajen en conjunto con las de los puetos C y E
Por eso las forma del bosquejo., pero por ahora ., esta armado de acuerdo al esquema fisico que ya tengo construido y asi probar
Bueno ahora lo que quedo es asi
Código: [Seleccionar]
//#define F_CPU 8000000
#include<util\delay.h>

#include<stdio.h>
#include<stdlib.h>
#include"fading_raibow.h"
#include <avr/interrupt.h>   
#include <avr/wdt.h>
 // *** establecer valor de WHILE  ***//
enum {FALSE=0, TRUE=1};
//*********************************//  
uint8_t count= 1; // contador del soft PWM

Short int velocidad,Rojo,Verde,Azul,V_out,R_out,A_out; //
 //*********************************//
const short int arraydimmer[256]={0,   0,   1,   1,   1,   1,   1,   2, 2,   2,   2,   3,   3,   3,   4,   4, 4,   5,   5,   5,   6,   6,   7,   7, 8,   8,   9,   9,  10,  10,  11,  11, 12,  12,  13,  13,  14,  14,  15,  15, 16,  16,  17,  17,  18,  18,  19,  19, 20,  20,  21,  21,  22,  22,  23,  23, 24,  24,  25,  25,  26,  27,  28,  29, 30,  30,  31,  32,  33,  34,  35,  36, 36,  37,  38,  39,  40,  41,  42,  43, 43,  44,  45,  46,  47,  48,  49,  50, 51,  52,  52,  53,  54,  55,  56,  57, 58,  59,  60,  61,  62,  63,  64,  65, 66,  67,  68,  69,  70,  71,  72,  73, 74,  75,  76,  77,  78,  79,  80,  81, 82,  83,  84,  85,  86,  88,  89,  90, 91,  92,  93,  94,  95,  96,  97,  98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 119, 120, 121, 122, 123, 124, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 144, 145, 146, 147, 149, 150, 151, 152, 154, 155, 156, 158, 159, 160, 161, 162, 164, 165, 167, 168, 169, 171, 172, 173, 174, 176, 177, 178, 180, 181, 182, 184, 185, 187, 188, 189, 191, 192, 193, 195, 196, 197, 199, 200, 202, 203, 204, 206, 207, 208, 210, 211, 213, 214, 216, 217, 218, 220, 221, 223, 224, 226, 227, 228, 230, 231, 233, 234, 236, 237, 239, 240, 242, 243, 245, 246, 248, 249, 251, 252, 254, 255}; // Lo que aparece como DC_Data
                                   
 // ****** Temporizador de inicialización para evitar efecto estroboscópico *****//
#define OV_COUNT 14 // 161 , 7  = 0.25ms
#define OV_SIZE 161 // comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
//************* Inicialización pines / port *****************//
void init_pinouts(){                   
    #ifdef USE_DIP
 
    DDRC  = 0; // establecer DIPs
    PORTC  = 0xFF;
    DDRE  &= ~((1<<PE2)|(1<<PE1));
    PORTE |=   (1<<PE2)|(1<<PE1);
 
    #endif
   
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE  |= (1<<PE0); //LED2 azul indicador
    PORTE = 0;
    }     
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}

 // ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
 
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp=   // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
     {
mode= FADING;
}else{
mode= RAINBOW_FADER;

     }
return;
}
//mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
//Temp=
// (!(PINC &(1<<PC0)) *1) +
// (!(PINC &(1<<PC1)) *2) +
// (!(PINC &(1<<PC2)) *4) +
// (!(PINC &(1<<PC3)) *8) +
// (!(PINC &(1<<PC4)) *16) +
// (!(PINC &(1<<PC5)) *32) +
// (!(PINC &(1<<PC6)) *64) +
// (!(PINC &(1<<PC7)) *128) +
// (!(PINE &(1<<PE2)) *256);
 
 
//if (Temp != 0)
// {
// Address= Temp;

// }
 
#endif
}
         
   int main(void)
     {
 //***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
   
sei();     // habilitar las interupciones globales  ???
int PWM_timer;  // inicializar el timer PWM
  while(1) // bucle principal (LOOP)
    {

        get_dips(); // Comprobar dip-switch y habilitar la funcion

      for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado
{
if (R_out>PWM_timer) //red
{
PORTB &= ~(1<<PB0); //LED OFF
}else{
PORTB |= (1<<PB0); //LED ON
}
 
if (V_out>PWM_timer)         //green
{
PORTB &= ~(1<<PB1); //LED OFF
}else{
PORTB |= (1<<PB1); //LED ON
}
 
if (V_out>PWM_timer)         //blue
{
PORTB &= ~(1<<PB2); //LED OFF
}else{
PORTB |= (1<<PB2); //LED ON
}
// if(!PINC6){ fading();}
    // if(!PINC5){ disco();}
    /*
    Aca mas codigo que realmente no influye en nada
    */
    }
     
     
     
    void fading(); {
     
    Velocidad = 127;
     
    while(!PINC6)
    {
    Rojo = 255;
    Verde = 0;
    Azul = 0;
     
    DimmerCurva();
    PORTE0 = 0;
     
    //rojo_amarillo
    while(Verde!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);
    PORTE0 = 1;
    Verde++;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //amarillo_verde
    while(Rojo && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Rojo--;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //verde_cyan
    while(Azul!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Azul++;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //cyan_azul
    while(Verde && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Verde--;
    DimmerCurva();
    }
    PORTE0 = 0;
     
    //azul_magenta
    while(Rojo!=255 && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Rojo++;
    DimmerCurva();
    }
    PORTE0 = 0;
   
    //magenta_rojo
    while(Azul && !PINC6)
    {
    if(PINC7) { rainbow_fader();}
    delay(velocidad);  //esperar
    PORTE0 = 1;
    Azul--;
    DimmerCurva();
    }
    PORTE0 = 0;
    }
    }
     
    void delay(int velocidad) {
     
    delay_ciclos();  // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
    // Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
     
    //temp2 = 1  si PINE1 = 0 sino temp2=2
    //temp1 = 64 si PINE2 = 0 sino temp1=255
     
    /*
     
    Ciclos a esperar
     
    temp2=1 temp1=255
    11445 * (velocidad-1) +28
     
    temp2=1 temp1=64
    2895 * (velocidad -1) +28
     
    temp2=2 temp1=255
    18303 * (velocidad-1) +28
     
    temp2=2 temp1=64
    4551 * (velocidad-1) +28
    */
    }
     
     
    void rainbow_fader();{
     
    int Temp_R,Temp_A,Temp_V;
    Velocidad = 254;
    Temp_R = Rojo;
    Temp_A = Azul;
    Temp_V = Verde;
     
    while(PINC7)
    {
    Rojo = 255;
    Verde = 0;
    Azul = 0;
    DimmerCurva();
    PORTE0 = 0;
     
    //rojo_verde
    while(Verde!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Rojo--;
    Verde++;
    DimmerCurva();
    }
    PORTE0=0;
     
    //verde_azul
    while(Azul!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Verde--;
    Azul++;
    DimmerCurva();
    }
    PORTE0=0;
     
    //azul_rojo
    while(Rojo!=255 && PINC7)
    {
    delay(velocidad);
    PORTE=1;
    Azul--;
    Rojo++;
    DimmerCurva();
    }
    PORTE0=0;
    }
     
    Rojo = Temp_R;
    Azul = Temp_A;
    Verde = Temp_V;
     
    }
     
    void DimmerCurva(){
     
    R_out=arraydimmer[Rojo];
    V_out=arraydimmer[Verde];
    A_out=arraydimmer[Azul];
     }
     if (count == 0xFF)
   { // Llamado con 122Hz
   count= 1;
   
   }
      else count++;
       }
}

 //***** inicio del ocilador Temporizador de interrupción ****//
 ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER;
count = OV_COUNT + DMXAddress;
break;
case FADING ;
count = OV_COUNT + DMXAddress * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;

if (mode==FADING){

}
 
}else{ timer_counter++; }

{

}
}

La libreria H que arme es esta
Código: [Seleccionar]
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define  USE_DIP
#define  F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
 
enum {RAINBOW_FADER,FADING,} mode;

volatile uint16_t DmxAddress; // Dirección inicial


extern void    get_dips(void);


Ahora lo que me larga error
Código: [Seleccionar]
Build started 20.8.2015 at 15:17:31
avr-gcc.exe  -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99       -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT fading_raibow.o -MF dep/fading_raibow.o.d  -c  ../fading_raibow.c
../fading_raibow.c:14: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'int'
../fading_raibow.c: In function 'main':
../fading_raibow.c:112: error: 'R_out' undeclared (first use in this function)
../fading_raibow.c:112: error: (Each undeclared identifier is reported only once
../fading_raibow.c:112: error: for each function it appears in.)
../fading_raibow.c:119: error: 'V_out' undeclared (first use in this function)
../fading_raibow.c:143: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:147: error: 'Rojo' undeclared (first use in this function)
../fading_raibow.c:148: error: 'Verde' undeclared (first use in this function)
../fading_raibow.c:149: error: 'Azul' undeclared (first use in this function)
../fading_raibow.c:151: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:152: error: lvalue required as left operand of assignment
../fading_raibow.c:157: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c:158: warning: implicit declaration of function 'delay'
../fading_raibow.c:158: error: 'velocidad' undeclared (first use in this function)
../fading_raibow.c:159: error: lvalue required as left operand of assignment
../fading_raibow.c:163: error: lvalue required as left operand of assignment
../fading_raibow.c:170: error: lvalue required as left operand of assignment
../fading_raibow.c:174: error: lvalue required as left operand of assignment
../fading_raibow.c:181: error: lvalue required as left operand of assignment
../fading_raibow.c:185: error: lvalue required as left operand of assignment
../fading_raibow.c:192: error: lvalue required as left operand of assignment
../fading_raibow.c:196: error: lvalue required as left operand of assignment
../fading_raibow.c:203: error: lvalue required as left operand of assignment
../fading_raibow.c:207: error: lvalue required as left operand of assignment
../fading_raibow.c:214: error: lvalue required as left operand of assignment
../fading_raibow.c:218: error: lvalue required as left operand of assignment
../fading_raibow.c: In function 'delay':
../fading_raibow.c:224: warning: implicit declaration of function 'delay_ciclos'
../fading_raibow.c: In function 'main':
../fading_raibow.c:249: warning: conflicting types for 'rainbow_fader'
../fading_raibow.c:157: warning: previous implicit declaration of 'rainbow_fader' was here
../fading_raibow.c:263: error: lvalue required as left operand of assignment
../fading_raibow.c:274: error: lvalue required as left operand of assignment
../fading_raibow.c:285: error: lvalue required as left operand of assignment
../fading_raibow.c:296: error: lvalue required as left operand of assignment
../fading_raibow.c: In function 'DimmerCurva':
../fading_raibow.c:309: error: 'A_out' undeclared (first use in this function)
../fading_raibow.c: In function '__vector_7':
../fading_raibow.c:324: error: expected ':' or '...' before ';' token
../fading_raibow.c:325: error: 'DMXAddress' undeclared (first use in this function)
../fading_raibow.c:327: error: expected ':' or '...' before ';' token
make: *** [fading_raibow.o] Error 1
Build failed with 31 errors and 6 warnings...
Bueno espero tus comentarios e ideas (estan buenisimas para mi)  cuando puedas con tu tiempo y desde ya gracias
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 23 de Agosto de 2015, 19:55:29
Bueno no voy a profundizar en el tema de los DIPS que agregaste. Ya que realmente no se que hacen, solo me limite a pasarte el ASM de la funcion que me diste a C.

Pero Voy a decirte 2 cosas sobre eso ( esto nomas incluye el codigo que te pase).

1 - PORTE1 , PORTE2 se utilizan para la rapidez con que cambian los colores (fading), eso tenes que tenerlo en cuenta.
2 - PORTC6, PORTC7 se utilizan para seleccionar los modos, es decir entre fading y ademas agregarle el rainbow_fading, PC6 te habilita a que se produzca el fading. SI ademas tenes habilitado PC7 se produce lo "rainbow" ademas del fading.

- El codigo de tus pines, funcion init_pinout() , le falta un #else, sino cuando pones el define USE_DIP, se ejecuta ambos codigos: y deberia ser asi:

Código: C
  1. void init_pinouts(){                                                                   
  2.     #ifdef USE_DIP
  3.  
  4.     DDRC  = 0;                  // establecer DIPs
  5.     PORTC  = 0xFF;
  6.     DDRE  &= ~((1<<PE2)|(1<<PE1));
  7.     PORTE |=   (1<<PE2)|(1<<PE1);
  8.  
  9.         #else          
  10.    
  11.         DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED                                                                                              
  12.         PORTB = 0;             
  13.         DDRE  |= (1<<PE0);      //LED2 azul indicador
  14.     PORTE = 0;
  15.         #endif
  16. }

- Tenes un problema en la definicion de las variables, decia Short int, estaba en mayusculas, directamente podes reemplazarlo por:

Código: C
  1. uint8_t velocidad,Rojo,Verde,Azul,V_out,R_out,A_out;

- Reemplaza todos los PINC7 y PINC6 por sus correspondientes, estos no daban errores pero mejor asegurarse.

Código: C
  1. (PINC & (1<<PC6))
  2. (PINC & (1<<PC7))

- Reemplaza lso PORTE0 =0 y PORTE = 1 por sus correspondientes, claramente esta dando errores, asi que mejor cambiarlos:

Código: C
  1. PORTE &= ~(1<<PE0);
  2. PORTE |= (1<<PE0);

- La funcion de delay te la habia pasado ya. Deberia quedar:

Código: C
  1. void delay(uint8_t Velocidad) {
  2.      
  3.         uint16_t tiempo;
  4.         switch((PINE&0x06))
  5.         {
  6.         case 0x00:
  7.                 tiempo=((362 * (velocidad-1)+3)/1000);
  8.                 _delay_ms(tiempo);
  9.                 break;
  10.         case 0x02:
  11.                 tiempo=((568 * (velocidad-1)+3)/1000);
  12.                 _delay_ms(tiempo);
  13.                 break;
  14.         case 0x04:
  15.                 tiempo=((1430 * (velocidad-1)+3)/1000);
  16.                 _delay_ms(tiempo);
  17.                 break;
  18.         case 0x06:
  19.                 tiempo=((2287 * (velocidad-1)+3)/1000);
  20.                 _delay_ms(tiempo);
  21.                 break;
  22.         }
  23. }

- Tenes un error en el switch...case en la interrupcion

Le pusiste un ; en ves de un :

- Tenes tal ves un error al tener una coma de mas aca (luego del FADING):

Código: C
  1. enum {RAINBOW_FADER,FADING,} mode;

- Lo mas importante:

 Sigo sin entender por que estas poniendo el for() en el main, sigo sin entender por que estas tocando la interrupcion del timer. A pesar que te pase como deberia ser y te dije como era un PWM por software, seguis implementando un concepto equivocado.
La idea de un PWM por software es que las porciones de tiempo sean fijas y que ademas tenga un periodo fijo, vos con tu for estas evitando todo eso. Por eso dije que las comparaciones deberian ir en la interrupcion y sin el for.
No se para que el switch case que agregaste en la interrupcion. realmente no se. por que esa interrupcion es del timer. la que te genera ese PWM.

Corrigiendo eso deberia creo yo eliminar todos los errores que tenes.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 24 de Agosto de 2015, 23:56:44
hola y gracias por tanta deferencia
bueno como dije por aca
hola
stk vos fuiste quien trajiste el post a este lugar. Estaba en el subforo de Atmel, te dejo el link para que le veas


http://www.todopic.com.ar/foros/index.php?topic=44884.0

Si lo se, pero el Tema al principio trataba sobre DMX512, por eso lo pase para aca,
lo que aconsejaria al Amigo Locodelafonola que abra un tema en el Subforo de Atmel,
Saludos


gracias a los dos ., basicamente espero poder compilar y que funcione
luego pasarlo a DMX ., en mi libreria base que funciona
En los comandos de recepcion y accionamiento no tengo problema ., por que basicamente trabajamos con valores de 0 a 255
Voy a aclarar un poco la cuestion ., esta funcion que quiero implementar (aprenderla mas que todo )., esta en los equipos DMX profecionales  
ya sea que tenga el comando DMX ., o cuando funcionan en manual o audioritmico .,  si se fijan el esquematico de mi montaje  !!!!! es DMX ¡¡¡¡¡  
igual que las funciones de la libreria que dio origen a este hilo., no se desvirtua (al menos eso creo)  
asi que no creo que alla problemas ., mientras pueda lograr algo y se comparta ., no importa el lugar ., gracias a los dos  
Bueno tal vez esto desoriente un poco ., pero con prestar atencion.,  uno se da cuenta enseguida de como funcionan esto
Y tal vez la confucion viene dada ., por la libreria que yo subi en asm ., que es para tres led solamente
Por que si nos fijamos  en la primer libreria ., que dio origen al hilo
En ella se nota claramente la funcion DMX y MANUAL-PROGRAMADO
Si hubieras traspasado al C esa libreria de ASM ., no hubiera habido problemas ., porque los pin/port y funciones son iguales al montaje que tengo ., y las librerias de USART en DMX son iguales
El problema que radica en esa compilacion ., es que maneja tres gupos de led rgb ., no un fading y rainbow-fader independiente
Ahora lo que desorienta ., es esta libreria que yo subi y comparti ., es que al aplicar las funciones  de ASM pasado a C .,  no me da la posibilidad de aplicar la funcin alternativa en DMX ., como lo tiene la primera libreria originaria de este hilo  
Yo a medida que se fue traduciondo la libreria ., me fui dando cuenta de eso ., es muy simple., las funciones de tiempo .,  se ocupa en las dos pociciones ON / OFF del mini dips de puerto PE1
Bueno que problema tengo alli ., si uso ese dips-swich ., para la funcion de tiempo y en sus dos variantes ( ON / OFF )  no puedo despues usar esa funcion para commutar a DMX
aca muestro el circuito esquematico de los dos librerias ASM de este hilo
(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=44207.0;attach=23381;image)
y como tengo el ARRAY de llaves sin ocupar (por la reforma que hice ) asi con los valores de DMX ., me da como maximo un valor de 256 (puesto que se suman los valores )., no puedo obtener el valor de 512 ., porque uso PE2  (valor de 256 en DMX =TABLA ) para el cambio de funciones
bueno pero eso no es problema ., porque los valores que se maneja en la compilacion.,  para manejar el PWM es con un maximo de 256 (0 a 255)
Ahora si se da el caso de necesitar valores mas altos para el fading ., tenemos la opcion aca
Código: [Seleccionar]
//***** inicio del ocilador Temporizador de interrupción ****//
 ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER :
count = OV_COUNT + DmxAddress;
break;
case FADING :
count = OV_COUNT + DmxAddress * 10;
break;
default:
count = OV_COUNT;
}
Donde tomamos el valor de 0V_COUNT mas el valor de DmxAddress ., en el caso de rainbow fader o como en fading., que aparte de las dos anteriores  mutiplica por 10
Bueno alli talvez ., habria que acomodar los valores  ., que se suman y los que se multiplican ( tal vez sea al revez )
los valores que me arroja por aca ., la "Velocidad" sigo sin entenderlos
Código: [Seleccionar]
   void delay(uint8_t Velocidad) {
        
     uint16_t tiempo;
     switch((PINE&0x06))
     {
     case 0x00:
     tiempo=((362 * (velocidad-1)+3)/1000);
     _delay_ms(tiempo);
     break;
     case 0x02:
     tiempo=((568 * (velocidad-1)+3)/1000);
     _delay_ms(tiempo);
     break;
     case 0x04:
     tiempo=((1430 * (velocidad-1)+3)/1000);
     _delay_ms(tiempo);
     break;
     case 0x06:
     tiempo=((2287 * (velocidad-1)+3)/1000);
     _delay_ms(tiempo);
     break;
     }
    }


sigo sin poder entender las "case " con valores exadecimales ., (no entiendo a que puertos se refiere ni a que BITS afecta
 
En cuanto al "FOR" del PWM ., si no lo coloco ., no me funciona con los potenciometros virtuales de DMX ( DmxRxField[DMX_CHANNELS] )
En cuanto a la asignacion de pines en PINUT esta corecta ( tengo que declara asi para que funciona las llaves y no podria ir nunca un ELSE ., porque los otros puertos que estan declarados alli son la salida y trabajan al mismo tiempo  
aparte con esa configuracion de PWM tan basica ., con el mismo he podido manejar motores  PAP y de C.C (obiamente con un poco de electronica asociada)
tambien modifique ( o sea tratar de volver al original de esta libreria ) ., estas sentencias V_out,R_out,A_out;  las cambie por estas  DmxRxField[0] , DmxRxField[1] , DmxRxField[2]
porque fueron de DMX llevadas a manual solamente ., pero usando la base delesquema electronico de DMX
Bueno con ese cambio de nombre a la sentencia ., ya me funciona .,  de las dos maneras la salida , obiamente agregando la libreria usart ., de recepcion DMX
Tratando de que esto funcione ., se lograria que funcione en dos modos .,el programado ., y aqui habria que hacer incapie en algo importante
Hasta ahora no he podido usar la libreria de Tx (transmicion) que poseo ., pues no tengo nada desarrollado (secuencias o cuadros o esenas .o como queran llamarle ) dentro del programa.,  para que funcione de modo MANUAL AUTOMATICO MASTER ., como lo es en este caso ., el FADING y y el RAINBOW_FADER  
Porque si se fijan en el esquema ., este no es solamente un receptor !!!! es un tranceptor ¡¡¡¡ ( puede recibir y emitir) por ahora una funcion a la vez ., pero con una pequeña reforma electronica ., puede hacer las dos cosas al mismo tiempo y tiene grandes ventajas
Estoy tratando de explicarte ., lo mejor que puedo para no causar tu enojo ., y el porque de esto ., si te causa alguna molestia te pido mil disculpas
yo sigo entendiendo las lecciones que encuentro por alli., y de cada uno ., que es mi profesor., pues mi ignorancia y analfabetismo ., me impiden ser critico de nadie ., y menos un  maestro  
Tal vez es una cuestion de entender ., que no todos tiene conociento en DMX ., y que muchos prefieren armar .,equipos audiortnicos ( que bien podria ser otra opcion mas para esto )
Se va haciendo dificil aprenderlo ., porque no se integra a aquellos que bien podrian usar estos equipos sin DMX
Te pido mil perdones si en algo te confundi y a causado tu enojo .,no es esa mi intencion .,  aca te pongo  la compilacion nueva  
Código: [Seleccionar]
//#define F_CPU 8000000
#include<util\delay.h>

#include<stdio.h>
#include<stdlib.h>
#include"fading_raibow.h"
#include <avr/interrupt.h>  
#include <avr/wdt.h>
 // *** establecer valor de WHILE  ***//
enum {FALSE=0, TRUE=1};
//*********************************//  
uint8_t count= 1; // contador del soft PWM
uint8_t velocidad,Rojo,Verde,Azul;
 
 //*********************************//
const short int arraydimmer[256]={0,   0,   1,   1,   1,   1,   1,   2, 2,   2,   2,   3,   3,   3,   4,   4, 4,   5,   5,   5,   6,   6,   7,   7, 8,   8,   9,   9,  10,  10,  11,  11, 12,  12,  13,  13,  14,  14,  15,  15, 16,  16,  17,  17,  18,  18,  19,  19, 20,  20,  21,  21,  22,  22,  23,  23, 24,  24,  25,  25,  26,  27,  28,  29, 30,  30,  31,  32,  33,  34,  35,  36, 36,  37,  38,  39,  40,  41,  42,  43, 43,  44,  45,  46,  47,  48,  49,  50, 51,  52,  52,  53,  54,  55,  56,  57, 58,  59,  60,  61,  62,  63,  64,  65, 66,  67,  68,  69,  70,  71,  72,  73, 74,  75,  76,  77,  78,  79,  80,  81, 82,  83,  84,  85,  86,  88,  89,  90, 91,  92,  93,  94,  95,  96,  97,  98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 119, 120, 121, 122, 123, 124, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 144, 145, 146, 147, 149, 150, 151, 152, 154, 155, 156, 158, 159, 160, 161, 162, 164, 165, 167, 168, 169, 171, 172, 173, 174, 176, 177, 178, 180, 181, 182, 184, 185, 187, 188, 189, 191, 192, 193, 195, 196, 197, 199, 200, 202, 203, 204, 206, 207, 208, 210, 211, 213, 214, 216, 217, 218, 220, 221, 223, 224, 226, 227, 228, 230, 231, 233, 234, 236, 237, 239, 240, 242, 243, 245, 246, 248, 249, 251, 252, 254, 255}; // Lo que aparece como DC_Data
volatile uint16_t DmxAddress; // Dirección inicial
volatile uint8_t DmxRxField[DMX_CHANNELS];                                    
 // ****** Temporizador de inicialización para evitar efecto estroboscópico *****//
#define OV_COUNT  14 // 161 , 7  = 0.25ms
#define OV_SIZE  161 // comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
//************* Inicialización pines / port *****************//
void init_pinouts(){                    
    #ifdef USE_DIP
 
    DDRC  = 0; // establecer DIPs
    PORTC  = 0xFF;
    DDRE  &= ~((1<<PE2)|(1<<PE1));
    PORTE |=   (1<<PE2)|(1<<PE1);
 
    #endif
    
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
PORTB = 0;
DDRE  |= (1<<PE0); //LED2 azul indicador
     PORTE = 0;
    }    
// ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}

 // ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
 
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
Temp=  // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // MODO : ON FADING / OFF RAINBOW_FADER
    {
mode= FADING;
}else{
mode= RAINBOW_FADER;

    }
return;
}
mode=DMX; // funcionamiento en DMX
Temp=
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128) +
(!(PINE &(1<<PE2)) *256);
 
 
if (Temp != 0)
{
DmxAddress= Temp;

}
 
#endif
}
        
   int main(void)
     {
 //***** Watchdog *****//
wdt_reset();
wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
wdt_reset();
cli();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
    
sei();    // habilitar las interupciones globales  ???
int PWM_timer;  // inicializar el timer PWM
 while(1) // bucle principal (LOOP)
   {

        get_dips(); // Comprobar dip-switch y habilitar la funcion

     for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado
{
if (DmxRxField[0]>PWM_timer) //red
{
PORTB &= ~(1<<PB0); //LED OFF
}else{
PORTB |= (1<<PB0); //LED ON
}
 
if (DmxRxField[1]>PWM_timer)        //green
{
PORTB &= ~(1<<PB1); //LED OFF
}else{
PORTB |= (1<<PB1); //LED ON
}
 
if (DmxRxField[2]>PWM_timer)        //blue
{
PORTB &= ~(1<<PB2); //LED OFF
}else{
PORTB |= (1<<PB2); //LED ON
}
// if(!PINC6){ fading();}
    // if(!PINC5){ disco();}
     /*
     Aca mas codigo que realmente no influye en nada
     */
    }
    
      void delay(uint8_t Velocidad) {
        
     uint16_t tiempo;
     switch((PINE&0x06))
     {
     case 0x00:
     tiempo=((362 * (velocidad-1)+3)/1000);
     _delay_ms(tiempo);
     break;
     case 0x02:
     tiempo=((568 * (velocidad-1)+3)/1000);
     _delay_ms(tiempo);
     break;
     case 0x04:
     tiempo=((1430 * (velocidad-1)+3)/1000);
     _delay_ms(tiempo);
     break;
     case 0x06:
     tiempo=((2287 * (velocidad-1)+3)/1000);
     _delay_ms(tiempo);
     break;
     }
    }  
    
    void fading() {
    
     Velocidad = 127;
    
     while(!PINC6)
     {
     Rojo = 255;
     Verde = 0;
     Azul = 0;
    
     DimmerCurva();
     PORTE &= ~(1<<PE0);
    
     //rojo_amarillo
     while(Verde!=255 && !PINC6)
     {
     if(PINC7) { rainbow_fader();}
     delay(velocidad);
     PORTE |= (1<<PE0);
     Verde++;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
    
     //amarillo_verde
     while(Rojo && !PINC6)
     {
     if(PINC7) { rainbow_fader();}
     delay(velocidad);  //esperar
     PORTE |= (1<<PE0);
     Rojo--;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
    
     //verde_cyan
     while(Azul!=255 && !PINC6)
     {
     if(PINC7) { rainbow_fader();}
     delay(velocidad);  //esperar
     PORTE |= (1<<PE0);
     Azul++;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
    
     //cyan_azul
     while(Verde && !PINC6)
     {
     if(PINC7) { rainbow_fader();}
     delay(velocidad);  //esperar
     PORTE |= (1<<PE0);
     Verde--;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
    
     //azul_magenta
     while(Rojo!=255 && !PINC6)
     {
     if(PINC7) { rainbow_fader();}
     delay(velocidad);  //esperar
     PORTE |= (1<<PE0);
     Rojo++;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
    
     //magenta_rojo
     while(Azul && !PINC6)
     {
     if(PINC7) { rainbow_fader();}
     delay(velocidad);  //esperar
     PORTE |= (1<<PE0);
     Azul--;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
     }
    }
    
  //  void delay (int velocidad) {
    
    // delay_ciclos();  // La cantida de ciclos va a depender de los siwthc que estan conectados a PINE2 y PINE1
     // Si podes simularlo con velocidad = 1 para saber que valor tenes que multiplicar a velocidad, es por que no se la cantidad de ciclos que consume cada instruccion
    
    //temp2 = 1  si PINE1 = 0 sino temp2=2
    //temp1 = 64 si PINE2 = 0 sino temp1=255
    
    /*
    
    Ciclos a esperar
    
    temp2=1 temp1=255
    11445 * (velocidad-1) +28
    
    temp2=1 temp1=64
    2895 * (velocidad -1) +28
    
    temp2=2 temp1=255
    18303 * (velocidad-1) +28
    
    temp2=2 temp1=64
    4551 * (velocidad-1) +28
    */
    }
    
    
    void rainbow_fader();{
    
     int Temp_R,Temp_A,Temp_V;
     Velocidad = 254;
     Temp_R = Rojo;
     Temp_A = Azul;
     Temp_V = Verde;
    
     while(PINC7)
     {
     Rojo = 255;
     Verde = 0;
     Azul = 0;
     DimmerCurva();
     PORTE &= ~(1<<PE0);
    
     //rojo_verde
     while(Verde!=255 && PINC7)
     {
     delay(velocidad);
     PORTE |= (1<<PE0);
     Rojo--;
     Verde++;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
    
     //verde_azul
     while(Azul!=255 && PINC7)
     {
     delay(velocidad);
     PORTE |= (1<<PE0);
     Verde--;
     Azul++;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
    
     //azul_rojo
     while(Rojo!=255 && PINC7)
     {
     delay(velocidad);
     PORTE |= (1<<PE0);
     Azul--;
     Rojo++;
     DimmerCurva();
     }
     PORTE &= ~(1<<PE0);
     }
    
     Rojo = Temp_R;
     Azul = Temp_A;
     Verde = Temp_V;
    
    }
    
    void DimmerCurva(){
    
     DmxRxField[0]=arraydimmer[Rojo];
     DmxRxField[1]=arraydimmer[Verde];
     DmxRxField[2]=arraydimmer[Azul];
     }
     if (count == 0xFF)
  { // Llamado con 122Hz
  count= 1;
 
  }
      else count++;
       }
// }

 //***** inicio del ocilador Temporizador de interrupción ****//
 ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case RAINBOW_FADER :
count = OV_COUNT + DmxAddress;
break;
case FADING :
count = OV_COUNT + DmxAddress * 10;
break;
default:
count = OV_COUNT;
}
if(timer_counter>=count){
timer_counter=0;

if (mode==FADING){

}
 
}else{ timer_counter++; }

{

}
}

tambien la libreria .H
Código: [Seleccionar]
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define  USE_DIP
#define  F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
#define DMX_CHANNELS    (14)  
enum {RAINBOW_FADER,FADING,DMX,} mode;
//


extern void    get_dips(void);


y estos son los eerores que me larga tan solo 4 ., que creo que seria cuestion de redefinir las formas (creo)
Código: [Seleccionar]
Build started 24.8.2015 at 20:39:54
avr-gcc.exe  -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99       -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT fading_raibow.o -MF dep/fading_raibow.o.d  -c  ../fading_raibow.c
../fading_raibow.c: In function 'fading':
../fading_raibow.c:166: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:166: error: (Each undeclared identifier is reported only once
../fading_raibow.c:166: error: for each function it appears in.)
../fading_raibow.c:174: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:180: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c: In function 'main':
../fading_raibow.c:272: warning: conflicting types for 'rainbow_fader'
../fading_raibow.c:180: warning: previous implicit declaration of 'rainbow_fader' was here
../fading_raibow.c:275: error: 'Velocidad' undeclared (first use in this function)
../fading_raibow.c:291: warning: implicit declaration of function 'delay'
make: *** [fading_raibow.o] Error 1
Build failed with 4 errors and 5 warnings...
[/code ]
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 25 de Agosto de 2015, 04:47:36
Primero que nada pedirte disculpas si me excedi de tono.
Me encontre confundido, por que un tema es el codigo del primer post, y el otro es el codigo que me pasaste.

El codigo del primer post es de DMX pero que yo realmente no tengo la menor idea de como es el DMX. Por eso simplemente me limite a modificar la salida luego de estudiar el codigo por encima.
Es mas en el primer codigo todo lo de DMX esta en una libreria que no se incluye.

Por otro lado el codigo que me pasaste hace uso de un PWM por software tal cual lo hace el primer codigo,  no hay libreria ni se aplica DMX, y pense que tu problema era que no podias pasar el programa de ASM a C.
El principal desencuentro que tuvimos es que vos pensabas agruparlo con el DMX y yo seguia pensando en el programa tal como estaba (Solamente PWM por soft). Entonces mientras vos ibas para un lado yo iba para el otro. Uno intentaba hacer una cosa y el otro otra.

Como no se DMX, nunca lo use, aunque no creo que sea complicado no puedo ayudarte mucho en esa parte, por eso mismo me limite a pasar el codigo de ASM a C. Con lo cual te voy a poder ayudar a resolver algunas dudas, pero no voy a poder con todas.

Citar
sigo sin poder entender las "case " con valores exadecimales ., (no entiendo a que puertos se refiere ni a que BITS afecta

switch((PINE&0x06))

PINE & 0000 0110

Ejemplo si PINE es 1010 0101 al hacerle una AND con 0000 0110 queda:

1010 0101
0000 0110
--------------
0000 0100

Es decir solo dejo los pines PINE1 y PINE2, los valores de esa operacion (recorda que una AND con un 0 logico es 0 siempre, y una AND con 1 logico es 1 o 0 segun el estado que tenia) puede darme 4 formas
0000 0000 - Caso que PINE1=0 y PINE2=0 - En hexa 0x00 - case 0x00
0000 0010 - Caso que PINE1=1 y PINE2=0 - En hexa 0x02 - case 0x02
0000 0100 - Caso que PINE1=0 y PINE2=1 - En hexa 0x04 - case 0x04
0000 0110 - Caso que PINE1=1 y PINE2=1 - En hexa 0x06 - case 0x06

Los demas bits quedan en 0 por que al hacerle justamente una AND van a quedar en 0 sea cual fuese su valor anterior.

Citar
En cuanto al "FOR" del PWM ., si no lo coloco ., no me funciona con los potenciometros virtuales de DMX ( DmxRxField[DMX_CHANNELS] )

Es por que seguro que tenes mal hecho el codigo. Como te digo no podes tener un for ahi, un for es muy aleatorio en tiempos, a pesar que pueda parecer un PWM por soft no lo es, es muy inconsistente. Yo imagino a DMX como algo que le envia los valores y el micro debe usar esos valores. Si vamos a que se necesita un PWM por software no podes tenerlo en el main, vuelvo a repetir que es un error de concepto/implementacion, deberias tenerlo en la interrupcion ( para eso es esa interrupcion, me refiero a la del timer ) y sin for() obviamente.

Citar
En cuanto a la asignacion de pines en PINUT esta corecta ( tengo que declara asi para que funciona las llaves y no podria ir nunca un ELSE ., porque los otros puertos que estan declarados alli son la salida y trabajan al mismo tiempo

Tal ves me confundi con eso, al ver los 2 valores asignados a un mismo registro me parecio que habias cometido un error. Estoy mas acostumbrado a ver algo como:

Código: C
  1. #ifdef xxxx
  2.     //conf Puertos si tuviera DIP
  3. #else
  4.     //conf de Puertos si no tuviera DIP
  5. #endif
Tal ves un poco de locura de parte mia

Citar
, estas sentencias V_out,R_out,A_out;  las cambie por estas  DmxRxField[0] , DmxRxField[1] , DmxRxField[2]

Ahi hay un error, en si todo el programa como creo que vos dijiste es imposible aplicarlo, no se cuales son las entradas de datos de DMX, ya que el fading modifica siempre esos valores que luego son usados en el PWM por soft. los colores ya estan preseleccionados en el codigo, es decir no tenes ninguna "variable" que puedas modificar. Si vos por ejemplo queres que por DMX llegue los valores de los colores y se produzca el fading, entonces eso es una cosa distinta a lo que el codigo estaba haciendo(que me pasaste). Reemplazar lo que reemplazaste no creo que sea lo correcto.

La seleccion de modo imagino tambien que vendra por algun comando. asi que no se por que esta hecho en la interrupcion del timer.
Si llegan los datos por UART entonces deberia haber una interrupcion de la UARt y ahi producirse el cambio de modo.

Con respecto a los errores que obtuviste es por que:

Velocidad no es lo mismo que velocidad, es case-sensitive asi que para quitarlo le cambias la V mayuscula por la minuscula.

Esto te va a solucionar los errores de sintaxis, pero esto no quiere decir que el codigo funcione. Ya que como dije el codigo esta realizado para hacer una cosa y yo recien ahora me entero que estas pidiendo otra totalmente distinta.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: stk500 en 25 de Agosto de 2015, 06:13:38
yo hace tiempo leo estos mensaje y debo decir que es una sopa de letras, creo que el amigo locodelafonola no ha leido lo que es el Protocologo DMX512, el codigo en si es para hace una funcion comandada por otros DMX512 Transmisor, recordar que el protocolo se compone de DMX512 Maestros y Esclavo, los Esclavos como es logico reciben Comando del Maestros , pero hay casos Tambien donde el Maestros hace las dos funciones.
Esta imagen le ha dado la vuelta a internet para aquellos que desconocen el protocologo.
(http://www.todopic.com.ar/foros/imgtiny/28ire54.jpg)
El amigo locodelafonola quiere cambiar un protocologo que no tiene nada que ver con DMX512 y es por eso que he dicho que abra un temas nuevos en el Subforo correspondiente.
Amigo Killerjc como ver en la imagen no es nada dificil y si te fija de algunos projectos de DMX512 en este Subforos lo Capta enseguidas.
otras aclaracion el Master o lo que hacen DMX512 como Maestros , programan la mesa con muchas secuencias de comandos.
Espero que me hayan comprendido. ;-)
Saludos
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 25 de Agosto de 2015, 15:18:24
Gracias stk500, yo me imaginaba algo asi. Ya que en fin era recibir un dato y hacer algo con ese dato. Sea cual sea el protocolo eso no cambiaba.
No tenia claro como es que se enviaba.
Por cierto aca el AN
http://ww1.microchip.com/downloads/en/AppNotes/01076A.pdf


Ya con eso me queda claro cuales son los valores de dimming. Es decir con la direccion que se le asigna al receptor este toma el byte que le corresponde de la trama (512bytes).
Ahora como es que se pueden enviar 3 valores o por ejemplo elegir el modo. Ejemplo yo quisiera elegir los 3 valores de RGB y elegir entre fading/fijo/rainbow_fading , como se discriminan los comandos ( como para cambiar el modo ) y los 3 datos de los colores?

O se envian todos en secuencia

512bytes con el comando
512bytes con  R
512bytes con  G
512bytes con  B

Asi ? y eso se repite ?

O los 512 bytes pertenece a un solo receptor y el Start Code es el que selecciona el "esclavo(receptor)" ?
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 25 de Agosto de 2015, 16:11:45
hola y gracias de nuevo
yo hace tiempo leo estos mensaje y debo decir que es una sopa de letras, creo que el amigo locodelafonola no ha leido lo que es el Protocologo DMX512, el codigo en si es para hace una funcion comandada por otros DMX512 Transmisor, recordar que el protocolo se compone de DMX512 Maestros y Esclavo, los Esclavos como es logico reciben Comando del Maestros , pero hay casos Tambien donde el Maestros hace las dos funciones.
Esta imagen le ha dado la vuelta a internet para aquellos que desconocen el protocologo.
(http://www.todopic.com.ar/foros/imgtiny/28ire54.jpg)
El amigo locodelafonola quiere cambiar un protocologo que no tiene nada que ver con DMX512 y es por eso que he dicho que abra un temas nuevos en el Subforo correspondiente.
Amigo Killerjc como ver en la imagen no es nada dificil y si te fija de algunos projectos de DMX512 en este Subforos lo Capta enseguidas.
otras aclaracion el Master o lo que hacen DMX512 como Maestros , programan la mesa con muchas secuencias de comandos.
Espero que me hayan comprendido. ;-) Saludos

a ver ., yo creo a mi entender que alli esta el problema de todo esto  
yo no se si no me explico bien o no me hago enteder .,YO NO QUIERO CAMBIAR EL PROTOCOPLO DMX 512 .,¿¿¿ donde escribi eso o donde lo pedi ????
Yo lo que pedi es pasar esas funciones de comando manual a DMX
no entiendo cual es el enpecinamiento en confundir las cosas ., si lo plantie bien claro ., primero que funcione en MNUAL (llaves mini-dips) y luego en DMX
aca esta el  link  del proyecto de mi libreria  
http://www.ledstyles.de/index.php/Thread/3928-Rainbow-Fader-mit-Zusatzfunktionen-Neu-mit-Dimmerkurve/?pageNo=1&s=bb5cd6c43d7e00c4ba4095728791824bd3ec56ae
alli se nita claramente en una foto el montaje DMX de  Hendrik Hoelscher
(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=44880.0;attach=24311;image)
y aclaremos algo ., ¿¿¿¿ como puedo usar la funcion de MAESTRO en STANDALONE ., si no tengo nada para enviar ???
Esto es programaion DMX ., donde se tiene que respetar ciertos parametros para que funcione
Yo al poner la llave mini-dips N° 10 en ON desabilito la recepcion .,  y habilito la trasmicion (obiamente hay que colocar una instruccion como init_DMX_RX();  aca muestro las librerias que tengo
Esta es la  lib_dmx_out.C
Código: [Seleccionar]
/**** A P P L I C A T I O N   N O T E   ************************************
*
* Title : DMX512 transmission library
* Version : v1.1
* Last updated : 30.07.07
* Target : Transceiver Rev.3.01 [ATmega8515]
* Clock : 8MHz, 16MHz
*
* written by hendrik hoelscher, www.hoelscher-hi.de
***************************************************************************
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version2 of
 the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 General Public License for more details.

 If you have no copy of the GNU General Public License, write to the
 Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 For other license models, please contact the author.

***************************************************************************/

#include "globals.h"
#include "lib_dmx_out.h"

// ********************* local definitions *********************
uint16_t gCurDmxCh; //current DMX channel

#define TX_BRK  (0xFFFF)
#define TX_SC (0)
#define TX_DATA (1)


// *************** DMX Reception Initialisation ****************
void init_DMX_TX(void)
{
//Ports
DDRD  |= (1<<2)|(1<<1);
PORTD |= (1<<2)|(1<<1); //enable transmission

//USART
UBRRH  = 0;
UBRRL  = ((F_OSC/4000)-1); //250kbaud, 8N2
UCSRC  = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB  = (1<<TXEN)|(1<<TXCIE);
UDR    = 0; //start USART

//Data
gCurDmxCh= TX_BRK; //start with break
}



// ****************** DMX Transmission ISR ********************

ISR (UART_TX_vect)
{
uint16_t DmxCh= gCurDmxCh;

if (DmxCh == TX_BRK) //start break
{
UBRRH  = 0;
if (Flags &(1<<SLOW_TX))
{
UBRRL  = 17;
}
else
{
UBRRL  = 9;
UCSRC  = (1<<URSEL)|(3<<UCSZ0); //8n1
}
UDR    = 0; //send break
gCurDmxCh= TX_SC;
}
else if (DmxCh == TX_SC)
{
UBRRH  = 0;
UBRRL  = ((F_OSC/4000)-1); //250kbaud
UCSRC  = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UDR    = 0; //send start byte
gCurDmxCh= TX_DATA;
}
else
{
if (Flags &(1<<SLOW_TX))
{
_delay_us(20); //inter byte gap in slow mode
}

if (DmxCh &(1<<0)) UDR=  TxVal; //send data
else   UDR= (0xFF -TxVal);

gCurDmxCh++;
if (Flags &(1<<SLOW_TX))
{
if (DmxCh == 511) gCurDmxCh= TX_BRK;
}
else
{
if (DmxCh == 48)  gCurDmxCh= TX_BRK;
}
}
}

esta es la lib_dmx_out.H
Código: [Seleccionar]
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>


volatile uint8_t TxVal; //array of DMX vals


extern void init_DMX_TX(void);
 
Ahora bien.,  si se sigue pensando que la programacion de standalone ., no tiene que seguir los protocolos DMX ., !!! alli esta el error ¡¡¡¡
Eso por el lado de la trasmicion ., por el lado de la recepcion ¿¿¿ qque pasaria si yo coloco esta intruccion dentro del WHILE(es donde trabaja el programa sin salir de alli ) ejemplo :  
Código: [Seleccionar]
  if (DmxRxField[3]> 10 < 255)    // comando del FADING
{
int FADING;    // inicio del fading

}
 
if (DmxRxField[4]> 10 < 255)    // comando del RAINBOW_FADER
{                                                                                                      int RAINBOW_FADER;              // inicio del rainbow_fader

}
Tal vez.,  las sentencias esten mal definidas en sus formas pero .,en si tendria que funcionar ., de hecho he probado experimentalmente algo parecido y funciono
Y para aclarar ., el protocolo DMX512 creo que lo entiendo bien (puedo estar equivocado porque aprendi solo )., aca la cuestion es ., hacer funcionar algo y que respete los lineamientos del protocolo de trasmicion y recepcion DMX 512 ., SIN CAMBIAR EL PROTOCOLO
sigo sin entender lo de los numeros binarios y exadecimales
Tambien el hecho de que no se cambien los PIN / PORT PE1 y PE2 ., esos no se pueden usar ., porque me imposibilita el uso de el DMX ., tengo sin usar los puertos con las llaves desde el PC0 a PC7
SI fuera el caso como esto ( esta mal porque no entiendo de alli mi confucion ) ejemplo :
Código: [Seleccionar]
 void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
 
if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER /DMX OUT
              init_DMX_RX();     Temp=  // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) 362 * (velocidad-1)+3)/1000)+
(!(PINC &(1<<PC1)) 568 * (velocidad-1)+3)/1000)+
(!(PINC &(1<<PC2)) 1430 * (velocidad-1)+3)/1000)+
(!(PINC &(1<<PC3)) 2287 * (velocidad-1)+3)/1000)+
(!(PINC &(1<<PC4)) *0) +
(!(PINC &(1<<PC5)) *0) +
(!(PINC &(1<<PC6)) *0) +
(!(PINC &(1<<PC7)) *0);
DmxAddress= Temp=_delay_ms(tiempo);
if (!(PINE &(1<<PE2))) // MODO : ON FADING / OFF RAINBOW_FADER
    {
mode= FADING;
}else{
mode= RAINBOW_FADER;
UCSRB &= ~(1<<RXCIE);// Receptor Desactivar si la dirección de inicio = 0     }
return;
}
mode=DMX; // funcionamiento en DMX
Temp=
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128) +
(!(PINE &(1<<PE2)) *256);
 
 
if (Temp != 0)
{
DmxAddress= Temp;

} telf oca 0260 442-5403
  
Y alli agregue (que no viene al caso., de lo que tratamos ) como se habilita la trasmicion y como se desabilita la recepcion ( con el pin PD0) algo que muchos no toman en cuenta ., pero eso es otra historia
Como dije puede ser que este mal la definicion ., en cuanto a funcion velocidad
estuve viendo que se ha compilcado mucho al no entenderme  
Entonces pence .,  que como uso el atmega 8515-16pu ., tengo los puertos libres de A (estan al lado de los puertos E y C colocar aunque sea dos llaves mini-dips alli
el problema que tengo es que no tengo mas llaves mini_DIPS disponibles (aca en mi pueblo no se consiguen ., solo en Bs.As)
Pero buendo dejando de lado  las llaves.,  como veras tampoco me compila .,ni siquiera copiando textualmemte lo  que diseñaste
si le prestas atencion ., a la compilacion que hice esta todo declarado ., igual asi maraca error ., no sera que la funcion velocidad tendria que tener un INIT aparte
como no se ASM ., no me doy cuenta ., si influye algo mas .,  de la compilacion original
en cuanto al autor aca hay un video de lo que hace
http://www.noisepop.de/led-forum/RGB-Fader/Rainbow-Fader-3.mov hola
Gracias stk500, yo me imaginaba algo asi. Ya que en fin era recibir un dato y hacer algo con ese dato. Sea cual sea el protocolo eso no cambiaba.
No tenia claro como es que se enviaba.
Por cierto aca el AN
http://ww1.microchip.com/downloads/en/AppNotes/01076A.pdf


Ya con eso me queda claro cuales son los valores de dimming. Es decir con la direccion que se le asigna al receptor este toma el byte que le corresponde de la trama (512bytes).
Ahora como es que se pueden enviar 3 valores o por ejemplo elegir el modo. Ejemplo yo quisiera elegir los 3 valores de RGB y elegir entre fading/fijo/rainbow_fading , como se discriminan los comandos ( como para cambiar el modo ) y los 3 datos de los colores?

O se envian todos en secuencia

512bytes con el comando
512bytes con  R
512bytes con  G
512bytes con  B

Asi ? y eso se repite ?

O los 512 bytes pertenece a un solo receptor y el Start Code es el que selecciona el "esclavo(receptor)" ?
bueno se envian en secuencia pero quedate tranquilo ., empieza en el 1 DmxRxField[0] , 2 DmxRxField[1] ., 3 DmxRxField[2], la informacion llega desde la consola por la USART.,  del circuito integrado y se aloja en esta variable  uint8_t DmxBuf[DMX_CHANNELS]; (
alli manejamos el valor del bufer total recibido (RAW) ., pero  estan separados  por (de un dmxchanel o otro dmxchanel ) por dos bit de para (que se ve en la trama que mostro STK500 )
tambien esta defino por la cantidad de canales que recibo de acuerdo alas funciones por esta variable  #define DMX_CHANNELS    (5 ) ., que serian en este caso R,G,B, fading y rainbow-fader
aver site aclro un poco ., en un universo de 512 canales se envia la trama des 0 a 511 ., pero en cada canal el valor maximo es 255
ejemplo : el primer canal es la direcion de inicio ., la menor que puede se es 1 (el cero se reserva para desabilitacion de recepcion ) ., a partir de alli tenemos nuestros 5 canales que son los que manejamos  
si tuvieramos otro equipo en la serie(dentro del mismo universo de 512) se tendria que colocar la direccion de inicio en 6 y luego vendrian los 5 canales que se usan y asi susesivamente
Pero quedate tranquilo ., que con eso no estamos trabajando ., lo que hice fue enparejar los comandos para que funcionen en las dos maneras (o al menos el intento  d hacerlo)
la verdad que si funciona lo vamos a saber en lo fisico., cuando lo pueda probar
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: stk500 en 25 de Agosto de 2015, 16:17:51
Hola KillerJC,
Las mesas de luces DMX512 algunas llevan muchos parametros para tu asignar a cada canal diferente comandos o individual o en grupos,
por ejemplo, luz que caminan, Flashig,Strobos, secuenciales y un sin fin, para implementar todos esos necesitas de un micro que tenga muchas RAM y claro EEprom para almacenar los parametros.
lo unico que he hecho yo como mesa de luces fue muy simple, usando el ADC de un Atmega8
mira aqui
http://www.todopic.com.ar/foros/index.php?topic=37357.0
eso me llevo muchos meses de trabajos y investigacion ya que nunca lo habia hechos.
para que tenga mas ideas de todos lo que te digo mira esta
estos esta hechos con el programa Madrix.
Saludos
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 25 de Agosto de 2015, 16:36:16
Bueno para solucionar todo esto..

locodelafonola

Explicame exactamente que necesitas que haga el programa. El efecto de fading esta. Ahora hay que unirlo al DMX, por eso necesito que me expliques como queres hacerlo.

Nombreame uno por uno los parametros que llegan, ejemplo:

DmxRxField[0] -> Modo, de 0 a 120 fijo, de 121 a 255 fading
DmxRxField[1] -> Color R
DmxRxField[2] -> Color G
......

Se que son 512 pero no creo que uses 512 para esto al menos por ahora.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 25 de Agosto de 2015, 17:07:11
Bueno para solucionar todo esto..

locodelafonola

Explicame exactamente que necesitas que haga el programa. El efecto de fading esta. Ahora hay que unirlo al DMX, por eso necesito que me expliques como queres hacerlo.

Nombreame uno por uno los parametros que llegan, ejemplo:

DmxRxField[0] -> Modo, de 0 a 120 fijo, de 121 a 255 fading
DmxRxField[1] -> Color R
DmxRxField[2] -> Color G
......

Se que son 512 pero no creo que uses 512 para esto al menos por ahora.
bueno alli me gusta la cosa
DmxRxField[0] , DmxRxField[1],DmxRxField[2], dejalos como estan ., ( DmxRxField[0] ., es elcanal rojo y ya lo cambiaste).,  lo qu hay que hacer es habilitar uno nuevo (o dos) ejemplo : DmxRxField[3 ] -> Modo, de 0 a 120 fijo, de 121 a 255 fading  y si queres DmxRxField[4 ]-> raibonw_fader  
ya con esa simple sentecia tenes el comando del bufer de recepcion sin que declares mas nada (una vez que se finaliza y todo funciona como se debe ., se define en la libreria .H cuantos se usan y listo) como te explique mas arriba
y algo para clarar., estas fuciones que quiero aprender ., son la que tiene los "tachos" o lampara par 64 o 56 , de led comerciales 
si te sirve aca te subo lo que que me funciona a mi (bastante probado ) y funciona joya
Código: [Seleccionar]
int PWM_timer;  // inicializar el timer PWM
char strobo = FALSE;  // valor de strobo
unsigned int strobo_timer=0; // Contador Strobo igual a cero



    while(1) // bucle principal (LOOP)
    {

        get_dips(); // Comprobar dip-switch y descargar la dirección DMX


//************************************* PWM leds *********************************//
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado
{

if(DmxRxField[4]>10){ // Si el canal de luz estroboscópica es menor a  10 es siempre mayor que los LED ,el estroboscópico está apagado,
if( strobo_timer>(unsigned int)((255-DmxRxField[4])*16)){// Dmx CH4 igual a 11, es el tiempo máximo , o igual a 255 es el Tiempo min
strobo_timer=0;// Restablecer el temporizador
if(strobo){ strobo=FALSE;}else{ strobo=TRUE;} // Cambiar autorización para ILUMINACIÓN
}else{
strobo_timer+=1;
}
    }else{
strobo=TRUE; // la Stroboscopica está apagada,
}

if ( ((unsigned int)((DmxRxField[0]*DmxRxField[3])/255)>PWM_timer) && strobo ) //ROJO
{
PORTB &= ~(1<<PB2); //LED OFF
}else{
PORTB |= (1<<PB2); //LED ON
}

if ( ((unsigned int)((DmxRxField[1]*DmxRxField[3])/255)>PWM_timer) && strobo ) //VERDE
{
PORTB &= ~(1<<PB1); //LED OFF
}else{
PORTB |= (1<<PB1); //LED ON
}

   if ( ((unsigned int)((DmxRxField[2]*DmxRxField[3])/255)>PWM_timer) && strobo ) //AZUL
{
PORTB &= ~(1<<PB0); //LED OFF
}else{
PORTB |= (1<<PB0); //LED ON
    }
Tiene  los tras canales RGB , mas el DIMMERMASTER ., mas el STROBO  ., esto a mi me funciona correctamente 
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 25 de Agosto de 2015, 17:26:38
Listo los datos son:

DmxRxField[0] -> R
DmxRxField[1] -> G
DmxRxField[2] -> B
DmxRxField[3] -> Modo -> 0..63 Fijo, 64..127 Fading_Color_Fijo , 128..191 Fading Automatico, 192..255 Rainbow_Fading
DmxRxField[4] -> Velocidad

Ahora solo me queda una cosa por hacer. Pasar la funcion que es "manual" como le decis a una que use los comandos esos.

Entonces los modos van a quedar:

Fijo ->
En este modo se usan los valores RGB del DMX, ya que es el unico que realmente cumple con esa funcion

Fading Color fijo ->
En este modo se va a producir el fading pero solo del color RGB, el cual va a ser un estilo "pulsante", Unicamente en el color que se le indique desde la consola DMX. Usa el valor de Velocidad

Fading Automatico ->
En este modo va a ir alternando los colores pero no va a hacer caso a los valores RGB ya que no tiene sentido aplicarlo. Si defino solo un color de comienzo luego va a ser modificado por el mismo "fading" a no ser que quieras que sea un color unico y que se produsca el fading solo de ese color y no que vaya pasando de colores

Rainbow_Fading ->
Una extension al Fading Automatico que en ves de navegar por los colores comunes Solo R, solo G y solo B, hace uso de varios colores. Tambien hace caso a Velocidad. Pero no a RGB


En fin creo que esto es lo que buscas

La velocidad se va a controlar desde el DMX por lo cual se le quita el soporte a los DIPs sobre eso. Y PINE1/PINE2 no deberian influir en eso.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 25 de Agosto de 2015, 17:47:47
Listo los datos son:

DmxRxField[0] -> R
DmxRxField[1] -> G
DmxRxField[2] -> B
DmxRxField[3] -> Modo -> 0..63 Fijo, 64..127 Fading_Color_Fijo , 128..191 Fading Automatico, 192..255 Rainbow_Fading
DmxRxField[4] -> Velocidad

Ahora solo me queda una cosa por hacer. Pasar la funcion que es "manual" como le decis a una que use los comandos esos.

Entonces los modos van a quedar:

Fijo ->
En este modo se usan los valores RGB del DMX, ya que es el unico que realmente cumple con esa funcion

Fading Color fijo ->
En este modo se va a producir el fading pero solo del color RGB, el cual va a ser un estilo "pulsante", Unicamente en el color que se le indique desde la consola DMX. Usa el valor de Velocidad

Fading Automatico ->
En este modo va a ir alternando los colores pero no va a hacer caso a los valores RGB ya que no tiene sentido aplicarlo. Si defino solo un color de comienzo luego va a ser modificado por el mismo "fading" a no ser que quieras que sea un color unico y que se produsca el fading solo de ese color y no que vaya pasando de colores

Rainbow_Fading ->
Una extension al Fading Automatico que en ves de navegar por los colores comunes Solo R, solo G y solo B, hace uso de varios colores. Tambien hace caso a Velocidad. Pero no a RGB


En fin creo que esto es lo que buscas

La velocidad se va a controlar desde el DMX por lo cual se le quita el soporte a los DIPs sobre eso. Y PINE1/PINE2 no deberian influir en eso.
!!!!! grande maestro ¡¡¡¡ listo asi es corecto ., fijate en lo que subi en el mesaje anterior ., esas funciones no usan nada de desarrollo.,  todo lo que es .,  es lo que ves escrito  alli ., y funcionan dentro del Loop de WHILE ., no hay mas nada que eso para que te des idea ., pero como yo no se como se implementa eso del ASM sugeri lode las llaves ., pero esta bien asi eso es lo que busco GRACIAS MIL !!!!! 
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 26 de Agosto de 2015, 04:00:43
Código: C
  1. #define F_CPU 8000000
  2. #include<util\delay.h>
  3.  
  4. #include<stdio.h>
  5. #include<stdlib.h>
  6. #include"fading_raibow.h"
  7. #include <avr/interrupt.h>
  8. #include <avr/wdt.h>
  9.  
  10.  
  11. enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode;
  12.  
  13. #define OV_COUNT        14              // 161 , 7  = 0.25ms
  14. #define OV_SIZE         161             // comenzando Contador inicial
  15.  
  16. // Dato proveniente de la consola DMX
  17.  
  18. #define DMX_R                   DmxRxField[1]   //Canal R              
  19. #define DMX_G                   DmxRxField[2]   //Canal G
  20. #define DMX_B                   DmxRxField[3]   //Canal B
  21. #define DMX_Modo                DmxRxField[4]   //Seleccion de Modo
  22. #define DMX_Velocidad   DmxRxField[5]   //Seleccion de Velocidad
  23.  
  24. // Para simplificar los datos del array de colores que estoy usando.
  25. // ArrayColores contiene los valores RGB del momento
  26.  
  27. #define Rojo                    ArrayColores[0]
  28. #define Verde                   ArrayColores[1]
  29. #define Azul                    ArrayColores[2]
  30.  
  31. //*********************************//
  32.  
  33. volatile uint16_t        DmxAddress;                            // Dirección inicial
  34.  
  35. uint8_t V_out,R_out,A_out;                                              // Valores que se comparan con el PWM
  36. uint8_t V_aux,R_aux,A_aux;                                              // Valores que se cambia para actualizar el PWM
  37. uint8_t PWM_timer=0;
  38. uint8_t estado=0,estador=0;                                     // Estado de los fading
  39.  
  40. const uint8_t arraydimmer[256]={
  41.                  0,     0,    1,    1,    1,    1,    1,    2,
  42.                  2,     2,    2,    3,    3,    3,    4,    4,
  43.                  4,     5,    5,    5,    6,    6,    7,    7,
  44.                  8,     8,    9,    9,   10,   10,   11,   11,
  45.                  12,   12,   13,   13,   14,   14,   15,   15,
  46.                  16,   16,   17,   17,   18,   18,   19,   19,
  47.                  20,   20,   21,   21,   22,   22,   23,   23,
  48.                  24,   24,   25,   25,   26,   27,   28,   29,
  49.                  30,   30,   31,   32,   33,   34,   35,   36,
  50.                  36,   37,   38,   39,   40,   41,   42,   43,
  51.                  43,   44,   45,   46,   47,   48,   49,   50,
  52.                  51,   52,   52,   53,   54,   55,   56,   57,
  53.                  58,   59,   60,   61,   62,   63,   64,   65,
  54.                  66,   67,   68,   69,   70,   71,   72,   73,
  55.                  74,   75,   76,   77,   78,   79,   80,   81,
  56.                  82,   83,   84,   85,   86,   88,   89,   90,
  57.                  91,   92,   93,   94,   95,   96,   97,   98,
  58.                  99,  100,  102,  103,  104,  105,  106,  107,
  59.                  108, 109,  110,  112,  113,  114,  115,  116,
  60.                  117, 119,  120,  121,  122,  123,  124,  126,
  61.                  127, 128,  129,  130,  132,  133,  134,  135,
  62.                  136, 138,  139,  140,  141,  142,  144,  145,
  63.                  146, 147,  149,  150,  151,  152,  154,  155,
  64.                  156, 158,  159,  160,  161,  162,  164,  165,
  65.                  167, 168,  169,  171,  172,  173,  174,  176,
  66.                  177, 178,  180,  181,  182,  184,  185,  187,
  67.                  188, 189,  191,  192,  193,  195,  196,  197,
  68.                  199, 200,  202,  203,  204,  206,  207,  208,
  69.                  210, 211,  213,  214,  216,  217,  218,  220,
  70.                  221, 223,  224,  226,  227,  228,  230,  231,
  71.                  233, 234,  236,  237,  239,  240,  242,  243,
  72.                  245, 246,  248,  249,  251,  252,  254,  255
  73. };
  74.  
  75. uint8_t ArrayColores[3]={255,0,0};                      // Rojo,Verde,Azul
  76.  
  77. const uint8_t ArrayColorFading[]={                      // Indice y valor a modificar   {1,2,3} y {-1,-2,-3}
  78.                  1,     //      Rojo    ->      Amarillo
  79.                  0,     //      Amarilo ->      Verde
  80.                  2,     //      Verde   ->      Cyan
  81.                  1,     //      Cyan    ->      Azul
  82.                  0,     //      Azul    ->      Magenta
  83.                  2      //      Magenta ->      Rojo
  84. };
  85.  
  86. const uint8_t ArrayColorFadingRainbow[]={                       // Indice y valor a modificar   {Resta,Suma}
  87.                 {0,1},  //      Rojo-   ->      Verde+
  88.                 {1,2},  //      Verde-  ->      Azul+
  89.                 {2,0}   //      Azul-   ->      Rojo+
  90. };
  91.  
  92. //************* Inicialización pines / port *****************//
  93. void init_pinouts(){
  94.     #ifdef USE_DIP
  95.  
  96.     DDRC  = 0;                  // establecer DIPs
  97.     PORTC  = 0xFF;
  98.     DDRE  &= ~((1<<PE2)|(1<<PE1));
  99.     PORTE |=   (1<<PE2)|(1<<PE1);
  100.         #endif
  101.  
  102.  
  103.         DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
  104.         PORTB = 0;
  105.         DDRE  |= (1<<PE0);      //LED2 azul indicador
  106.     PORTE = 0;
  107.  
  108. }
  109.  
  110. // ***** inicializacion del timer****//
  111.  
  112. void init_timer(){
  113.                 TCCR0|= (1<<CS02) ;     // Precontador 256
  114.                 TIMSK|= (1<<TOIE0);     // desbordamientos de la interrupción
  115.                 TCNT0= OV_SIZE;
  116.         }
  117.  
  118.  // ************* obtener DMX dirección de inicio **************
  119.  
  120. void get_dips(void)
  121. {
  122. #ifdef USE_DIP
  123. uint16_t Temp;
  124.  
  125. if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
  126.         Temp=                     // DMXAdress = tiempo de retardo
  127.                 (!(PINC &(1<<PC0)) *1) +
  128.                 (!(PINC &(1<<PC1)) *2) +
  129.                 (!(PINC &(1<<PC2)) *4) +
  130.                 (!(PINC &(1<<PC3)) *8) +
  131.                 (!(PINC &(1<<PC4)) *16) +
  132.                 (!(PINC &(1<<PC5)) *32) +
  133.                 (!(PINC &(1<<PC6)) *64) +
  134.                 (!(PINC &(1<<PC7)) *128);
  135.         DmxAddress= Temp;
  136.         if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
  137.              {
  138.                 mode= FADING;
  139.         }else{
  140.                 mode= RAINBOW_FADER;
  141.  
  142.              }
  143.                 return;
  144.         }
  145. //mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
  146. //Temp=
  147. //      (!(PINC &(1<<PC0)) *1) +
  148. //      (!(PINC &(1<<PC1)) *2) +
  149. //      (!(PINC &(1<<PC2)) *4) +
  150. //      (!(PINC &(1<<PC3)) *8) +
  151. //      (!(PINC &(1<<PC4)) *16) +
  152. //      (!(PINC &(1<<PC5)) *32) +
  153. //      (!(PINC &(1<<PC6)) *64) +
  154. //      (!(PINC &(1<<PC7)) *128) +
  155. //      (!(PINE &(1<<PE2)) *256);
  156.  
  157.  
  158. //if (Temp != 0)
  159. //      {
  160. //      Address= Temp;
  161.  
  162. //      }
  163.  
  164. #endif
  165. }
  166.  
  167. int main(void)
  168. {
  169.  //***** Watchdog *****//
  170.         wdt_reset();
  171.         wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
  172.         wdt_reset();
  173.         cli();
  174.         init_pinouts(); // Establecer los puertos de E / S
  175.         init_timer();   // Establecer el temporizador
  176.        
  177.         mode = FIXED;           //Valores iniciales, hasta que llegue la trama del DMX
  178.         Rojo = 0;
  179.         Verde = 0;
  180.         Azul = 0;
  181.        
  182.         sei();              // habilitar las interupciones globales  ???
  183.  
  184.         while(1)        // bucle principal (LOOP)
  185.             {
  186.                 get_dips();     // Toma la direccion y la actualiza, esto es para no tener que reiniciar a cada rato el DMX
  187.                 switch(mode)
  188.                 {
  189.                 case FIXED:
  190.                                 Rojo = DMX_R;           // Colores tomados directamente del DMX para fijo
  191.                                 Verde = DMX_G;
  192.                                 Azul = DMX_B;
  193.                                 DimmerCurva();          // Actualizo colores para el PWM
  194.                                 break;
  195.                 case FADING_FIX:
  196.                                 fading_fijo();
  197.                                 break;
  198.                 case FADING:
  199.                                 fading_auto();
  200.                                 break;
  201.                 case RAINBOW_FADING:
  202.                                 rainbow_fader();
  203.                                 break;
  204.                 default:
  205.                                 break;
  206.                 }
  207.             }
  208. }
  209.  
  210. void fading_fijo(){
  211.  
  212. }
  213.  
  214.  
  215.  
  216. void fading_auto(){
  217.  
  218.                 // Valores iniciales seteados cuando se cambia de modo
  219.        
  220.                 //Espera
  221.                 delay(DMX_Velocidad);  //esperar
  222.                 //Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
  223.                 if(estado%2)
  224.                 {       //Caso impar
  225.                         if(++ArrayColores[estado]==255) estado++;
  226.                 }
  227.                 else
  228.                 {       //Caso par
  229.                         if(--ArrayColores[estado]==0) estado++;
  230.                 }
  231.                 if(estado>=6) estado=0;
  232.                 DimmerCurva();
  233. }
  234.  
  235. void rainbow_fader(){
  236.  
  237.         int Temp_R,Temp_A,Temp_V;
  238.         Temp_R = Rojo;
  239.         Temp_A = Azul;
  240.         Temp_V = Verde;
  241.  
  242.         if (estador==0){                                                                                                        //Caso inicial, Para que comienze con los valores que debe
  243.                 Rojo = 255;
  244.                 Verde = 0;
  245.                 Azul = 0;
  246.         }
  247.         DimmerCurva();
  248.  
  249.                 ArrayColores[ArrayColorFadingRainbow[estador][1]]++;                            //Sumo
  250.                 ArrayColores[ArrayColorFadingRainbow[estador][0]]--;                            //Resto
  251.                 if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++;       //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
  252.  
  253.         Rojo = Temp_R;
  254.         Azul = Temp_A;
  255.         Verde = Temp_V;
  256.        
  257.                 if(estador>=3) estador=0; fading_auto();                                                        //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
  258.  
  259. }
  260.  
  261. void DimmerCurva(){
  262.  
  263.         R_aux=arraydimmer[Rojo];
  264.         V_aux=arraydimmer[Verde];
  265.         A_aux=arraydimmer[Azul];
  266. }
  267.  
  268. void delay(uint8_t DMX_Velocidad) {
  269.  
  270.         // Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
  271.         // Tiempo Minimo = 3us
  272.         // Tiempo Maximo = 580ms
  273.         // Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
  274.        
  275.         uint16_t tiempo;
  276.         if (DMX_Velocidad>127)
  277.         {       //Tiempo en milisegundos, Recta de 1ms a 508ms
  278.                 tiempo = 4*DMX_Velocidad - 511;
  279.                 //_delay_ms(tiempo);
  280.         }
  281.         else
  282.         {       //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
  283.                 tiempo = 7*DMX_Velocidad +3;
  284.                 //_delay_us(tiempo);
  285.         }
  286. }
  287.  
  288.  
  289.  //***** inicio del ocilador Temporizador de interrupción ****//
  290.  void ISR(TIMER0_OVF_vect){
  291.  
  292.         if (R_out>=PWM_timer) { salida &= 0x06; }
  293.         if (V_out>=PWM_timer) { salida &= 0x05; }
  294.         if (A_out>=PWM_timer) { salida &= 0x03; }
  295.         if (PWM_timer==255)
  296.         {
  297.                 //Cargo los colores nuevos ya que finalizo el ciclo del PWM
  298.                 R_out = R_aux;
  299.                 V_out = V_aux;
  300.                 A_out = A_aux;
  301.                 //Observo si se cambio el modo, asi cambio el modo y seteo los valores iniciales de ser necesario
  302.                 Cambiarmodo();
  303.         }
  304.         PWM_timer++;
  305. }
  306.  
  307.  void Cambiarmodo(){
  308.          switch(DMX_Modo&0xC0)  // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
  309.          {
  310.          case 0xC0:                                             //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
  311.                  if(mode!=RAINBOW_FADING)       //Reviso que ya no este en este modo.
  312.                  {
  313.                          mode=RAINBOW_FADING;
  314.                          Rojo=255;                              // Set de colores iniciales            
  315.                          Verde=0;
  316.                          Azul=0;
  317.                          estado=0;                              // Set de estado inicial para el fading
  318.                          estador=0;                             // Set de estado inicial para el rainbow_fading
  319.                  }
  320.                  break;
  321.          case 0x80:                                             //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
  322.                  if(mode!=FADING)                       // Si ya esta en el modo, que no lo modifique.
  323.                  {
  324.                          mode=FADING;
  325.                          Rojo=255;                              // Set de colores iniciales            
  326.                          Verde=0;
  327.                          Azul=0;
  328.                          estado=0;                              // Set de estado inicial para el fading
  329.                  }
  330.                  break;
  331.          case 0x40:                                             //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
  332.                  mode=FADING_FIX;                       // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
  333.                  break;
  334.          case 0x00:                                             //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
  335.                  mode=FIXED;                            // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
  336.                  break;
  337.          }
  338.  }

Ahi va mi codigo... tiene una forma distinta de aplicacion. Tiene una forma distinta de como es que funciona el programa.
Por eso tuve que modificar completamente las funciones fading_auto y rainbow_fader, ya que de intentar cambiar rapidamente de modo, implicaba grandes demoras del micro hasta que realmente pudiera hacerlo.

Si observas el while del main esta continuamente entrando al modo que le corresponde, se hace lo que se debe y vuelve a salir al while de afuera.
El PWM esta corriendo siempre y es independiente de todo. Unicamente se cambia de modo Y de color si es que termino el ciclo del PWM, para evitar glitches

Lo que llegue desde el DMX, va a cargarse segun se requiera:

Modo Fijo (FIXED):
El programa arranca en este modo y colores RGB 0,0,0
El color se carga desde los valores del DMX, y se procede a actualizar lo que va a ir en la salida. Cuando el PWM termina el ciclo procede a cargar esos nuevos valores, asi por un ciclo mas.

Modo Fading Fijo (FADING_FIXED):
Este no lo hice, no esta realizado el codigo, deberia tomar el color y hacer un fading con el color que le manda el DMX. Creo que aca deberia aplicar un alpha asi afectar a todos los colores. Como no tengo seguro como hacerlo todavia no lo hice.

Modo Fading (FADING):
Este modo cuando se selecciona cuando el PWM llega a 255, esto hace que se le asignen los valores que deben ser para que inicie el modo fading tal cual estaba en el codigo anterior. Ademas pone los estados en 0 del fading para el nuevo codigo.

Modo Rainbow_Fading (RAINBOW_FADING):
Este modo utilizaba varias formas se producia el RAINBOW completo y luego se procedia a hacer 1 sola etapa del FADING. Asi hasta completar todas las etapas de FADING.

La Velocidad en que cambian los colores esta dado por el valor del DMX, el cual se actualiza al instante.
Tambien cambie la forma, queria hacer un cambio lineal de 3us a 580ms que era lo que tenia el programa en ASM, pero hacer una ecuacion lineal para eso era ridiculo ya que me encontraba con rangos de 0.003 a 580ms o de 3us a 580000ms
Entonces procedi a dividirlo en 2 rectas. 1 para los microsegundos para cuando DMX_Velocidad es de 0 a 127 y la otra para los milisegundos cuando DMX_Velocidad es de 128 a 255. Esto valores exigian operaciones con numeros flotantes. Por lo tanto me incline a hacerlo lo mas entero posible, por eso mismo la primera recta va desde 3us a 890us y luego pasa de 1ms a 508ms. Lo unico malo es que de 127 a 128 hay un salto de 100us, pero que espero no afecte demasiado.

Consideraciones que tuve:

El DIP solo entrega la direccion nada mas, esta puesto en el while asi de esa forma uno puede cambiar a direccion del equipo mientras esta encendido.
Quite seguramente algunas cosas como para poder programar mejor, seguro que vos luego se los vas a agregar de vuelta, tal como el WDT.
Y espero no haberle errado mucho.


Los valores de Rojo,Verde,Azul los puse todos en un array llamado ArrayColores, esto me permitio crear otros arrays mas para simplificar el programa. Ejemplo:

Código: C
  1. const uint8_t ArrayColorFading[]={                      // Indice y valor a modificar   {1,2,3} y {-1,-2,-3}
  2.                  1,     //      Rojo    ->      Amarillo
  3.                  0,     //      Amarilo ->      Verde
  4.                  2,     //      Verde   ->      Cyan
  5.                  1,     //      Cyan    ->      Azul
  6.                  0,     //      Azul    ->      Magenta
  7.                  2      //      Magenta ->      Rojo
  8. };

El Fading (solo este sin rainbow) hacia:
0- Incrementaba verde hasta 255
1- Decrementaba rojo hasta 0
2- Incrementaba azul hasta 255
3- Decrementaba verde
4- Incrementaba rojo
5- Decrementa Azul

Si observas los pares 0,2,4 son todos incrementos y los impares 1,3,5 decrementos
Si observas tambien los numeros del array que cree solo hay numeros de 0 a 2, esto me indica el indice {R,G,B}  el 0 es Rojo, 1 Verde, 2 Azul.
Entonces se que si tengo un 0 en la posicion 2, entonces debo INCREMENTAR rojo.

El mismo principio se aplica al Rainbow, nomas que alli se incrementa y decrementa a la misma ves, por lo tanto procedi a crear otro array distinto para ese.
Esto ultimo es por si me preguntabas que habia realizado. No quise meterme con punteros para no complicarle la vida a nadie.

Creo que estaria todo terminado a excepcion de la funcion de fading fijo (que seguro la termino dentro de poco). todo lo demas agregado que no sea parte de la implementacion del codigo ya creo que va a pasar a ser un tema tuyo.
Si no me equivoco deberia funcionar masomenos correctamente. Me preocupan un par de detalles minusciosos pero que tal ves me este rompiendo mas la cabeza de lo que debo.
(Como crear otro valor de modo para que solo se cambie en cierta ocasion de esa forma evitar cualquier posible error)

PD: Si observas y el por que de mi enojo es que es muy distinto un programa hecho de forma lineal como teniamos, a uno realizado de la forma que esta ahora. Tal ves demasiado, a pesar que "hacen lo mismo" la aplicacion es totalmente distinta.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 27 de Agosto de 2015, 01:11:18
 hola
Código: C
  1. #define F_CPU 8000000
  2. #include<util\delay.h>
  3.  
  4. #include<stdio.h>
  5. #include<stdlib.h>
  6. #include"fading_raibow.h"
  7. #include <avr/interrupt.h>
  8. #include <avr/wdt.h>
  9.  
  10.  
  11. enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode;
  12.  
  13. #define OV_COUNT        14              // 161 , 7  = 0.25ms
  14. #define OV_SIZE         161             // comenzando Contador inicial
  15.  
  16. // Dato proveniente de la consola DMX
  17.  
  18. #define DMX_R                   DmxRxField[1]   //Canal R              
  19. #define DMX_G                   DmxRxField[2]   //Canal G
  20. #define DMX_B                   DmxRxField[3]   //Canal B
  21. #define DMX_Modo                DmxRxField[4]   //Seleccion de Modo
  22. #define DMX_Velocidad   DmxRxField[5]   //Seleccion de Velocidad
  23.  
  24. // Para simplificar los datos del array de colores que estoy usando.
  25. // ArrayColores contiene los valores RGB del momento
  26.  
  27. #define Rojo                    ArrayColores[0]
  28. #define Verde                   ArrayColores[1]
  29. #define Azul                    ArrayColores[2]
  30.  
  31. //*********************************//
  32.  
  33. volatile uint16_t        DmxAddress;                            // Dirección inicial
  34.  
  35. uint8_t V_out,R_out,A_out;                                              // Valores que se comparan con el PWM
  36. uint8_t V_aux,R_aux,A_aux;                                              // Valores que se cambia para actualizar el PWM
  37. uint8_t PWM_timer=0;
  38. uint8_t estado=0,estador=0;                                     // Estado de los fading
  39.  
  40. const uint8_t arraydimmer[256]={
  41.                  0,     0,    1,    1,    1,    1,    1,    2,
  42.                  2,     2,    2,    3,    3,    3,    4,    4,
  43.                  4,     5,    5,    5,    6,    6,    7,    7,
  44.                  8,     8,    9,    9,   10,   10,   11,   11,
  45.                  12,   12,   13,   13,   14,   14,   15,   15,
  46.                  16,   16,   17,   17,   18,   18,   19,   19,
  47.                  20,   20,   21,   21,   22,   22,   23,   23,
  48.                  24,   24,   25,   25,   26,   27,   28,   29,
  49.                  30,   30,   31,   32,   33,   34,   35,   36,
  50.                  36,   37,   38,   39,   40,   41,   42,   43,
  51.                  43,   44,   45,   46,   47,   48,   49,   50,
  52.                  51,   52,   52,   53,   54,   55,   56,   57,
  53.                  58,   59,   60,   61,   62,   63,   64,   65,
  54.                  66,   67,   68,   69,   70,   71,   72,   73,
  55.                  74,   75,   76,   77,   78,   79,   80,   81,
  56.                  82,   83,   84,   85,   86,   88,   89,   90,
  57.                  91,   92,   93,   94,   95,   96,   97,   98,
  58.                  99,  100,  102,  103,  104,  105,  106,  107,
  59.                  108, 109,  110,  112,  113,  114,  115,  116,
  60.                  117, 119,  120,  121,  122,  123,  124,  126,
  61.                  127, 128,  129,  130,  132,  133,  134,  135,
  62.                  136, 138,  139,  140,  141,  142,  144,  145,
  63.                  146, 147,  149,  150,  151,  152,  154,  155,
  64.                  156, 158,  159,  160,  161,  162,  164,  165,
  65.                  167, 168,  169,  171,  172,  173,  174,  176,
  66.                  177, 178,  180,  181,  182,  184,  185,  187,
  67.                  188, 189,  191,  192,  193,  195,  196,  197,
  68.                  199, 200,  202,  203,  204,  206,  207,  208,
  69.                  210, 211,  213,  214,  216,  217,  218,  220,
  70.                  221, 223,  224,  226,  227,  228,  230,  231,
  71.                  233, 234,  236,  237,  239,  240,  242,  243,
  72.                  245, 246,  248,  249,  251,  252,  254,  255
  73. };
  74.  
  75. uint8_t ArrayColores[3]={255,0,0};                      // Rojo,Verde,Azul
  76.  
  77. const uint8_t ArrayColorFading[]={                      // Indice y valor a modificar   {1,2,3} y {-1,-2,-3}
  78.                  1,     //      Rojo    ->      Amarillo
  79.                  0,     //      Amarilo ->      Verde
  80.                  2,     //      Verde   ->      Cyan
  81.                  1,     //      Cyan    ->      Azul
  82.                  0,     //      Azul    ->      Magenta
  83.                  2      //      Magenta ->      Rojo
  84. };
  85.  
  86. const uint8_t ArrayColorFadingRainbow[]={                       // Indice y valor a modificar   {Resta,Suma}
  87.                 {0,1},  //      Rojo-   ->      Verde+
  88.                 {1,2},  //      Verde-  ->      Azul+
  89.                 {2,0}   //      Azul-   ->      Rojo+
  90. };
  91.  
  92. //************* Inicialización pines / port *****************//
  93. void init_pinouts(){
  94.     #ifdef USE_DIP
  95.  
  96.     DDRC  = 0;                  // establecer DIPs
  97.     PORTC  = 0xFF;
  98.     DDRE  &= ~((1<<PE2)|(1<<PE1));
  99.     PORTE |=   (1<<PE2)|(1<<PE1);
  100.         #endif
  101.  
  102.  
  103.         DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
  104.         PORTB = 0;
  105.         DDRE  |= (1<<PE0);      //LED2 azul indicador
  106.     PORTE = 0;
  107.  
  108. }
  109.  
  110. // ***** inicializacion del timer****//
  111.  
  112. void init_timer(){
  113.                 TCCR0|= (1<<CS02) ;     // Precontador 256
  114.                 TIMSK|= (1<<TOIE0);     // desbordamientos de la interrupción
  115.                 TCNT0= OV_SIZE;
  116.         }
  117.  
  118.  // ************* obtener DMX dirección de inicio **************
  119.  
  120. void get_dips(void)
  121. {
  122. #ifdef USE_DIP
  123. uint16_t Temp;
  124.  
  125. if (!(PINE &(1<<PE1))){ // Modo FADING / RAINBOW_FADER
  126.         Temp=                     // DMXAdress = tiempo de retardo
  127.                 (!(PINC &(1<<PC0)) *1) +
  128.                 (!(PINC &(1<<PC1)) *2) +
  129.                 (!(PINC &(1<<PC2)) *4) +
  130.                 (!(PINC &(1<<PC3)) *8) +
  131.                 (!(PINC &(1<<PC4)) *16) +
  132.                 (!(PINC &(1<<PC5)) *32) +
  133.                 (!(PINC &(1<<PC6)) *64) +
  134.                 (!(PINC &(1<<PC7)) *128);
  135.         DmxAddress= Temp;
  136.         if (!(PINE &(1<<PE2))) // MODO FADING / OFF RAINBOW_FADER
  137.              {
  138.                 mode= FADING;
  139.         }else{
  140.                 mode= RAINBOW_FADER;
  141.  
  142.              }
  143.                 return;
  144.         }
  145. //mode= xxx; // ACA PUEDE IR OTRA FUNCION CON LOS DIPS
  146. //Temp=
  147. //      (!(PINC &(1<<PC0)) *1) +
  148. //      (!(PINC &(1<<PC1)) *2) +
  149. //      (!(PINC &(1<<PC2)) *4) +
  150. //      (!(PINC &(1<<PC3)) *8) +
  151. //      (!(PINC &(1<<PC4)) *16) +
  152. //      (!(PINC &(1<<PC5)) *32) +
  153. //      (!(PINC &(1<<PC6)) *64) +
  154. //      (!(PINC &(1<<PC7)) *128) +
  155. //      (!(PINE &(1<<PE2)) *256);
  156.  
  157.  
  158. //if (Temp != 0)
  159. //      {
  160. //      Address= Temp;
  161.  
  162. //      }
  163.  
  164. #endif
  165. }
  166.  
  167. int main(void)
  168. {
  169.  //***** Watchdog *****//
  170.         wdt_reset();
  171.         wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
  172.         wdt_reset();
  173.         cli();
  174.         init_pinouts(); // Establecer los puertos de E / S
  175.         init_timer();   // Establecer el temporizador
  176.        
  177.         mode = FIXED;           //Valores iniciales, hasta que llegue la trama del DMX
  178.         Rojo = 0;
  179.         Verde = 0;
  180.         Azul = 0;
  181.        
  182.         sei();              // habilitar las interupciones globales  ???
  183.  
  184.         while(1)        // bucle principal (LOOP)
  185.             {
  186.                 get_dips();     // Toma la direccion y la actualiza, esto es para no tener que reiniciar a cada rato el DMX
  187.                 switch(mode)
  188.                 {
  189.                 case FIXED:
  190.                                 Rojo = DMX_R;           // Colores tomados directamente del DMX para fijo
  191.                                 Verde = DMX_G;
  192.                                 Azul = DMX_B;
  193.                                 DimmerCurva();          // Actualizo colores para el PWM
  194.                                 break;
  195.                 case FADING_FIX:
  196.                                 fading_fijo();
  197.                                 break;
  198.                 case FADING:
  199.                                 fading_auto();
  200.                                 break;
  201.                 case RAINBOW_FADING:
  202.                                 rainbow_fader();
  203.                                 break;
  204.                 default:
  205.                                 break;
  206.                 }
  207.             }
  208. }
  209.  
  210. void fading_fijo(){
  211.  
  212. }
  213.  
  214.  
  215.  
  216. void fading_auto(){
  217.  
  218.                 // Valores iniciales seteados cuando se cambia de modo
  219.        
  220.                 //Espera
  221.                 delay(DMX_Velocidad);  //esperar
  222.                 //Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
  223.                 if(estado%2)
  224.                 {       //Caso impar
  225.                         if(++ArrayColores[estado]==255) estado++;
  226.                 }
  227.                 else
  228.                 {       //Caso par
  229.                         if(--ArrayColores[estado]==0) estado++;
  230.                 }
  231.                 if(estado>=6) estado=0;
  232.                 DimmerCurva();
  233. }
  234.  
  235. void rainbow_fader(){
  236.  
  237.         int Temp_R,Temp_A,Temp_V;
  238.         Temp_R = Rojo;
  239.         Temp_A = Azul;
  240.         Temp_V = Verde;
  241.  
  242.         if (estador==0){                                                                                                        //Caso inicial, Para que comienze con los valores que debe
  243.                 Rojo = 255;
  244.                 Verde = 0;
  245.                 Azul = 0;
  246.         }
  247.         DimmerCurva();
  248.  
  249.                 ArrayColores[ArrayColorFadingRainbow[estador][1]]++;                            //Sumo
  250.                 ArrayColores[ArrayColorFadingRainbow[estador][0]]--;                            //Resto
  251.                 if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++;       //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
  252.  
  253.         Rojo = Temp_R;
  254.         Azul = Temp_A;
  255.         Verde = Temp_V;
  256.        
  257.                 if(estador>=3) estador=0; fading_auto();                                                        //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
  258.  
  259. }
  260.  
  261. void DimmerCurva(){
  262.  
  263.         R_aux=arraydimmer[Rojo];
  264.         V_aux=arraydimmer[Verde];
  265.         A_aux=arraydimmer[Azul];
  266. }
  267.  
  268. void delay(uint8_t DMX_Velocidad) {
  269.  
  270.         // Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
  271.         // Tiempo Minimo = 3us
  272.         // Tiempo Maximo = 580ms
  273.         // Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
  274.        
  275.         uint16_t tiempo;
  276.         if (DMX_Velocidad>127)
  277.         {       //Tiempo en milisegundos, Recta de 1ms a 508ms
  278.                 tiempo = 4*DMX_Velocidad - 511;
  279.                 //_delay_ms(tiempo);
  280.         }
  281.         else
  282.         {       //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
  283.                 tiempo = 7*DMX_Velocidad +3;
  284.                 //_delay_us(tiempo);
  285.         }
  286. }
  287.  
  288.  
  289.  //***** inicio del ocilador Temporizador de interrupción ****//
  290.  void ISR(TIMER0_OVF_vect){
  291.  
  292.         if (R_out>=PWM_timer) { salida &= 0x06; }
  293.         if (V_out>=PWM_timer) { salida &= 0x05; }
  294.         if (A_out>=PWM_timer) { salida &= 0x03; }
  295.         if (PWM_timer==255)
  296.         {
  297.                 //Cargo los colores nuevos ya que finalizo el ciclo del PWM
  298.                 R_out = R_aux;
  299.                 V_out = V_aux;
  300.                 A_out = A_aux;
  301.                 //Observo si se cambio el modo, asi cambio el modo y seteo los valores iniciales de ser necesario
  302.                 Cambiarmodo();
  303.         }
  304.         PWM_timer++;
  305. }
  306.  
  307.  void Cambiarmodo(){
  308.          switch(DMX_Modo&0xC0)  // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
  309.          {
  310.          case 0xC0:                                             //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
  311.                  if(mode!=RAINBOW_FADING)       //Reviso que ya no este en este modo.
  312.                  {
  313.                          mode=RAINBOW_FADING;
  314.                          Rojo=255;                              // Set de colores iniciales            
  315.                          Verde=0;
  316.                          Azul=0;
  317.                          estado=0;                              // Set de estado inicial para el fading
  318.                          estador=0;                             // Set de estado inicial para el rainbow_fading
  319.                  }
  320.                  break;
  321.          case 0x80:                                             //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
  322.                  if(mode!=FADING)                       // Si ya esta en el modo, que no lo modifique.
  323.                  {
  324.                          mode=FADING;
  325.                          Rojo=255;                              // Set de colores iniciales            
  326.                          Verde=0;
  327.                          Azul=0;
  328.                          estado=0;                              // Set de estado inicial para el fading
  329.                  }
  330.                  break;
  331.          case 0x40:                                             //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
  332.                  mode=FADING_FIX;                       // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
  333.                  break;
  334.          case 0x00:                                             //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
  335.                  mode=FIXED;                            // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
  336.                  break;
  337.          }
  338.  }

Ahi va mi codigo... tiene una forma distinta de aplicacion. Tiene una forma distinta de como es que funciona el programa.
Por eso tuve que modificar completamente las funciones fading_auto y rainbow_fader, ya que de intentar cambiar rapidamente de modo, implicaba grandes demoras del micro hasta que realmente pudiera hacerlo.

Si observas el while del main esta continuamente entrando al modo que le corresponde, se hace lo que se debe y vuelve a salir al while de afuera.
El PWM esta corriendo siempre y es independiente de todo. Unicamente se cambia de modo Y de color si es que termino el ciclo del PWM, para evitar glitches

Lo que llegue desde el DMX, va a cargarse segun se requiera:

Modo Fijo (FIXED):
El programa arranca en este modo y colores RGB 0,0,0
El color se carga desde los valores del DMX, y se procede a actualizar lo que va a ir en la salida. Cuando el PWM termina el ciclo procede a cargar esos nuevos valores, asi por un ciclo mas.

Modo Fading Fijo (FADING_FIXED):
Este no lo hice, no esta realizado el codigo, deberia tomar el color y hacer un fading con el color que le manda el DMX. Creo que aca deberia aplicar un alpha asi afectar a todos los colores. Como no tengo seguro como hacerlo todavia no lo hice.

Modo Fading (FADING):
Este modo cuando se selecciona cuando el PWM llega a 255, esto hace que se le asignen los valores que deben ser para que inicie el modo fading tal cual estaba en el codigo anterior. Ademas pone los estados en 0 del fading para el nuevo codigo.

Modo Rainbow_Fading (RAINBOW_FADING):
Este modo utilizaba varias formas se producia el RAINBOW completo y luego se procedia a hacer 1 sola etapa del FADING. Asi hasta completar todas las etapas de FADING.

La Velocidad en que cambian los colores esta dado por el valor del DMX, el cual se actualiza al instante.
Tambien cambie la forma, queria hacer un cambio lineal de 3us a 580ms que era lo que tenia el programa en ASM, pero hacer una ecuacion lineal para eso era ridiculo ya que me encontraba con rangos de 0.003 a 580ms o de 3us a 580000ms
Entonces procedi a dividirlo en 2 rectas. 1 para los microsegundos para cuando DMX_Velocidad es de 0 a 127 y la otra para los milisegundos cuando DMX_Velocidad es de 128 a 255. Esto valores exigian operaciones con numeros flotantes. Por lo tanto me incline a hacerlo lo mas entero posible, por eso mismo la primera recta va desde 3us a 890us y luego pasa de 1ms a 508ms. Lo unico malo es que de 127 a 128 hay un salto de 100us, pero que espero no afecte demasiado.

Consideraciones que tuve:

El DIP solo entrega la direccion nada mas, esta puesto en el while asi de esa forma uno puede cambiar a direccion del equipo mientras esta encendido.
Quite seguramente algunas cosas como para poder programar mejor, seguro que vos luego se los vas a agregar de vuelta, tal como el WDT.
Y espero no haberle errado mucho.


Los valores de Rojo,Verde,Azul los puse todos en un array llamado ArrayColores, esto me permitio crear otros arrays mas para simplificar el programa. Ejemplo:

Código: C
  1. const uint8_t ArrayColorFading[]={                      // Indice y valor a modificar   {1,2,3} y {-1,-2,-3}
  2.                  1,     //      Rojo    ->      Amarillo
  3.                  0,     //      Amarilo ->      Verde
  4.                  2,     //      Verde   ->      Cyan
  5.                  1,     //      Cyan    ->      Azul
  6.                  0,     //      Azul    ->      Magenta
  7.                  2      //      Magenta ->      Rojo
  8. };

El Fading (solo este sin rainbow) hacia:
0- Incrementaba verde hasta 255
1- Decrementaba rojo hasta 0
2- Incrementaba azul hasta 255
3- Decrementaba verde
4- Incrementaba rojo
5- Decrementa Azul

Si observas los pares 0,2,4 son todos incrementos y los impares 1,3,5 decrementos
Si observas tambien los numeros del array que cree solo hay numeros de 0 a 2, esto me indica el indice {R,G,B}  el 0 es Rojo, 1 Verde, 2 Azul.
Entonces se que si tengo un 0 en la posicion 2, entonces debo INCREMENTAR rojo.

El mismo principio se aplica al Rainbow, nomas que alli se incrementa y decrementa a la misma ves, por lo tanto procedi a crear otro array distinto para ese.
Esto ultimo es por si me preguntabas que habia realizado. No quise meterme con punteros para no complicarle la vida a nadie.

Creo que estaria todo terminado a excepcion de la funcion de fading fijo (que seguro la termino dentro de poco). todo lo demas agregado que no sea parte de la implementacion del codigo ya creo que va a pasar a ser un tema tuyo.
Si no me equivoco deberia funcionar masomenos correctamente. Me preocupan un par de detalles minusciosos pero que tal ves me este rompiendo mas la cabeza de lo que debo.
(Como crear otro valor de modo para que solo se cambie en cierta ocasion de esa forma evitar cualquier posible error)

PD: Si observas y el por que de mi enojo es que es muy distinto un programa hecho de forma lineal como teniamos, a uno realizado de la forma que esta ahora. Tal ves demasiado, a pesar que "hacen lo mismo" la aplicacion es totalmente distinta.
bueno amigo alli compile y agregue algunas cosas que faltaban al juntako con DMX
pero me largo error ., y calculo que los errores tiene el mismo origen que es el PWM en e lIRS
y te vuelvo a repetir en DMX se tiene que ejecitar en WHILE o FOR pero fuera del IRS
la razon es que te afecta la recepcion del USAT como te explique antes  
aca te subo las tres librerias  la de recepcion" lib_dmx_in.c " ," lib_dmx_in.h" y "fading_raibow.c "
LIB_DMX_IN.C
Código: [Seleccionar]
#include "lib_dmx_in.h"
#include "lib_indicator.h"
// ********************* definiciones locales*********************
 
enum {IDLE, BREAK, STARTB, STARTADR};// estados DMX

    
    
  uint8_t gDmxState;
uint8_t *gDmxPnt;
uint16_t DmxCount;  
                                                                                                                                                                                              
//volatile uint8_t gDmxState;
 
 
// *************** DMX recepción de inicialización ****************
void init_DMX_RX(void)
{
#ifdef USE_DIP
 
DDRC  = 0; // establecer DIPs
PORTC  = 0xFF;
DDRE  &= ~((1<<PE2)|(1<<PE1));
PORTE |=   (1<<PE2)|(1<<PE1);
 
#endif
 
DDRD  |= (1<<2);
PORTD &= ~(1<<2);
UBRRH  = 0; // Habilitar recepción
UBRRL  = ((F_OSC/4000)-1);// 250kBaud, 8N2
UCSRC  = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB  = (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;

uint8_t i;
for (i=0; i<DMX_CHANNELS; i++)
{
DmxRxField[i]= 0;
}

}
 
 
 
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
 
if (!(PINE &(1<<PE1))){ // Modo Manual
Temp=  // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // Manual,
    {
mode= FADING;
}else{
mode= RAINBOW_FADER;

     }
UCSRB &= ~(1<<RXCIE);// Receptor Desactivar si la dirección de inicio = 0

return;

 }
mode=DMX;
Temp=
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128) +
(!(PINE &(1<<PE2)) *256);
 
if (Temp != 0)
{
DmxAddress= Temp;
if (!(UCSRB &(1<<RXCIE)))// Si el receptor esta desabilitado -> habilitar y esperar descanso
{
gDmxState= IDLE;
UCSRB |= (1<<RXCIE);

}
}
else
{
UCSRB &= ~(1<<RXCIE); // Receptor Desactivar si la dirección de inicio = 0

uint8_t i;
for (i=0; i<sizeof(DmxRxField); i++)
{
DmxRxField[i]= 0;
}
}
 
#endif
}
 
 
 
// *************** DMX recepción ISR ****************//
ISR (UART_RX_vect)
{
static  uint16_t DmxCount;
uint8_t  USARTstate= UCSRA; // Obtener estado antes de los datos!
uint8_t  DmxByte   = UDR; // Obtener los datos
uint8_t  DmxState  = gDmxState;// Cargar una sola vez de SRAM para aumentar la velocidad
IndFlags |= (1<<SIGNAL_COMING);// Recibir somedata
if (DmxState == BREAK)
{
UCSRA &= ~(1<<FE); // Cambiar Posible FE: a causa de MAB
if (DmxByte == 0)
{
gDmxState= STARTB;// Código de inicio normal detectado
gDmxPnt= ((uint8_t*)DmxRxField +1);
}
else
{
gDmxState= IDLE;
}
}

else if (USARTstate &(1<<FE)) // Comprobar para el descanso de la señal
{
UCSRA &= ~(1<<FE); // Restablecer bandera
if (DmxByte == 0) // Los datos de descanso debe ser 0
{
gDmxState= BREAK;
DmxCount= DmxAddress; // Restablecer contador de fotogramas
}
else
{
gDmxState= IDLE; // Bien es FE -> esperar descanso
}
}

else if (DmxState == STARTB)
{
if (--DmxCount == 0)// Dirección inicial alcanzada?
{
gDmxState= STARTADR;
DmxRxField[0]= DmxByte;
}
}

else if (DmxState == STARTADR)
{
uint8_t *DmxPnt;
DmxPnt= gDmxPnt;
*DmxPnt= DmxByte;
if (++DmxPnt >= (DmxRxField + DMX_CHANNELS )) // los (CHANNEL) canales recibidos?
{
Flags |= (1<<EVAL_DMX);// Conjunto de datos listo -> eval en principal (MAIN)
gDmxState= IDLE;
}
else
{
gDmxPnt= DmxPnt;
}
}
}

 aca LIB_DMX_IN.H
Código: [Seleccionar]
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define DMX_CHANNELS    (13)
#define  USE_DIP
#define  F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
enum {EVAL_DMX, IND};
volatile uint8_t Flags;
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode;

volatile uint16_t DmxAddress; // Dirección inicial
volatile int  color_number;// numero de la tabla de Color del sonido / manual actual
volatile uint8_t DmxRxField[DMX_CHANNELS]; // Conjunto de vals DMX (cruda)
extern void    init_DMX_RX(void);
extern void    get_dips(void);
extern void    set_color(int color);

aca el MAIN o FADING_RAIBOW.C
Código: [Seleccionar]
  // #define F_CPU 8000000
    #include<util\delay.h>
    #include "lib_dmx_in.h"
    #include<stdio.h>
    #include<stdlib.h>
   // #include"fading_raibow.h"
    #include <avr/interrupt.h>
    #include <avr/wdt.h>
 //************************************************************//    
    volatile uint8_t DmxRxField[DMX_CHANNELS];
    uint8_t DmxBuf[DMX_CHANNELS];
 //**********************************************************//    
    #define OV_COUNT 14 // 161 , 7  = 0.25ms
    #define OV_SIZE 161 // comenzando Contador inicial
    
    // Dato proveniente de la consola DMX
    
    #define DMX_R DmxRxField[1] //Canal R
    #define DMX_G DmxRxField[2] //Canal G
    #define DMX_B DmxRxField[3] //Canal B
    #define DMX_Modo DmxRxField[4] //Seleccion de Modo
    #define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
    
    // Para simplificar los datos del array de colores que estoy usando.
    // ArrayColores contiene los valores RGB del momento
    
    #define Rojo ArrayColores[0]
    #define Verde ArrayColores[1]
    #define Azul ArrayColores[2]
    
    //*********************************//
    
    volatile uint16_t DmxAddress; // Dirección inicial
    
    uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
    uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
    uint8_t PWM_timer=0;
    uint8_t estado=0,estador=0; // Estado de los fading
    
    const uint8_t arraydimmer[256]={
     0,     0,    1,    1,    1,    1,    1,    2,
     2,     2,    2,    3,    3,    3,    4,    4,
     4,     5,    5,    5,    6,    6,    7,    7,
     8,     8,    9,    9,   10,   10,   11,   11,
     12,   12,   13,   13,   14,   14,   15,   15,
     16,   16,   17,   17,   18,   18,   19,   19,
     20,   20,   21,   21,   22,   22,   23,   23,
     24,   24,   25,   25,   26,   27,   28,   29,
     30,   30,   31,   32,   33,   34,   35,   36,
     36,   37,   38,   39,   40,   41,   42,   43,
     43,   44,   45,   46,   47,   48,   49,   50,
     51,   52,   52,   53,   54,   55,   56,   57,
     58,   59,   60,   61,   62,   63,   64,   65,
     66,   67,   68,   69,   70,   71,   72,   73,
     74,   75,   76,   77,   78,   79,   80,   81,
     82,   83,   84,   85,   86,   88,   89,   90,
     91,   92,   93,   94,   95,   96,   97,   98,
     99,  100,  102,  103,  104,  105,  106,  107,
     108, 109,  110,  112,  113,  114,  115,  116,
     117, 119,  120,  121,  122,  123,  124,  126,
     127, 128,  129,  130,  132,  133,  134,  135,
     136, 138,  139,  140,  141,  142,  144,  145,
     146, 147,  149,  150,  151,  152,  154,  155,
     156, 158,  159,  160,  161,  162,  164,  165,
     167, 168,  169,  171,  172,  173,  174,  176,
     177, 178,  180,  181,  182,  184,  185,  187,
     188, 189,  191,  192,  193,  195,  196,  197,
     199, 200,  202,  203,  204,  206,  207,  208,
     210, 211,  213,  214,  216,  217,  218,  220,
     221, 223,  224,  226,  227,  228,  230,  231,
     233, 234,  236,  237,  239,  240,  242,  243,
     245, 246,  248,  249,  251,  252,  254,  255
    };
    
    uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
    
    const uint8_t ArrayColorFading[]={ // Indice y valor a modificar {1,2,3} y {-1,-2,-3}
     1, // Rojo -> Amarillo
     0, // Amarilo -> Verde
     2, // Verde -> Cyan
     1, // Cyan -> Azul
     0, // Azul -> Magenta
     2 // Magenta -> Rojo
    };
    
    const uint8_t ArrayColorFadingRainbow[]={ // Indice y valor a modificar {Resta,Suma}
     {0,1}, // Rojo- -> Verde+
     {1,2}, // Verde- -> Azul+
     {2,0} // Azul- -> Rojo+
    };
    
    //************* Inicialización pines / port *****************//
    void init_pinouts(){
        #ifdef USE_DIP
    
        DDRC  = 0; // establecer DIPs
        PORTC  = 0xFF;
        DDRE  &= ~((1<<PE2)|(1<<PE1));
        PORTE |=   (1<<PE2)|(1<<PE1);
     #endif
    
    
     DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
     PORTB = 0;
     DDRE  |= (1<<PE0); //LED2 azul indicador
        PORTE = 0;
    
    }
    
    // ***** inicializacion del timer****//
    
    void init_timer(){
     TCCR0|= (1<<CS02) ; // Precontador 256
     TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
     TCNT0= OV_SIZE;
     }
    
        
    int main(void)
    {
     //***** Watchdog *****//
     wdt_reset();
     wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
     wdt_reset();
     cli();
     init_pinouts(); // Establecer los puertos de E / S
     init_timer(); // Establecer el temporizador
     init_DMX_RX(); // Inicializar recpcion DMX
     mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
     Rojo = 0;
     Verde = 0;
     Azul = 0;
    
     sei();    // habilitar las interupciones globales  ???
    
     while(1) // bucle principal (LOOP)
        {
             get_dips(); // Toma la direccion y la actualiza, esto es para no tener que reiniciar a cada rato el DMX
             switch(mode)
             {
             case FIXED:
             Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
             Verde = DMX_G;
             Azul = DMX_B;
             DimmerCurva(); // Actualizo colores para el PWM
             break;
             case FADING_FIX:
             fading_fijo();
             break;
             case FADING:
             fading_auto();
             break;
             case RAINBOW_FADING:
             rainbow_fader();
             break;
             default:
             break;
             }
        }
    }
    
    void fading_fijo(){
    
    }
    
    
    
    void fading_auto(){
    
     // Valores iniciales seteados cuando se cambia de modo
    
     //Espera
     delay(DMX_Velocidad);  //esperar
     //Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
     if(estado%2)
     { //Caso impar
     if(++ArrayColores[estado]==255) estado++;
     }
     else
     { //Caso par
     if(--ArrayColores[estado]==0) estado++;
     }
     if(estado>=6) estado=0;
     DimmerCurva();
    }
    
    void rainbow_fader(){
    
         int Temp_R,Temp_A,Temp_V;
         Temp_R = Rojo;
         Temp_A = Azul;
         Temp_V = Verde;
    
         if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
             Rojo = 255;
             Verde = 0;
             Azul = 0;
         }
         DimmerCurva();
    
       ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
       ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
       if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
    
         Rojo = Temp_R;
         Azul = Temp_A;
         Verde = Temp_V;
        
       if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
    
    }
    
    void DimmerCurva(){
    
         R_aux=arraydimmer[Rojo];
         V_aux=arraydimmer[Verde];
         A_aux=arraydimmer[Azul];
    }
    
    void delay(uint8_t DMX_Velocidad) {
    
     // Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
     // Tiempo Minimo = 3us
     // Tiempo Maximo = 580ms
     // Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
    
     uint16_t tiempo;
     if (DMX_Velocidad>127)
     { //Tiempo en milisegundos, Recta de 1ms a 508ms
     tiempo = 4*DMX_Velocidad - 511;
     //_delay_ms(tiempo);
     }
     else
     { //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
     tiempo = 7*DMX_Velocidad +3;
     //_delay_us(tiempo);
     }
    }
    
    
     //***** inicio del ocilador Temporizador de interrupción ****//
     void ISR(TIMER0_OVF_vect){
          
     if (R_out>=PWM_timer) { salida &= 0x06; }
     if (V_out>=PWM_timer) { salida &= 0x05; }
     if (A_out>=PWM_timer) { salida &= 0x03; }
     if (PWM_timer==255)
     {
     //Cargo los colores nuevos ya que finalizo el ciclo del PWM
     R_out = R_aux;
     V_out = V_aux;
     A_out = A_aux;
     //Observo si se cambio el modo, asi cambio el modo y seteo los valores iniciales de ser necesario
     Cambiarmodo();
     }
     PWM_timer++;
    }
    
     void Cambiarmodo(){
     switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
     {
     case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
     if(mode!=RAINBOW_FADING) //Reviso que ya no este en este modo.
     {
     mode=RAINBOW_FADING;
     Rojo=255; // Set de colores iniciales
     Verde=0;
     Azul=0;
     estado=0; // Set de estado inicial para el fading
     estador=0; // Set de estado inicial para el rainbow_fading
     }
     break;
     case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
     if(mode!=FADING) // Si ya esta en el modo, que no lo modifique.
     {
     mode=FADING;
     Rojo=255; // Set de colores iniciales
     Verde=0;
     Azul=0;
     estado=0; // Set de estado inicial para el fading
     }
     break;
     case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
     mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
     break;
     case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
     mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
     break;
     }
     }
 aca los errores
Código: [Seleccionar]
Build started 26.8.2015 at 22:08:44
avr-gcc.exe  -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99       -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT fading_raibow.o -MF dep/fading_raibow.o.d  -c  ../fading_raibow.c
../fading_raibow.c:87: warning: braces around scalar initializer
../fading_raibow.c:87: warning: (near initialization for 'ArrayColorFadingRainbow[0]')
../fading_raibow.c:87: warning: excess elements in scalar initializer
../fading_raibow.c:87: warning: (near initialization for 'ArrayColorFadingRainbow[0]')
../fading_raibow.c:88: warning: braces around scalar initializer
../fading_raibow.c:88: warning: (near initialization for 'ArrayColorFadingRainbow[1]')
../fading_raibow.c:88: warning: excess elements in scalar initializer
../fading_raibow.c:88: warning: (near initialization for 'ArrayColorFadingRainbow[1]')
../fading_raibow.c:89: warning: braces around scalar initializer
../fading_raibow.c:89: warning: (near initialization for 'ArrayColorFadingRainbow[2]')
../fading_raibow.c:89: warning: excess elements in scalar initializer
../fading_raibow.c:89: warning: (near initialization for 'ArrayColorFadingRainbow[2]')
../fading_raibow.c: In function 'main':
../fading_raibow.c:145: warning: implicit declaration of function 'DimmerCurva'
../fading_raibow.c:148: warning: implicit declaration of function 'fading_fijo'
../fading_raibow.c:151: warning: implicit declaration of function 'fading_auto'
../fading_raibow.c:154: warning: implicit declaration of function 'rainbow_fader'
../fading_raibow.c: At top level:
../fading_raibow.c:162: warning: conflicting types for 'fading_fijo'
../fading_raibow.c:148: warning: previous implicit declaration of 'fading_fijo' was here
../fading_raibow.c:168: warning: conflicting types for 'fading_auto'
../fading_raibow.c:151: warning: previous implicit declaration of 'fading_auto' was here
../fading_raibow.c: In function 'fading_auto':
../fading_raibow.c:173: warning: implicit declaration of function 'delay'
../fading_raibow.c: At top level:
../fading_raibow.c:187: warning: conflicting types for 'rainbow_fader'
../fading_raibow.c:154: warning: previous implicit declaration of 'rainbow_fader' was here
../fading_raibow.c: In function 'rainbow_fader':
../fading_raibow.c:201: error: subscripted value is neither array nor pointer
../fading_raibow.c:202: error: subscripted value is neither array nor pointer
../fading_raibow.c:203: error: subscripted value is neither array nor pointer
../fading_raibow.c: At top level:
../fading_raibow.c:213: warning: conflicting types for 'DimmerCurva'
../fading_raibow.c:145: warning: previous implicit declaration of 'DimmerCurva' was here
../fading_raibow.c:220: warning: conflicting types for 'delay'
../fading_raibow.c:173: warning: previous implicit declaration of 'delay' was here
../fading_raibow.c:242: error: two or more data types in declaration specifiers
../fading_raibow.c: In function '__vector_7':
../fading_raibow.c:244: error: 'salida' undeclared (first use in this function)
../fading_raibow.c:244: error: (Each undeclared identifier is reported only once
../fading_raibow.c:244: error: for each function it appears in.)
../fading_raibow.c:254: warning: implicit declaration of function 'Cambiarmodo'
../fading_raibow.c: At top level:
../fading_raibow.c:259: warning: conflicting types for 'Cambiarmodo'
../fading_raibow.c:254: warning: previous implicit declaration of 'Cambiarmodo' was here
make: *** [fading_raibow.o] Error 1
Build failed with 7 errors and 30 warnings...
bueno espero que te alla aclarado eso ., o al menos hice el intento de explicartelo  
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 27 de Agosto de 2015, 01:14:13
 
Bueno aca te subo para que veas (en el otro mensaje no me entraba) es para que veas,  es un proyecto que estoy armando ., son lo tres led y dos motores PAP (funciona con 8 y 16 bits )., me funciona perfecto
El problema lo tengo con los motores (todos recuperados )., pero las vueltas y los pasos son ditintos en todos ., pero de funcionar.,  funciona perfectamente
El motivo es para que veas como trabajan los IRS  ., si te fijas NO hay ningun PWM en los IRS ( uso los dos timer del integado ) todos los PWM estan en el WHILIE
Aparte probe con la libreria reformada ., compilo sin error ( tuve que declarar FADING y RAIBOW_FADER
y desabilita perfectamente la recepcion al poner el mini-dips N°10 en ON la consola DMX dice "desabilitado"
o sea que esa parte esta perfecta ., cuando la coloco en OFF mi montaje funciona perfectamente ., de la otra manera ., como es obio ., no funciona PORQUE NO HAY NADA
 
Código: [Seleccionar]
/**** A P P L I C A T I O N   N O T E   ************************************
*
* Title : DMX512 2 axis microstep controller
* Version : v1.1
* Last updated : 03.04.08
* Target : Transceiver Rev.3.01 [ATmega8515]
* Clock : 8MHz
*
* written by hendrik hoelscher, www.hoelscher-hi.de
***************************************************************************
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version2 of
 the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 General Public License for more details.

 If you have no copy of the GNU General Public License, write to the
 Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 For other license models, please contact the author.

;***************************************************************************/
#include<stdio.h>
#include "lib_indicator.h"
#include "lib_dmx_in.h"
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <util/delay.h>
 //*********************************//
 uint8_t count= 1; //counter für soft PWM
uint8_t IndiCnt= 1; //counter für LED indicator
uint8_t DmxBuf[DMX_CHANNELS];    enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode;
//*** Inicialización pines / port ***//
void init_pinouts(){                   
//DDRA=  0xFF; // salidas bajas
    //PORTA= 0;
    DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
    PORTB= 0;
    DDRD |= (1<<PD2); // El selector de la transmisión de salida colocación
    PORTD |= (1<<PD2); // Establecer el estado de la RX 0 - entrada de transmisión

// Temporizador de inicialización para evitar cortar efecto estroboscópico
#define OV_COUNT 14 // 161 metros, 7 no repleta? = 0.25ms
#define OV_SIZE 161 // Worth ?? comenzando Contador inicial
volatile int timer_counter=0;// Contador del temporizador
 // ***** inicializacion del timer****//
void init_timer(){
TCCR0|= (1<<CS02) ; // Precontador 256
TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
TCNT0= OV_SIZE;
}
// Restablecer el temporizador
void reset_timer(){
TCNT0= OV_SIZE; // Worth ?? comenzando Contador inicial
timer_counter=0;
}
 // *** establecer valor de WHILE y sound_time ***//
enum {FALSE=0, TRUE=1};
volatile char sound_time=TRUE;



//

uint16_t  Accel;
volatile uint8_t   Flags;
uint16_t  IndCnt= 1000;
volatile uint8_t   BasePat;



struct axis{ //all private data for X and Y axes
   uint16_t   Ist; //current position
   uint16_t   Soll; //destination pos
   uint16_t   Max; //max position
           uint8_t   State; //status flags
   int8_t   Speed;      //current speed (raw)
   uint16_t   StpRate;
   uint8_t   TopPat; //PWM pattern
   };
   
struct axis X;
struct axis Y;


enum {TICK, POS_CHANGED};
enum {POS};

#define OFFSET (4)
#define IND_TIME (2200)

#define X_MAX_H (1) //EEPROM usage
#define X_MAX_L (2)
#define Y_MAX_H (3)
#define Y_MAX_L (4)
#define ACC_H (5)
#define ACC_L (6)


const uint8_t bStep[] PROGMEM = { //halfsteps (DCBA DCBA)
0b00010001,
0b01010101,
0b01000100,
0b01100110,
0b00100010,
0b10101010,
0b10001000,
0b10011001,
0b00010001
};
const uint8_t buStep[] PROGMEM = { //1/8 steps
    0b00010001,

0b01010001,
0b01010001,
0b01010001,

0b01010101,

0b01010100,
0b01010100,
0b01010100,

0b01000100,

0b01100100,
0b01100100,
0b01100100,

0b01100110,

0b01100010,
0b01100010,
0b01100010,

0b00100010,

0b10100010,
0b10100010,
0b10100010,

0b10101010,

0b10101000,
0b10101000,
0b10101000,

0b10001000,

0b10011000,
0b10011000,
0b10011000,

0b10011001,

0b10010001,
0b10010001,
0b10010001,

0b00010001
};



const uint8_t Step[] PROGMEM = { //halfsteps
0b00010001,
0b00110011,
0b00100010,
0b01100110,
0b01000100,
0b11001100,
0b10001000,
0b10011001,
0b00010001
};
const uint8_t uStep[] PROGMEM = { //1/8 steps
0b00010001,

0b00110001,
0b00110001,
0b00110001,

0b00110011,

0b00110010,
0b00110010,
0b00110010,

0b00100010,

0b01100010,
0b01100010,
0b01100010,

0b01100110,

0b01100100,
0b01100100,
0b01100100,

0b01000100,

0b11000100,
0b11000100,
0b11000100,

0b11001100,

0b11001000,
0b11001000,
0b11001000,

0b10001000,

0b10011000,
0b10011000,
0b10011000,

0b10011001,

0b10010001,
0b10010001,
0b10010001,

0b00010001
};

const uint16_t uAngle[] PROGMEM = {
0xF0, 176, 90, 41, 0xF0, 41, 90, 176
};



const uint16_t Ramp[] PROGMEM = {//acceleration, deceleration (step durations)
27145, 20829, 17560, 15471, 13987, 12862, 11972, 11244, 10635, 10115, 9665,  9270,  8920,  8606,
8324,  8068,  7834,  7619,  7421,  7238,  7067,  6908,  6760,  6620,  6489,  6366,  6249,  6138,
6033,  5933,  5839,  5748,  5662,  5579,  5500,  5424,  5351,  5281,  5214,  5149,  5087,  5026,
4968,  4912,  4858,  4805,  4754,  4705,  4657,  4611,  4566,  4522
};




// *************** Stepper Homing ****************
void home_stepper(void)
{
//postion reset (homing)
uint8_t tmp, tmpA= 0, tmpB= 0;
X.Ist= (X.Max>>1) +20 +OFFSET;
Y.Ist= (Y.Max>>1) +20 +OFFSET;
uint16_t delay;
while ((X.Ist != OFFSET) || (Y.Ist != OFFSET))
   {
if (X.Ist > OFFSET)
{
if (PIND &(1<<PD4))
{
if (PIND &(1<<PD6)) tmpA= pgm_read_byte(&Step[(--X.Ist &7)]); //move through full range (open loop)
else         tmpA= pgm_read_byte(&bStep[(--X.Ist &7)]);
tmpA &= 0b00001111;
}
else X.Ist= OFFSET; //Anschlag detected (closed loop reference)
}
if (Y.Ist > OFFSET)
{
if (PIND &(1<<PD5))
{
if (PIND &(1<<PD6)) tmpB= pgm_read_byte(&Step[(--Y.Ist &7)]);
else         tmpB= pgm_read_byte(&bStep[(--Y.Ist &7)]);
tmpB &= 0b11110000;
}
else Y.Ist= OFFSET;
}
tmp= tmpA;
tmp |= tmpB;
PORTA= tmp;
wdt_reset();
delay= Accel>>1;
while (delay != 0)
{
_delay_us(35);
delay--;
}
}

}




// *************** Initialization ****************
void init_system(void)
{
wdt_reset();
wdt_enable(WDTO_500MS); //enable watchdog (Timeout= 0.5s)
wdt_reset();

DDRA=  0xFF; //low outputs
PORTA= 0;

DDRD=  0b10000110; //DMX, spare, LED1
PORTD= 0b01111010;

TCCR1A = (1<<WGM10);
TCCR1B = (1<<CS10)|(1<<WGM12); //set T1 @clock freq, 8bit fast PWM
TIMSK |= (1<<TOIE1)|(1<<OCIE1A)|(1<<OCIE1B); //enable compare and overflow interrupts (u-step, system)


if (eeprom_read_byte(0) == 1)
{
X.Max= (uint16_t)(eeprom_read_byte(X_MAX_H)<<8) +(uint16_t)eeprom_read_byte(X_MAX_L);
Y.Max= (uint16_t)(eeprom_read_byte(Y_MAX_H)<<8) +(uint16_t)eeprom_read_byte(Y_MAX_L);
Accel= (uint16_t)(eeprom_read_byte(ACC_H)<<8)   +(uint16_t)eeprom_read_byte(ACC_L);
}
else
{
X.Max= 1600;
Y.Max= 1600;
Accel= 256;
}

     home_stepper();
init_pinouts(); // Establecer los puertos de E / S
init_timer(); // Establecer el temporizador
     init_DMX_RX();


}

// *************** Stepper speed control ****************
void check_speed(struct axis* Stp)
    {
    if (abs(Stp->Soll -Stp->Ist) <= abs(Stp->Speed)) //decel speed short before target position
    {
    if      (Stp->Speed < 0) Stp->Speed++;
    else if (Stp->Speed > 0) Stp->Speed--;
    }

    else if (Stp->Ist < Stp->Soll)//shall move in positive direction
   {
   if (Stp->Speed < 50) Stp->Speed++; //accel speed
   }

   else if (Stp->Ist > Stp->Soll) //shall move in negative direction
  {
  if (Stp->Speed > -50) Stp->Speed--; //accel speed
  }

  if      (Stp->Speed > 0) Stp->Ist++;
  else if (Stp->Speed < 0) Stp->Ist--;

  uint32_t tmp= (uint32_t)pgm_read_word(&Ramp[abs(Stp->Speed)]);
   Stp->StpRate= (tmp * Accel)>>16;
  }
//*************** PROGRAMA PRINCIPAL ************//
int main(void)

{
cli();
init_system(); // iniciar sistema
sei();
int PWM_timer;  // inicializar el timer PWM
char strobo = FALSE;  // valor de strobo
unsigned int strobo_timer=0; // Contador Strobo igual a cero

while(1) // bucle principal (LOOP)
    {
    get_dips(); // establecer direccion de inicio
     //************************************* PWM leds *********************************//
for (PWM_timer=0; PWM_timer<255 ; PWM_timer++)  // Loop timer general en un ciclo de llenado
{

if(DmxRxField[4]>20){ // Si el canal de luz stroboscópica es menor a  10 es siempre mayor que los LED ,el estroboscópico está apagado,
if( strobo_timer>(unsigned int)((255-DmxRxField[4])*16)){// Dmx CH4 igual a 11, es el tiempo máximo , o igual a 255 es el Tiempo min
strobo_timer=0;// Restablecer el temporizador
if(strobo){ strobo=FALSE;}else{ strobo=TRUE;} // Cambio habilitacion para ILUMINACIÓN
}else{
strobo_timer+=1; // base de tiempo strobo
}
}else{
strobo=TRUE; // la Stroboscopica está apagada,
}

if ( ((unsigned int)((DmxRxField[0]*DmxRxField[3])/255)>PWM_timer) && strobo ) //ROJO
{
PORTB &= ~(1<<PB0); //LED OFF
}else{
PORTB |= (1<<PB0); //LED ON
}

if ( ((unsigned int)((DmxRxField[1]*DmxRxField[3])/255)>PWM_timer) && strobo ) //VERDE
{
PORTB &= ~(1<<PB1); //LED OFF
}else{
PORTB |= (1<<PB1); //LED ON
}

if ( ((unsigned int)((DmxRxField[2]*DmxRxField[3])/255)>PWM_timer) && strobo ) //AZUL
{
PORTB &= ~(1<<PB2); //LED OFF
}else{
PORTB |= (1<<PB2); //LED ON

if (Flags &(1<<TICK))
     {
Flags &= ~(1<<TICK);
wdt_reset();
if (IndCnt-- == 0)
{
IndCnt= IND_TIME;
indicate();
}
     if (X.StpRate-- == 0)
{
      uint32_t tmp= ((uint32_t)DmxRxField[5]<<8) +(uint32_t)DmxRxField[6];
     tmp= OFFSET +((tmp * X.Max)>>16);
     if (tmp != X.Soll)
{
X.Soll= tmp;
IndFlags |= (1<<DATA_REFRESHED);
}
check_speed(&X);
Flags |= (1<<POS_CHANGED);
}
if (Y.StpRate-- == 0)
{
uint32_t tmp= ((uint32_t)DmxRxField[7]<<8) +(uint32_t)DmxRxField[8];
     tmp= OFFSET +((tmp * Y.Max)>>16);
     if (tmp != Y.Soll)
{
Y.Soll= tmp;
IndFlags |= (1<<DATA_REFRESHED);
}
check_speed(&Y);
Flags |= (1<<POS_CHANGED);
}

if (Flags &(1<<POS_CHANGED))
{
Flags &= ~(1<<POS_CHANGED);
uint8_t PatBuf;
if (PIND &(1<<PD6))
{
PatBuf= pgm_read_byte(&uStep[(X.Ist &31)]);//get new X pattern
}
else PatBuf= pgm_read_byte(&buStep[(X.Ist &31)]);
OCR1A= pgm_read_word(&uAngle[(X.Ist &0b111)]);
X.TopPat = (PatBuf>>4);
PatBuf= (PatBuf &0b00001111);
uint8_t Ytmp;
    if (PIND &(1<<PD6))
{
Ytmp= pgm_read_byte(&uStep[(Y.Ist &31)]);//get new Y pattern
}
else Ytmp= pgm_read_byte(&buStep[(Y.Ist &31)]);
OCR1B= pgm_read_word(&uAngle[(Y.Ist &0b111)]);
Y.TopPat = (Ytmp &0b11110000);
PatBuf |= (Ytmp<<4);
BasePat= PatBuf;
}
if (count == 0xFF)
{ // Llamado con 122Hz
count= 1;
   Flags |= (1<<IND);       // señalizar
   }
      else count++;
       }
}
  }
}
 
 //***** inicio del ocilador Temporizador de interrupción ****//
ISR(TIMER0_OVF_vect){
int count;
switch(mode){
case FADING;
count = OV_COUNT + DmxAddress;
break;
case RAINBOW_FADER;
count = OV_COUNT + DmxAddress * 10;
break;
default:
count = OV_COUNT;
     }
if(timer_counter>=count){
timer_counter=0;

if (mode==RAINBOW_FADER){

    indicate(); // señalizar con led azul
         }
  }else{ timer_counter++; }
if (Flags &(1<<EVAL_DMX)) // Universo DMX se actualiza
{
Flags &= ~(1<<EVAL_DMX);
IndFlags |= (1<<VALID_DMX); // Señal DMX Válida llegada
uint8_t i;
for (i=0; i<DMX_CHANNELS; i++)
{
if (DmxRxField[i] != DmxBuf[i]) // Un valor DMX ha cambiado?
{
DmxBuf[i]= DmxRxField[i];
IndFlags |= (1<<DATA_REFRESHED); // Sí -> borrar y actualizar dato!
}
}

}

if (Flags &(1<<IND)) // indicador LED, DIP
{
Flags &= ~(1<<IND);
    wdt_reset(); // Restablecer perro guardián

if (--IndiCnt == 0)
{
IndiCnt= 8;
indicate(); // señalizar con led azul
}
}
}




// *************** ISRs ****************
ISR (TIMER1_OVF_vect)
{ //half step
Flags |= (1<<TICK); //tick system
PORTA= BasePat;
}


ISR (TIMER1_COMPA_vect) //X-axis µ-Stepping
{
uint8_t buf;
buf  = PORTA;
buf &= 0b11110000;
buf |= X.TopPat;
PORTA= buf;
}


ISR (TIMER1_COMPB_vect) //Y-Axis µ-Stepping
{
uint8_t buf;
buf  = PORTA;
buf &= 0b00001111;
buf |= Y.TopPat;
PORTA= buf;
}
ac se ve claramente como funcionan los IRS en DMX  .,toma en consideracion que estan los dos timer usandose
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 27 de Agosto de 2015, 02:54:46
Citar
pero me largo error ., y calculo que los errores tiene el mismo origen que es el PWM en e lIRS

Ninguno de los errores/warning es debido a eso. Si lees claramente que dice cada uno.

Citar
y te vuelvo a repetir en DMX se tiene que ejecitar en WHILE o FOR pero fuera del IRS
la razon es que te afecta la recepcion del USAT como te explique antes  

Estas muy equivocado. Obviamente puedo hacer un "PWM" en el while. haciendo un for como vos pedis, es TOTALMENTE posible, pero practicamente insano hacerlo. tratar de que cada vuelta del for dure exactamente lo mismo para todos los modos, o posibilidades com oque tome un salto o no es realmente para sacarse el sombrero el que lo hace asi, vuelvo a decir, se puede, pero olvidate que alguien se va a complicar tanto para hacerlo cuando lo puede hacer mas facil, no se como estaras pensandolo vos pero yo me estoy fijando hasta la diferencia en micro segundos. Y lo pienso hasta el punto de ASM y ciclos de reloj.

A continuacion voy a darte una comparacion entre los 2:

Para darte un ejemplo, supongamos un PWM de 2 bits, es decir tenes 25% 50% 75% 100% duty. Esto para ser mucho mas simple y no de 8 bits con 255 pasos.
Que tenga un periodo de 1 segundo la señal de PWM ( Si tiene un periodo, este periodo es FIJO ), Cada seccion deberia poner a 0 o dejarla a 1 a la señal cada 0.25s

Nuestro caso es que tenemos un timer que lo hace cada 0.25s, entonces cuando ocurre eso nos fijamos y listo. si tuvieramos 25% de duty seleccionado, a los 0.25s exactamente verias la señal irse de 1 a 0. Genial. Se cumple con lo previsto
Cambiamos de modo. esto NO afecta al timer. sigue ejecutandose con su periodo inalterable y su duty perfecto.

Ahora imaginate un for(), en el que el primer paso por el for (valores tomados al azar pero que si lo haces en los 255 vas a ver que hay diferencia), le toma 200 instrucciones, el segundo paso le toma 240, el tercero le toma 210, el cuarto 220.

Bueno genial tenemos nuestro periodo, por que va a durar 200+240+210+220 (870) instrucciones, la primer vuelta para vos seria un 25% si usamos la logica que esta planteada. PERO realmente no es un 25% de duty sino que es 200/870 un 23%
Y bueno pero es una diferencia de 2%, nadie lo va a notar. Pero eso es por que yo seleccione valores cercanos, si esa primer vuelta hubiera sido de 50 instrucciones ( y no 200, ahora el total seria de 740 instrucciones ) tu duty (que vos supones de 25%) es de solo 50/740 = 7%. Ahora tenes un error de 18%.

Ahora si vos me aseguras que ese que lo hizo en C ( un lenguaje en el que no tiene control sobre la cantidad de instrucciones en ASM que se traduce en ciclos y tiempo a utilizar ) conto 1 por 1 las instrucciones de ASM por cada vuelta y por cada condicion si es que entra a algun IF o no, o lo que se le ocurra al compilador poner realmente tengo que creer que estas mintiendo.

Sigamos analizando el ejemplo que te di antes. Supone que dentro de ese for() tenes varios modos, no solo 1, tal cual tenemos en nuestro ejemplo FADING, FIJO, etc. el modo anterior duraba en total 740 instrucciones, ahora vamos a un modo mucho mas simple como es el de tener un valor fijo de color. Esto deberia llevar unas 20+20+20+20= 80 ( si todos iguales por que no se pregunta nada, simplemente se asigna y listo), Genial al no tener IF ni nada es fijo en cada una de las vueltas, lo cual mi 25% de duty es realmente mi 25%. Pero tengo que ahora dura un total de 80 instrucciones hacer todo el ciclo. Y exactamente aca le cambie el periodo/frecuencia de mi PWM. Que deberia ser un valor FIJO.

Peor aun y siendo mas estricto, una ves que se termino de hacer las 4 (o 255 si haces de 8 bits) vueltas del for. hay que hacer varias instrucciones mas hasta volver a entrar al for, esto puede tener una duracion fija o varaible, Supongamos que es fija. Analizemos los casos que presentamos ya

50+240+210+230= 740
20+20+20+20=80

Pero ahora tenemos eso y que supongamos sean unos 30 instrucciones mas entre que termina todo el for y vuelve a entrar a otro for

740 + 30
80 + 30

Aun mas GENIAL. estamos modificando aun mas el periodo de la señal, y sorpresa, ya nuestro 100% de duty ni siquiera es 100%.

740/770 = 96%
80/110 = 72%

Y ya no estamos hablando de DMX o lo que sea, sino que estamos hablando ya de no saber que es un PWM ( tanto Software como Hardware ). Por eso te vengo diciendo que es un error de concepto.

------------------

Ya con esto te explique claramente el por que NO debe usarse el for como vos opinas o crees para crear un PWM al menos no para algo tan complejo, lo que esta en ese codigo me parece es una aberracion como esta ejecutado el PWM.
Estoy mas que seguro que cualquier persona aca deberia decirte exactamente lo mismo. Sino sos libre de preguntar en

http://www.todopic.com.ar/foros/index.php?board=8.0

Y pregunta si un PWM deberia hacerse con un for(), por si crees que estoy loco ( aunque un poco no lo niego )
Espero que hasta con este ejemplo veas lo mal que esta aplicado por mas que vos creas que esta bien.

Citar
la razon es que te afecta la recepcion del USAT como te explique antes  

JAMAS, la UART deberia recibir el dato completo pasarlo a un buffer ( en el caso del ATmega8515 es el UDR) y luego seguir recibiendo el otro envio sin molestia al procesador. Cuando se ubica el dato en el buffer, ocurren 2 cosas, se sigue recibiendo datos por la UART y se activa la interrupcion de la UART el cual ubica el dato en donde corresponde, si existen 2 interrupciones juntas como la de la UART y el timer, se atenderia primero una y luego la otra (a no ser que tengan prioridades es una condicion de carrera y no se puede decir cual es primero).Sin afectar a nadie. Si tomara demasiado tiempo la interrupcion de la UART entonces estaria modificando los valores del periodo de la señal. Pero nada mas

Normalmente una interrupcion deberia contener el minimo de codigo para realizar lo que deba y continuar.
El ultimo codigo que me pasaste claramente usa los timers para los motores, estara bien o estara mal? Eso depende. Pero tranquilamente podria haber usado 1 timer al menos y con eso controlar todo.


--------------------------------------------------------


Otra cosa mas a recalcar con respecto a esto:

Citar
Aparte probe con la libreria reformada ., compilo sin error ( tuve que declarar FADING y RAIBOW_FADER

Que compile significa que el codigo esta bien escrito. NADA MAS
Que funcione como debe el codigo es otra cosa, podes tener un codigo que esta bien escrito semanticamente y sintacticamente pero no haga lo que uno trato de hacer estrictamente hablando.

Para terminar esto una consideracion mas.

El programa que te pase  si posee errores como que puse Array[] en ves de Array [3][2] y algunos mas ( que en realidad son 7 errores ) mas unos warning por no tener los prototipos de funciones.
En fin ese programa se abstrae completamente de lo que es el DMX, el DMX deberia funcionar tranquilamente aparte del programa y no afectarlo en ningun motivo.
Se podria separar en 2 partes independientes entre una y otra.
- Hacer el fading con los tiempos que deben ser. (Aqui uso los valores del DMX, y cuando me refiero a valores me refiero a cualquier cosa, podria haber definido 3 registros que me lleguen por SPI y aun asi funcionaria igual)
- Hacer el PWM por software (El cual se actualiza cuando debe y no depende de nadie, toma los valores y hace su trabajo)

El codigo del DMX deberia hacer lo mismo, solamente tomar los valores de la UART y ubicarlos donde deberia. FIN
Con eso tenes una independencia entre cada uno de los codigos, tal ves no se llegue a tal grado de independencia pero aun asi se logra bastante.

Es tu decisión final de como vas a terminar haciendolo al programa y el objetivo de mi post fue hacerte ver (con ejemplos) que estaba mal tu idea de como es un PWM por software. Aun asi sos libre de hacerlo como quieras.
Estoy por igual para responder cualquier duda que se te presente.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 27 de Agosto de 2015, 22:05:56
hola bueno
la verdad que no sabria que desirte amigo. por que eres la primer persona ., que me enseña desde 2013 que empece con los microsy la programacion
En ningun momento pongo en duda o contradigo lo que dices., 
porque me regalas tu experiencia y tu tiempo al compartir lo que apendio
pero le aclaro que no pongo en duda lo que dice.,(y explica con tanto detalle)
y le cuento por que .,yo aprendi solo y adquiri los conosimientos de acuerdo a lo que vi lei y razone
pero son trabjos de otras persionas ., yo jamas podria hacer eso ni mucho menos ( tengo muchisimo que aprender
yo lo pocoque se lo lo se por http://www.hoelscher-hi.de/hendrik/light/ressources.htm alli tiene varios ejemplos para mirar ., y tambien del mismo autor  http://www.hoelscher-hi.de/hendrik/light/openrdm.htm en la parte que dice DMX (a la izquierda) son ejemplos practicos con monyajes y librerias
tambien esta este señor http://www.ulrichradig.de/home/index.php/dmx (aunque aqui hat muchas cosa que no comprendo)
tambien consuto por aca http://www.mikrocontroller.net/forum/mikrocontroller-elektronik?filter=Henne%C2%B4s+DMX+Transceiver
y aca tambien http://www.avrfreaks.net/search/site/dmx?solrsort=ds_created%20desc
Pero principal inconveniente que tengo ., si yo  a medias se el español ., menos otros idiomas ., como el aleman , ingles , ruso o polaco
Por mas que use el traductor del navegador.,  las explicaciones me resultan incoerentes y menos entendible ., por no ser tecnico
Ahora al mirar los ejemplos de la red., los configuro como estan., si ellos se equivocan ., por supuesto que yo tambien
le suplico que le pegue una mirada ., talvez de esa manera me pueda explicar mejor
porque yo le digo sinseramente no ew visto ningun PWM en el IRS solo los COUNT que los manejan (hay otras formas como la de los motores pero no son PWM)
siseramente he quedado muy confundido ., pero es el precio que paga la ignorancia de las masa
todo lo que usted me explico lo encuentro razonable y logico
es lo otro lo que ya no entiendo
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 27 de Agosto de 2015, 22:24:26
Si, los comentarios cuando son en otro idioma son dificiles de agarrar, lo bueno es que el codigo funciona de la misma forma.
Puede que estes confundido por que ya habias asumido que se realizaba asi. Creo que con el ejemplo que te di aunque tal ves exagerado ves cual es la diferencia entre uno y otro. Y el por que se realiza de esa forma.

Por si las dudas, revise las paginas que me pasaste por si alguno cometia el error de hacerlo con un for, y saque estos ejemplos

De las paginas que me pasaste:
http://www.ulrichradig.de/home/index.php/avr/avr-rgb-leds

El codigo tiene esto:


Código: C
  1. ISR (TIMER0_OVF0_vect)
  2. {
  3.         if (pwm_counter++ > 63)
  4.         {
  5.                 PORTB = 0x00;
  6.                 pwm_counter = 0;
  7.         }
  8.         if (pwm_counter > pwm_r) PORTB |= LED_R;
  9.         if (pwm_counter > pwm_g) PORTB |= LED_G;
  10.         if (pwm_counter > pwm_b) PORTB |= LED_B;       
  11. }

Ese no usa DMX, es solo un PWM pero que recibe datos desde la UART, pero ahora vamos a ver un proyecto que usa DMX y realiza un "PWM" parecido ya que en realidad es un control de angulo de fase, pero tiene el mismo principio.
http://www.ulrichradig.de/home/index.php/avr/dmx-dimmer
Aqui lo que usa el codigo:

Ademas del ISR de la UART, tiene esta (Notaras la aplicacion que es identica o igual):
Código: C
  1. ISR (TIMER2_COMPA_vect)
  2. //############################################################################
  3. {
  4.         phase_off_count++;
  5.        
  6.         if(phase_off_count > 90) phase_off_count = 0;
  7.        
  8.         #if SSR_RELAIS1
  9.                 if(phase_off_count>val1)
  10.                 {
  11.                         SSR1_ON
  12.                 }
  13.                 else
  14.                 {
  15.                         SSR1_OFF
  16.                 }
  17.         #endif
  18.        
  19.         #if SSR_RELAIS2
  20.                 if(phase_off_count>val2)
  21.                 {
  22.                         SSR2_ON
  23.                 }
  24.                 else
  25.                 {
  26.                         SSR2_OFF
  27.                 }
  28.         #endif
  29.        
  30.         #if SSR_RELAIS3
  31.                 if(phase_off_count>val3)
  32.                 {
  33.                         SSR3_ON
  34.                 }
  35.                 else
  36.                 {
  37.                         SSR3_OFF
  38.                 }
  39.         #endif
  40.  
  41.         if(dmx_lost<DMX_LOST_TIMEOUT)
  42.         {
  43.                 dmx_lost++;
  44.         }
  45. }

de AVRFreaks:

http://www.avrfreaks.net/projects/8-channel-soft-pwm-dmx-receiver?skey=dmx%20pwm

DMX y un PWM por software de 8 canales ( es decir 8 salidas), Usa el Timer0

Código: C
  1. // Interrupt Service Routine
  2. SIGNAL (SIG_TIMER0_OVF)
  3. {
  4.   static unsigned char pinlevelB=0xFF; // was portmask
  5.   static unsigned char softcount=0xFF;
  6.  
  7.   PORTB = pinlevelB;            // update outputs
  8.  
  9.   if(++softcount == 0){         // increment modulo 256 counter and update
  10.                                 // the compare values only when counter = 0.
  11.     compare[0] = compbuff[0];   // verbose code for speed
  12.     compare[1] = compbuff[1];
  13.     compare[2] = compbuff[2];
  14.     compare[3] = compbuff[3];
  15.     compare[4] = compbuff[4];
  16.     compare[5] = compbuff[5];
  17.     compare[6] = compbuff[6];
  18.     compare[7] = compbuff[7];  // last element should equal CHMAX - 1
  19.  
  20.     pinlevelB = 0xFF;     // set all port pins high
  21.  
  22.   }
  23.   // clear port pin on compare match (executed on next interrupt)
  24.   if(compare[0] == softcount) CH0_CLEAR;
  25.   if(compare[1] == softcount) CH1_CLEAR;
  26.   if(compare[2] == softcount) CH2_CLEAR;
  27.   if(compare[3] == softcount) CH3_CLEAR;
  28.   if(compare[4] == softcount) CH4_CLEAR;
  29.   if(compare[5] == softcount) CH5_CLEAR;
  30.   if(compare[6] == softcount) CH6_CLEAR;
  31.   if(compare[7] == softcount) CH7_CLEAR;
  32.  
  33. } // end of ISR ...
  34.  
  35.  
  36. // *************** DMX Reception ISR ****************
  37. ISR (USART_RX_vect)

No busque muchos proyectos para encontrar eso, directamente busque aquellos con las siglas DMX y PWM, los primeros que abri me encontre con eso. Con esto quiero decirte que no estoy buscando si o si la excusa sino que realmente fueron los primeros que abri.

De la primer pagina que me pasaste ( http://www.hoelscher-hi.de/hendrik/light/dmxled.htm ) ya estan en ASM. pero incluso busque a la izquierda LED y abri el zip para encontrar esto:

Código: ASM
  1. ;interrupt vectors
  2. .org 0 
  3.         rjmp init               ;reset vector address
  4.         reti                    ;External Interrupt0 Vector Address
  5.         reti                    ;External Interrupt1 Vector Address
  6.         reti                    ;Input Capture1 Interrupt Vector Address
  7.         rjmp strobe             ;Output Compare1A Interrupt Vector Address
  8.         reti                    ;Output Compare1B Interrupt Vector Address
  9.         reti                    ;Overflow1 Interrupt Vector Address
  10.         rjmp pwm                ;Overflow0 Interrupt Vector Address
  11.         reti                    ;SPI Interrupt Vector Address
  12.         rjmp get_byte   ;UART Receive Complete Interrupt Vector Address

Utiliza la interrupcion ( por overflow ) del timer0 para generar el PWM. Y la interrupcion de la UART para los datos que llegan.
Y ahora que lo veo tiene un codigo parecido o el mismo al que inicio este hilo. En el que el PWM esta realizado con la interrupcion del Timer0 y aplicado de la misma forma que en todos los demas.

Es decir un contador que cuando llega a un punto se retea , en nuestro caso 255, algunos lo hacen con menos resolucion es decir pasos mas grandes y lo hacen 64. Eso depende de cada uno y el grado de variacion que va a poder tener.

Citar
es lo otro lo que ya no entiendo

Como te dije, sos libre de preguntar que si se la respuesta te la voy a intentar contestar, si no la conozco voy a buscarla, si realmente no me queda claro o no lo se, no me queda otra que decirte que no lo conozco, tal cual hice con lo de DMX. El cual no conocia como era el protocolo hasta que stk500 me dio ese empuje con la Nota de Applicacion.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 28 de Agosto de 2015, 02:09:04
!!!! perfecto mi amigo mas claro imposible ¡¡¡¡
la verdad que talvez habria convenido traducir la primer libreria de este hilo, porque son las mismas librerias DMX ., que yo uso (esta en ASM y la mia en C., pero son del mismo autor)
bueno aca te paso los errores que me da ahora en el primer caso NO ES el PWM ., sino que falta definir la funcion lo que es la palabra "salida" alli tengo tres errores
Código: [Seleccionar]
//***** inicio del ocilador Temporizador de interrupción ****//
     // void ISR(TIMER0_OVF_vect){
           ISR(TIMER0_OVF_vect){
      if (R_out>=PWM_timer) { salida &= 0x06; }
        if (V_out>=PWM_timer) { salida &= 0x05; }
    if (A_out>=PWM_timer) { salida &= 0x03; }
    if (PWM_timer==255)
    {
 
y los errores son estos
Código: [Seleccionar]
../fading_raibow.c:244: error: 'salida' undeclared (first use in this function)
../fading_raibow.c:244: error: (Each undeclared identifier is reported only once
../fading_raibow.c:244: error: for each function it appears in.)
La verdad que mire y pense la compilacion.,  y se que alli queres definir los puertos de salida ., estoy en la duda si te referis a PORTB (PORTB0 ,PORTB1 y PORTB2) 
bueno los otros errores que me larga son aca (lo escribiste antes pero no entendi como cambialos
Código: [Seleccionar]
DimmerCurva();
     
        ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
        ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
        if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
     
        Rojo = Temp_R;
        Azul = Temp_A;
        Verde = Temp_V;
       
        if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
     
    }
esto es lo que dice el compilador
Código: [Seleccionar]
../fading_raibow.c:201: error: subscripted value is neither array nor pointer
../fading_raibow.c:202: error: subscripted value is neither array nor pointer
../fading_raibow.c:203: error: subscripted value is neither array nor pointer
Espero que pueda compilar., asi probar y trato de hacer un video ., (por ahora pruebo con tras led de 5mm de 30°
pero ya compre 2 led de 20w rgb y estoy esperando que me lleguen
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 28 de Agosto de 2015, 02:34:12
../fading_raibow.c:201: error: subscripted value is neither array nor pointer
../fading_raibow.c:202: error: subscripted value is neither array nor pointer
../fading_raibow.c:203: error: subscripted value is neither array nor pointer

Esos imagino que fueron por que lo defini mal, si observas este es el codigo que tengo:

Código: C
  1. const uint8_t ArrayColorFadingRainbow[]={                       // Indice y valor a modificar   {Resta,Suma}
  2.                 {0,1},  //      Rojo-   ->      Verde+
  3.                 {1,2},  //      Verde-  ->      Azul+
  4.                 {2,0}   //      Azul-   ->      Rojo+
  5. };

Cambialo por :

Código: C
  1. const uint8_t ArrayColorFadingRainbow[3][2]={                   // Indice y valor a modificar   {Resta,Suma}
  2.                 {0,1},  //      Rojo-   ->      Verde+
  3.                 {1,2},  //      Verde-  ->      Azul+
  4.                 {2,0}   //      Azul-   ->      Rojo+
  5. };

Citar
La verdad que mire y pense la compilacion.,  y se que alli queres definir los puertos de salida ., estoy en la duda si te referis a PORTB (PORTB0 ,PORTB1 y PORTB2)

Con respecto a salida, fue un error de copy paste, tome el codigo que habia puesto anteriormente en el post y lo pegue, Vos elegis que salidas vas a usar ahi. Basicamente ahi lo que deberia hacer es poner a 0 cada una de los pin de salida. Si supongamos tenes el PORTB0 como salida del rojo

Código: C
  1. if (R_out>=PWM_timer) { PORTB &= ~(1<<PB0); }  // AND 1111 1110 (0xFE) , pone a 0 PORTB0
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 28 de Agosto de 2015, 16:19:43
Bueno amigo ., alli probe ., no me funciona., los sintomas son
  • las llaves mini-dips no funcionan., o sea no produce ningun cambio
  • tampoco hay cambio  a la funcion DMX ., (al no cambiar no funciona)
  • los led (encienden los tres) ocila su encendido (pestañeo)  tambien enciende PE0
  • en el traceo de avrstudio ., pasa de las nini-dips  a switch(mode)
si nesesita otra indicacion que pueda aportar para guiarlo  ., aviceme
asi quedo el codigo
Código: [Seleccionar]
  // #define F_CPU 8000000
    #include<util\delay.h>
    #include "lib_dmx_in.h"
    #include<stdio.h>
    #include<stdlib.h>
  
    #include <avr/interrupt.h>
    #include <avr/wdt.h>
 //************************************************************//    
    volatile uint8_t DmxRxField[DMX_CHANNELS];
    uint8_t DmxBuf[DMX_CHANNELS];
 //**********************************************************//    
  
    
    // Dato proveniente de la consola DMX
    
    #define DMX_R DmxRxField[1] //Canal R
    #define DMX_G DmxRxField[2] //Canal G
    #define DMX_B DmxRxField[3] //Canal B
    #define DMX_Modo DmxRxField[4] //Seleccion de Modo
    #define DMX_Velocidad DmxRxField[5] //Seleccion de Velocidad
    
    // Para simplificar los datos del array de colores que estoy usando.
    // ArrayColores contiene los valores RGB del momento
    
    #define Rojo ArrayColores[0]
    #define Verde ArrayColores[1]
    #define Azul ArrayColores[2]
    
    //*********************************//
    
    volatile uint16_t DmxAddress; // Dirección inicial
    
    uint8_t V_out,R_out,A_out; // Valores que se comparan con el PWM
    uint8_t V_aux,R_aux,A_aux; // Valores que se cambia para actualizar el PWM
    uint8_t PWM_timer=0;
    uint8_t estado=0,estador=0; // Estado de los fading
    
    const uint8_t arraydimmer[256]={
     0,     0,    1,    1,    1,    1,    1,    2,
     2,     2,    2,    3,    3,    3,    4,    4,
     4,     5,    5,    5,    6,    6,    7,    7,
     8,     8,    9,    9,   10,   10,   11,   11,
     12,   12,   13,   13,   14,   14,   15,   15,
     16,   16,   17,   17,   18,   18,   19,   19,
     20,   20,   21,   21,   22,   22,   23,   23,
     24,   24,   25,   25,   26,   27,   28,   29,
     30,   30,   31,   32,   33,   34,   35,   36,
     36,   37,   38,   39,   40,   41,   42,   43,
     43,   44,   45,   46,   47,   48,   49,   50,
     51,   52,   52,   53,   54,   55,   56,   57,
     58,   59,   60,   61,   62,   63,   64,   65,
     66,   67,   68,   69,   70,   71,   72,   73,
     74,   75,   76,   77,   78,   79,   80,   81,
     82,   83,   84,   85,   86,   88,   89,   90,
     91,   92,   93,   94,   95,   96,   97,   98,
     99,  100,  102,  103,  104,  105,  106,  107,
     108, 109,  110,  112,  113,  114,  115,  116,
     117, 119,  120,  121,  122,  123,  124,  126,
     127, 128,  129,  130,  132,  133,  134,  135,
     136, 138,  139,  140,  141,  142,  144,  145,
     146, 147,  149,  150,  151,  152,  154,  155,
     156, 158,  159,  160,  161,  162,  164,  165,
     167, 168,  169,  171,  172,  173,  174,  176,
     177, 178,  180,  181,  182,  184,  185,  187,
     188, 189,  191,  192,  193,  195,  196,  197,
     199, 200,  202,  203,  204,  206,  207,  208,
     210, 211,  213,  214,  216,  217,  218,  220,
     221, 223,  224,  226,  227,  228,  230,  231,
     233, 234,  236,  237,  239,  240,  242,  243,
     245, 246,  248,  249,  251,  252,  254,  255
    };
    
    uint8_t ArrayColores[3]={255,0,0}; // Rojo,Verde,Azul
    
    const uint8_t ArrayColorFading[]={ // Indice y valor a modificar {1,2,3} y {-1,-2,-3}
     1, // Rojo -> Amarillo
     0, // Amarilo -> Verde
     2, // Verde -> Cyan
     1, // Cyan -> Azul
     0, // Azul -> Magenta
     2 // Magenta -> Rojo
    };
    
     const uint8_t ArrayColorFadingRainbow[3][2]={ // Indice y valor a modificar {Resta,Suma}
     {0,1}, // Rojo- -> Verde+
     {1,2}, // Verde- -> Azul+
     {2,0} // Azul- -> Rojo+
    };
    
    //************* Inicialización pines / port *****************//
    void init_pinouts(){
        #ifdef USE_DIP
    
        DDRC  = 0; // establecer DIPs
        PORTC  = 0xFF;
        DDRE  &= ~((1<<PE2)|(1<<PE1));
        PORTE |=   (1<<PE2)|(1<<PE1);
     #endif
    
    
     DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); // Salida pin LED
     PORTB = 0;
     DDRE  |= (1<<PE0); //LED2 azul indicador
        PORTE = 0;
    
    }
    
    // ***** inicializacion del timer****//
    
    void init_timer(){
     TCCR0|= (1<<CS02) ; // Precontador 256
     TIMSK|= (1<<TOIE0); // desbordamientos de la interrupción
    
     }
    
        
    int main(void)
    {
     //***** Watchdog *****//
     wdt_reset();
     wdt_enable(WDTO_500MS); // Habilitar el watchdog (timeout = 0.5s)
     wdt_reset();
     cli();
     init_pinouts(); // Establecer los puertos de E / S
     init_timer(); // Establecer el temporizador
     init_DMX_RX(); // Inicializar recpcion DMX
     mode = FIXED; //Valores iniciales, hasta que llegue la trama del DMX
     Rojo = 0;
     Verde = 0;
     Azul = 0;
    
     sei();    // habilitar las interupciones globales  ???
    
     while(1) // bucle principal (LOOP)
        {
             get_dips(); // Toma la direccion y la actualiza, esto es para no tener que reiniciar a cada rato el DMX
             switch(mode)
             {
             case FIXED:
             Rojo = DMX_R; // Colores tomados directamente del DMX para fijo
             Verde = DMX_G;
             Azul = DMX_B;
             DimmerCurva(); // Actualizo colores para el PWM
             break;
             case FADING_FIX:
             fading_fijo();
             break;
             case FADING:
             fading_auto();
             break;
             case RAINBOW_FADING:
             rainbow_fader();
             break;
             default:
             break;
             }
        }
    }
    
    void fading_fijo(){
    
    }
    
    
    
    void fading_auto(){
    
     // Valores iniciales seteados cuando se cambia de modo
    
     //Espera
     delay(DMX_Velocidad);  //esperar
     //Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
     if(estado%2)
     { //Caso impar
     if(++ArrayColores[estado]==255) estado++;
     }
     else
     { //Caso par
     if(--ArrayColores[estado]==0) estado++;
     }
     if(estado>=6) estado=0;
     DimmerCurva();
    }
    
    void rainbow_fader(){
    
         int Temp_R,Temp_A,Temp_V;
         Temp_R = Rojo;
         Temp_A = Azul;
         Temp_V = Verde;
    
         if (estador==0){ //Caso inicial, Para que comienze con los valores que debe
             Rojo = 255;
             Verde = 0;
             Azul = 0;
         }
         DimmerCurva();
    
       ArrayColores[ArrayColorFadingRainbow[estador][1]]++; //Sumo
       ArrayColores[ArrayColorFadingRainbow[estador][0]]--; //Resto
       if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++; //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
    
         Rojo = Temp_R;
         Azul = Temp_A;
         Verde = Temp_V;
        
       if(estador>=3) estador=0; fading_auto(); //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
    
    }
    
    void DimmerCurva(){
    
         R_aux=arraydimmer[Rojo];
         V_aux=arraydimmer[Verde];
         A_aux=arraydimmer[Azul];
    }
    
    void delay(uint8_t DMX_Velocidad) {
    
     // Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
     // Tiempo Minimo = 3us
     // Tiempo Maximo = 580ms
     // Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
    
     uint16_t tiempo;
     if (DMX_Velocidad>127)
     { //Tiempo en milisegundos, Recta de 1ms a 508ms
     tiempo = 4*DMX_Velocidad - 511;
     //_delay_ms(tiempo);
     }
     else
     { //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
     tiempo = 7*DMX_Velocidad +3;
     //_delay_us(tiempo);
     }
    }
    
    
     //***** inicio del ocilador Temporizador de interrupción ****//
          ISR(TIMER0_OVF_vect){
          
     if (R_out>=PWM_timer) { PORTB &= ~(1<<PB0); }  // AND 1111 1110 (0xFE) , pone a 0 PORTB0
      if (V_out>=PWM_timer) { PORTB &= ~(1<<PB1); }  // AND 1111 1110 (0xFE) , pone a 0 PORTB0
     if (R_out>=PWM_timer) { PORTB &= ~(1<<PB2); }  // AND 1111 1110 (0xFE) , pone a 0 PORTB0
     if (PWM_timer==255)
     {
     //Cargo los colores nuevos ya que finalizo el ciclo del PWM
     R_out = R_aux;
     V_out = V_aux;
     A_out = A_aux;
     //Observo si se cambio el modo, asi cambio el modo y seteo los valores iniciales de ser necesario
     Cambiarmodo();
     }
     PWM_timer++;
    }
    
     void Cambiarmodo(){
     switch(DMX_Modo&0xC0) // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
     {
     case 0xC0: //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
     if(mode!=RAINBOW_FADING) //Reviso que ya no este en este modo.
     {
     mode=RAINBOW_FADING;
     Rojo=255; // Set de colores iniciales
     Verde=0;
     Azul=0;
     estado=0; // Set de estado inicial para el fading
     estador=0; // Set de estado inicial para el rainbow_fading
     }
     break;
     case 0x80: //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
     if(mode!=FADING) // Si ya esta en el modo, que no lo modifique.
     {
     mode=FADING;
     Rojo=255; // Set de colores iniciales
     Verde=0;
     Azul=0;
     estado=0; // Set de estado inicial para el fading
     }
     break;
     case 0x40: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
     mode=FADING_FIX; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
     break;
     case 0x00: //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
     mode=FIXED; // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
     break;
     }
     }
la libreria de dmx .C
Código: [Seleccionar]
#include "lib_dmx_in.h"
//#include "lib_indicator.h"
// ********************* definiciones locales*********************
 
enum {IDLE, BREAK, STARTB, STARTADR};// estados DMX

    
    
  uint8_t gDmxState;
uint8_t *gDmxPnt;
uint16_t DmxCount;  
                                                                                                                                                                                              
//volatile uint8_t gDmxState;
 
 
// *************** DMX recepción de inicialización ****************
void init_DMX_RX(void)
{
#ifdef USE_DIP
 
DDRC  = 0; // establecer DIPs
PORTC  = 0xFF;
DDRE  &= ~((1<<PE2)|(1<<PE1));
PORTE |=   (1<<PE2)|(1<<PE1);
 
#endif
 
DDRD  |= (1<<2);
PORTD &= ~(1<<2);
UBRRH  = 0; // Habilitar recepción
UBRRL  = ((F_OSC/4000)-1);// 250kBaud, 8N2
UCSRC  = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB  = (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;

uint8_t i;
for (i=0; i<DMX_CHANNELS; i++)
{
DmxRxField[i]= 0;
}

}
 
 
 
// ************* obtener DMX dirección de inicio **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp;
 
if (!(PINE &(1<<PE1))){ // Modo Manual
Temp=  // DMXAdress = tiempo de retardo
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
     (!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128);
DmxAddress= Temp;
if (!(PINE &(1<<PE2))) // Manual,
    {
mode= FADING;
}else{
mode= RAINBOW_FADING;

     }
UCSRB &= ~(1<<RXCIE);// Receptor Desactivar si la dirección de inicio = 0

return;

 }
mode=DMX;
Temp=
(!(PINC &(1<<PC0)) *1) +
(!(PINC &(1<<PC1)) *2) +
(!(PINC &(1<<PC2)) *4) +
(!(PINC &(1<<PC3)) *8) +
(!(PINC &(1<<PC4)) *16) +
(!(PINC &(1<<PC5)) *32) +
(!(PINC &(1<<PC6)) *64) +
(!(PINC &(1<<PC7)) *128) +
(!(PINE &(1<<PE2)) *256);
 
if (Temp != 0)
{
DmxAddress= Temp;
if (!(UCSRB &(1<<RXCIE)))// Si el receptor esta desabilitado -> habilitar y esperar descanso
{
gDmxState= IDLE;
UCSRB |= (1<<RXCIE);

}
}
else
{
UCSRB &= ~(1<<RXCIE); // Receptor Desactivar si la dirección de inicio = 0

uint8_t i;
for (i=0; i<sizeof(DmxRxField); i++)
{
DmxRxField[i]= 0;
}
}
 
#endif
}
 
 
 
// *************** DMX recepción ISR ****************//
ISR (UART_RX_vect)
{
static  uint16_t DmxCount;
uint8_t  USARTstate= UCSRA; // Obtener estado antes de los datos!
uint8_t  DmxByte   = UDR; // Obtener los datos
uint8_t  DmxState  = gDmxState;// Cargar una sola vez de SRAM para aumentar la velocidad
  
if (DmxState == BREAK)
{
UCSRA &= ~(1<<FE); // Cambiar Posible FE: a causa de MAB
if (DmxByte == 0)
{
gDmxState= STARTB;// Código de inicio normal detectado
gDmxPnt= ((uint8_t*)DmxRxField +1);
}
else
{
gDmxState= IDLE;
}
}

else if (USARTstate &(1<<FE)) // Comprobar para el descanso de la señal
{
UCSRA &= ~(1<<FE); // Restablecer bandera
if (DmxByte == 0) // Los datos de descanso debe ser 0
{
gDmxState= BREAK;
DmxCount= DmxAddress; // Restablecer contador de fotogramas
}
else
{
gDmxState= IDLE; // Bien es FE -> esperar descanso
}
}

else if (DmxState == STARTB)
{
if (--DmxCount == 0)// Dirección inicial alcanzada?
{
gDmxState= STARTADR;
DmxRxField[0]= DmxByte;
}
}

else if (DmxState == STARTADR)
{
uint8_t *DmxPnt;
DmxPnt= gDmxPnt;
*DmxPnt= DmxByte;
if (++DmxPnt >= (DmxRxField + DMX_CHANNELS )) // los (CHANNEL) canales recibidos?
{
Flags |= (1<<EVAL_DMX);// Conjunto de datos listo -> eval en principal (MAIN)
gDmxState= IDLE;
}
else
{
gDmxPnt= DmxPnt;
}
}
}

y la libreria dmx.H
Código: [Seleccionar]
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define DMX_CHANNELS    (13)
#define  USE_DIP
#define  F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
enum {EVAL_DMX, IND};
volatile uint8_t Flags;
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING,DMX} mode;
volatile uint16_t DmxAddress; // Dirección inicial
volatile int  color_number;// numero de la tabla de Color del sonido / manual actual
volatile uint8_t DmxRxField[DMX_CHANNELS]; // Conjunto de vals DMX (cruda)
extern void    init_DMX_RX(void);
extern void    get_dips(void);
extern void    set_color(int color);

Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 28 de Agosto de 2015, 20:31:48
Ya voy a ver cual es el problema. Se me ocurren algunas cosas que puede haber mal.

Citar
las llaves mini-dips no funcionan., o sea no produce ningun cambio
tampoco hay cambio  a la funcion DMX ., (al no cambiar no funciona)

Algun conflicto en como se toman los datos, ademas veo que usas el "mode" ahi dentro del codigo del DMX, el cual no deberias, la libreria de DMX deberia ser totalmente ajena a como es el programa principal, sino cada vez que compilas un codigo tenes que reformar la libreria, tambien cada uno de los codigos hace uso de variables que no me parecen estar bien definidas. Ya que el .hex lo esta definiendo en el main.c y en la libreria de DMX .c y poseen un scope de file por lo que a no ser que se use un extern no podrias acceder a la otra. Por otro lado tampoco deberias. Tampoco se por que estan definidas las funciones con "extern" en el .h.
En fin ya voy a verla y lo modifico y ves como queda.

Una pregunta El DIP
Los bits de 0 a 6 es la direccion y el 7 lo queres poner manual/dmx ?
Por que si es asi tengo que reformar el programa :P un poquito

Citar
los led (encienden los tres) ocila su encendido (pestañeo)  tambien enciende PE0

Yo le quite todo el soporte a PE0 , antes encendia y apagaba a cada ratito. simplmente opte por quitarlo. debe encenderse al comienzo del programa sino no se por que lo hace.
Con respecto a que los leds pestañeen puede ser que este mal configurado el tiempo del timer. ya que no le preste atencion a los tiempos de carga ni preescalers.
Otra causa puede ser el WDT, se podria quitar para probar inicialmente el codigo. Tenes que recordar que hay delays que duran hasta 580ms y vos tenes un WDT de 0.5s ( si es que llega a ese tiempo )

Citar
en el traceo de avrstudio ., pasa de las nini-dips  a switch(mode)
Realmente no se por que.
Ahora simplemente tengo que ver todos los codigos para ver que esta pasando.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 28 de Agosto de 2015, 23:10:03
hola
bueno yo tambientenia dudas de eso y compile con otra libria dmx_in  pero paso lo mismo ., el pin N° 10 no desabilita ni habilita
no se enque parte de tu codigo esta esa llave talves como compilo tenga dos funciones y no una
la libreria que probe que te dije  es esta
 
Código: [Seleccionar]
/**** A P P L I C A T I O N   N O T E   ************************************
*
* Title : DMX512 reception library
* Version : v1.3
* Last updated : 13.04.09
* Target : Transceiver Rev.3.01 [ATmega8515]
* Clock : 8MHz, 16MHz
*
*
***************************************************************************
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version2 of
 the License, or (at your option) any later version.

;***************************************************************************/

#include "lib_dmx_in.h"

// ********************* local definitions *********************

enum {IDLE, BREAK, STARTB, STARTADR}; //DMX states

volatile uint8_t gDmxState;


// *************** DMX Reception Initialisation ****************
void init_DMX_RX(void)
{
#ifdef USE_DIP
DDRC   = 0; //set up DIPs
PORTC  = 0xFF;
DDRE  &= ~((1<<PE2)|(1<<PE1));
PORTE |=   (1<<PE2)|(1<<PE1);
#endif

DDRD  |= (1<<2);
PORTD &= ~(1<<2);
UBRRH  = 0; //enable reception
UBRRL  = ((F_OSC/4000)-1); //250kbaud, 8N2
UCSRC  = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
UCSRB  = (1<<RXEN)|(1<<RXCIE);
gDmxState= IDLE;
}



// ************* get DMX start address **************
void get_dips(void)
{
#ifdef USE_DIP
uint16_t Temp= (0xFF-PINC);//invert DIP state
if (!(PINE &(1<<2)))
{
Temp += 256; //9th bit
}
if (Temp != 0)
{
DmxAddress= Temp;
if (!(UCSRB &(1<<RXCIE))) //if receiver was disabled -> enable and wait for break
{
gDmxState= IDLE;
UCSRB |= (1<<RXCIE);
}
}
else
{
UCSRB &= ~(1<<RXCIE);//disable Receiver if start address = 0
uint8_t i;
for (i=0; i<sizeof(DmxRxField); i++)
{
DmxRxField[i]= 0;
}
}
#endif
}



// *************** DMX Reception ISR ****************
ISR (UART_RX_vect)
{
static  uint16_t DmxCount;
uint8_t  USARTstate= UCSRA;//get state before data!
uint8_t  DmxByte   = UDR;//get data
uint8_t  DmxState  = gDmxState; //just load once from SRAM to increase speed
 
if (USARTstate &(1<<FE))//check for break
{
UCSRA &= ~(1<<FE); //reset flag (necessary for simulation in AVR Studio)
DmxCount =  DmxAddress; //reset channel counter (count channels before start address)
gDmxState= BREAK;
}

else if (DmxState == BREAK)
{
if (DmxByte == 0) gDmxState= STARTB;//normal start code detected
else   gDmxState= IDLE;
}

else if (DmxState == STARTB)
{
if (--DmxCount == 0) //start address reached?
{
DmxCount= 1;//set up counter for required channels
DmxRxField[0]= DmxByte;//get 1st DMX channel of device
gDmxState= STARTADR;
}
}

else if (DmxState == STARTADR)
{
DmxRxField[DmxCount++]= DmxByte;//get channel
if (DmxCount >= sizeof(DmxRxField)) //all ch received?
{
gDmxState= IDLE; //wait for next break
}
}
}

corregi lo dela libreria .H  quedo asi
Código: [Seleccionar]
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#define DMX_CHANNELS    (13)
#define  USE_DIP
#define  F_OSC (8000) // Frec oscilador. en kHz (8MHz típico o 16MHz)
enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING,DMX} mode;
volatile uint16_t DmxAddress; // Dirección inicial
enum {EVAL_DMX, IND};
volatile uint8_t Flags;
volatile uint8_t DmxRxField[DMX_CHANNELS]; // Conjunto de vals DMX (cruda)
extern void    init_DMX_RX(void);
extern void    get_dips(void);


Y hace lo mismo .,
En cuanto a lo MINI-DIPS si te fijas el la ultima libreria que subi (es distinta a la otra ., esta es la original sin reformas) prestale atencion a los dips., porque esta dedinidos a GND ., ojo (la otra tambien ) pero eran del PINC0 a PINC7 y PINE1 , PINE2 tiene dos posiciones definidas !!!!pero ojo son 9 llaves la de dmx NO 8 ¡¡¡
la llave N° 10 no se usa como direccion sino que se usa como conmutador , (en off DMX y en on (lo que quiera hacer manual ) ., si o si es reservada funcion DMX NO se TOCA porque es la que desabilita la recepcion """ if (!(UCSRB &(1<<RXCIE)))   //if receiver was disabled -> enable and wait for break """ ., sin pasa lo que ahora.,  no funciana dmx (peroesta habilitado
Esa era mi incitencia ., que usaras las llaves del primer array ., porque el segundo era para dmx .,y se leen con la funcion GEP_dip ., asi de facil (se use o no la recepcion de DMX., igual te las lee   
el WDT lo desgrabe de la configuracion de fuses """"" wdt_enable(WDTO_500MS);""" y son 500ms .,pero no es alli el problema ., pero hace el mismo defecto .(fijate que no esta puesto o conectado el pin RESET del uC)
cualquier otro dato que nesesites te lo aporto
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 31 de Agosto de 2015, 03:44:30
Por fin termine el codigo, no se que tal estara ya que no se TODOS los errores que pueden salir, debido a que no lo compile :P. A partir de aca creo que estas solo pero no voy a poder dedicarle mucho tiempo como ya lo hice, por que necesito dedicarme a otras cosas que tengo que hacer. Pero cuando tenga un tiempo te doy una mano.

main.c
Código: C
  1. /*
  2.  *  DMX_RGB FADING/FIXED/RAINBOW
  3.  *
  4.  *  Created on: 23/08/2015
  5.  *  Author:
  6.  */
  7.  
  8.  
  9.  
  10. /*
  11.  *  SECCION DE INCLUDES
  12.  *
  13.  */
  14.  
  15. // Include para la definicion de las variables
  16. #include <stdint.h>
  17.  
  18. // Include liberias del micro, Interrupcion / WDT / delay
  19.  
  20. #include <util\delay.h>
  21. #include <avr/interrupt.h>
  22. //#include <avr/wdt.h>
  23.  
  24.  
  25. // Include funcione de DMX
  26. #include "dmx.h"
  27.  
  28. /*
  29.  *
  30.  *  PROTOTIPOS DE FUNCIONES
  31.  *
  32.  *
  33.  */
  34.  
  35. // Funciones de inicializacion de modulos
  36. void vInitPinout(void);
  37. void vInitTimer0(void);
  38.  
  39. //Funciones Auxiliares
  40. void DimmerCurva(void);
  41. void delay(void);
  42. void Cambiarmodo(void);
  43.  
  44. // Modos
  45. void fixed_color(void);
  46. void fading_fijo(void);
  47. void fading_auto(void);
  48. void rainbow_fader(void);
  49.  
  50. /*
  51.  *
  52.  *
  53.  * DEFINICION DE VARIABLES
  54.  *
  55.  *
  56.  */
  57.  
  58. enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode,last_mode;
  59.  
  60. // Dato proveniente de la consola DMX
  61.  
  62. extern uint8_t DmxRxField[DMX_CHANNELS];        // Valores externos tomados desde la libreria.
  63.  
  64. #define DMX_R                   DmxRxField[1]   //Canal R
  65. #define DMX_G                   DmxRxField[2]   //Canal G
  66. #define DMX_B                   DmxRxField[3]   //Canal B
  67. #define DMX_Modo                DmxRxField[4]   //Seleccion de Modo
  68. #define DMX_Velocidad   DmxRxField[5]   //Seleccion de Velocidad
  69.  
  70. // Para simplificar los datos del array de colores que estoy usando.
  71. // ArrayColores contiene los valores RGB del momento
  72.  
  73. #define Rojo                    ArrayColores[0]
  74. #define Verde                   ArrayColores[1]
  75. #define Azul                    ArrayColores[2]
  76.  
  77. // Definicion de salidas para los colores
  78.  
  79. #define DDR_PWM                 DDRB
  80. #define PORT_PWM                PORTB
  81. #define PWM_R                   PB0
  82. #define PWM_G                   PB1
  83. #define PWM_B                   PB2
  84.  
  85. //*********************************//
  86.  
  87. uint8_t V_out,R_out,A_out;                                              // Valores que se comparan con el PWM
  88. uint8_t V_aux,R_aux,A_aux;                                              // Valores que se cambia para actualizar el PWM
  89. uint8_t PWM_timer=0,Alpha;
  90. uint8_t estado=0,estador=0;                                     // Estado de los fading
  91.  
  92. const uint8_t arraydimmer[256]={
  93.                  0,     0,    1,    1,    1,    1,    1,    2,
  94.                  2,     2,    2,    3,    3,    3,    4,    4,
  95.                  4,     5,    5,    5,    6,    6,    7,    7,
  96.                  8,     8,    9,    9,   10,   10,   11,   11,
  97.                  12,   12,   13,   13,   14,   14,   15,   15,
  98.                  16,   16,   17,   17,   18,   18,   19,   19,
  99.                  20,   20,   21,   21,   22,   22,   23,   23,
  100.                  24,   24,   25,   25,   26,   27,   28,   29,
  101.                  30,   30,   31,   32,   33,   34,   35,   36,
  102.                  36,   37,   38,   39,   40,   41,   42,   43,
  103.                  43,   44,   45,   46,   47,   48,   49,   50,
  104.                  51,   52,   52,   53,   54,   55,   56,   57,
  105.                  58,   59,   60,   61,   62,   63,   64,   65,
  106.                  66,   67,   68,   69,   70,   71,   72,   73,
  107.                  74,   75,   76,   77,   78,   79,   80,   81,
  108.                  82,   83,   84,   85,   86,   88,   89,   90,
  109.                  91,   92,   93,   94,   95,   96,   97,   98,
  110.                  99,  100,  102,  103,  104,  105,  106,  107,
  111.                  108, 109,  110,  112,  113,  114,  115,  116,
  112.                  117, 119,  120,  121,  122,  123,  124,  126,
  113.                  127, 128,  129,  130,  132,  133,  134,  135,
  114.                  136, 138,  139,  140,  141,  142,  144,  145,
  115.                  146, 147,  149,  150,  151,  152,  154,  155,
  116.                  156, 158,  159,  160,  161,  162,  164,  165,
  117.                  167, 168,  169,  171,  172,  173,  174,  176,
  118.                  177, 178,  180,  181,  182,  184,  185,  187,
  119.                  188, 189,  191,  192,  193,  195,  196,  197,
  120.                  199, 200,  202,  203,  204,  206,  207,  208,
  121.                  210, 211,  213,  214,  216,  217,  218,  220,
  122.                  221, 223,  224,  226,  227,  228,  230,  231,
  123.                  233, 234,  236,  237,  239,  240,  242,  243,
  124.                  245, 246,  248,  249,  251,  252,  254,  255
  125. };
  126.  
  127. uint8_t ArrayColores[3]={255,0,0};                      // Rojo,Verde,Azul
  128.  
  129. const uint8_t ArrayColorFading[6]={                     // Indice y valor a modificar   {0,1,2} = {R,G,B} ; indice par = incremento ; indice impar = decremento
  130.                  1,     //      Rojo    ->      Amarillo
  131.                  0,     //      Amarilo ->      Verde
  132.                  2,     //      Verde   ->      Cyan
  133.                  1,     //      Cyan    ->      Azul
  134.                  0,     //      Azul    ->      Magenta
  135.                  2      //      Magenta ->      Rojo
  136. };
  137.  
  138. const uint8_t ArrayColorFadingRainbow[3][2]={                   // Indice y valor a modificar   {Decremento,Incremento}
  139.                 {0,1},  //      Rojo-   ->      Verde+
  140.                 {1,2},  //      Verde-  ->      Azul+
  141.                 {2,0}   //      Azul-   ->      Rojo+
  142. };
  143.  
  144. /*
  145.  *
  146.  *
  147.  *  CODIGOS DE INICIALIZACION DE MODULOS
  148.  *
  149.  *
  150.  */
  151.  
  152. //************* Inicialización pines / port *****************//
  153. void vInitPinout(void){
  154.  
  155.         // Configuracion de las llaves DIP para el DMX
  156.  
  157.     // Configuracion de salidas
  158.         DDR_PWM |= (1<<PWM_R) | (1<<PWM_G) | (1<<PWM_B);                // Salida pin LEDs , PB0 = Rojo, PB1 = Verde, PB2 = Azul
  159.         PORT_PWM = 0;
  160.         DDRE  |= (1<<PE0);                              // LED indicador de funcionamiento en PE0
  161.     PORTE = 0;
  162.  
  163. }
  164.  
  165. // ***** inicializacion del timer****//
  166.  
  167. void vInitTimer0(void){
  168.                 TCCR0= (1<<CS00) ;      // Preescaler 1:1
  169.                 TIMSK|= (1<<TOIE0);     // desbordamientos de la interrupción
  170. }
  171.  
  172. /*
  173.  *
  174.  *
  175.  *  PROGRAMA PRINCIPAL
  176.  *
  177.  *
  178.  */
  179.  
  180. int main(void)
  181. {
  182.  
  183.         vInitPinout();          // Establecer los puertos de E / S
  184.         vInitTimer0();          // Establecer el timer
  185.         vInit_DMX_RX();         // Iniciar la UART y puertos para la llave DIP
  186.  
  187.         last_mode = mode = FIXED;               //Valores iniciales, hasta que llegue la trama del DMX
  188.         Rojo = 0;
  189.         Verde = 0;
  190.         Azul = 0;
  191.  
  192.         sei();              // habilitar las interupciones, Timer/UART(DMX) habilitados
  193.  
  194.         while(1)        // bucle principal (LOOP)
  195.             {
  196.                         if(!bGetDips()){last_mode=mode=FADING;}         // Pregunto si esta activo el DMX y Toma la direccion y la actualiza, tambien desabilita el DMX de ser necesario
  197.                 if(last_mode!=mode){Cambiarmodo();}                     // Caso que desde el DMX se pida cambiar el modo, cambia unicamente cuando termino la rutina
  198.                 switch(last_mode)
  199.                 {
  200.                 case FIXED:
  201.                                 fixed_color();
  202.                                 break;
  203.                 case FADING_FIX:
  204.                                 fading_fijo();
  205.                                 break;
  206.                 case FADING:
  207.                                 fading_auto();
  208.                                 break;
  209.                 case RAINBOW_FADING:
  210.                                 rainbow_fader();
  211.                                 break;
  212.                 default:
  213.                                 break;
  214.                 }
  215.             }
  216. }
  217.  
  218. /*
  219.  *
  220.  *
  221.  *  MODOS DE OPERACION
  222.  *
  223.  *  fixed_color() - Color fijo, tomado desde el DMX.
  224.  *  fading_fijo() - Produce el efecto de fading con el color tomado del DMX, pero solo ese color, de 0 a 255.
  225.  *  fading_auto() - Comienza la ejecucion de fading de distintos colores, solo toma en cuenta la velocidad, solo 1 color a la ves.
  226.  *  rainbow_fading() - Agregado al  fading_auto(), en caso que se seleccione este, se modificaran 2 colores en ves de 1.
  227.  */
  228.  
  229. void fixed_color(void){
  230.         Rojo = DMX_R;           // Colores tomados directamente del DMX para fijo
  231.         Verde = DMX_G;
  232.         Azul = DMX_B;
  233.         DimmerCurva();          // Actualizo colores para el PWM
  234. }
  235.  
  236. void fading_fijo(void){
  237.         Rojo = DMX_R * (Alpha/255);             // Colores tomados directamente del DMX para fijo
  238.         Verde = DMX_G * (Alpha/255);
  239.         Azul = DMX_B * (Alpha/255);
  240.         DimmerCurva();
  241.         Alpha++;
  242.         delay();
  243. }
  244.  
  245.  
  246.  
  247. void fading_auto(void){
  248.  
  249.                 // Valores iniciales seteados cuando se cambia de modo
  250.  
  251.                 //Espera
  252.                 delay();  //esperar
  253.                 //Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
  254.                 if(estado%2)
  255.                 {       //Caso impar
  256.                         if(++ArrayColores[estado]==255) estado++;
  257.                 }
  258.                 else
  259.                 {       //Caso par
  260.                         if(--ArrayColores[estado]==0) estado++;
  261.                 }
  262.                 if(estado>=6) estado=0;
  263.                 DimmerCurva();
  264. }
  265.  
  266. void rainbow_fader(void){
  267.  
  268.         int Temp_R,Temp_A,Temp_V;
  269.         Temp_R = Rojo;
  270.         Temp_A = Azul;
  271.         Temp_V = Verde;
  272.  
  273.         if (estador==0){                                                                                                        //Caso inicial, Para que comienze con los valores que debe
  274.                 Rojo = 255;
  275.                 Verde = 0;
  276.                 Azul = 0;
  277.         }
  278.         DimmerCurva();
  279.  
  280.                 ArrayColores[ArrayColorFadingRainbow[estador][1]]++;                            //Sumo
  281.                 ArrayColores[ArrayColorFadingRainbow[estador][0]]--;                            //Resto
  282.                 if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++;       //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
  283.  
  284.         Rojo = Temp_R;
  285.         Azul = Temp_A;
  286.         Verde = Temp_V;
  287.  
  288.                 if(estador>=3) estador=0; fading_auto();                                                        //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
  289.  
  290. }
  291.  
  292. /*
  293.  *
  294.  *
  295.  *  UTILIDADES
  296.  *
  297.  *
  298.  * DimmerCurva() - Actualiza los colores para que el PWM tome los valores nuevos
  299.  * delay() - Demora introducida para modificar la velocidad de los efectos
  300.  * Cambiarmodo() - Funcion usada que toma el valor del DMX, traduciendolo y efectua el cambio.
  301.  */
  302.  
  303. void DimmerCurva(void){
  304.  
  305.         R_aux=arraydimmer[Rojo];
  306.         V_aux=arraydimmer[Verde];
  307.         A_aux=arraydimmer[Azul];
  308. }
  309.  
  310. void delay(void) {
  311.  
  312.         // Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
  313.         // Tiempo Minimo = 3us
  314.         // Tiempo Maximo = 580ms
  315.         // Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
  316.  
  317.         uint16_t tiempo;
  318.         if (DMX_Velocidad>127)
  319.         {       //Tiempo en milisegundos, Recta de 1ms a 508ms
  320.                 tiempo = 4*DMX_Velocidad - 511;
  321.                 //_delay_ms(tiempo);
  322.         }
  323.         else
  324.         {       //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
  325.                 tiempo = 7*DMX_Velocidad +3;
  326.                 //_delay_us(tiempo);
  327.         }
  328. }
  329.  
  330.  
  331. void Cambiarmodo(void){
  332.  
  333.          last_mode=mode;
  334.  
  335.          switch(mode)   // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
  336.          {
  337.          case RAINBOW_FADING:           //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
  338.                  Rojo=255;                              // Set de colores iniciales
  339.                  Verde=0;
  340.                  Azul=0;
  341.                  estado=0;                              // Set de estado inicial para el fading
  342.                  estador=0;                             // Set de estado inicial para el rainbow_fading
  343.                  break;
  344.          case FADING:                           //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
  345.                  Rojo=255;                              // Set de colores iniciales
  346.                  Verde=0;
  347.                  Azul=0;
  348.                  estado=0;                              // Set de estado inicial para el fading
  349.                  break;
  350.          default:                                       //Case FADING_FIX, de 64 a 127, y FIXED, de 0 a 63. Bits de mayor peso quedan siempre en 01 y 00
  351.                  break;
  352.          }
  353.  }
  354.  
  355. void SetMode(void){
  356.  
  357.          switch(DMX_Modo&0xC0)  // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
  358.          {
  359.          case 0xC0:                                             //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
  360.                  mode=RAINBOW_FADING;
  361.                  break;
  362.          case 0x80:                                             //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
  363.                  mode=FADING;
  364.                  break;
  365.          case 0x40:                                             //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
  366.                  mode=FADING_FIX;                       // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
  367.                  break;
  368.          case 0x00:                                             //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
  369.                  mode=FIXED;                            // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
  370.                  break;
  371.          }
  372.  }
  373.  
  374.  /*
  375.   *
  376.   *
  377.   *  ESPACIO PARA INTERRUPCIONES
  378.   *
  379.   *
  380.   *  Timer0 - Por Overflow - Para el PWM por software
  381.   *  UART - RX - Para el DMX
  382.   */
  383.  
  384.  
  385.  void ISR(TIMER0_OVF_vect){
  386.  
  387.         if (!PWM_timer) PORT_PWM |= ((1<<PWM_R)|(1<<PWM_R)|(1<<PWM_R));         // Si es 0 el PWM_timer pone a 1 las salidas
  388.         if (R_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_R); }                                      // Cuando se cumple el tiempo las pone a 0, es decir cuando tenga 255 es el maximo que van a estar encendidas
  389.         if (V_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_G); }
  390.         if (A_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_B); }
  391.         if (PWM_timer==255)
  392.         {
  393.                 //Cargo los colores nuevos ya que finalizo el ciclo del PWM
  394.                 R_out = R_aux;
  395.                 V_out = V_aux;
  396.                 A_out = A_aux;
  397.                 //Observo si se cambio el modo, si cambio el modo cargo el nuevo modo y espero que el programa principal termine lo que estaba haciendo para comenzar con el nuevo modo
  398.                 SetMode();
  399.         }
  400.         PWM_timer++;
  401. }
  402.  
  403.  
  404.  void ISR (UART_RX_vect)
  405.  {
  406.          vHook_DMX_UART();
  407.  }

dmx.h
Código: C
  1. /*
  2.  *  dmx.h
  3.  *
  4.  *  Created on: 30/08/2015
  5.  *      Author:
  6.  */
  7.  
  8. #ifndef DMX_H_
  9. #define DMX_H_
  10.  
  11. // Definiciones para el DMX
  12.  
  13. #define         F_OSC   (8000)                          // Frec oscilador, para setear la UART
  14. #define         DMX_CHANNELS  6                         // Cantidad de canales usados en el DMX
  15.  
  16. // Habilita el uso del DIP en caso no NO estar habilitado es necesario definir una direccion
  17.  
  18. #define         USE_DIP
  19. #define         DMX_ADDRESS     0x1FF
  20.  
  21. // Definicion de pines para el DIP del DMX
  22.  
  23. #define         PORT_DIP_C      PORTC                   // Puerto Completo
  24. #define         DDR_DIP_C       DDRC
  25. #define         PIN_DIP_C       PINC
  26.  
  27. #define         PORT_DIP_I      PORTE                   // Puerto incompleto , Pines que faltan para completar el DIP
  28. #define         DDR_DIP_I       DDRE
  29. #define         PIN_DIP_I       PINE
  30.  
  31. #define         PIN_DIP_ADD     PE2                             // Pin que tiene el bit de mayor peso de la direccion
  32. #define         PIN_DIP_MAN     PE1                             // Pin que tiene la seleccion Manual/DMX
  33.  
  34. // Prototipos de funciones
  35.  
  36. void    vInit_DMX_RX(void);
  37. uint1_t bGetDips(void);
  38.  
  39. #endif /* DMX_H_ */

dmx.c
Código: C
  1. /*
  2.  *    dmx.c
  3.  *
  4.  *   Para que funcione este codigo en otros proyectos es necesario crear 1 funcion en el main
  5.  *   Esta funcion es para el ISR de la UART y que llame a vHook_DMX_UART()
  6.  *
  7.  */
  8.  
  9.  
  10.  
  11. #include "dmx.h"
  12. #include <avr/io.h>
  13. #include <stdint.h>
  14.  
  15. // ********************* definiciones locales*********************
  16.  
  17. enum {IDLE, BREAK, STARTB, STARTADR};// estados DMX
  18. enum {EVAL_DMX, IND};
  19.  
  20. uint8_t         gDmxState;
  21. uint8_t         *gDmxPnt;
  22. uint8_t         Flags;
  23. uint8_t         DmxRxField[DMX_CHANNELS];       // Conjunto de vals DMX (cruda)
  24.  
  25. uint16_t        DmxCount;
  26. uint16_t        DmxAddress; // Dirección inicial
  27.  
  28.  
  29. // *************** DMX recepción de inicialización ****************
  30. void vInit_DMX_RX(void)
  31. {
  32.  
  33.         #ifdef USE_DIP
  34.     // Configuracion de salidas
  35.         DDR_DIP_C  = 0;                                                                         // Todas entradas port completo
  36.         PORT_DIP_C  = 0xFF;                                                                     // Activo Pull-up
  37.         DDR_DIP_I  &= ~((1<<PIN_DIP_ADD)|(1<<PIN_DIP_MAN));     // Port Incompleto, solo esas entradsa
  38.         PORT_DIP_I |=   (1<<PIN_DIP_ADD)|(1<<PIN_DIP_MAN);  // Activo sus Pull-up
  39.         #endif
  40.  
  41.         // Configuracion de la UART
  42.     DDRD  |= (1<<2);
  43.     PORTD &= ~(1<<2);
  44.     UBRRH  = 0; // Habilitar recepción
  45.     UBRRL  = ((F_OSC/4000)-1);// 250kBaud, 8N2
  46.     UCSRC  = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
  47.     UCSRB  = (1<<RXEN)|(1<<RXCIE);
  48.     gDmxState= IDLE;
  49.  
  50.     uint8_t i;
  51.     for (i=0; i<DMX_CHANNELS; i++) DmxRxField[i]=0;
  52. }
  53.  
  54.  
  55.  
  56. // ************* obtener DMX dirección de inicio **************
  57. uint1_t bGetDips(void)
  58. {
  59.         uint8_t i;
  60.         uint16_t Temp;
  61.  
  62.         #ifdef USE_DIP
  63.         Temp= (!(PIN_DIP_I &(1<<PIN_DIP_ADD)) *256) + PIN_DIP_C;                        //Tomo la direccion desde los DIPs PORT_INCOPLETO:PORT_COMPLETO_7-0 (9 bits)
  64.         i = (PIN_DIP_I &(1<<PIN_DIP_MAN));
  65.         #else
  66.         Temp= DMX_ADDRESS;
  67.         i=0;
  68.         #endif
  69.  
  70.         if (!i && Temp != 0)                                    //Si es Manual deshabilito DMX, si PIN_DIP_MAN=0 activo DMX solo si la direccion es distinta de 0.
  71.         {
  72.                 DmxAddress= Temp;
  73.                 if (!(UCSRB &(1<<RXCIE)))                                                                               // Si el receptor esta desabilitado -> habilitar y setear modo de DMX en espera (IDLE).
  74.                 {
  75.                         gDmxState= IDLE;
  76.                         UCSRB |= (1<<RXCIE);
  77.                 }
  78.                 return 1;
  79.         }
  80.         else
  81.         {
  82.                 UCSRB &= ~(1<<RXCIE);                                                                                   // Manual o Direccion=0, Deshabilito la UART y limpio los valores del DMX ( no se para que )
  83.                 for (i=0; i<DMX_CHANNELS; i++) DmxRxField[i]=0;
  84.                 return 0;
  85.         }
  86. }
  87.  
  88.  
  89. // *************** DMX recepción ISR ****************//
  90. void vHook_DMX_UART(void)
  91. {
  92. static  uint16_t DmxCount;
  93.                 uint8_t  USARTstate= UCSRA;     // Obtener estado antes de los datos!
  94.                 uint8_t  DmxByte   = UDR;       // Obtener los datos
  95.                 uint8_t  DmxState  = gDmxState;// Cargar una sola vez de SRAM para aumentar la velocidad
  96.  
  97.         if (DmxState == BREAK)
  98.         {
  99.         UCSRA &= ~(1<<FE);      // Cambiar Posible FE: a causa de MAB
  100.         if (DmxByte == 0)
  101.                 {
  102.                 gDmxState= STARTB;// Código de inicio normal detectado
  103.                 gDmxPnt= ((uint8_t*)DmxRxField +1);
  104.                 }
  105.         else
  106.                 {
  107.                 gDmxState= IDLE;
  108.                 }
  109.         }
  110.  
  111. else if (USARTstate &(1<<FE)) // Comprobar para el descanso de la señal
  112.         {
  113.         UCSRA &= ~(1<<FE);      // Restablecer bandera
  114.         if (DmxByte == 0)       // Los datos de descanso debe ser 0
  115.                 {
  116.                 gDmxState= BREAK;
  117.                 DmxCount= DmxAddress;    // Restablecer contador de fotogramas
  118.                 }
  119.         else
  120.                 {
  121.                 gDmxState= IDLE;         // Bien es FE -> esperar descanso
  122.                 }
  123.         }
  124.  
  125. else if (DmxState == STARTB)
  126.         {
  127.         if (--DmxCount == 0)// Dirección inicial alcanzada?
  128.                 {
  129.                 gDmxState= STARTADR;
  130.                 DmxRxField[0]= DmxByte;
  131.                 }
  132.         }
  133.  
  134. else if (DmxState == STARTADR)
  135.         {
  136.         uint8_t *DmxPnt;
  137.         DmxPnt= gDmxPnt;
  138.         *DmxPnt= DmxByte;
  139.         if (++DmxPnt >= (DmxRxField + DMX_CHANNELS )) // los (CHANNEL) canales recibidos?
  140.                 {
  141.                 Flags |= (1<<EVAL_DMX);// Conjunto de datos listo -> eval en principal (MAIN)
  142.                 gDmxState= IDLE;
  143.                 }
  144.         else
  145.                 {
  146.                 gDmxPnt= DmxPnt;
  147.                 }
  148.         }
  149. }


Creo que esta lo suficientemente documentado con los comentarios que hay. Y espero que funcione a la primera, seria lo ideal.
Luego contas como te fue y si lo solucionaste o diste marcha atras :)

Hay muchas cosas que cambie, hice nuevas funciones, modifique funciones, etc.
Como por ejemplo, ahora los pines para los DIPs se configuran desde dmx.h , ahi tenes el puerto completo (PORTC) y el puerto incompleto (PORTE) para formar la direccion, aunque intente darle un poco de flexibilidad si es que moves las llaves a otro puerto. Aun asi todavia el del puerto incompleto es el bit de mayor peso de los 9. Esta tambien separado cual es el pin que hace que pase a ser manual o no.

Ahora la funcion de ISR se encuentra en el main. y se llama a la funcion del DMX
Al actualizar la direccion del DMX si se cumple que la direccion es 0 o que esta en manual retorna un valor dejandolo en fading_auto.
Cambie la velocidad del timer, tenia preescaler 1/256 lo puse con 1/1 como estaba en el ejemplo que pasaste.
Modifique un poco el codigo del PWM por soft, de esa forma se pone a 1 cuando comienza en 0 y luego se desactiva de ser necesario. ( Aunque no es lo ideal y que tenia pensado hacer )
Tambien se puede modificar las salidas modificando los define al comienzo del main.
Y ya no recuerdo mas que otras cositas toque. Parece un programa corto pero no lo es tanto. xD

Tambien modifique le codigo para cuando no queres usar el DIP y que tenga una direccion FIJA, esto te va a inhabilitar que puedas pasarlo de Manual a DMX o viceversa. Aunque se puede modificar eso con facilidad para dejar que se pueda usar 1 llave sola y no le preste atencion a lo demas.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: stk500 en 31 de Agosto de 2015, 04:09:40
joder Killer !!! como te lo hace!!
ahora mismo estoy liado con un projectos pero cuando tenga Tiempo lo voy a probar y te comento.
Podria poner una emplanacion de los pines que usas y funciones?
asi podria hacer un Esquemas subirlo por aqui. no cree?

Saludos
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 31 de Agosto de 2015, 04:23:51
Realmente stk, estoy haciendolo todo en el "aire" no tengo nada concreto. No utilizo el compilador de Atmel, no tengo placa para probarlo. No tengo nada.
Solo agarre un editor como es el Code Composer Studio, basado en elipse, cree 3 archivos y lo hice desde alli y los codigos que me dio locodelafonola, por mas que no puedo compilarlo me iba a ayudar a quitar algunos errores de tipeo.

En fin todo comenzo por que locodelafonola queria pasar una funcion que estaba en ASM a C. El cual accedi a ayudar. Yo a todo esto sin conocimiento de DMX, sin conocimiento del circuito y por si fuera poco sin haber tocado nunca un micro de Atmel.
Comence a pasarlo cuando tuvimos el primer problema. El programa pasado del ASM al C no permitia un "correcto" manejo y cambio de modos. Ya que si usabamos el codigo de antes al intentar cambiar de modo el programa tenia que terminar el modo anterior y eso podia llevar unos cuantos segundos. Por eso mismo reescribi las funciones para que pueda ser usado y cambiado desde la interrupcion, con un delay maximo de unos 580ms que es el maximo delay que podia ocurrir en el ASM aproximadamente.
Con esto quiero decir. No hay nada concreto, no tome ningun valor y dije "voy a comenzar desde aqui" o "tiene que cumplir estos valores", sino que el pasarlo desde uno a otro termino con ese codigo por lo cual no se que tan exacto o correcto funcionara. No se si habra que modificar el valor del timer para el PWM eso no lo se, tambien otra cosa que puede necesitar modificarse es la formula de delay. No me puse a hacer las matematicas ni nada por el estilo. Pero la programacion es la programacion y solo afectara unos pequeños detalles o partes del codigo, asi que es lo mismo.

Con respecto al HW, locodelafonola colgo el esquema en la 2da pagina, sino aqui te proveo del link:
http://www.todopic.com.ar/foros/index.php?topic=44880.msg373782#msg373782
El cual pertenece al codigo antiguo sino me equivoco. pero que tome como referencia para lo demas.

Aca tambien los modos (Aunque esta explicado en los comentarios):
http://www.todopic.com.ar/foros/index.php?topic=44880.msg373824#msg373824
Los modos a excepcion del fijo y fading de un solo color que los cree yo como para "agregarle" algo mas, los demas son traducidos del programa que dio en ASM.

Hay muchas cosas que se pueden hacer para que quede mas limpio y ordenado, como todas las definiciones y declaraciones de variables podrian tranquilamente ir en un .h
Tambien las funciones que declare como auxiliares y modos en otro archivo, asi de esa forma solo queda el main() y los ISR en el main.c y queda un poco mas ordenado.

Pero hacer eso aqui en el foro significa 5/6 partes de codigo que deberian luego unirse y pienso que es mas comlpejo hacerlo que solo 3. Asi que lo deje asi.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: stk500 en 31 de Agosto de 2015, 04:41:10
Ok!  :)

Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: stk500 en 31 de Agosto de 2015, 08:02:52
estoy probando tu codigo killer y me sale 3 Errores y 3 Avisos, los aviso no le doy importancia ya que no lo Optimos tu codigo.
Mira la imagen
(http://www.todopic.com.ar/foros/imgtiny/jrbktd.jpg)
ojos hay que definir el CPU- Crystal , le he puesto 8Mhz
Saludos
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 31 de Agosto de 2015, 08:24:09
bueno no veo que puede ser en algunos casos por que parece que esta corrido el tema del numero de lineas. Pero por lo que parece es:

por haber puesto:

void ISR (xxxx)
en ves de
ISR (xxx)

Parece que ya ISR define un tipo. Eso quitaria 2 errores, los de las lineas 385/404 que tenes

Me falto definir en el .h la funcion vHook_DMX_UART, esto quitaria el warning en la linea 406, ademas permite usarlo
No se por que el warning de la linea 196, esta definido en el .h

Ahi cambie los uint1_t por bool y agregue la libreria stdbool.h
Para solucionar el error de la linea 37 en el .h

Agregue un define F_CPU 8000000

Dejo el codigo de nuevo, vas a tener que ponerle nuevamente la frecuencia del cristal o acomodarlo si es que lo puse mal (me refiero a la linea que puse antes).

Y la proxima copialo y pegalo asi puedo leerlo completo al error y me guio un poco mas, por ejemplo el primer warning no se de que es.

main.c
Código: C
  1. /*
  2.  *  DMX_RGB FADING/FIXED/RAINBOW
  3.  *
  4.  *  Created on: 23/08/2015
  5.  *  Author:
  6.  */
  7.  
  8.  
  9.  
  10. /*
  11.  *  SECCION DE INCLUDES
  12.  *
  13.  */
  14.  
  15. // Include para la definicion de las variables
  16. #include <stdint.h>
  17.  
  18. // Include liberias del micro, Interrupcion / WDT / delay
  19.  
  20. #define F_CPU 8000000   //Para que funcione el delay
  21. #include <util\delay.h>
  22. #include <avr/interrupt.h>
  23. //#include <avr/wdt.h>
  24.  
  25.  
  26. // Include funcione de DMX
  27. #include "dmx.h"
  28.  
  29. /*
  30.  *
  31.  *  PROTOTIPOS DE FUNCIONES
  32.  *
  33.  *
  34.  */
  35.  
  36. // Funciones de inicializacion de modulos
  37. void vInitPinout(void);
  38. void vInitTimer0(void);
  39.  
  40. //Funciones Auxiliares
  41. void DimmerCurva(void);
  42. void delay(void);
  43. void Cambiarmodo(void);
  44.  
  45. // Modos
  46. void fixed_color(void);
  47. void fading_fijo(void);
  48. void fading_auto(void);
  49. void rainbow_fader(void);
  50.  
  51. /*
  52.  *
  53.  *
  54.  * DEFINICION DE VARIABLES
  55.  *
  56.  *
  57.  */
  58.  
  59. enum {FIXED,FADING_FIX,FADING,RAINBOW_FADING} mode,last_mode;
  60.  
  61. // Dato proveniente de la consola DMX
  62.  
  63. extern uint8_t DmxRxField[DMX_CHANNELS];        // Valores externos tomados desde la libreria.
  64.  
  65. #define DMX_R                   DmxRxField[1]   //Canal R
  66. #define DMX_G                   DmxRxField[2]   //Canal G
  67. #define DMX_B                   DmxRxField[3]   //Canal B
  68. #define DMX_Modo                DmxRxField[4]   //Seleccion de Modo
  69. #define DMX_Velocidad   DmxRxField[5]   //Seleccion de Velocidad
  70.  
  71. // Para simplificar los datos del array de colores que estoy usando.
  72. // ArrayColores contiene los valores RGB del momento
  73.  
  74. #define Rojo                    ArrayColores[0]
  75. #define Verde                   ArrayColores[1]
  76. #define Azul                    ArrayColores[2]
  77.  
  78. // Definicion de salidas para los colores
  79.  
  80. #define DDR_PWM                 DDRB
  81. #define PORT_PWM                PORTB
  82. #define PWM_R                   PB0
  83. #define PWM_G                   PB1
  84. #define PWM_B                   PB2
  85.  
  86. //*********************************//
  87.  
  88. uint8_t V_out,R_out,A_out;                                              // Valores que se comparan con el PWM
  89. uint8_t V_aux,R_aux,A_aux;                                              // Valores que se cambia para actualizar el PWM
  90. uint8_t PWM_timer=0,Alpha;
  91. uint8_t estado=0,estador=0;                                     // Estado de los fading
  92.  
  93. const uint8_t arraydimmer[256]={
  94.                  0,     0,    1,    1,    1,    1,    1,    2,
  95.                  2,     2,    2,    3,    3,    3,    4,    4,
  96.                  4,     5,    5,    5,    6,    6,    7,    7,
  97.                  8,     8,    9,    9,   10,   10,   11,   11,
  98.                  12,   12,   13,   13,   14,   14,   15,   15,
  99.                  16,   16,   17,   17,   18,   18,   19,   19,
  100.                  20,   20,   21,   21,   22,   22,   23,   23,
  101.                  24,   24,   25,   25,   26,   27,   28,   29,
  102.                  30,   30,   31,   32,   33,   34,   35,   36,
  103.                  36,   37,   38,   39,   40,   41,   42,   43,
  104.                  43,   44,   45,   46,   47,   48,   49,   50,
  105.                  51,   52,   52,   53,   54,   55,   56,   57,
  106.                  58,   59,   60,   61,   62,   63,   64,   65,
  107.                  66,   67,   68,   69,   70,   71,   72,   73,
  108.                  74,   75,   76,   77,   78,   79,   80,   81,
  109.                  82,   83,   84,   85,   86,   88,   89,   90,
  110.                  91,   92,   93,   94,   95,   96,   97,   98,
  111.                  99,  100,  102,  103,  104,  105,  106,  107,
  112.                  108, 109,  110,  112,  113,  114,  115,  116,
  113.                  117, 119,  120,  121,  122,  123,  124,  126,
  114.                  127, 128,  129,  130,  132,  133,  134,  135,
  115.                  136, 138,  139,  140,  141,  142,  144,  145,
  116.                  146, 147,  149,  150,  151,  152,  154,  155,
  117.                  156, 158,  159,  160,  161,  162,  164,  165,
  118.                  167, 168,  169,  171,  172,  173,  174,  176,
  119.                  177, 178,  180,  181,  182,  184,  185,  187,
  120.                  188, 189,  191,  192,  193,  195,  196,  197,
  121.                  199, 200,  202,  203,  204,  206,  207,  208,
  122.                  210, 211,  213,  214,  216,  217,  218,  220,
  123.                  221, 223,  224,  226,  227,  228,  230,  231,
  124.                  233, 234,  236,  237,  239,  240,  242,  243,
  125.                  245, 246,  248,  249,  251,  252,  254,  255
  126. };
  127.  
  128. uint8_t ArrayColores[3]={255,0,0};                      // Rojo,Verde,Azul
  129.  
  130. const uint8_t ArrayColorFading[6]={                     // Indice y valor a modificar   {0,1,2} = {R,G,B} ; indice par = incremento ; indice impar = decremento
  131.                  1,     //      Rojo    ->      Amarillo
  132.                  0,     //      Amarilo ->      Verde
  133.                  2,     //      Verde   ->      Cyan
  134.                  1,     //      Cyan    ->      Azul
  135.                  0,     //      Azul    ->      Magenta
  136.                  2      //      Magenta ->      Rojo
  137. };
  138.  
  139. const uint8_t ArrayColorFadingRainbow[3][2]={                   // Indice y valor a modificar   {Decremento,Incremento}
  140.                 {0,1},  //      Rojo-   ->      Verde+
  141.                 {1,2},  //      Verde-  ->      Azul+
  142.                 {2,0}   //      Azul-   ->      Rojo+
  143. };
  144.  
  145. /*
  146.  *
  147.  *
  148.  *  CODIGOS DE INICIALIZACION DE MODULOS
  149.  *
  150.  *
  151.  */
  152.  
  153. //************* Inicialización pines / port *****************//
  154. void vInitPinout(void){
  155.  
  156.         // Configuracion de las llaves DIP para el DMX
  157.  
  158.     // Configuracion de salidas
  159.         DDR_PWM |= (1<<PWM_R) | (1<<PWM_G) | (1<<PWM_B);                // Salida pin LEDs , PB0 = Rojo, PB1 = Verde, PB2 = Azul
  160.         PORT_PWM = 0;
  161.         DDRE  |= (1<<PE0);                              // LED indicador de funcionamiento en PE0
  162.     PORTE = 0;
  163.  
  164. }
  165.  
  166. // ***** inicializacion del timer****//
  167.  
  168. void vInitTimer0(void){
  169.                 TCCR0= (1<<CS00) ;      // Preescaler 1:1
  170.                 TIMSK|= (1<<TOIE0);     // desbordamientos de la interrupción
  171. }
  172.  
  173. /*
  174.  *
  175.  *
  176.  *  PROGRAMA PRINCIPAL
  177.  *
  178.  *
  179.  */
  180.  
  181. int main(void)
  182. {
  183.  
  184.         vInitPinout();          // Establecer los puertos de E / S
  185.         vInitTimer0();          // Establecer el timer
  186.         vInit_DMX_RX();         // Iniciar la UART y puertos para la llave DIP
  187.  
  188.         last_mode = mode = FIXED;               //Valores iniciales, hasta que llegue la trama del DMX
  189.         Rojo = 0;
  190.         Verde = 0;
  191.         Azul = 0;
  192.  
  193.         sei();              // habilitar las interupciones, Timer/UART(DMX) habilitados
  194.  
  195.         while(1)        // bucle principal (LOOP)
  196.             {
  197.                         if(!bGetDips()){mode=FADING;}           // Pregunto si esta activo el DMX y Toma la direccion y la actualiza, tambien desabilita el DMX de ser necesario
  198.                 if(last_mode!=mode){Cambiarmodo();}                     // Caso que desde el DMX se pida cambiar el modo, cambia unicamente cuando termino la rutina
  199.                 switch(last_mode)
  200.                 {
  201.                 case FIXED:
  202.                                 fixed_color();
  203.                                 break;
  204.                 case FADING_FIX:
  205.                                 fading_fijo();
  206.                                 break;
  207.                 case FADING:
  208.                                 fading_auto();
  209.                                 break;
  210.                 case RAINBOW_FADING:
  211.                                 rainbow_fader();
  212.                                 break;
  213.                 default:
  214.                                 break;
  215.                 }
  216.             }
  217. }
  218.  
  219. /*
  220.  *
  221.  *
  222.  *  MODOS DE OPERACION
  223.  *
  224.  *  fixed_color() - Color fijo, tomado desde el DMX.
  225.  *  fading_fijo() - Produce el efecto de fading con el color tomado del DMX, pero solo ese color, de 0 a 255.
  226.  *  fading_auto() - Comienza la ejecucion de fading de distintos colores, solo toma en cuenta la velocidad, solo 1 color a la ves.
  227.  *  rainbow_fading() - Agregado al  fading_auto(), en caso que se seleccione este, se modificaran 2 colores en ves de 1.
  228.  */
  229.  
  230. void fixed_color(void){
  231.         Rojo = DMX_R;           // Colores tomados directamente del DMX para fijo
  232.         Verde = DMX_G;
  233.         Azul = DMX_B;
  234.         DimmerCurva();          // Actualizo colores para el PWM
  235. }
  236.  
  237. void fading_fijo(void){
  238.         Rojo = DMX_R * (Alpha/255);             // Colores tomados directamente del DMX para fijo
  239.         Verde = DMX_G * (Alpha/255);
  240.         Azul = DMX_B * (Alpha/255);
  241.         DimmerCurva();
  242.         Alpha++;
  243.         delay();
  244. }
  245.  
  246. void fading_auto(void){
  247.  
  248.                 // Valores iniciales seteados cuando se cambia de modo
  249.  
  250.                 //Espera
  251.                 delay();  //esperar
  252.                 //Cambio los valores, cuando se cambia de modo se procede a setear los valores iniciales
  253.                 if(estado%2)
  254.                 {       //Caso impar
  255.                         if(++ArrayColores[estado]==255) estado++;
  256.                 }
  257.                 else
  258.                 {       //Caso par
  259.                         if(--ArrayColores[estado]==0) estado++;
  260.                 }
  261.                 if(estado>=6) estado=0;
  262.                 DimmerCurva();
  263. }
  264.  
  265. void rainbow_fader(void){
  266.  
  267.         int Temp_R,Temp_A,Temp_V;
  268.         Temp_R = Rojo;
  269.         Temp_A = Azul;
  270.         Temp_V = Verde;
  271.  
  272.         if (estador==0){                                                                                                        //Caso inicial, Para que comienze con los valores que debe
  273.                 Rojo = 255;
  274.                 Verde = 0;
  275.                 Azul = 0;
  276.         }
  277.         DimmerCurva();
  278.  
  279.                 ArrayColores[ArrayColorFadingRainbow[estador][1]]++;                            //Sumo
  280.                 ArrayColores[ArrayColorFadingRainbow[estador][0]]--;                            //Resto
  281.                 if(!ArrayColores[ArrayColorFadingRainbow[estador][0]]) estador++;       //Compruebo que llegue al final, es decir pase por los 255 valores, en este caso cuando llega a 0 y continuo con la otra seccion.
  282.  
  283.         Rojo = Temp_R;
  284.         Azul = Temp_A;
  285.         Verde = Temp_V;
  286.  
  287.                 if(estador>=3) estador=0; fading_auto();                                                        //En caso que pase por todos los colores y pasas por el fade comun, tal cual estaba en el otro programa
  288.  
  289. }
  290.  
  291. /*
  292.  *
  293.  *
  294.  *  UTILIDADES
  295.  *
  296.  *
  297.  * DimmerCurva() - Actualiza los colores para que el PWM tome los valores nuevos
  298.  * delay() - Demora introducida para modificar la velocidad de los efectos
  299.  * Cambiarmodo() - Funcion usada que toma el valor del DMX, traduciendolo y efectua el cambio.
  300.  */
  301.  
  302. void DimmerCurva(void){
  303.  
  304.         R_aux=arraydimmer[Rojo];
  305.         V_aux=arraydimmer[Verde];
  306.         A_aux=arraydimmer[Azul];
  307. }
  308.  
  309. void delay(void) {
  310.  
  311.         // Se toma el valor actual de la velocidad entregada por el DMX, no hace falta esperar que termine el PWM
  312.         // Tiempo Minimo = 3us
  313.         // Tiempo Maximo = 580ms
  314.         // Dividi el tiempo en 2 partes 0..127 para tiempos de micro segundos y 128..255 para tiempos de milisegundos
  315.  
  316.         uint16_t tiempo;
  317.         if (DMX_Velocidad>127)
  318.         {       //Tiempo en milisegundos, Recta de 1ms a 508ms
  319.                 tiempo = 4*DMX_Velocidad - 511;
  320.                 //_delay_ms(tiempo);
  321.         }
  322.         else
  323.         {       //Tiempo en microsegundos de 3us a 892us, valores elegidos para que resulte mas facil multiplicarlos
  324.                 tiempo = 7*DMX_Velocidad +3;
  325.                 //_delay_us(tiempo);
  326.         }
  327. }
  328.  
  329. void Cambiarmodo(void){
  330.  
  331.          last_mode=mode;
  332.  
  333.          switch(mode)   // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
  334.          {
  335.          case RAINBOW_FADING:           //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
  336.                  Rojo=255;                              // Set de colores iniciales
  337.                  Verde=0;
  338.                  Azul=0;
  339.                  estado=0;                              // Set de estado inicial para el fading
  340.                  estador=0;                             // Set de estado inicial para el rainbow_fading
  341.                  break;
  342.          case FADING:                           //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
  343.                  Rojo=255;                              // Set de colores iniciales
  344.                  Verde=0;
  345.                  Azul=0;
  346.                  estado=0;                              // Set de estado inicial para el fading
  347.                  break;
  348.          default:                                       //Case FADING_FIX, de 64 a 127, y FIXED, de 0 a 63. Bits de mayor peso quedan siempre en 01 y 00
  349.                  break;
  350.          }
  351.  }
  352.  
  353. void SetMode(void){
  354.  
  355.          switch(DMX_Modo&0xC0)  // Tomo los 2 bits superiores del Modo que viene del DMX y le hago una AND con 1100 0000, dejando los 2 bits superiores y los demas en 0
  356.          {
  357.          case 0xC0:                                             //Caso RAINBOW_FADING de 192 a 255, los bits con mas pesos siempre se mantienen en 1100
  358.                  mode=RAINBOW_FADING;
  359.                  break;
  360.          case 0x80:                                             //Case FADING, de 128 a 191, bits de mayor peso quedan siempre en 1000
  361.                  mode=FADING;
  362.                  break;
  363.          case 0x40:                                             //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0100
  364.                  mode=FADING_FIX;                       // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
  365.                  break;
  366.          case 0x00:                                             //Case FADING_FIX, de 64 a 127, bits de mayor peso quedan siempre en 0000
  367.                  mode=FIXED;                            // Aqui no importa si esta asignadosele a cada rato , ya que no hay valores iniciales
  368.                  break;
  369.          }
  370.  }
  371.  
  372.  /*
  373.   *
  374.   *
  375.   *  ESPACIO PARA INTERRUPCIONES
  376.   *
  377.   *
  378.   *  Timer0 - Por Overflow - Para el PWM por software
  379.   *  UART - RX - Para el DMX
  380.   */
  381.  
  382.  
  383.  ISR(TIMER0_OVF_vect){
  384.  
  385.         if (!PWM_timer) PORT_PWM |= ((1<<PWM_R)|(1<<PWM_R)|(1<<PWM_R));         // Si es 0 el PWM_timer pone a 1 las salidas
  386.         if (R_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_R); }                                      // Cuando se cumple el tiempo las pone a 0, es decir cuando tenga 255 es el maximo que van a estar encendidas
  387.         if (V_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_G); }
  388.         if (A_out>=PWM_timer) { PORT_PWM &= ~(1<<PWM_B); }
  389.         if (PWM_timer==255)
  390.         {
  391.                 //Cargo los colores nuevos ya que finalizo el ciclo del PWM
  392.                 R_out = R_aux;
  393.                 V_out = V_aux;
  394.                 A_out = A_aux;
  395.                 //Observo si se cambio el modo, si cambio el modo cargo el nuevo modo y espero que el programa principal termine lo que estaba haciendo para comenzar con el nuevo modo
  396.                 SetMode();
  397.         }
  398.         PWM_timer++;
  399. }
  400.  
  401.  
  402.  ISR (UART_RX_vect)
  403.  {
  404.          vHook_DMX_UART();
  405.  }

dmx.h
Código: C
  1. /*
  2.  *  dmx.h
  3.  *
  4.  *  Created on: 30/08/2015
  5.  *      Author:
  6.  */
  7.  
  8. #ifndef DMX_H_
  9. #define DMX_H_
  10.  
  11. // Definiciones para el DMX
  12.  
  13. #define         F_OSC   (8000)                          // Frec oscilador, para setear la UART
  14. #define         DMX_CHANNELS  6                         // Cantidad de canales usados en el DMX
  15.  
  16. // Habilita el uso del DIP en caso no NO estar habilitado es necesario definir una direccion
  17.  
  18. #define         USE_DIP
  19. #define         DMX_ADDRESS     0x1FF
  20.  
  21. // Definicion de pines para el DIP del DMX
  22.  
  23. #define         PORT_DIP_C      PORTC                   // Puerto Completo
  24. #define         DDR_DIP_C       DDRC
  25. #define         PIN_DIP_C       PINC
  26.  
  27. #define         PORT_DIP_I      PORTE                   // Puerto incompleto , Pines que faltan para completar el DIP
  28. #define         DDR_DIP_I       DDRE
  29. #define         PIN_DIP_I       PINE
  30.  
  31. #define         PIN_DIP_ADD     PE2                             // Pin que tiene el bit de mayor peso de la direccion
  32. #define         PIN_DIP_MAN     PE1                             // Pin que tiene la seleccion Manual/DMX
  33.  
  34. // Prototipos de funciones
  35.  
  36. void    vInit_DMX_RX(void);
  37. uint8_t bGetDips(void);
  38. void    vHook_DMX_UART(void);
  39.  
  40. #endif /* DMX_H_ */

dmx.c
Código: C
  1. /*
  2.  *    dmx.c
  3.  *
  4.  *   Para que funcione este codigo en otros proyectos es necesario crear 1 funcion en el main
  5.  *   Esta funcion es para el ISR de la UART y que llame a vHook_DMX_UART()
  6.  *
  7.  */
  8.  
  9.  
  10.  
  11. #include "dmx.h"
  12. #include <avr/io.h>
  13. #include <stdint.h>
  14.  
  15. // ********************* definiciones locales*********************
  16.  
  17. enum {IDLE, BREAK, STARTB, STARTADR};// estados DMX
  18. enum {EVAL_DMX, IND};
  19.  
  20. uint8_t         gDmxState;
  21. uint8_t         *gDmxPnt;
  22. uint8_t         Flags;
  23. uint8_t         DmxRxField[DMX_CHANNELS];       // Conjunto de vals DMX (cruda)
  24.  
  25. uint16_t        DmxCount;
  26. uint16_t        DmxAddress; // Dirección inicial
  27.  
  28.  
  29. // *************** DMX recepción de inicialización ****************
  30. void vInit_DMX_RX(void)
  31. {
  32.  
  33.         #ifdef USE_DIP
  34.     // Configuracion de salidas
  35.         DDR_DIP_C  = 0;                                                                         // Todas entradas port completo
  36.         PORT_DIP_C  = 0xFF;                                                                     // Activo Pull-up
  37.         DDR_DIP_I  &= ~((1<<PIN_DIP_ADD)|(1<<PIN_DIP_MAN));     // Port Incompleto, solo esas entradsa
  38.         PORT_DIP_I |=   (1<<PIN_DIP_ADD)|(1<<PIN_DIP_MAN);  // Activo sus Pull-up
  39.         #endif
  40.  
  41.         // Configuracion de la UART
  42.     DDRD  |= (1<<2);
  43.     PORTD &= ~(1<<2);
  44.     UBRRH  = 0; // Habilitar recepción
  45.     UBRRL  = ((F_OSC/4000)-1);// 250kBaud, 8N2
  46.     UCSRC  = (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
  47.     UCSRB  = (1<<RXEN)|(1<<RXCIE);
  48.     gDmxState= IDLE;
  49.  
  50.     uint8_t i;
  51.     for (i=0; i<DMX_CHANNELS; i++) DmxRxField[i]=0;
  52. }
  53.  
  54.  
  55.  
  56. // ************* obtener DMX dirección de inicio **************
  57. uint8_t bGetDips(void)
  58. {
  59.         uint8_t i;
  60.         uint16_t Temp;
  61.  
  62.         #ifdef USE_DIP
  63.         Temp= (!(PIN_DIP_I &(1<<PIN_DIP_ADD)) *256) + PIN_DIP_C;                        //Tomo la direccion desde los DIPs PORT_INCOPLETO:PORT_COMPLETO_7-0 (9 bits)
  64.         i = (PIN_DIP_I &(1<<PIN_DIP_MAN));
  65.         #else
  66.         Temp= DMX_ADDRESS;
  67.         i=0;
  68.         #endif
  69.  
  70.         if (!i && Temp != 0)                                    //Si es Manual deshabilito DMX, si PIN_DIP_MAN=0 activo DMX solo si la direccion es distinta de 0.
  71.         {
  72.                 DmxAddress= Temp;
  73.                 if (!(UCSRB &(1<<RXCIE)))                                                                               // Si el receptor esta desabilitado -> habilitar y setear modo de DMX en espera (IDLE).
  74.                 {
  75.                         gDmxState= IDLE;
  76.                         UCSRB |= (1<<RXCIE);
  77.                 }
  78.                 return 1;
  79.         }
  80.         else
  81.         {
  82.                 UCSRB &= ~(1<<RXCIE);                                                                                   // Manual o Direccion=0, Deshabilito la UART y limpio los valores del DMX ( no se para que )
  83.                 for (i=0; i<DMX_CHANNELS; i++) DmxRxField[i]=0;
  84.                 return 0;
  85.         }
  86. }
  87.  
  88.  
  89. // *************** DMX recepción ISR ****************//
  90. void vHook_DMX_UART(void)
  91. {
  92. static  uint16_t DmxCount;
  93.                 uint8_t  USARTstate= UCSRA;     // Obtener estado antes de los datos!
  94.                 uint8_t  DmxByte   = UDR;       // Obtener los datos
  95.                 uint8_t  DmxState  = gDmxState;// Cargar una sola vez de SRAM para aumentar la velocidad
  96.  
  97.         if (DmxState == BREAK)
  98.         {
  99.         UCSRA &= ~(1<<FE);      // Cambiar Posible FE: a causa de MAB
  100.         if (DmxByte == 0)
  101.                 {
  102.                 gDmxState= STARTB;// Código de inicio normal detectado
  103.                 gDmxPnt= ((uint8_t*)DmxRxField +1);
  104.                 }
  105.         else
  106.                 {
  107.                 gDmxState= IDLE;
  108.                 }
  109.         }
  110.  
  111. else if (USARTstate &(1<<FE)) // Comprobar para el descanso de la señal
  112.         {
  113.         UCSRA &= ~(1<<FE);      // Restablecer bandera
  114.         if (DmxByte == 0)       // Los datos de descanso debe ser 0
  115.                 {
  116.                 gDmxState= BREAK;
  117.                 DmxCount= DmxAddress;    // Restablecer contador de fotogramas
  118.                 }
  119.         else
  120.                 {
  121.                 gDmxState= IDLE;         // Bien es FE -> esperar descanso
  122.                 }
  123.         }
  124.  
  125. else if (DmxState == STARTB)
  126.         {
  127.         if (--DmxCount == 0)// Dirección inicial alcanzada?
  128.                 {
  129.                 gDmxState= STARTADR;
  130.                 DmxRxField[0]= DmxByte;
  131.                 }
  132.         }
  133.  
  134. else if (DmxState == STARTADR)
  135.         {
  136.         uint8_t *DmxPnt;
  137.         DmxPnt= gDmxPnt;
  138.         *DmxPnt= DmxByte;
  139.         if (++DmxPnt >= (DmxRxField + DMX_CHANNELS )) // los (CHANNEL) canales recibidos?
  140.                 {
  141.                 Flags |= (1<<EVAL_DMX);// Conjunto de datos listo -> eval en principal (MAIN)
  142.                 gDmxState= IDLE;
  143.                 }
  144.         else
  145.                 {
  146.                 gDmxPnt= DmxPnt;
  147.                 }
  148.         }
  149. }

Una cosa que no me di cuenta fue el maximo de _delay_ms()
Creo que lo mejor va a ser reemplazarlo por:

__builtin_avr_delay_cycles(unsigned long)
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 31 de Agosto de 2015, 11:54:38
hola
a mi el unico error que me larga es
Código: [Seleccionar]
avr-gcc.exe  -mmcu=atmega8515 -Wall -gdwarf-2 -std=gnu99         -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT lib_dmx_in.o -MF dep/lib_dmx_in.o.d  -c  ../lib_dmx_in.c
In file included from ../lib_dmx_in.c:11:
../lib_dmx_in.h:58: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'bGetDips'
make: *** [lib_dmx_in.o] Error 1
Build failed with 1 errors and 0 warnings...
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 31 de Agosto de 2015, 12:06:30
parece que no tiene soporte para devolver un booleano. es decir un true false.
Es simple arreglarlo, cambiar el bool por un uint8_t en dmx.h y dmx.c y listo. se arreglaria con eso.

EDIT: Ya actualize el ultimo codigo, para no poner TODO de vuelta.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 31 de Agosto de 2015, 12:50:18
bueno alli lo solucione
la parte de .H creo nque estarabien asi., o me estoy equivocando
Código: [Seleccionar]
  // Prototipos de funciones
     
    void    vInit_DMX_RX(void);
extern void bGetDips(void);
    void vHook_DMX_UART(void);
     
puse eso , saque esto
Código: [Seleccionar]
// Prototipos de funciones
 
void    vInit_DMX_RX(void);
uint8_t bGetDips(void);
void vHook_DMX_UART(void);
 
otro cosa que cambie fue esto
Código: [Seleccionar]
// ************* obtener DMX dirección de inicio **************
void  bGetDips(void)
{
uint8_t i;
uint16_t Temp;
 
y saque esto
Código: [Seleccionar]
// ************* obtener DMX dirección de inicio **************
uint8_t bGetDips(void)
{
uint8_t i;
uint16_t Temp;
 
Ahora el error que me aparece es este ., y no entiendo bien esa funcion
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 31 de Agosto de 2015, 12:58:03
no se de donde sacaste ese codigo que pusiste.

Pero yo modifique el codigo para ponerle el uint8_t
Antes daba error por que tenia un

bool   bGetDips(void);

Ya que imagino que no estaba definido bool, o que no lo soporta el compilador.

Lo que hiciste esta mal. no hay necesidad de definirlo como extern, realmente nunca vi la necesidad de definir como extern una funcion cuando estas usando el .h para acceder a la misma.
Tambien estas usando un void cuando la funcion esta devolviendo un valor. Ese es otro error.
Usa el codigo que puse al ultimo. Yo lo habia modificado para arreglar eso.

Seguro que hay muchos mas errores con respecto al funcionamiento pero al menos error de sintaxis/compilacion no deberia haber.
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 31 de Agosto de 2015, 13:12:35
no se de donde sacaste ese codigo que pusiste.

Pero yo modifique el codigo para ponerle el uint8_t
Antes daba error por que tenia un

bool   bGetDips(void);

Ya que imagino que no estaba definido bool, o que no lo soporta el compilador.

Lo que hiciste esta mal. no hay necesidad de definirlo como extern ( realmente nunca vi la necesidad de definir como extern una funcion ) cuando estas usando el .h para acceder a la misma.
Tambien estas usando un void cuando la funcion esta devolviendo un valor. Ese es otro error.
Usa el codigo que puse al ultimo. Yo lo habia modificado para arreglar eso.

Seguro que hay muchos mas errores con respecto al funcionamiento pero al menos error de sintaxis/compilacion no deberia haber.
cuando llamas una variable de otra libreria., se tiene que usar  la sentecia extern ., y el inicio de la funcion es void., fijate en la librias originales ., lo IRS son los que no se llaman ., de esa manera el compilador no me dice error
Título: Re: Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 31 de Agosto de 2015, 13:23:00
Citar
cuando llamas una variable de otra libreria., se tiene que usar  la sentecia extern ., y el inicio de la funcion es void., fijate en la librias originales ., lo IRS son los que no se llaman ., de esa manera el compilador no me dice error

Justamente una variable. Y esa variable no debe estar definida en el .h por eso mismo yo puse en el main.c:

extern uint8_t DmxRxField[DMX_CHANNELS];   // Valores externos tomados desde la libreria.

Pero en el .h tenemos definidos los prototipos nomas de las funciones. Luego el Linker va a ser capaz de ubicar el dmx.c si es que las rutas de acceso estan bien configuradas y agarrar la funcion necesaria. no hay necesidad de marcarla como extern como ya dije.

Ahora si tu programa no posee realmente un .h, como por ejemplo omitieramos el dmx.h, entonces ahi si en el main.c pondrias:

extern    void    vInit_DMX_RX(void);
extern    uint8_t    bGetDips(void);
extern    void   vHook_DMX_UART(void);

Ahora... el por que no poner void y ponerle uin8_t o int como mas te guste. La libreria original es esa libreria y su funcion no devuelve nada, yo modifique simplemente la funcion para que sea un poco mas flexible para mi.
Ya que necesito saber si es que realmente esta en manual o no la llave. entonces hago que retorne un valor.
El por que no poner void Es por que la funcion esta devolviendo un valor, si te fijas en bGetDips() hay 2 instrucciones que dicen:

return 1;
return 0;

Si defino a esa funcion como void no puedo devolver ese valor. como era un 1 o 0, entonces me bastaba con 1 bit, pero veo que el compilador se vuelve loco cuando usas "bool" que es lo que C posee y te tira error. entonces prefiero pasar un valor de 8 bits y dejar de complicarme la vida, aunque solo necesite 1 bit solo.

Entonces si yo en mi main.c hago:

a = bGetDips();

en "a" voy a tener el valor 1 o 0 dependiendo si esta activo o no. para eso lo hice. Sino deberia haber creado otra funcion que me indicara si esta o no activo.

Si por ejemplo yo quisera que mi funcion me devuelva una variable un float deberia ser:

Código: C
  1. float fGetPi()
  2. {
  3.    return 3.14159;
  4. }
  5.  
  6. main() {
  7.   float Pi;
  8.   Pi = fGetPi();
  9. }

Si quisiera que me devuelva una estructura

Código: C
  1. struct Coords {
  2.    uint8_t x,
  3.    uint8_t y
  4. };
  5.  
  6. struct Coords sGetCoordenadas() {
  7.   struct Coords a;
  8.   a.x = 10;
  9.   a.y = 20;
  10.   return a;
  11. }
  12.  
  13. main() {
  14.   struct Coords MiCoordenada;
  15.   MiCoordenada = sGetCoordenada();
  16.   // MiCoordenada.x va a ser igual a 10 e y igual a 20
  17. }
Título: Re:Invertir pwm en Atmega 8515 asembler
Publicado por: holik en 27 de Mayo de 2016, 12:51:34
Que tal caballeros del foro me acabo de inscribir y es el primer mensaje, e estado leyendo el post y me intereso mucho el proyecto, me parece que lo podría implementar para modificar unas luces led que no tienen DMX y poder crearle secuencias y efectos nuevos al estilo de las luces comerciales.
Me pregunto si ya alguno de los dos caballeros tiene trabajando el código en alguno de los compiladores y claro saber si ya esta trabajando en físico.
en mi opinión es un excelente proyecto que quedo quieto y me gustaría ponerlo en practica.
Título: Re:Invertir pwm en Atmega 8515 asembler
Publicado por: KILLERJC en 27 de Mayo de 2016, 14:57:02
Yo no lo toque mas por que fue simplemente un desafio de pasar el ASM a C, pero no se si locodelafonola siguio con el proyecto, ya que a el no le funcionaba el codigo que habia presentado, puedo tener errores ya que jamas lo compile.

El codigo esta y puede ser modificado, asi ver tambien que es lo que esta fallando y arreglarlo. Alguien con un poco de experiencia en C podria hacerlo.
Título: Re:Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 28 de Mayo de 2016, 04:39:51
hola
Que tal caballeros del foro me acabo de inscribir y es el primer mensaje, e estado leyendo el post y me intereso mucho el proyecto, me parece que lo podría implementar para modificar unas luces led que no tienen DMX y poder crearle secuencias y efectos nuevos al estilo de las luces comerciales.
Me pregunto si ya alguno de los dos caballeros tiene trabajando el código en alguno de los compiladores y claro saber si ya esta trabajando en físico.
en mi opinión es un excelente proyecto que quedo quieto y me gustaría ponerlo en practica.
 
bueno .,  si presisas algunos de los dos codigos que subi ., te los puedo facilitar cimpletos
he probado los dos ., y armado con exito en lo fisico
eso si son compilaciones en ASM ( nunca pude hacer funcionar lo del C)
querido amigo KILLERJC 
Yo no lo toque mas por que fue simplemente un desafio de pasar el ASM a C, pero no se si locodelafonola siguio con el proyecto, ya que a el no le funcionaba el codigo que habia presentado, puedo tener errores ya que jamas lo compile.

El codigo esta y puede ser modificado, asi ver tambien que es lo que esta fallando y arreglarlo. Alguien con un poco de experiencia en C podria hacerlo.
yo sigo muy agradesido ., por el tiempo y la enseñanza que pusiste ., en este codigo
lastima ., que recien ahora .,  entiendo un poco mas como funciona ., como por ejemplo que las librerias de DMX ., ya estaban ., pero no entendia como asociarlas
y lo que hoy se ., es que solo tendriamos que haberlos enfocado .,  en las funciones de las llaves .,  nada mas
porque  los valores de señal de cada canal ., ya estan separados y guardadas ., en el bufer (DmxRxField (x) ., donde la x coresponde al numero de canal
cualquier cosa siempre ando en el foro ., y si hay que seguir con esto ., soy materia dispuesta ., tengo la parte fisica para probar y compilacion para aportar
tambien nuevas ideas que fui probando ., funciones simples sobre todo
y vuelvo ., a dar las gracias ., al amigo KILLERJC ., es muy dificil ., que alguien se tome el tiempo de enseñar ( y menos a alguien de 53 años y bastante ignorante en esto ) y que hace poco empezo con los micros ., gracias amigo por tu tiempo y dedicacion
.... juan
Título: Re:Invertir pwm en Atmega 8515 asembler
Publicado por: holik en 31 de Mayo de 2016, 12:48:19
Gracias a los dos caballeros por responder, en cuanto al ofrecimiento de "locodelafonola" estaría agradecido por códigos y librerías que me pueda facilitar vi en el mensaje numero 35 un código que subió de control RGB y motores PAP ese codigo seria para un estilo de luz Movie Head estoy en lo correcto? solo faltaría control de un servo adicional o PAP para controlar una plantilla te figuras y quedaría perfecto!
Volviendo al tema también estaría agradecido por material de lo que se trabajo poder manipular efectos ya preestablecidos en el código y asignados a un canal en especifico por medio de DMX.
esto para lo que les comentaba de actualizar luces led que no tienen DMX al estilo de miniflower o duomoon led.

 
Título: Re:Invertir pwm en Atmega 8515 asembler
Publicado por: locodelafonola en 02 de Junio de 2016, 16:22:38
hola
Gracias a los dos caballeros por responder, en cuanto al ofrecimiento de "locodelafonola" estaría agradecido por códigos y librerías que me pueda facilitar vi en el mensaje numero 35 un código que subió de control RGB y motores PAP ese codigo seria para un estilo de luz Movie Head estoy en lo correcto? solo faltaría control de un servo adicional o PAP para controlar una plantilla te figuras y quedaría perfecto!
Volviendo al tema también estaría agradecido por material de lo que se trabajo poder manipular efectos ya preestablecidos en el código y asignados a un canal en especifico por medio de DMX.
esto para lo que les comentaba de actualizar luces led que no tienen DMX al estilo de miniflower o duomoon led.
bueno esa libreria que indicas.,  nunca me enduvo muchos errores al funcionar (lectura de bucle) ., aunque si me compilo ., yo no uso simulador pruebo siempre en lo fisico .,  eso fue una prueba nada mas ., tome la libreria delos STEPEER ., de http://www.hoelscher-hi.de/hendrik/english/stepper.htm ., y sobre ella hice el agregado .,  en realidad par hacer lo que vos queres ., hay que empezar de cero ., con esta libreria (mensaje N° 5)., que NO tiene DMX ., son funciones con las llaves solamente ., eso lo he probado y re-probado funciona expectacularmente ., y esa serian las funcines que buscas., pero claro estan en ASM para ATMEGA8515 ., tambien subi el esquematico y tambien tengo el PCB ., vos diras