Quellcode: DMX Sende Modul für ATxMega

Gast #4216317
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
}
#4216363
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
Gast #4247717
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)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren