1 ,数模转换概述
MSP430 带有的 DAC12 模块,可以将运算处理的结果转换为模拟量,以便操作被控制对象的工作过程。
MSP430 的 DAC12 模块是 12 位 R 阶,电压输出的数模转换模块,在使用的过程中可以被设置为 8 位或
者 12 位转换模式,并能够和 DMA 控制器结合使用。当 MSP430 包含有多个 DAC12 模块的时候,MSP430
可以对他们进行统一管理。
MSP430 的 DAC12 模块只要性能指标有以下几点:
[1]分辨率:这相指标反映了数字在最低位上的数字变化 1 时的模拟输出变化。对 12 位 DAC 来说,其分辨
率达到了 1/4096,即 0.025%。
[2]偏移误差,它指的是输入数字为 0 的时候,输出模拟量对 0 的误差
[3]线性度:指的是 DAC 模块的实际转移特性与理想直线之间的最大偏差。
[4]转换速度:即每秒种转换的次数
[5]其他因素:例如数字输入特性,输入的码制,数据格式;输出特性,输出的是电流还是电压;等...
2 ,DAC12 结构与性能
MSP430F169 单片机的 DAC12 模块有 2 个 DAC 通道,这两个通道在操作上是完全平等的。并且可以用
DAC12GRP 控制位将多个 DAC12 通道组合起来,实现同步更新,硬件还能确保同步更新独立于任何中断
或者 NMI 事件。
DAC12 的主要特征
DAC12 结构原理图
3, DAC12 寄存器
[1] DAC12_xCTL DAC12 控制寄存器
其中灰色的部分只有在 DAC12ENC=0 的时候才能修改,位 DAC12GRP 只有在 DAC12_1 才使用。
DAC12REFx:选择 DAC12 的参考源
0,1 Vref+
2,3 Veref+
DAC12RES:选择 DAC12 分辨率
0 12 位分辨率
1 8 分辨率
DAC12LSELx:锁存器触发源选择
当 DAC12 锁存器得到触发之后,能够将锁存器中的数据传送到 DAC12 的内核。
当 DAC12LSELx=0 的时候,DAC 数据更新不受 DAC12ENC 的影响。
0 DAC12_XDAT 执行写操作将触发(不考虑 DAC12ENC 的状态)
1 DAC12_XDAT 执行写操作将触发(考虑 DAC12ENC 的状态)
2 Timer_A3.OUT1 的上升沿
3 Timer_B7.OUT2 的上升沿
DAC12CALON:DAC12 校验操作控制
置位后启动校验操作,校验完成后自动被复位。校验操作可以校正偏移误差。
0 没有启动校验操作
1 启动校验操作
DAC12IR:DAC12 输入范围
设定输入参考电压和输出的关系
0 DAC12 的满量程为参考电压的 3 倍(不操作 AVcc)
1 DAC12 的满量程为参考电压
DAC12AMPx:DAC12 运算放大器设置
0 输入缓冲器关闭,输出缓冲器关闭,高阻
1 输入缓冲器关闭,输出缓冲器关闭,0V
2 输入缓冲器低速低电流,输出缓冲器低速低电流
3 输入缓冲器低速低电流,输出缓冲器中速中电流
4 输入缓冲器低速低电流,输出缓冲器高速高电流
5 输入缓冲器中速中电流,输出缓冲器中速中电流
6 输入缓冲器中速中电流,输出缓冲器高速高电流
7 输入缓冲器高速高电流,输出缓冲器高速高电流
DAC12DF:DAC12 的数据格式
0 二进制
1 二进制补码
DAC12IE:DAC12 的中断允许
0 禁止中断
1 允许中断
DAC12IFG:DAC12 的中断标志位
0 没有中断请求
1 有中断请求
DAC12ENC:DAC12 转换控制位
DAC12LSEL>0 的时候,DAC12ENC 才有效。
0 DAC12 停止
1 DAC12 转换
DAC12GRP:DAC12 组合控制位
0 没有组合
1 组合
[2] DAC12_xDAT 数据寄存器
DAC12_xDAT 高 4 位为 0,不影响 DAC12 的工作。如果 DAC12 工作在 8 位模式的话,DAC12_xDAT 的
值最大为 0x00FF;ADC12 工作在 12 位模式时,DAC12_xDAT 的最大值为 0x0FFF。
4 ,DAC12 的操作
[1]选择参考电压
参考电压是唯一影响 DAC12 输出量的模拟参数,是 DAC12 转换模块的重要部分。DAC12 可以选择内部
或者外部的参考电压,其中内部的参考电压来自与 ADC12 中的内部参考电压发生器生成的 1.5V 或者 2.5V
参考电压。
DAC12 参考电压的输入和电压输出缓冲器的时间和功耗可以通过编程来控制使其工作的最佳状态
(DAC12AMPx 控制)。
[2]DAC12 内核
用 DAC12RES 位选择 DAC12 的 8 位或者 12 位精度。DAC12IR 位控制 DAC12 的最大输出电压为参考电
压的 1 或 3 倍(在不超过电源电压的情况下)。DAC12DF 设置写到 DAC12 的数据的格式。
[3]更新 DAC12 的电压输出
DAC12 输出引脚和断口 P6 以及 ADC12 模拟输入复用,当 DAC12AMPx>0 时,不管当前端口 P6 的 P6SEL
和 P6DIR 对应的位的状态是什么。该引脚自动被选择到 DAC12 的功能上。
DAC12_xDAT 可以直接将数据传送到 DAC12 的内核以及 DAC12 的两个缓冲器。DAC12LSELx 位可以触
发对 DAC12 的电压输出更新。当 DAC12LSELx=0 的时候,数据锁存变的透明,不管当前的 DAC12ENC
处于什么状态,只要 DAC12_xDAT 被更新,则 DAC12 的内核立刻被更新。当 DAC12LSELx=1 的时候,
除非有新的数据写入 DAC12_xDAT,否则 DAC12 的数据一直被缩存。当 DAC12LSELx=2、3 的时候,
数据在 TA 的 TACCR1 或者 TB 的 TBCCR2 输出信号上升沿时刻被锁存。当 DAC12LSELx>0 的时候,
DAC12ENC 用来使能 DAC12 的锁存。
[4]DAC12_xDAT 的数据格式
DAC12 支持二进制数或者 2 的补码输入。
[5]校正 DAC12 的输出
DAC12 存在偏移误差,可以通过 DAC12 自动校正偏移量,
在使用 DAC12 之前。通过设置控制位 DAC12CALON 能够初始化偏移校正操作,操作完成后
DAC12CALON 会自动复位。
5,运用——正弦波,三角波信号产生器
1 #include <msp430f169.h> 2 /* 3 * 软件延时函数 4 */ 5 #define CPU_F ((double)8000000) //外部高频晶振8MHZ 6 #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) 7 #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) 8 9 #define uchar unsigned char 10 #define uint unsigned int 11 uchar k=0; 12 uchar sin_table[256]={ 13 0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c, 14 0x9f,0xa2,0xa5,0xa8,0xab,0xae, 15 0xb1,0xb4,0xb7,0xba,0xbc,0xbf,0xc2,0xc5,0xc7,0xca, 16 0xcc,0xcf,0xd1,0xd4,0xd6,0xd8, 17 0xda,0xdd,0xdf,0xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec, 18 0xee,0xef,0xf1,0xf2,0xf4,0xf5, 19 0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe, 20 0xff,0xff,0xff,0xff,0xff,0xff, 21 0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc, 22 0xfb,0xfa,0xf9,0xf8,0xf7,0xf6, 23 0xf5,0xf4,0xf2,0xf1,0xef,0xee,0xec,0xea,0xe9,0xe7, 24 0xe5,0xe3,0xe1,0xde,0xdd,0xda, 25 0xd8,0xd6,0xd4,0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2, 26 0xbf,0xbc,0xba,0xb7,0xb4,0xb1, 27 0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99,0x96,0x93, 28 0x90,0x8d,0x89,0x86,0x83,0x80, 29 0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63, 30 0x60,0x5d,0x5a,0x57,0x55,0x51, 31 0x4e,0x4c,0x48,0x45,0x43,0x40,0x3d,0x3a,0x38,0x35, 32 0x33,0x30,0x2e,0x2b,0x29,0x27, 33 0x25,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16,0x15,0x13, 34 0x11,0x10,0x0e,0x0d,0x0b,0x0a, 35 0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x02,0x01, 36 0x00,0x00,0x00,0x00,0x00,0x00, 37 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x02,0x03, 38 0x04,0x05,0x06,0x07,0x08,0x09, 39 0x0a,0x0b,0x0d,0x0e,0x10,0x11,0x13,0x15,0x16,0x18, 40 0x1a,0x1c,0x1e,0x20,0x22,0x25, 41 0x27,0x29,0x2b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d, 42 0x40,0x43,0x45,0x48,0x4c,0x4e, 43 0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66,0x69,0x6c, 44 0x6f,0x72,0x76,0x79,0x7c,0x80 45 }; 46 /* 47 * 时钟配置 48 */ 49 void Clock_Init() 50 { 51 uchar i; 52 BCSCTL1&=~XT2OFF; //打开XT2振荡器 53 BCSCTL2|=SELM1+SELS; //MCLK为8MHZ,SMCLK为8MHZ 54 do{ 55 IFG1&=~OFIFG; //清楚振荡器错误标志 56 for(i=0;i<100;i++) 57 _NOP(); 58 } 59 while((IFG1&OFIFG)!=0); //如果标志位1,则继续循环等待 60 IFG1&=~OFIFG; 61 } 62 /* 63 * DAC12初始化设置 64 */ 65 void Init_DAC12() 66 { 67 ADC12CTL0 |= REFON + REF2_5V; //内部参考电压位2.5v 68 DAC12_0CTL |= DAC12IR+DAC12AMP_5; //1倍参考电压,中速电流输入输出, 69 DAC12_0CTL |= DAC12ENC; //DAC12使能 70 DAC12_0DAT = 0x0000; //DAC12_0DAT赋初值 71 } 72 /* 73 * 三角波发生函数 74 */ 75 void Sanjiao() 76 { 77 uchar l; 78 for(l=0;l<255;l++) 79 { 80 DAC12_0DAT=l; 81 } 82 for(l=255;l>0;l--) 83 { 84 DAC12_0DAT=l; 85 } 86 } 87 /* 88 * 余弦波发生器 89 */ 90 void Sin() 91 { 92 DAC12_0DAT=sin_table[k++]; 93 delay_us(3); 94 } 95 /** 96 * 主函数 97 */ 98 void main(void) 99 { 100 WDTCTL = WDTPW | WDTHOLD; // 关闭看门狗 101 P6SEL |= 0xFF; 102 P6DIR |= 0xFF; 103 Clock_Init(); 104 Init_DAC12(); 105 106 while(1) 107 { 108 Sin(); 109 //Sanjiao(); 110 } 111 }