Forum: Projekte & Code Quellcode: DMX Sende Modul für ATxMega


von CeeKay (Gast)


Lesenswert?

Hallo Forum,

ich stelle an dieser Stelle mal meinen Code für das Senden von DMX auf 
der Atmel XMega Plattform zur Verfügung. Meine Implementation nutzt DMA 
Transfer für das Übertragen der 512 Bytes zum UART Buffer. Das ist aber 
mehr als Beispiel zu sehen, als eine sinnvolle Anwendung von DMA, da ich 
schön brav auf das Ende des DMA Transfers warte. Der gesamte Ablauf 
benötigt keine Interrupts und basiert auf dem umkonfiguieren der 
Baudrate zur Erzeugung des DMA Frame Formates.
1
/*        _         _             _       _                  _          _            _            _   _            _
2
*         /\ \      /\ \         /\ \     /\_\               / /\       /\ \         /\ \         /\_\/\_\ _      /\ \
3
*        /  \ \     \_\ \       /  \ \   / / /         _    / /  \      \_\ \       /  \ \       / / / / //\_\   /  \ \
4
*       / /\ \ \    /\__ \     / /\ \ \  \ \ \__      /\_\ / / /\ \__   /\__ \     / /\ \ \     /\ \/ \ \/ / /__/ /\ \ \
5
*      / / /\ \_\  / /_ \ \   / / /\ \ \  \ \___\    / / // / /\ \___\ / /_ \ \   / / /\ \ \   /  \____\__/ //___/ /\ \ \
6
*     / / /_/ / / / / /\ \ \ / / /  \ \_\  \__  /   / / / \ \ \ \/___// / /\ \ \ / / /  \ \_\ / /\/________/ \___\/ / / /
7
*    / / /__\/ / / / /  \/_// / /    \/_/  / / /   / / /   \ \ \     / / /  \/_// / /   / / // / /\/_// / /        / / /
8
*   / / /_____/ / / /      / / /          / / /   / / /_    \ \ \   / / /      / / /   / / // / /    / / /        / / /    _
9
*  / / /\ \ \  / / /      / / /________  / / /___/ / //_/\__/ / /  / / /      / / /___/ / // / /    / / /         \ \ \__/\_\
10
* / / /  \ \ \/_/ /      / / /_________\/ / /____\/ / \ \/___/ /  /_/ /      / / /____\/ / \/_/    / / /           \ \___\/ /
11
* \/_/    \_\/\_\/       \/____________/\/_________/   \_____\/   \_\/       \/_________/          \/_/             \/___/_/
12
*
13
*
14
* DMX Output for ATxMega
15
* Tested with ATxMega256A3U
16
* Uses external 16 MHz oscillator together with internal PLL to generate 32MHz system clock
17
* DMX Signal will be transmitted through Port PC3
18
* DMA transfer added for fun but not needed since we are waiting for DMA to finish before next transfer
19
*
20
* Released under the "Don't care" license
21
* Feel free to use this code in any way you want
22
* Also no support will be given in any way
23
*
24
* Code V1.0 
25
* 30.07.2015
26
*/
27
28
29
#include <avr/io.h>
30
#include <util/delay.h>
31
32
33
enum{BREAK, STARTBYTE, DMXDATA};
34
unsigned char DMXStatus = BREAK;
35
36
37
38
39
40
void Clock_init(void)
41
{
42
  //Xosc Bit 7&6 to 11 | Bit 3 to 0 as 1011
43
  OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
44
  //Bit 3 to 1 to enable external oscillator
45
  OSC.CTRL |= OSC_XOSCEN_bm;
46
  //wait for stable clock
47
  while(!(OSC.STATUS & OSC_XOSCRDY_bm));
48
  //Disable register protection for 4 clocks
49
  CCP = CCP_IOREG_gc;
50
  //Set Bit 2:0 to 011 for external oscillator
51
  CLK.CTRL = CLK_SCLKSEL_XOSC_gc;
52
}
53
54
void PLL_init(void)
55
{
56
  //Bit 7:0 to 11 for external oscillator as PLL source | 2 as multiplication value
57
  OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 0x02;
58
  //enable PLL
59
  OSC.CTRL |= OSC_PLLEN_bm;
60
  //wait for stable oscillation
61
  while (!(OSC.STATUS & OSC_PLLRDY_bm));
62
  //Disable register protection for 4 clocks
63
  CCP = CCP_IOREG_gc;
64
  //Set Bit 2:0 for PLL as clock source
65
  CLK.CTRL = CLK_SCLKSEL_PLL_gc;
66
}
67
68
void Init_uart(void)
69
{
70
    //configure usart
71
    // Pin from USARTC0 TxD C3 set to output
72
    PORTC.DIRSET = PIN3_bm;
73
    // Pin from USARTC0 TxD C3 to high
74
    PORTC.OUTSET = PIN3_bm;
75
    // Asynchronous Modus Bit 7 & 6 to 0
76
    USARTC0.CTRLC = (USARTC0.CTRLC & ~USART_CMODE_gm ) | USART_CMODE_ASYNCHRONOUS_gc;
77
    // No parity Bit 5 & 4 to 0
78
    USARTC0.CTRLC = (USARTC0.CTRLC & ~USART_PMODE_gm ) | USART_PMODE_DISABLED_gc;
79
    // 2 stop bits Bit 3 to 1
80
    USARTC0.CTRLC = (USARTC0.CTRLC & ~USART_SBMODE_bm) | (0x01<<3);
81
    // 8 data bits Bit 2 to 0 set to 011
82
    USARTC0.CTRLC = (USARTC0.CTRLC & ~USART_CHSIZE_gm ) | USART_CHSIZE_8BIT_gc;
83
    // 100 kBaud
84
    USARTC0.BAUDCTRLA = 19;
85
    // 100 kBaud
86
    USARTC0.BAUDCTRLB =(0x00 << USART_BSCALE0_bp)|(19 >> 8);
87
    // activate USARTC1
88
    USARTC0.CTRLB = USART_TXEN_bm;
89
}
90
91
//Configure DMA to transfer data from DMX array into UART buffer
92
void dma_set(unsigned char *dmxdata, unsigned int length){
93
  
94
  // activate single buffer, burst size 1Byte
95
  DMA.CTRL = DMA_CH_ENABLE_bm;
96
  
97
  //Modus transaction, increase and decrease, Burst
98
  DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_TRANSACTION_gc | DMA_CH_SRCDIR_INC_gc| DMA_CH_DESTRELOAD_NONE_gc | DMA_CH_DESTDIR_FIXED_gc;
99
100
  // Trigger Source is USARTC1 trigger if data buffer is empty
101
  DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_USARTC0_DRE_gc;
102
103
  //Set number of dmx channels to transfer
104
  DMA.CH0.TRFCNT = length;
105
106
  //8Bit source register
107
  DMA.CH0.SRCADDR0  =(((uint16_t)(dmxdata))>>0*8)&0xFF;
108
  DMA.CH0.SRCADDR1  =(((uint16_t)(dmxdata))>>1*8)&0xFF;
109
  DMA.CH0.SRCADDR2  = 0;
110
111
  //8Bit target register at USARTC1
112
  DMA.CH0.DESTADDR0 = ((uint16_t) &USARTC0.DATA >>0*8)&0xFF;
113
  DMA.CH0.DESTADDR1 = ((uint16_t) &USARTC0.DATA >>1*8)&0xFF;
114
  DMA.CH0.DESTADDR2 = 0;
115
}
116
117
118
void Send_DMX_DMA(unsigned char *dmxdata, unsigned int length)
119
{
120
  //DMX is 250 kBaud 8N2 format
121
  //Each package is framed by 1 start bit (0) and 2 stop bits (1)
122
  //Start Condition is a >88µs break followed by >8 µs mark
123
  //To generate Start condition reconfigure baud rate setting to 100 kBaud and send 0x00
124
  //0x00 is 0000 0000 together with normal start bit = 9 low bits followed by two high bits from stop bits of 8N2 format
125
  //At 100 kBaud a single bit time is 10µs
126
  //9 x 10 µs = 90 µs low and 2 x 10 µs = 20 µs high
127
  //Calculated register settings for 100 kBaud are BSCALE = 0 & BSEL = 019
128
  //Calculated register settings for 250 kBaud are BSCALE = 0 & BSEL = 007
129
  //Than always transfer a Null package to determine data type for channel transmission
130
  //After this send out DMX payload data
131
  
132
  //Generate break condition
133
  if(DMXStatus==BREAK)
134
  {
135
    //Reconfigure baud rate to 100 kBaud
136
    USARTC0.BAUDCTRLA = 19;
137
    USARTC0.BAUDCTRLB =(0 << USART_BSCALE0_bp)|(19 >> 8);
138
    //Send a Zero to generate Break and Mark
139
    USARTC0.DATA = 0x00;
140
    //Check for finished physical transmission and clear flag
141
    while (!(USARTC0.STATUS & USART_TXCIF_bm));
142
    USARTC0.STATUS |= USART_TXCIF_bm;
143
    //Switch to next step in DMX protocol. The start byte 0x00
144
    DMXStatus = STARTBYTE;
145
  }
146
  
147
148
149
  //Send information about type of DMX transmission
150
  if(DMXStatus == STARTBYTE)
151
  {
152
    //Reconfigure baud rate to 250 kBaud
153
    USARTC0.BAUDCTRLA = 07;
154
    USARTC0.BAUDCTRLB =(0 << USART_BSCALE0_bp)|(07 >> 8);
155
    //Send a Zero to let DMX receivers know that now channels values will be send
156
    USARTC0.DATA = 0x00;
157
    //Check for finished physical transmission and clear flag
158
    while (!(USARTC0.STATUS & USART_TXCIF_bm));
159
    USARTC0.STATUS |= USART_TXCIF_bm;
160
    //Switch to next step in DMX protocol and send channel informations
161
    DMXStatus = DMXDATA;
162
163
  }
164
165
166
  //Send DMX channel data
167
  if(DMXStatus == DMXDATA)
168
  {
169
    //Configure DMA to transmission data register and length
170
    dma_set(dmxdata, length);
171
    //Activate DMA CH0 and send rest of DMX stream via DMA access
172
    DMA.CH0.REPCNT = 0;
173
    DMA.CH0.CTRLA = DMA_CH_ENABLE_bm |DMA_CH_SINGLE_bm|DMA_CH_BURSTLEN_1BYTE_gc;
174
    //Check for running DMA transfer and clear flag
175
    while (!(DMA.INTFLAGS & DMA_CH0TRNIF_bm) || (DMA.CH0.CTRLB & (DMA_CH_CHBUSY_bm | DMA_CH_CHPEND_bm)));
176
    DMA.INTFLAGS |= DMA_CH0TRNIF_bm;
177
    //Deactivate DMA
178
    DMA.CH0.CTRLA &= ~DMA_CH_ENABLE_bm;
179
    //Check for finished physical transmission and clear flag
180
    while (!(USARTC0.STATUS & USART_TXCIF_bm));
181
    USARTC0.STATUS |= USART_TXCIF_bm;
182
    //Go back to start of DMX protocol
183
    DMXStatus = BREAK;
184
  }
185
}
186
187
188
int main(void)
189
{
190
  Clock_init();
191
  PLL_init();
192
  Init_uart();
193
  //Port E to Output and High for routing Uart to SP3T Output
194
  PORTE.DIRSET |= PIN6_bm;
195
  PORTE.OUTSET |= PIN6_bm;
196
  
197
  unsigned char white[512] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
198
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
199
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
200
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
201
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
202
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
203
  
204
    while(1)
205
    {      
206
  Send_DMX_DMA(&white[0],512);
207
  _delay_ms(1000);
208
  }
209
  
210
}

von Falk B. (falk)


Lesenswert?

@CeeKay (Gast)

>der Atmel XMega Plattform zur Verfügung. Meine Implementation nutzt DMA
>Transfer für das Übertragen der 512 Bytes zum UART Buffer. Das ist aber
>mehr als Beispiel zu sehen, als eine sinnvolle Anwendung von DMA, da ich
>schön brav auf das Ende des DMA Transfers warte. Der gesamte Ablauf
>benötigt keine Interrupts

"Niemand ist unnütze. Er kann auch als schlechtes Beispiel dienen."

Im Ernst, was soll denn das? Hat die Welt wirklich ein sooo schlechtes 
Beispiel gebraucht? Da ist jede Routone mit Interrupt und ohne DMA 
besser als das hier. 100% CPU Ausbremsung für NICHTS!

DONT LIKE

von CeeKay (Gast)


Lesenswert?

Berühmtes Zitat "Rofelcopter"

Zitiert noch die Passage, dass der DMA Zugriff nicht sinnvoll genutzt 
wird und bashed trotzdem drauf rum. Aber die Tatsache, dass das gesate 
Program eigentlich nichts nützliches macht, außer alle Kanäle permanent 
auf FF zu setzten wird gekonnt ignoriert. Nun ja geben wir dem Troll 
noch etwas Futter. Hier nun eine etwas sinnvollere Anwendung von DMA, 
dafür aber mit Interrupts.
1
/*        _         _             _       _                  _          _            _            _   _            _
2
*         /\ \      /\ \         /\ \     /\_\               / /\       /\ \         /\ \         /\_\/\_\ _      /\ \
3
*        /  \ \     \_\ \       /  \ \   / / /         _    / /  \      \_\ \       /  \ \       / / / / //\_\   /  \ \
4
*       / /\ \ \    /\__ \     / /\ \ \  \ \ \__      /\_\ / / /\ \__   /\__ \     / /\ \ \     /\ \/ \ \/ / /__/ /\ \ \
5
*      / / /\ \_\  / /_ \ \   / / /\ \ \  \ \___\    / / // / /\ \___\ / /_ \ \   / / /\ \ \   /  \____\__/ //___/ /\ \ \
6
*     / / /_/ / / / / /\ \ \ / / /  \ \_\  \__  /   / / / \ \ \ \/___// / /\ \ \ / / /  \ \_\ / /\/________/ \___\/ / / /
7
*    / / /__\/ / / / /  \/_// / /    \/_/  / / /   / / /   \ \ \     / / /  \/_// / /   / / // / /\/_// / /        / / /
8
*   / / /_____/ / / /      / / /          / / /   / / /_    \ \ \   / / /      / / /   / / // / /    / / /        / / /    _
9
*  / / /\ \ \  / / /      / / /________  / / /___/ / //_/\__/ / /  / / /      / / /___/ / // / /    / / /         \ \ \__/\_\
10
* / / /  \ \ \/_/ /      / / /_________\/ / /____\/ / \ \/___/ /  /_/ /      / / /____\/ / \/_/    / / /           \ \___\/ /
11
* \/_/    \_\/\_\/       \/____________/\/_________/   \_____\/   \_\/       \/_________/          \/_/             \/___/_/
12
*
13
*
14
* DMX Output for ATxMega
15
* Tested with ATxMega256A3U
16
* Uses external 16 MHz oscillator together with internal PLL to generate 32MHz system clock
17
* DMX Signal will be transmitted through Port PC3
18
* DMA transfer used for transmission of DMX data to UART registers
19
* Low level interrupt priority für DMA transfer set
20
*
21
* Released under the "Don't care" license
22
* Feel free to use this code in any way you want
23
* Also no support will be given in any way
24
*
25
* Code V1.1 
26
* 26.08.2015
27
*/
28
29
30
#include <avr/io.h>
31
#include <util/delay.h>
32
33
34
enum{BREAK, STARTBYTE, DMXDATA};
35
unsigned char DMXStatus = BREAK;
36
37
38
39
void Clock_init(void)
40
{
41
  //Xosc Bit 7&6 to 11 | Bit 3 to 0 as 1011
42
  OSC.XOSCCTRL = OSC_FRQRANGE_12TO16_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
43
  //Bit 3 to 1 to enable external oscillator
44
  OSC.CTRL |= OSC_XOSCEN_bm;
45
  //wait for stable clock
46
  while(!(OSC.STATUS & OSC_XOSCRDY_bm));
47
  //Disable register protection for 4 clocks
48
  CCP = CCP_IOREG_gc;
49
  //Set Bit 2:0 to 011 for external oscillator
50
  CLK.CTRL = CLK_SCLKSEL_XOSC_gc;
51
}
52
53
void PLL_init(void)
54
{
55
  //Bit 7:0 to 11 for external oscillator as PLL source | 2 as multiplication value
56
  OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 0x02;
57
  //enable PLL
58
  OSC.CTRL |= OSC_PLLEN_bm;
59
  //wait for stable oscillation
60
  while (!(OSC.STATUS & OSC_PLLRDY_bm));
61
  //Disable register protection for 4 clocks
62
  CCP = CCP_IOREG_gc;
63
  //Set Bit 2:0 for PLL as clock source
64
  CLK.CTRL = CLK_SCLKSEL_PLL_gc;
65
}
66
67
void Init_uart(void)
68
{
69
    //configure usart
70
    // Pin from USARTC0 TxD C3 set to output
71
    PORTC.DIRSET = PIN3_bm;
72
    // Pin from USARTC0 TxD C3 to high
73
    PORTC.OUTSET = PIN3_bm;
74
    // Asynchronous Modus Bit 7 & 6 to 0
75
    USARTC0.CTRLC = (USARTC0.CTRLC & ~USART_CMODE_gm ) | USART_CMODE_ASYNCHRONOUS_gc;
76
    // No parity Bit 5 & 4 to 0
77
    USARTC0.CTRLC = (USARTC0.CTRLC & ~USART_PMODE_gm ) | USART_PMODE_DISABLED_gc;
78
    // 2 stop bits Bit 3 to 1
79
    USARTC0.CTRLC = (USARTC0.CTRLC & ~USART_SBMODE_bm) | (0x01<<3);
80
    // 8 data bits Bit 2 to 0 set to 011
81
    USARTC0.CTRLC = (USARTC0.CTRLC & ~USART_CHSIZE_gm ) | USART_CHSIZE_8BIT_gc;
82
    // 100 kBaud
83
    USARTC0.BAUDCTRLA = 19;
84
    // 100 kBaud
85
    USARTC0.BAUDCTRLB =(0x00 << USART_BSCALE0_bp)|(19 >> 8);
86
    // activate USARTC1
87
    USARTC0.CTRLB = USART_TXEN_bm;
88
}
89
90
//Configure DMA to transfer data from DMX array into UART buffer
91
void dma_set(unsigned char *dmxdata, unsigned int length){
92
  
93
  // activate single buffer, burst size 1Byte
94
  DMA.CTRL = DMA_CH_ENABLE_bm;
95
  
96
  //Modus transaction, increase and decrease, Burst
97
  DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_TRANSACTION_gc | DMA_CH_SRCDIR_INC_gc| DMA_CH_DESTRELOAD_NONE_gc | DMA_CH_DESTDIR_FIXED_gc;
98
99
  // Trigger Source is USARTC1 trigger if data buffer is empty
100
  DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_USARTC0_DRE_gc;
101
102
  //Set number of dmx channels to transfer
103
  DMA.CH0.TRFCNT = length;
104
105
  //8Bit source register
106
  DMA.CH0.SRCADDR0  =(((uint16_t)(dmxdata))>>0*8)&0xFF;
107
  DMA.CH0.SRCADDR1  =(((uint16_t)(dmxdata))>>1*8)&0xFF;
108
  DMA.CH0.SRCADDR2  = 0;
109
110
  //8Bit target register at USARTC1
111
  DMA.CH0.DESTADDR0 = ((uint16_t) &USARTC0.DATA >>0*8)&0xFF;
112
  DMA.CH0.DESTADDR1 = ((uint16_t) &USARTC0.DATA >>1*8)&0xFF;
113
  DMA.CH0.DESTADDR2 = 0;
114
115
  //Set CH0 transmission completed interrupt level to low
116
  DMA.CH0.CTRLB |= DMA_CH_TRNINTLVL_LO_gc;
117
}
118
119
120
void Send_DMX_DMA(unsigned char *dmxdata, unsigned int length)
121
{
122
  //DMX is 250 kBaud 8N2 format
123
  //Each package is framed by 1 start bit (0) and 2 stop bits (1)
124
  //Start Condition is a >88µs break followed by >8 µs mark
125
  //To generate Start condition reconfigure baud rate setting to 100 kBaud and send 0x00
126
  //0x00 is 0000 0000 together with normal start bit = 9 low bits followed by two high bits from stop bits of 8N2 format
127
  //At 100 kBaud a single bit time is 10µs
128
  //9 x 10 µs = 90 µs low and 2 x 10 µs = 20 µs high
129
  //Calculated register settings for 100 kBaud are BSCALE = 0 & BSEL = 019
130
  //Calculated register settings for 250 kBaud are BSCALE = 0 & BSEL = 007
131
  //Than always transfer a Null package to determine data type for channel transmission
132
  //After this send out DMX payload data
133
  
134
  //Generate break condition
135
  if(DMXStatus==BREAK)
136
  {
137
    //Reconfigure baud rate to 100 kBaud
138
    USARTC0.BAUDCTRLA = 19;
139
    USARTC0.BAUDCTRLB =(0 << USART_BSCALE0_bp)|(19 >> 8);
140
    //Send a Zero to generate Break and Mark
141
    USARTC0.DATA = 0x00;
142
    //Check for finished physical transmission and clear flag
143
    while (!(USARTC0.STATUS & USART_TXCIF_bm));
144
    USARTC0.STATUS |= USART_TXCIF_bm;
145
    //Switch to next step in DMX protocol. The start byte 0x00
146
    DMXStatus = STARTBYTE;
147
  }
148
  
149
150
151
  //Send information about type of DMX transmission
152
  if(DMXStatus == STARTBYTE)
153
  {
154
    //Reconfigure baud rate to 250 kBaud
155
    USARTC0.BAUDCTRLA = 07;
156
    USARTC0.BAUDCTRLB =(0 << USART_BSCALE0_bp)|(07 >> 8);
157
    //Send a Zero to let DMX receivers know that now channels values will be send
158
    USARTC0.DATA = 0x00;
159
    //Check for finished physical transmission and clear flag
160
    while (!(USARTC0.STATUS & USART_TXCIF_bm));
161
    USARTC0.STATUS |= USART_TXCIF_bm;
162
    //Switch to next step in DMX protocol and send channel informations
163
    DMXStatus = DMXDATA;
164
165
  }
166
167
168
  //Send DMX channel data
169
  if(DMXStatus == DMXDATA)
170
  {
171
    //Configure DMA to transmission data register and length
172
    dma_set(dmxdata, length);
173
    //Activate DMA CH0 and send rest of DMX stream via DMA access
174
    DMA.CH0.REPCNT = 0;
175
    DMA.CH0.CTRLA = DMA_CH_ENABLE_bm |DMA_CH_SINGLE_bm|DMA_CH_BURSTLEN_1BYTE_gc;
176
  }
177
}
178
179
180
int main(void)
181
{
182
  Clock_init();
183
  PLL_init();
184
  Init_uart();
185
  //Port E to Output and High for routing Uart to SP3T Output
186
  PORTE.DIRSET |= PIN6_bm;
187
  PORTE.OUTSET |= PIN6_bm;
188
189
  /* Enable LO interrupt level. */
190
  PMIC.CTRL |= PMIC_LOLVLEN_bm;
191
  sei();
192
  
193
  unsigned char white[512] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
194
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
195
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
196
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
197
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
198
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
199
  
200
    while(1)
201
    {      
202
  Send_DMX_DMA(&white[0],512);
203
  _delay_ms(1000);
204
  }
205
  
206
}
207
208
ISR(DMA_CH0_vect)
209
{
210
  //clear interrupt flag
211
  DMA.CH0.CTRLB |= DMA_CH_TRNIF_bm;
212
  //Deactivate DMA
213
  DMA.CH0.CTRLA &= ~DMA_CH_ENABLE_bm;
214
  //Check for finished physical transmission and clear flag
215
  while (!(USARTC0.STATUS & USART_TXCIF_bm));
216
  USARTC0.STATUS |= USART_TXCIF_bm;
217
  //Go back to start of DMX protocol
218
  DMXStatus = BREAK;
219
}

Quizfrage wo liegt das Problem in dieser Form der Implementierung, 
welche hier nicht abgefangen wird? Der beste Flame erhält einen 
Rofelcopter als kostenloses GIF (Jiff)

von Rajat (Gast)


Lesenswert?

Your posting is abselutoly on the point!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.