Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - SPI MCP4922: what changed

Revision 1 to 2. 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-<table>
7170<thead>
72-<tr>
73-<th>Bit</th>
74-<th>Name</th>
75-<th>Description</th>
76-</tr>
71+
7772</thead>
7873<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 />
74+
8375<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 />
76+
8977<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 />
78+
9579<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 />
80+
10181<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>
82+
10883</tbody>
109-</table>
11084
11185### Send to DAC
11286
11387``` pascal
11488 procedure MCP4922sendValue(Value : UInt16; Channel : Byte);
11589 type
11690 TADC = bitpacked record
11791 Value : 0..4095; // bits 0-11
11892 ShutDown, // bit 12
11993 Gain, // bit 13
12094 VRef, // bit 14
12195 DAC : 0..1; // bit 15
12296 end;
12397
12498 begin
12599 with TADC(Value) do
126100 begin
127101 ShutDown := 1;
128102 Gain := 1;
129103 VRef := 0;
130104 Dac := Channel;
131105 end;
132106
133107 SPIWrite(@Value, 2);
134108 end;
135109```
136110
137111## Example program
138112
139113This example shows the output of two analog values ​​from the DAC. Two LEDs connected to the DAC flash alternately with a very smooth transition.
140114
141115### Constants and variables
142116
143117A counting variable that counts up to 4095.
144118
145119``` pascal
146120 var
147121 z : Int16 ;
148122```
149123
150124### Main program
151125
152126Alternately write a value in DAC 0 & 1.
153127
154128``` pascal
155129 begin
156130 // initialize SPI.
157131 SPIInit;
158132
159133 repeat
160134 for z := 0 to 4095 do
161135 begin
162136 MCP4922sendValue(4095 - z, 0);
163137 MCP4922sendValue(z, 1);
164138 end;
165139 until 1 = 2;
166140 end.
167141```
168142
169143# See also
170144
171145- Overview page - [[AVR Embedded Tutorials]].
172146- Use of the hardware SPI interface with an ATmega328 / Arduino - [[AVR Embedded Tutorial - SPI|SPI]].
173147
174148---
175149*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