Hallo, ich möchte den Code von hier: http://www.hoelscher-hi.de/hendrik/light/ressources.htm auf einen ATmega644P portieren. Ich habe dabei die Register nach bestem Wissen angepasst. Aber ihr Experten seht vermutlich auf den ersten Blick an welcher Stelle mir der Fehler unterlaufen ist. Hier der Original-Code der Datei lib_dmx_in.h
1 | #include <avr/io.h> |
2 | #include <stdint.h> |
3 | #include <avr/interrupt.h> |
4 | |
5 | |
6 | #define USE_DIP //use DIPs?
|
7 | #define DMX_CHANNELS (2) //use at least 2ch
|
8 | #define F_OSC (8000) //oscillator freq. in kHz (typical 8MHz or 16MHz)
|
9 | |
10 | |
11 | volatile uint8_t DmxField[DMX_CHANNELS]; //array of DMX vals (raw) |
12 | volatile uint16_t DmxAddress; //start address |
13 | |
14 | extern void init_DMX(void); |
15 | extern void get_dips(void); |
lib_dmx_in.c
1 | /**** A P P L I C A T I O N N O T E ************************************
|
2 | *
|
3 | * Title : DMX512 reception library
|
4 | * Version : v1.2
|
5 | * Last updated : 21.04.07
|
6 | * Target : Transceiver Rev.3.01 [ATmega8515]
|
7 | * Clock : 8MHz, 16MHz
|
8 | *
|
9 | * written by hendrik hoelscher, www.hoelscher-hi.de */
|
10 | #include "lib_dmx_in.h" |
11 | // ********************* local definitions *********************
|
12 | |
13 | |
14 | enum {IDLE, BREAK, STARTB, STARTADR}; //DMX states |
15 | |
16 | uint8_t gDmxState; |
17 | uint8_t *gDmxPnt; |
18 | uint16_t DmxCount; |
19 | |
20 | // *************** DMX Reception Initialisation ****************
|
21 | void init_DMX(void) |
22 | {
|
23 | #ifdef USE_DIP
|
24 | DDRC= 0; //set up DIPs |
25 | PORTC= 0xFF; |
26 | DDRE &= ~((1<<2)|(1<<1)); |
27 | PORTE |= (1<<2)|(1<<1); |
28 | #endif
|
29 | |
30 | DDRD |= (1<<2); |
31 | PORTD &= ~(1<<2); //enable reception |
32 | UBRRH = 0; |
33 | UBRRL = ((F_OSC/4000)-1); //250kbaud, 8N2 |
34 | UCSRC |= (1<<URSEL)|(3<<UCSZ0)|(1<<USBS); |
35 | UCSRB |= (1<<RXEN)|(1<<RXCIE); |
36 | gDmxState= IDLE; |
37 | |
38 | uint8_t i; |
39 | for (i=0; i<DMX_CHANNELS; i++) |
40 | {
|
41 | DmxField[i]= 0; |
42 | }
|
43 | |
44 | }
|
45 | |
46 | // ************* get DMX start address **************
|
47 | |
48 | void get_dips(void) |
49 | {
|
50 | #ifdef USE_DIP
|
51 | uint16_t Temp= (255-PINC); //invert DIP state |
52 | if (!(PINE &(1<<2))) |
53 | {
|
54 | Temp= Temp +256; //9th bit |
55 | }
|
56 | |
57 | if (Temp != 0) |
58 | {
|
59 | DmxAddress= Temp; |
60 | if (!(UCSRB &(1<<RXCIE))) //if receiver was disabled -> enable and wait for break |
61 | {
|
62 | gDmxState= IDLE; |
63 | UCSRB |= (1<<RXCIE); |
64 | }
|
65 | }
|
66 | else
|
67 | {
|
68 | UCSRB &= ~(1<<RXCIE); //disable Receiver if start address = 0 |
69 | for (Temp=0; Temp<DMX_CHANNELS; Temp++) |
70 | {
|
71 | DmxField[Temp]= 0; |
72 | }
|
73 | }
|
74 | #endif
|
75 | }
|
76 | |
77 | // *************** DMX Reception ISR ****************
|
78 | ISR (UART_RX_vect) |
79 | {
|
80 | uint8_t USARTstate= UCSRA; //get state |
81 | uint8_t DmxByte= UDR; //get data |
82 | uint8_t DmxState= gDmxState; //just get once from SRAM!!! |
83 | |
84 | if (USARTstate &(1<<FE)) //check for break |
85 | {
|
86 | UCSRA &= ~(1<<FE); //reset flag |
87 | DmxCount= DmxAddress; //reset frame counter |
88 | gDmxState= BREAK; |
89 | }
|
90 | |
91 | else if (DmxState == BREAK) |
92 | {
|
93 | if (DmxByte == 0) |
94 | {
|
95 | gDmxState= STARTB; //normal start code detected |
96 | gDmxPnt= ((uint8_t*)DmxField +1); |
97 | }
|
98 | else gDmxState= IDLE; |
99 | }
|
100 | |
101 | else if (DmxState == STARTB) |
102 | {
|
103 | if (--DmxCount == 0) //start address reached? |
104 | {
|
105 | gDmxState= STARTADR; |
106 | DmxField[0]= DmxByte; |
107 | }
|
108 | }
|
109 | |
110 | else if (DmxState == STARTADR) |
111 | {
|
112 | uint8_t *DmxPnt; |
113 | DmxPnt= gDmxPnt; |
114 | *DmxPnt= DmxByte; |
115 | if (++DmxPnt >= (DmxField +DMX_CHANNELS)) //all ch received? |
116 | {
|
117 | gDmxState= IDLE; |
118 | }
|
119 | else gDmxPnt= DmxPnt; |
120 | }
|
121 | }
|
Und hier meine angepassten Versionen für den ATmega644P lib_dmx_in.h
1 | #include <avr/io.h> |
2 | #include <stdint.h> |
3 | #include <avr/interrupt.h> |
4 | |
5 | //#define USE_DIP //use DIPs?
|
6 | #define DMX_CHANNELS (2) //use at least 2ch
|
7 | #define F_OSC (14746) //oscillator freq. in kHz (typical 8MHz or 16MHz)
|
8 | |
9 | volatile uint8_t DmxField[DMX_CHANNELS]; //array of DMX vals (raw) |
10 | volatile uint16_t DmxAddress; //start address |
11 | |
12 | extern void init_DMX(void); |
13 | extern void get_dips(void); |
lib_dmx_in.c
1 | /**** A P P L I C A T I O N N O T E ************************************
|
2 | *
|
3 | * Title : DMX512 reception library
|
4 | * Version : v1.2
|
5 | * Last updated : 21.04.07
|
6 | * Target : Transceiver Rev.3.01 [ATmega8515]
|
7 | * Clock : 8MHz, 16MHz
|
8 | *
|
9 | * written by hendrik hoelscher, www.hoelscher-hi.de
|
10 | ***************************************************************************
|
11 | This program is free software; you can redistribute it and/or
|
12 | modify it under the terms of the GNU General Public License
|
13 | as published by the Free Software Foundation; either version2 of
|
14 | the License, or (at your option) any later version.
|
15 | |
16 | This program is distributed in the hope that it will be useful,
|
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
19 | General Public License for more details.
|
20 | |
21 | If you have no copy of the GNU General Public License, write to the
|
22 | Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
23 | |
24 | For other license models, please contact the author.
|
25 | |
26 | ;***************************************************************************/
|
27 | |
28 | #include <avr/io.h> |
29 | #include "lib_dmx_in.h" |
30 | |
31 | // ********************* local definitions *********************
|
32 | |
33 | enum {IDLE, BREAK, STARTB, STARTADR}; //DMX states |
34 | |
35 | uint8_t gDmxState; |
36 | uint8_t *gDmxPnt; |
37 | uint16_t DmxCount; |
38 | |
39 | |
40 | // *************** DMX Reception Initialisation ****************
|
41 | void init_DMX(void) |
42 | {
|
43 | #ifdef USE_DIP
|
44 | DDRC= 0; //set up DIPs |
45 | PORTC= 0xFF; |
46 | DDRE &= ~((1<<2)|(1<<1)); |
47 | PORTE |= (1<<2)|(1<<1); |
48 | #endif
|
49 | |
50 | DDRD |= (1<<2); |
51 | PORTD &= ~(1<<2); //enable reception |
52 | //UBRRH = 0;
|
53 | UBRR0H = 0; // NEW |
54 | //UBRRL = ((F_OSC/4000)-1); //250kbaud, 8N2
|
55 | UBRR0L = ((F_OSC/4000)-1); // NEW //250kbaud, 8N2 |
56 | //UCSRC |= (1<<URSEL)|(3<<UCSZ0)|(1<<USBS);
|
57 | UCSR0C |= (3<<UCSZ01)|(1<<USBS0); // NEW |
58 | //UCSRB |= (1<<RXEN)|(1<<RXCIE);
|
59 | UCSR0B |= (1<<RXEN0)|(1<<RXCIE0); // NEW |
60 | gDmxState= IDLE; |
61 | |
62 | uint8_t i; |
63 | for (i=0; i<DMX_CHANNELS; i++) |
64 | {
|
65 | DmxField[i]= 0; |
66 | }
|
67 | |
68 | }
|
69 | |
70 | |
71 | // ************* get DMX start address **************
|
72 | void get_dips(void) |
73 | {
|
74 | #ifdef USE_DIP
|
75 | uint16_t Temp= (255-PINC); //invert DIP state |
76 | if (!(PINE &(1<<2))) |
77 | {
|
78 | Temp= Temp +256; //9th bit |
79 | }
|
80 | if (Temp != 0) |
81 | {
|
82 | DmxAddress= Temp; |
83 | if (!(UCSRB &(1<<RXCIE))) //if receiver was disabled -> enable and wait for break |
84 | {
|
85 | gDmxState= IDLE; |
86 | UCSRB |= (1<<RXCIE); |
87 | }
|
88 | }
|
89 | else
|
90 | {
|
91 | UCSRB &= ~(1<<RXCIE); //disable Receiver if start address = 0 |
92 | for (Temp=0; Temp<DMX_CHANNELS; Temp++) |
93 | {
|
94 | DmxField[Temp]= 0; |
95 | }
|
96 | }
|
97 | #endif
|
98 | DmxAddress = 1; |
99 | }
|
100 | |
101 | |
102 | // *************** DMX Reception ISR ****************
|
103 | ISR (USART0_RX_vect) |
104 | {
|
105 | //uint8_t USARTstate= UCSRA; //get state
|
106 | uint8_t USARTstate= UCSR0A; //NEW //get state |
107 | //uint8_t DmxByte= UDR; //get data
|
108 | uint8_t DmxByte= UDR0; // NEW //get data |
109 | uint8_t DmxState= gDmxState; //just get once from SRAM!!! |
110 | |
111 | //if (USARTstate &(1<<FE)) //check for break
|
112 | if (USARTstate &(1<<FE0)) // NEW //check for break |
113 | {
|
114 | //UCSRA &= ~(1<<FE); //reset flag
|
115 | UCSR0A &= ~(1<<FE0); //NEW //reset flag |
116 | DmxCount= DmxAddress; //reset frame counter |
117 | gDmxState= BREAK; |
118 | }
|
119 | |
120 | else if (DmxState == BREAK) |
121 | {
|
122 | if (DmxByte == 0) |
123 | {
|
124 | gDmxState= STARTB; //normal start code detected |
125 | gDmxPnt= ((uint8_t*)DmxField +1); |
126 | }
|
127 | else gDmxState= IDLE; |
128 | }
|
129 | |
130 | else if (DmxState == STARTB) |
131 | {
|
132 | if (--DmxCount == 0) //start address reached? |
133 | {
|
134 | gDmxState= STARTADR; |
135 | DmxField[0]= DmxByte; |
136 | }
|
137 | }
|
138 | |
139 | else if (DmxState == STARTADR) |
140 | {
|
141 | uint8_t *DmxPnt; |
142 | DmxPnt= gDmxPnt; |
143 | *DmxPnt= DmxByte; |
144 | if (++DmxPnt >= (DmxField +DMX_CHANNELS)) //all ch received? |
145 | {
|
146 | gDmxState= IDLE; |
147 | }
|
148 | else gDmxPnt= DmxPnt; |
149 | }
|
150 | }
|
Zu meiner Schaltung Ich verwende einen 14.7456 MHz-Quarz und den 71576B als Wandlerchip von RS485 nach RS232 an der UART-Schnittstelle. Verbunden habe ich so (Chip -- Mikrocontroller): RE -- INT0 DE -- INT0 R -- RXD D -- TXD Leider togglet PD7 nicht, wenn ich an meinem DMX-Mischpult die Regler rauf- und runterfahre (habe einen PAR64-LED zur Kontrolle angeschlossen). Ich steuere mit dem Pult die Kanäle 1 bis 6. Als DMX-Adresse habe ich in der Funktion get_dips() die eins (1) eingestellt. Wo sind die Fehler in meiner Portierung? Achja: Die main-Datei ist in der portierten Version nicht verändert worden:
1 | #include "lib_dmx_in.h" |
2 | |
3 | int main(void) |
4 | {
|
5 | cli(); |
6 | DDRD |= (1<<PD7); //red LED pin is output |
7 | init_DMX(); |
8 | sei(); |
9 | |
10 | for(;;) |
11 | {
|
12 | get_dips(); |
13 | if (DmxField[0] >= 127) //enable LED if 1st DMX val is >127 |
14 | {
|
15 | PORTD &= ~(1<<PD7); //LED ON |
16 | }
|
17 | else
|
18 | {
|
19 | PORTD |= (1<<PD7); //LED OFF |
20 | }
|
21 | }
|
22 | }
|