Hallo,
ich möchte mit einem atmega8 16 Bit mithilfe der SPI Hardware an einen
MPC 4921 DAC senden.
Datenblatt:
http://www.reichelt.de/?;ACTION=7;LA=28;OPEN=0;INDEX=0;FILENAME=A200%252FMCP4921_MCP4922_MIC.pdf;SID=32Y2QSRawQASAAAGETf-08bce0255a2066c93b1cc58e240af89af
Den DAC konnte ich bereits per Software ansteuern, leider funktioniert
es mit der Hardware nicht.
Den CS (low aktiv) habe ich auf Pin B0 gesetzt. Dieser wird vorm senden
des 1. Byte auf low gesetzt, nachdem das 2. Byte gesendet ist wieder auf
high.
Ein globales statusbyte gibt an ob der spi bus frei ist oder ob gerade
das 1. oder 2. byte geschickt wird.
Ein Interrupt wird ausgelöst, wenn ein Byte verschickt wurde, je nachdem
in welchem Status er sich befindet wird das 2. Byte verschickt oder der
SPD Bus im Status freigegeben. Leider funktioniert der Code nicht.
(Der ADC erwartet 4 Controlbits (0111), danach 12 Bit für den DAC. Die
12 sind die 12 höchsten Bit eines zeichenlosen 16 Bit Wortes. Bei der
Hardware Version soll ein weiteres verschicken eines 16 Bit Wortes
einfach ignoriert werden. In der Main Funktion wird in einer
Endlosschleife 65535 versendet)
main:
1 | #include <avr/io.h>
|
2 | #include "mcp_4921.h"
|
3 |
|
4 |
|
5 | int main(void)
|
6 | {
|
7 | mcp_init();
|
8 | while(1)
|
9 | {
|
10 | mcp_setValue(65535);
|
11 | }
|
12 | return 0;
|
13 | }
|
mcp_4921.h:
1 | #ifndef MODUL_MCP_4921_H
|
2 | #define MODUL_MCP_4921_H
|
3 |
|
4 | #include <avr/io.h>
|
5 |
|
6 |
|
7 |
|
8 | #define SCK 5
|
9 | #define SDI 3
|
10 | #define CS 0
|
11 | #define LDAC 1
|
12 |
|
13 | #define DDR_SPI DDRB
|
14 | #define PORT_SPI PORTB
|
15 |
|
16 |
|
17 | void mcp_setValue(uint16_t value);
|
18 | void mcp_init(void);
|
19 |
|
20 | volatile int8_t spi_status;
|
21 | uint8_t lower_byte;
|
22 |
|
23 | #endif
|
mcp4921.c in Software (funktioniert):
1 | #include "mcp_4921.h"
|
2 | #include <avr/io.h>
|
3 |
|
4 | void mcp_init(void)
|
5 | {
|
6 | DDR_SPI |= (1<<CS)|(1<<SCK)|(1<<SDI)|(1<<LDAC); // Setzte Busausgänge
|
7 |
|
8 | PORT_SPI |= (1<<CS)|(1<<LDAC); // MPC ist nicht für SPI aktiv
|
9 | PORT_SPI &=~ (1<<SCK); // Setzt clock-Flanke auf low
|
10 | }
|
11 |
|
12 |
|
13 | void mcp_setValue(uint16_t value)
|
14 | {
|
15 | int8_t i;
|
16 |
|
17 | PORT_SPI &=~ (1<<CS); // Wähle DAC als SPI Empfänger aus
|
18 |
|
19 | PORT_SPI &=~ (1<<SDI); // Wähle ADC_A
|
20 | PORT_SPI |= (1<<SCK); PORT_SPI &=~ (1<<SCK); // Takt
|
21 |
|
22 | PORT_SPI |= (1<<SDI); // Die andereren 3 Config Bits sind High
|
23 | PORT_SPI |= (1<<SCK); PORT_SPI &=~ (1<<SCK); // Takt
|
24 | PORT_SPI |= (1<<SCK); PORT_SPI &=~ (1<<SCK); // Takt
|
25 | PORT_SPI |= (1<<SCK); PORT_SPI &=~ (1<<SCK); // Takt
|
26 |
|
27 | for(i=0;i<12;i++)
|
28 | {
|
29 | if(value&(1<<(15-i)))
|
30 | {
|
31 | PORT_SPI |= (1<<SDI);
|
32 | }
|
33 | else
|
34 | {
|
35 | PORT_SPI &=~ (1<<SDI);
|
36 | }
|
37 | PORT_SPI |= (1<<SCK); PORT_SPI &=~ (1<<SCK); // Takt
|
38 | }
|
39 |
|
40 | PORT_SPI |= (1<<CS); // DAC als SPI Empfänger deaktivieren
|
41 | PORT_SPI &=~ (1<<LDAC);
|
42 | PORT_SPI |= (1<<LDAC);
|
43 | }
|
und mcp4921.c in Hardware (funktioniert nicht):
1 | #include "mcp_4921.h"
|
2 | #include <avr/io.h>
|
3 | #include <avr/interrupt.h>
|
4 |
|
5 |
|
6 | ISR(SPI_STC_vect) /* SPI Transfer Complete Handler */
|
7 | {
|
8 | switch(spi_status)
|
9 | {
|
10 | case 1:
|
11 | /* 1. Byte wurde gesendet */
|
12 | SPDR = lower_byte; // Sende 2. Byte
|
13 | spi_status = 2; // Status: 2. Byte wird an ADC gesendet
|
14 | break;
|
15 | case 2:
|
16 | /* 1. Byte wurde gesendet */
|
17 | PORT_SPI |= (1<<CS); // Deaktiviere mpc als SPI Empfänger
|
18 | PORT_SPI &=~ (1<<LDAC); // Lade ADC Wert
|
19 | PORT_SPI |= (1<<LDAC);
|
20 | spi_status = 0; // SPI frei
|
21 | break;
|
22 | }
|
23 | }
|
24 |
|
25 |
|
26 | void mcp_init(void)
|
27 | {
|
28 | DDR_SPI = (1<<CS)|(1<<SCK)|(1<<SDI)|(1<<LDAC); // Setzte Busausgänge
|
29 | SPCR = (1<<SPIE)|(1<<SPE)|(1<<MSTR); // SPI Interruppt Enable, Enable SPI, Master, set clock rate fck/4
|
30 | spi_status = 0; // SPI frei
|
31 | sei();
|
32 | }
|
33 |
|
34 | void mcp_setValue(uint16_t value)
|
35 | {
|
36 |
|
37 | if(spi_status==0)
|
38 | {
|
39 | PORT_SPI &=~ (1<<CS); // Wähle DAC als SPI Empfänger aus
|
40 | spi_status = 1; // Status: 1. Byte wird an ADC gesendet
|
41 | lower_byte = (uint8_t) (value>>4); // Merke dir niederwertiges Byte (Die höchsten 12 Bit werden versendet)
|
42 | SPDR = 0b01110000|(value>>12); // Setze Controlbits '0111', verschiebe die 4 höchsten Bits an die richtige Stelle und starte SPI senden
|
43 |
|
44 | }
|
45 |
|
46 | }
|
Wäre sehr dankbar wenn mir jemand helfen kann.
Gruß
Tobi