Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - SPI MCP4922: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: AVR Embedded Tutorial - SPI MCP4922

OldNewLine
1+# Control an MCP4922 12 bit DAC via SPI
2+
3+This 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).
4+
5+The following functions are described in other tutorials:
6+
7+- [[AVR Embedded Tutorial - Simple GPIO on and off output|GPIO]] - Output/Input - How do I access the GPIO on the AVR.
8+- [[AVR Embedded Tutorial - SPI|SPI]] - use of the hardware SPI interface.
9+
10+This example shows how to control the MCP4922 DAC via SPI.
11+
12+## Functions for the 74HC595 shift register
13+
14+### Constants
15+
16+Pins which are required at PORTB for SPI.
17+
18+``` pascal
19+ type
20+ TSPIGPIO = bitpacked record
21+ p0, p1, SlaveSelect, MOSI, MISO, Clock, p6, p7 : boolean;
22+ end;
23+
24+ var
25+ SPI_PORT : TSPIGPIO absolute PORTB;
26+ SPI_DDR : TSPIGPIO absolute DDRB;
27+```
28+
29+### Initialize SPI
30+
31+``` pascal
32+ procedure SPIInit;
33+ begin
34+ // Setup SPI port for output
35+ SPI_DDR.MOSI := True;
36+ SPI_DDR.Clock := True;
37+ SPI_DDR.SlaveSelect := True;
38+
39+ 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);
40+ SPSR := 1 shl SPI2X; // SCK x 2 on 1 MHz
41+ end;
42+```
43+
44+### Write SPI
45+
46+``` pascal
47+ procedure SPIWrite(p : PByte; len : byte);
48+ var
49+ i : byte;
50+ begin
51+ SPI_Port.SlaveSelect := False;
52+
53+ for i := len - 1 downto 0 do
54+ begin
55+ SPDR := p[i];
56+
57+ while(SPSR and (1 shl SPIF)) = 0 do
58+ begin
59+ end;
60+ end;
61+
62+ SPI_Port.SlaveSelect := True;
63+ end;
64+```
65+
66+## MCP4922 functions
67+
68+Bit assignments for the MCP4922:
69+
70+<table>
71+<thead>
72+<tr>
73+<th>Bit</th>
74+<th>Name</th>
75+<th>Description</th>
76+</tr>
77+</thead>
78+<tbody>
79+<tr>
80+<td>15</td>
81+<td><strong>A/B:</strong> DACA or DACB Selection bit</td>
82+<td><strong>0</strong> = Write to DACA<br />
83+<strong>1</strong> = Write to DACB</td>
84+</tr>
85+<tr>
86+<td>14</td>
87+<td><strong>BUF:</strong> Vref Input Buffer Controlbit</td>
88+<td><strong>0</strong> = Unbuffered<br />
89+<strong>1</strong> = Buffered</td>
90+</tr>
91+<tr>
92+<td>13</td>
93+<td><strong>GA:</strong>Output Gain Selection bit</td>
94+<td><strong>0</strong> = 2x (VOUT = 2 * VREF * D / 4096)<br />
95+<strong>1</strong> = 1x (VOUT = VREF * D / 4096)</td>
96+</tr>
97+<tr>
98+<td>12</td>
99+<td><strong>SHDN:</strong> Output Shutdown Control bit</td>
100+<td><strong>0</strong> = 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)<br />
101+<strong>1</strong> = Active mode operation. VOUT is available.</td>
102+</tr>
103+<tr>
104+<td>11:0</td>
105+<td><strong>D11:D0:</strong> DAC Input Data bits. Bit x is ignored.</td>
106+<td></td>
107+</tr>
108+</tbody>
109+</table>
110+
111+### Send to DAC
112+
113+``` pascal
114+ procedure MCP4922sendValue(Value : UInt16; Channel : Byte);
115+ type
116+ TADC = bitpacked record
117+ Value : 0..4095; // bits 0-11
118+ ShutDown, // bit 12
119+ Gain, // bit 13
120+ VRef, // bit 14
121+ DAC : 0..1; // bit 15
122+ end;
123+
124+ begin
125+ with TADC(Value) do
126+ begin
127+ ShutDown := 1;
128+ Gain := 1;
129+ VRef := 0;
130+ Dac := Channel;
131+ end;
132+
133+ SPIWrite(@Value, 2);
134+ end;
135+```
136+
137+## Example program
138+
139+This example shows the output of two analog values ​​from the DAC. Two LEDs connected to the DAC flash alternately with a very smooth transition.
140+
141+### Constants and variables
142+
143+A counting variable that counts up to 4095.
144+
145+``` pascal
146+ var
147+ z : Int16 ;
148+```
149+
150+### Main program
151+
152+Alternately write a value in DAC 0 & 1.
153+
154+``` pascal
155+ begin
156+ // initialize SPI.
157+ SPIInit;
158+
159+ repeat
160+ for z := 0 to 4095 do
161+ begin
162+ MCP4922sendValue(4095 - z, 0);
163+ MCP4922sendValue(z, 1);
164+ end;
165+ until 1 = 2;
166+ end.
167+```
168+
169+# See also
170+
171+- Overview page - [[AVR Embedded Tutorials]].
172+- Use of the hardware SPI interface with an ATmega328 / Arduino - [[AVR Embedded Tutorial - SPI|SPI]].
173+
174+---
175+*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