电设工作小结之——MSP430G2553学习笔记——2
接上一篇:
(四),ADC10
1,ADC10是十位的AD,在g2553上有A0~A7八个可以外接的AD通道,A10接到片上的温度传感器上,其他的通道都接在内部的VCC或GND上。因为是10为的AD所以计算公式如下:
2 ,ADC参考电压的选择:ADC的参考电压可以为:
由ADC控制寄存器0 ADC10CTL0控制。但是要提高ADC的精度的话,尽量不要用内部的参考电压,最好外接一个比较稳定的电压作为参考电压,因为内部的产生的参考电压不是特别稳定或精度不是特别的高。例如我在使用时遇到的情况如下:
Vref设为2.5V 但实际的值大概为2.475V, 选择VCC VSS作为参考,用电压表测得大概为3.58V 还是不小的偏差的。
另外,在有可能的情况下,尽量采用较大的VR+和VR-,以减小纹波对采样结果的影响。 3,ADC10的采样方式有:单通道单次采样,单通道多次采样,多通道单次采样,多通道多次采样。
4,DTC:因为ADC10只有一个采样结果存储寄存器ADC10MEM,所以除了在单通道单次采样的模式下,其他的三个模式都必须使用DCT,否则转换结果会不停地被新的结果给覆盖。 DTC是转换结果传送控制,也就是转换结果可以不用CPU的干预,就可以自动地存储在指定的存储空间内。使用这种方式转换速度快,访问方便,适用于高速采样模式中。DTC的使用可以从下面的例子中很容易看明白: #include
uchar s1[]={\
uchar s2[]={\
void ADC_init() {
ADC10CTL1 = CONSEQ_3 + INCH_1; // 2通道多次转换, 最大转换通道为A1
ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE; // ADC10ON, interrupt enabl 参考电压选默认值VCC和VSS
//采样保持时间为16 x ADC10CLKs,ADC内核开,中断使能 MSC多次转换选择开 //如果MSC置位,则第一次开始转换时需要触发源触发一次,以后的转换会自动进行 中断使能
//使用DTC时,当一个块传送结束,产生中断
//数据传送控制寄存器0 ADC10DTC0设置为默认模式:单传送块模式,单块传送完停止 ADC10DTC1 = 0x04; //数据传送控制寄存器1 4 conversions 定义在每块的传送数目 一共采样4次 所以单块传送4次
//以后就停止了传送 因为是两通道的,所以是每个通道采样数据传送2次
ADC10AE0 |= BIT0+BIT1; // P1.0 P1.1 ADC option select 使能模拟输入脚A0 A1
//不知道为什么,当P10 P11都悬空时,采样值不同,用电压表测得悬空电压不同,但是当都接上采样源的时候, //采样是相同的 }
void main(void) {
uint adc_sample[8]={0}; //存储ADC序列采样结果 WDTCTL = WDTPW+WDTHOLD;
BCSCTL1 = CALBC1_12MHZ; //设定cpu时钟DCO频率为12MHz DCOCTL = CALDCO_12MHZ;
P2DIR |=BIT3+BIT4; //液晶的两条线
init_lcd(); ADC_init();
wr_string(0,0,s1); wr_string(0,3,s2);
for (;;) {
ADC10CTL0 &= ~ENC; //ADC不使能 其实这句话可以放在紧接着CPU唤醒之后的,因为CPU唤醒了,说明我们想要的
//转换数据传送完成了,如果ADC继续转换,那么转换结果也不再传输,是无用的。所以紧接着放在CPU唤醒之后 //计时关闭ADC,有利于降低功耗
while (ADC10CTL1 & BUSY); // Wait if ADC10 core is active 等待忙
ADC10SA = (unsigned int)adc_sample; //数据传送开始地址寄存器 设置DTC的开始地址 Data buffer start
//设置数据开始传送的地址为数组adc_sample[]的首地址,因为寄存器ADC10SA和转换结果都是16位的,所以要把
//地址强制转换为16位的int或unsigned int //应该也可以用指针直接访问DTC的存储区,还没试过
//例如:前面定义了单块传送4次数据,所以每次传送完成了一个块,也就是4次,就会把中断标志位置位,产生中断
//因为上面设置的地址为数组adc_sample[]的首地址,所以每次转换的结果就会传送到该数组的前4位上,所以如果
//一切正常的话,数组里应该是前4位为转换的结果,后4位为初始值0 通过下面的显示,验证转换是正确的
//一次触发首先对A1、A0采样,放入a[0]和a[1]中,再对A1、A0采样,放入a[2]和a[3]中。如此循环下去。
//验证得知,当多通道采样时,先采高的通道,再采低的通道。如上面每次采样时,先采A1 再A0
//因为一共采样传送4次,所以数组的后4位为初始值0
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start ADC使能,开始转换 ADC10SC为采样触发源
//不需要cpu的干预,DTC就可以把采样结果存储到指定的存储区中
__bis_SR_register(CPUOFF + GIE); // LPM0, ADC10_ISR will force exit 如果转换结果传送完成,
//就会进入中断,CPU唤醒 继续往下运行
wr_int(2,0,adc_sample[0]); //显示转换结果 A1 wr_int(6,0,adc_sample[1]); //A0 wr_int(0,1,adc_sample[2]); //A1 wr_int(3,1,adc_sample[3]); //A0 wr_int(6,1,adc_sample[4]); wr_int(0,2,adc_sample[5]); wr_int(3,2,adc_sample[6]); wr_int(6,2,adc_sample[7]);
}
}
// ADC10 interrupt service routine #pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR(void) //中断响应以后,中断标志位自动清零 {
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR) }
上面的例子是把存储结果存储在了uint型的数组中。也可以用指针直接指定要存放的地址,然后再用指针进行访问(理论上可以,但还没有试过)。也可以把存储结果直接存放在一个16位的寄存器中,如:
ADC10SA = (unsigned int)&TACCR1; // Data transfer location 把转换结果存储在TACCR1所在的
//位置处,就相当于存储在TACCR1中 因为ADC转换结果和寄存器TACCR1都是16位的,所以要把地址强制转换为16位的 //int 或 unsigned int型
5,ADC采样注意事项:用片上的ADC10进行采样,如果外部分压电路的电阻过大(比如几K以上),AD引脚会把电压拉高,使采样结果发生很大的偏差。应换成小电阻(几十~几百欧),如果要求更精确的话,要加运放进行电压跟随。 6,AD采样交流信号:
一般是50Hz,100Hz,1000Hz。方法是在交流信号的一个周期内采样多次(如40次,30次等),然后利用公式可以求出交流信号的有效值,平均值等。 7,片上温度传感器
ADC的A10通道接片上的温度传感器,MSP430内嵌的温度传感器实际上就是一个输出电压随环境温度而变化的温度二极管。
当使用片上温度传感器时,采样周期必须大于30us 片上温度传感器的偏移很大,所以精确测量需要
进行校准。选择片上温度传感器INCH_10,ADC其他的设置都和外部通道的设置相同,包括参考电压源的选择和转换存储的选择
选择了片上温度传感器,会自动地打开片上参考电压源发生器作为温度传感器的电压源,但是这并不会时能VREF+输出,也不会
影响AD转换参考源的选择,转换参考源的选择和其他通道的选择相同 公式为:VTEMP=0.00355(TEMPC)+0.986
片上温度传感器的校准,可以参见我的温度传感器校准程序,也可以参考其他的论文。下面只给出程序的一部分: void ADC_init()
{
ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // ADC10ON, interrupt enabled 参考电压选默认值VCC和VSS
//采样保持时间为16 x ADC10CLKs,ADC开,中断使能
ADC10CTL1 = INCH_10; // ADC输入通道选择A10,为内部的温度传感器
//其他是默认,采样触发输入源选择为ADC10SC,采样输入信号不翻转,转换时钟选择内部时钟源:ADC10OSC,3.7~6.3MHz //不分频,单通道单次转换
//ADC10AE0 |= 0x02; // PA.1 ADC option select 使能模拟输入脚A1
//P1DIR |= 0x01; // Set P1.0 to output direction
//所以是P11为ADC输入脚,P10控制led }
(五),通用串行通信接口(USCI) 1,USCI_A:支持UART, IrDA, SPI USCI_B:支持I2C, SPI
2,UART 这个模块没什么好说的,和其他的一写处理器如S12,ARM等差不多。只要设置好几个控制寄存器,波特率,写几个收发函数就可以了。下面就给出msp430g2553于PC用UART通信的基本程序: #include \
unsigned char rev;
char *string1=\
char string2[]=\是换行符
void putchar(unsigned char c) //发送字符函数 {
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? 等待TX buffer为空
UCA0TXBUF = c; // TX -> RXed character 发送字符c }
void putstr(char *s) //发送字符串函数 {