Hardware Introduction:
The MSP430x14x series does not contain the DAC12 module, so the implementation in this article can only be used in MCUs such as the 16 series that contain the DAC12 module.
The DAC12 module of the MSP430F169 microcontroller has two DAC channels, which are completely equal in operation. The DAC12GRP control bit can be used to combine multiple DAC12 channels to achieve synchronous updates, and the hardware can also ensure that the synchronous updates are independent of any interrupt or NMI event.
This DAC12 module has the following features: 8-bit or 12-bit adjustable resolution, programmable time-to-energy loss, optional internal or external reference source, support for binary original code and complement code input, self-checking function, multi-channel DAC synchronous update, and DMA, etc.
What is implemented here is a relatively simplified version. You need to be able to add or rewrite functions yourself, such as calling a self-checking function inside the initialization function, which can perform self-checking at each initialization.
Each DAC12 module has only two registers: control register and data register. The control register is used to initialize and set the module, and the data register is used to store the voltage digital value to be output. The registers of 169 DAC are as follows:
DAC12_0 control register DAC12_0CTL
DAC12_0 data register DAC12_0DAT
DAC12_1 control register DAC12_1CTL
DAC12_1 data register DAC12_1DAT
The functions of each bit of the control register are as follows:
DAC12REFx: Select the reference source of DAC12
0, 1 Vref+
2, 3 Veref+
DAC12RES: Select the resolution of DAC12
0 12-bit resolution
1 8-bit resolution
DAC12LSELx: Latch trigger source selection
When the DAC12 latch is triggered, the data in the latch can be transferred to the core of DAC12.
When DAC12LSELx=0, the DAC data update is not affected by DAC12ENC.
0 DAC12_XDAT will trigger when writing (regardless of the state of DAC12ENC)
1 DAC12_XDAT will trigger when writing (considering the state of DAC12ENC)
2 The rising edge of Timer_A3.OUT1
3 The rising edge of Timer_B7.OUT2
DAC12CALON: DAC12 calibration operation control
starts the calibration operation after setting, and is automatically reset after the calibration is completed. The calibration operation can correct the offset error.
0 No calibration operation started
1 Start calibration operation
DAC12IR: DAC12 input range
sets the relationship between input reference voltage and output
0 The full scale of DAC12 is 3 times the reference voltage (AVcc is not operated)
1 The full scale of DAC12 is the reference voltage
DAC12AMPx: DAC12 operational amplifier setting
0 Input buffer off, output buffer off, high impedance
1 Input buffer off, output buffer off, 0V
2 Input buffer low speed low current, output buffer low speed low current
3 Input buffer low speed low current, output buffer medium speed medium current
4 Input buffer low speed low current, output buffer high speed high current
5 Input buffer medium speed medium current, output buffer medium speed medium current
6 Input buffer medium speed medium current, output buffer high speed high current
7 Input buffer high speed high current, output buffer high speed high current
DAC12DF: DAC12 data format
0 Binary
1 Twos complement
DAC12IE: DAC12 interrupt enable
0 Disable interrupt
1 Enable interrupt
DAC12IFG: DAC12 interrupt flag
0 No interrupt request
1
DAC12ENC: DAC12 conversion control bit
DAC12LSEL>0, DAC12ENC is valid.
0 DAC12 stop 1
DAC12 conversion
DAC12GRP: DAC12 combination control bit
0 No combination
1 Combination
For detailed information about DAC12, please refer to the user guide provided by TI.
Program implementation:
The program of the DAC12 module is relatively simple, because each group has only one register for control; the functions implemented by this program are as follows: DAC module initialization, completes the initialization of two DAC modules, and can determine which module to initialize or both, or update two modules at the same time according to the parameters; uses parameters to pass the value of DAC12AMPx for easy setting. The comments in the program are very detailed. If you don’t understand, you can directly set AMPx to 5 or 0x05; calibration function, completes the self-calibration of the DAC12 module, and also passes the module to be calibrated through parameters; voltage output function, this also uses parameters to pass the module to be output.
initialization:
/****************************************************** *******
* Function name: DAC12Init
* Function: Initialize the related resources used by DAC12
* Parameters:
* module 0: use module DAC12_0
* 1: Use module DAC12_1
* 2: Use module DAC12_0/1
* 3: Use module DAC12_0/1 to update together
* DAC12AMPx: DAC op amp settings:
* 0 Input buffer off, output buffer off, high impedance
* 1 Input buffer off, output buffer off, 0V
* 2 Input buffer low speed/current, output buffer low speed/current
* 3 Input buffer low speed/current, output buffer medium speed/current
* 4 Input buffer low speed/current, output buffer high speed/current
* 5 Input buffer medium speed/current, output buffer medium speed/current
* 6 Input buffer medium speed/current, output buffer high speed/current
* 7 Input buffer high speed/current, output buffer high speed/current
* Return value: char, 1 if setting is successful, 0 if parameter error occurs
* Note: Other defaults are: 12-bit solution, write and update output, module mode
* When the block is 3, both are written and updated; the full scale of DAC12 is the reference voltage.
* Voltage; Internal 2.5v reference voltage: AD setting reference source is required to open 2.5.
*************************************************** *******/
char DAC12Init(char module,char DAC12AMPx)
{
if(DAC12AMPx>7)
{
return(0);
}
//---------------------------Set up module-------------------------------
switch(module)
{
case 0:case'0': DAC12_0Init(DAC12AMPx); break; //Module 0
case 1: case'1': DAC12_1Init(DAC12AMPx); break; //Module 1
case 2: case'2':
DAC12_0Init(DAC12AMPx);
DAC12_1Init(DAC12AMPx);
break; //Module 0, 1
case 3: case'3':
DAC12_0Init(DAC12AMPx);
DAC12_1Init(DAC12AMPx);
DAC12_0CTL |= DAC12GRP;
break; //No check
default : return(0); //Parameter error
}
return (1);
}
Here, if the parameter is invalid, 0 is returned, and if the setting is completed, 1 is returned. However, it should be noted that before using the DAC, the internal reference source must be turned on (in the ADC module, please refer to the usage example for details).
The contents of DAC12_0Init and DAC12_1Init functions are the same, except that the control registers are DAC12_0CTL and DAC12_0CTL respectively. Here we only give the function of DAC12_0Init. Another reference source program:
void DAC12_0Init(char DAC12AMPx)
{
// Internal ref gain 1
DAC12_0CTL = DAC12SREF_0 + DAC12IR;
DAC12_0CTL |= DAC12LSEL_1 + (DAC12AMPx << 5);
DAC12_0CTL |= DAC12ENC;
}
This function only completes the setting of the control register. Select the internal reference source, the output full scale is 1 times the reference voltage, and the update method is: write to update. If group is set, both are written to update.
Calibration function: complete the DAC12 module self-calibration,
void DAC12Cal(char module)
{
switch(module)
{
case 0: case'0':
DAC12_0CTL |= DAC12CALON; // Start verification DAC
while((DAC12_0CTL & DAC12CALON) != 0); // Wait for verification to complete
break; //Module 0
case 1: case'1':
DAC12_1CTL |= DAC12CALON; // Start verification DAC
while((DAC12_1CTL & DAC12CALON) != 0); // Wait for verification to complete
break; //Module 1
case 2: case'2':
case 3: case'3':
DAC12_0CTL |= DAC12CALON; // Start verification DAC
while((DAC12_0CTL & DAC12CALON) != 0); // Wait for verification to complete
DAC12_1CTL |= DAC12CALON; // Start verification DAC
while((DAC12_1CTL & DAC12CALON) != 0); // Wait for verification to complete
break; //Module 0, 1
default : return; //Parameter error
}
}
The meaning of the parameters is the same as that of the previously initialized function, for consistency when using the function.
Output function:
void DAC12Out(char module,int out)
{
switch(module)
{
case 0:case'0': DAC12_0DAT=out; break; //Module 0
case 1: case'1': DAC12_1DAT=out; break; //Module 1
case 2: case'2':
case 3:case'3': DAC12_0DAT=out; DAC12_1DAT=out; break; //Module 0, 1
default : return; //Parameter error
}
}
The parameters of the output function have the same meaning as the initialized module parameters. This function is relatively simple and only assigns the value to be output to the DAT register.
That's all the DAC12 program library. DAC12 can also update data strictly according to time to output a waveform of a certain frequency. It can be set to update data on the rising edge of TA out1 or the rising edge of TB out2. In addition, it can be used together with DMA to complete more complex functions; none of them are implemented here, but if necessary, it can be implemented based on the register function.
That’s it for the program part.