Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - SPI MCP4922: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# Control an MCP4922 12 bit DAC via SPI
22
33This code is for an Atmega328 / Arduino with a 16MHz clock and an SPI compatible [MCP4922](https://www.microchip.com/wwwproducts/en/MCP4922) Digital/Analog Converter (DAC).
44
55The following functions are described in other tutorials:
66
77- [[AVR Embedded Tutorial - Simple GPIO on and off output|GPIO]] - Output/Input - How do I access the GPIO on the AVR.
88- [[AVR Embedded Tutorial - SPI|SPI]] - use of the hardware SPI interface.
99
1010This example shows how to control the MCP4922 DAC via SPI.
1111
1212## Functions for the 74HC595 shift register
1313
1414### Constants
1515
1616Pins which are required at PORTB for SPI.
1717
1818``` pascal
1919 type
2020 TSPIGPIO = bitpacked record
2121 p0, p1, SlaveSelect, MOSI, MISO, Clock, p6, p7 : boolean;
2222 end;
2323
2424 var
2525 SPI_PORT : TSPIGPIO absolute PORTB;
2626 SPI_DDR : TSPIGPIO absolute DDRB;
2727```
2828
2929### Initialize SPI
3030
3131``` pascal
3232 procedure SPIInit;
3333 begin
3434 // Setup SPI port for output
3535 SPI_DDR.MOSI := True;
3636 SPI_DDR.Clock := True;
3737 SPI_DDR.SlaveSelect := True;
3838
3939 SPCR := (1 shl SPE) or (0 shl SPIE) or (0 shl DORD) or (1 shl MSTR) or (0 shl CPOL) or (0 shl CPHA) or (%01 shl SPR);
4040 SPSR := 1 shl SPI2X; // SCK x 2 on 1 MHz
4141 end;
4242```
4343
4444### Write SPI
4545
4646``` pascal
4747 procedure SPIWrite(p : PByte; len : byte);
4848 var
4949 i : byte;
5050 begin
5151 SPI_Port.SlaveSelect := False;
5252
5353 for i := len - 1 downto 0 do
5454 begin
5555 SPDR := p[i];
5656
5757 while(SPSR and (1 shl SPIF)) = 0 do
5858 begin
5959 end;
6060 end;
6161
6262 SPI_Port.SlaveSelect := True;
6363 end;
6464```
6565
6666## MCP4922 functions
6767
6868Bit assignments for the MCP4922:
6969
70-<thead>
71-
72-</thead>
73-<tbody>
74-
75-<strong>1</strong> = Write to DACB</td>
76-
77-<strong>1</strong> = Buffered</td>
78-
79-<strong>1</strong> = 1x (VOUT = VREF * D / 4096)</td>
80-
81-<strong>1</strong> = Active mode operation. VOUT is available.</td>
82-
83-</tbody>
70+| Bit | Name | Description |
71+|---|---|---|
72+| 15 | **A/B:** DACA or DACB Selection bit | **0** = Write to DACA · **1** = Write to DACB |
73+| 14 | **BUF:** Vref Input Buffer Controlbit | **0** = Unbuffered · **1** = Buffered |
74+| 13 | **GA:**Output Gain Selection bit | **0** = 2x (VOUT = 2 * VREF * D / 4096) · **1** = 1x (VOUT = VREF * D / 4096) |
75+| 12 | **SHDN:** Output Shutdown Control bit | **0** = Shutdown the selected DAC channel. Analog output is not available at the channel that was shut down. VOUT pin is connected to 500 kOhm(typical) · **1** = Active mode operation. VOUT is available. |
76+| 11:0 | **D11:D0:** DAC Input Data bits. Bit x is ignored. | |
8477
8578### Send to DAC
8679
8780``` pascal
8881 procedure MCP4922sendValue(Value : UInt16; Channel : Byte);
8982 type
9083 TADC = bitpacked record
9184 Value : 0..4095; // bits 0-11
9285 ShutDown, // bit 12
9386 Gain, // bit 13
9487 VRef, // bit 14
9588 DAC : 0..1; // bit 15
9689 end;
9790
9891 begin
9992 with TADC(Value) do
10093 begin
10194 ShutDown := 1;
10295 Gain := 1;
10396 VRef := 0;
10497 Dac := Channel;
10598 end;
10699
107100 SPIWrite(@Value, 2);
108101 end;
109102```
110103
111104## Example program
112105
113106This example shows the output of two analog values ​​from the DAC. Two LEDs connected to the DAC flash alternately with a very smooth transition.
114107
115108### Constants and variables
116109
117110A counting variable that counts up to 4095.
118111
119112``` pascal
120113 var
121114 z : Int16 ;
122115```
123116
124117### Main program
125118
126119Alternately write a value in DAC 0 & 1.
127120
128121``` pascal
129122 begin
130123 // initialize SPI.
131124 SPIInit;
132125
133126 repeat
134127 for z := 0 to 4095 do
135128 begin
136129 MCP4922sendValue(4095 - z, 0);
137130 MCP4922sendValue(z, 1);
138131 end;
139132 until 1 = 2;
140133 end.
141134```
142135
143136# See also
144137
145138- Overview page - [[AVR Embedded Tutorials]].
146139- Use of the hardware SPI interface with an ATmega328 / Arduino - [[AVR Embedded Tutorial - SPI|SPI]].
147140
148141---
149142*From the Free Pascal wiki, page "AVR Embedded Tutorial - SPI MCP4922", as it stood on 2020-03-08 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history