1、电设工作小结之MSP430G2553 学习笔记 1一,MSP430G2553 单片机的各个功能模块(一),IO 口模块,1,我们所用的 MSP430G2553 有两组 IO 口,P1 和 P2。2,IO 口的寄存器有:方向选择寄存器 PxDIR,输出寄存器 PxOUT,输入寄存器PxIN,IO 口内部上拉或下拉电阻使能寄存器 PxREN, IO 口功能选择寄存器 PxSEL 和PxSEL2,IO 口中断使能寄存器 PxIE,中断沿选择寄存器 PxIES,IO 口中断标志寄存器PxIFG。3,所有的 IO 都带有中断,其中所有的 P1 口公用一个中断向量,所有的 P2 口公用一个中断向量。所以在
2、使用中断时,当进入中断后,还要判断到底是哪一个 IO 口产生的中断,判断方法可以是判断各个 IO 口的电平。4,中断标志 PxIFG 需要软件清除,也可以用软件置位,从而用软件触发一个中断。注意:在设置 PxIESx 时根据 PxINx 有可能会引起相应的 PxIFGx 置位(具体的情况见用户指南),所以在初始化完 IO 口中断以后,正式使用 IO 中断前要先将对应的 PxIFGx 清零。程序如下:void IO_interrupt_init() /IO 中断初始化函数P1REN |= BIT4+BIT5+BIT6+BIT7; / pull up 内部上拉电阻使能/使用中断时,使能内部的上拉电
3、阻这样当该脚悬空是,电平不会跳变,防止悬空时电平跳变不停的触发中断P1OUT = BIT4+BIT5+BIT6+BIT7; / 当引脚上的上拉或下拉电阻使能时,PxOUT 选择是上拉还是下来/0:下拉,1:上拉P1IE |= BIT4+BIT5+BIT6+BIT7; / interrupt enabled P13 中断使能P1IES |= BIT4+BIT5+BIT6+BIT7; / Hi/lo edge 下降沿中断/P1IES /上升沿触发中断P1IFG /中断标志位清零5,PxOUT:如果引脚选择了内部的上拉或下拉电阻使能,则 PxOUT 设定电阻是上拉还是下拉,0:下拉,1:上拉6,当
4、IO 口不用时,最好不要设为输入,且为浮动状态(这是 IO 口的默认状态),因为当输入为浮动时,输入电压有可能会在 VIL 和 VIH 之间,这样会产生击穿电流。所以不用的 IO 口可以设为输出状态,或设为输入状态但通过外围电路接至 VCC 或 GND,或接一个上拉/下拉电阻。7,当使用 msp430g2553 的 IO 口时要注意,因为 g2553 的 IO 口寄存器的操作,不像51,它不能单独针对某一位进行操作,必须对整个寄存器进行操作。所以就不像51,g2553 不可以定义 bit 型的数据。所以在使用 msp 的 IO 口时要注意对需要位的操作,而不要影响其他无关的位,可以 用 | /
5、RS = P2.0#define SET_RS P2OUT|=BIT0;#define CLR_RW P2OUT /RW = P2.1#define SET_RW P2OUT|=BIT1;#define CLR_EN P2OUT /EN = P2.2#define SET_EN P2OUT|=BIT2;#define DataPort P1OUT8,g2553 的 P27 和 P26 脚分别接外部晶体的输出和输入脚 XOUT 和 XIN,默认是自动设为了晶振管脚功能,但是当想把它们用为普通的 IO 时,也可以,设置对应的 SEL 设为普通的 IO 即可,如下:P2DIR |= BIT6+BIT
6、7; /把 P26 和 P27 配置为普通 IO 并为输出脚 默认为晶振的输入和输出引脚 作为 dac0832 的P2SEL /cs 和 wr 控制端P2SEL2 (二),时钟系统1,msp430 能做到超低功耗,合理的时钟模块是功不可没的。但是功能强大的时钟模块设置起来也相对复杂一些。2,msp430 的时钟源有:(1),外接低频晶振 LFXT1CLK:低频模式接手表晶体 32768Hz,高频模式450KHz8MHz;(2),外接高速晶振 XT2CLK:8MHz ;(3),内部数字控制振荡器 DCO:是一个可控的 RC 振荡器,频率在 016MHz;(4),超低功耗低频振荡器 VLO:不可控
7、,420KHz 典型值为 12KHz;3,时钟模块:430 的时钟模块有 MCLK SMCLK ACLK :(1),主系统时钟 MCLK:提供给 MSP430 的 CPU 时钟。可以来自LFXT1CLK XT2CLK DCO VLO 可选,默认为 DCO。(2),子系统时钟 SMCLK: 提供给高速外设。可以来自 LFXT1CLK XT2CLK DCO VLO可选,默认为 DCO。(3),辅助系统时钟 ACLK:提供给低速外设。可来自 LFXT1CLK VLO。 4,内部的振荡器 DCO 和 VLO 提供的时钟频率不是很精确,随外部环境变化较大。DCO 默认的频率大概为 800KHz,但我用示
8、波器观察的为 1.086MHz 左右,当 DCO 设置的过高时,用示波器可以看到波形不再是方波,而是类似于正弦波。DCO 可以用 CCS 提供的宏定义进行相对比较精确的设置,如下:DCOCTL = CALDCO_12MHZ; /DCO 设为 12MHz 这种方法设 DCO 频率比较精确,实际测得为 12.08MHz 左右 正弦波BCSCTL1 = CALBC1_12MHZ;用这种方法可以设置 1,8,12,16MHz宏定义如下:#ifndef _DisableCalDataSFR_8BIT(CALDCO_16MHZ); SFR_8BIT(CALBC1_16MHZ); SFR_8BIT(CALD
9、CO_12MHZ); SFR_8BIT(CALBC1_12MHZ); SFR_8BIT(CALDCO_8MHZ); SFR_8BIT(CALBC1_8MHZ); SFR_8BIT(CALDCO_1MHZ); SFR_8BIT(CALBC1_1MHZ); #endif 5,使用超低功耗低频振荡器 VLO 可以很大程度地降低系统功耗,下面的例子是设置ACLK 为 VLO,MCLK 为 VLO 的 8 分频:#include /1 延时/#define CPU_F (double)16000000)/cpu frequency16000000#define CPU_F (double)1630)/c
10、pu frequency1630 /CPU 的实际 MCLK 大约为 13.05/8=1.63KHz#define delay_us(x) _delay_cycles(long)(CPU_F*(double)x/1000000.0)#define delay_ms(x) _delay_cycles(long)(CPU_F*(double)x/1000.0)void main(void)volatile unsigned int i; / Volatile to prevent removalWDTCTL = WDTPW + WDTHOLD; / Stop watchdog timerBCSCT
11、L3 |= LFXT1S_2; / LFXT1 = VLO 低频时钟选择为 VLO ACLK 选为 VLOIFG1 / Clear OSCFault flag清除振荡器错误中断标志_bis_SR_register(SCG1 + SCG0); / Stop DCO SCG1 禁止SMCLK SCG0 禁止 DCOBCSCTL2 |= SELM_3 + DIVM_3; / MCLK = LFXT1/8/因为前面已经选择了 LFXT1 = VLO 所以 MCLK 选为 VLO 8 分频 所以 CPU 的MCLK 大约为 1.5KHzP1DIR = 0xFF; / All P1.x outputsP1
12、OUT = 0; / All P1.x resetP2DIR = 0xFF; / All P2.x outputsP2OUT = 0; / All P2.x resetP1SEL |= BIT0+BIT4; / P10 P14options 功能选择为外围模块/p10 输出 ACLK,来自 VLO,p14 输出 SMCLK, 因为禁止了 SMCLK,所以 P14 脚无波形输出/VLO 典型值为 12KHz 实际用示波器测得为:13.05KHz 左右波动/所以 CPU 的实际 MCLK 大约为 13.05/8=1.63KHzfor (;)P1OUT = BIT6; / P1.6 闪烁delay_
13、ms(1000);6,如上面的程序所示,其中的延迟函数用那种方法,使用系统的延迟周期函数_delay_cycles(int n); 可以达到比较精确的延迟,如下:/more_/1 延时/#define CPU_F (double)16000000)/cpu frequency16000000#define CPU_F (double)12000000)/cpu frequency12000000#define delay_us(x) _delay_cycles(long)(CPU_F*(double)x/1000000.0)#define delay_ms(x) _delay_cycles(l
14、ong)(CPU_F*(double)x/1000.0)/2 空函数#define nop() _NOP();7,系统上电后默认使用的是 DCO 时钟,DCO 默认的频率大概为 800KHz,但我用示波器观察的为 1.086MHz 左右,当 DCO 设置的过高时,用示波器可以看到波形不再是方波,而是类似于正弦波。(三),定时器 Timer_A1,MSP430g2553 具有两个 16 位的定时器:Timer0_A Timer1_A。分别具有三个捕捉/比较寄存器,具有输入捕捉,输出比较功能。可以产生定时中断,也可以产生 PWM。2,产生 PWM,例子如下:#include void Timer_
15、A0_1_init() /TA0.1 输出 PWMTACTL|= TASSEL_1+MC_1;/ACLK,增计数CCTL1=OUTMOD_7;/输出模式为复位/ 置位CCR0=328;/时钟频率为 32768HZ,100HZ/CCR1=164;/时钟频率为 32768HZ,占空比 CCR1/CCR0=50%CCR1=109;/占空比 CCR1/CCR0=1/3 TA0.1 由P1.2 P1.6 输出void Timer_A1_2_init() /TA1.2 输出 PWMTA1CTL|= TASSEL_1+MC_1;/ACLK,增计数TA1CCTL2=OUTMOD_7;/输出模式为复位/置位,注
16、意 CCTL2 要写为 TA1CCTL2TA1CCR0=164;/时钟频率为 32768HZ,波形 32768/CCR0=199HZTA1CCR2=41;/占空比 CCR2/CCR0=1/4,注意 CCR2 要写成 TA1CCR2 TA1.2由 P2.4 P2.5 输出void Timer_A1_1_init() /TA1.1 输出 PWMTA1CCTL1=OUTMOD_7;TA1CCR1=123; /占空比 CCR1/CCR0=3/4,注意 CCR1 要写成 TA1CCR1 TA1.1由 P2.1 P2.2 输出void IO_init()P1SEL|=BIT2+BIT6;P1DIR|=BI
17、T2+BIT6;/P1.2 P1.6 输出 TA0.1 OUT1P2SEL|=BIT4+BIT5;P2DIR|=BIT4+BIT5;/P2.4 P2.5 输出 TA1.2 OUT2P2SEL|=BIT1+BIT2;P2DIR|=BIT1+BIT2; /P2.1 P2.2 输出 TA1.1 OUT1void main(void) WDTCTL=WDTPW+WDTHOLD;IO_init();Timer_A0_1_init();Timer_A1_2_init();Timer_A1_1_init();_BIS_SR(CPUOFF); / Enter LPM0 进入低功耗模式 0 SMCLK ON,A
18、CLK ON3,Timer_A 的捕获/比较寄存器TAR 寄存器是 Timer_A 的 16 位的计数寄存器。TACCRx 是 Timer_A 的捕获/比较寄存器,当为捕获模式时:当捕获发生时,把 TAR 的值装载到 TACCRx 中。当为比较模式时:TACCRx 中装的是要与 TAR 寄存器相比较的值。4,捕获模式捕获外部输入的信号的上升沿或下降沿或上升沿下降沿都捕捉,当捕捉发生时,把 TAR 的值装载到 TACCRx 中,同时也可以进入中断,执行相应的操作。这样利用捕捉上升沿或下降沿就可以计算外部输入信号的周期,得出频率。利用捕捉上升沿和下降沿可以得出输入信号的高电平或低电平的持续时间。也
19、可以算出占空比。下面是一个例子,是 Timer_A 捕获初始化的程序:void timer_init() /使用 Timer1_A 时要特别注意各个寄存器的写法,因为Timer0_A 的寄存器都简写了,所以在写/Timer1_A 的寄存器时,要特别注意与 Timer0_A 的不同P1SEL |= BIT2; /选择 P12 作为捕捉的输入端子 Timer0_A/TACCTL1 |=CM_3+SCS+CAP+CCIE; /上下沿都触发捕捉,用于测脉宽,同步模式、时能中断 CCI1ATACCTL1 |=CM_1+SCS+CAP+CCIE; /上升沿触发捕捉,同步模式、时能中断 CCI1ATACTL
20、 |= TASSEL1+MC_2; /选择 SMCLK 时钟作为计数时钟源,不分频 增计数模式不行,必须连续计数模式P2SEL |= BIT1; /选择 P21 作为捕捉的输入端子 Timer1_A/TA1CCTL1 |=CM_3+SCS+CAP+CCIE; /上下沿都触发捕捉,用于测脉宽,同步模式、时能中断 CCI1ATA1CCTL1 |=CM_1+SCS+CAP+CCIE; /上升沿触发捕捉,同步模式、时能中断 CCI1ATA1CTL |= TASSEL1+MC_2; /选择 SMCLK 时钟作为计数时钟源,不分频 增计数模式不行,必须连续计数模式相对应的中断函数如下:#pragma ve
21、ctor=TIMER0_A1_VECTOR /Timer0_A CC1 的中断向量_interrupt void Timer_A(void)/ CCI0A 使用的捕捉比较寄存器是 TA0CCR0,TA0CCR0 单独分配给一个/中断向量 TIMER1_A0_VECTOR,所以进入中断后直接就是 Timer0_A CC0 产生的中断,不用经过类似/下面的方法判断中断源了 。/Timer0_A CC1-4, TA0 公用一个中断向量 TIMER0_A1_VECTOR,所以进入了中断后还要用下面/的方法进行判断是哪一个中断源产生的中断switch(TAIV) /如果是 Timer0_A CC1 产生
22、的中断case 2:flag=1;LPM1_EXIT; /退出低功耗模式/ _BIC_SR_IRQ(LPM1_bits);/_bic_SR_register_on_exit(LPM1_bits);break;case 4: break;case 10:break;#pragma vector=TIMER1_A1_VECTOR /Timer1_A CC1 的中断向量_interrupt void Timer_A1(void)/ P1OUT|=BIT0; /led 调试用的/ LPM1_EXIT; /退出低功耗模式 因为使用的是 CCI0A 使用的捕捉比较寄存器是TA1CCR0,TA1CCR0 单
23、独分配给一个/中断向量 TIMER1_A0_VECTOR,所以进入中断后直接就是Timer1_A CC0 产生的中断,不用经过类似/下面注释掉的方法判断 。/而 Timer1_A CC1-4, TA1 则公用一个中断向量TIMER1_A1_VECTOR,所以进入了中断后还要用下面/的方法进行判断是哪一个中断源产生的中断switch(TA1IV) /如果是 Timer1_A CC1 产生的中断case 2:flag=2;LPM1_EXIT; /退出低功耗模式/ _BIC_SR_IRQ(LPM1_bits);/_bic_SR_register_on_exit(LPM1_bits);break;ca
24、se 4:break;case 10:break;/如果要测量更低频率的信号的话,可以在中断中判断溢出中断发生的次数,这样就可以得到溢出的次数,从而可以测量更/低频率的信号5,Timer_A 的计数模式计数模式有:增计数模式,连续计数模式和增减计数模式。具体的各个模式的详解,参见用户指南。6,定时器的定时中断在使用定时器的定时中断时,要注意定时器计数模式的选择。在使用中断时,要注意中断向量的使用和中断源的判断,下面就举一个例子,注释的也较详细:#include unsigned int t=0;void main(void)WDTCTL = WDTPW + WDTHOLD; / Stop WD
25、TP1DIR |= 0x01; / P1.0 outputCCTL0 = CCIE; / CCTLx 是捕获/比较控制寄存器 interrupt enabled CCIE=0x0010时能定时器 A 中断CCR0 = 50000; /捕获/比较寄存器 设置计数器 CCR0 的初值 16 位寄存器,最大值为 65535/默认 SMCLK 使用的是 DCO,默认的 DCO 大约为 800KHz,而CCR0=50000,所以中断产生的频率大约为 16HzTACTL = TASSEL_2 + MC_2; / SMCLK, contmode 连续计数模式从0 计到 0FFFFh/TACTL = TASS
26、EL_2 + MC_1; / SMCLK, upmode 增计数模式从 0计到 CCR0_BIS_SR(LPM0_bits + GIE); / Enter LPM0 w/ interrupt 进入低功耗模式 0,允许中断/ Timer A0 interrupt service routine#pragma vector=TIMER0_A0_VECTOR_interrupt void Timer_A (void) /CCIFG 中断被响应后,该标志位自动清零/P1OUT = 0x01; / Toggle P1.0t+;if(t=5)P1OUT = BIT0; / Toggle P1.0t=0;C
27、CR0 += 50000; / Add Offset to CCR0 增加 CCR0 偏移/定时器总是从 0 开始往上计数,一直到计满再从 0 开始,在连续计数模式下,当定时器的值等于 CCR0 时,产生中断/在中断中对 CCR0 增加 50000,这样的话定时器从当前值到下一时刻再次等于 CCR0时的间隔为 50000,恒定/这样产生中断的时间间隔就相等了/所以在连续计数模式下,要想使中断的时间间隔一定,就要有 CCR0 += n;这句话/在中断中 CCR0 不需要从新赋值,区别于 51中断的使用注意情况:还是把举个例子吧:#include void main(void)WDTCTL = W
28、DTPW + WDTHOLD; / Stop WDTP1DIR |= 0x01; / P1.0 outputTACTL = TASSEL_2 + MC_2 + TAIE; / SMCLK, contmode, interrupt TAIE允许定时器溢出中断_BIS_SR(LPM0_bits + GIE); / Enter LPM0 w/ interrupt GIE 允许中断/ Timer_A3 Interrupt Vector (TA0IV) handler#pragma vector=TIMER0_A1_VECTOR_interrupt void Timer_A(void)switch( T
29、A0IV ) /TAIV 中断向量寄存器 用于case 2: break; / CCR1 not used 捕获/比较器 1case 4: break; / CCR2 not used 捕获/比较器 2case 10: P1OUT = 0x01; / overflow 定时器溢出break;7,注意:定时器 Timer0_A 的时钟可以选择为外接时钟输入 TACLK(P10 ),这样当外接一个信号时,定时器 Timer0_A 就相当于一个计数器使用。这样就可以用 Timer0_A 接外接信号,Timer1_A 接标准的时钟如 32768Hz 的晶振,就可以实现等精度测频了。其实Timer1_A
30、 的时钟也可以外接的,但是在 g2553 中没有这个外接管脚(P37),所以就只能选择正常的时钟了。Timer0_A 的外接时钟输入 TACLK(P10 )的设置如下:下面是我实现等精度测频时,两个定时器的初始化程序:void timer0_init()TACTL |= TASSEL_0+MC_2+TACLR; /选择 TACLK 时钟作为计数时钟源,不分频 必须连续计数模式P1SEL |= BIT0; /P10 为 Timer0_A 的时钟 TACLK 输入,接外部待测信号,这样Timer0_A 就当作计数器用/Timer1_A 采用 ACLK 作为时钟源计数,这样 ACLK 就相当于是标准
31、信号,这样两个定时器相当于都工作在计数器方式,/ACLK 32768Hz 作为标准信号,这样可以实现等精度测频void timer1_init()TA1CCTL0 = CCIE;TA1CCR0 = 32768; /1s 定时TA1CTL |= TASSEL_1+MC_2+TACLR; /选择 ACLK 时钟作为计数时钟源,不分频 必须连续计数模式8,用定时器和比较器可以实现 DAC使用定时器也可以实现串口通信(四),ADC101,ADC10 是十位的 AD,在 g2553 上有 A0A7 八个可以外接的 AD 通道,A10 接到片上的温度传感器上,其他的通道都接在内部的 V或 GND 上。因为
32、是为的所以计算公式如下:2 ,ADC 参考电压的选择:ADC 的参考电压可以为:由 ADC 控制寄存器 0 ADC10CTL0 控制。但是要提高 ADC 的精度的话,尽量不要用内部的参考电压,最好外接一个比较稳定的电压作为参考电压,因为内部的产生的参考电压不是特别稳定或精度不是特别的高。例如我在使用时遇到的情况如下:Vref 设为 2.5V 但实际的值大概为 2.475V, 选择 VCC VSS 作为参考,用电压表测得大概为 3.58V 还是不小的偏差的。另外,在有可能的情况下,尽量采用较大的 VR+和 VR-,以减小纹波对采样结果的影响。3,ADC10 的采样方式有:单通道单次采样,单通道多
33、次采样,多通道单次采样,多通道多次采样。4,DTC:因为 ADC10 只有一个采样结果存储寄存器 ADC10MEM,所以除了在单通道单次采样的模式下,其他的三个模式都必须使用 DCT,否则转换结果会不停地被新的结果给覆盖。DTC 是转换结果传送控制,也就是转换结果可以不用 CPU 的干预,就可以自动地存储在指定的存储空间内。使用这种方式转换速度快,访问方便,适用于高速采样模式中。DTC 的使用可以从下面的例子中很容易看明白:#include #include “ser_12864.h“uchar s1=“DTC:“;uchar s2=“2_cha_2_time_DTC“;void ADC_in
34、it()ADC10CTL1 = CONSEQ_3 + INCH_1; / 2 通道多次转换, 最大转换通道为 A1ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE; / ADC10ON, interrupt enabl 参考电压选默认值 VCC 和 VSS/采样保持时间为 16 x ADC10CLKs,ADC 内核开,中断使能 MSC 多次转换选择开/如果 MSC 置位,则第一次开始转换时需要触发源触发一次,以后的转换会自动进行中断使能/使用 DTC 时,当一个块传送结束,产生中断/数据传送控制寄存器 0 ADC10DTC0 设置为默认模式:单传
35、送块模式,单块传送完停止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_sample8=0; /存储 ADC 序列采样结果WDT
36、CTL = WDTPW+WDTHOLD;BCSCTL1 = CALBC1_12MHZ; /设定 cpu 时钟 DCO 频率为 12MHzDCOCTL = CALDCO_12MHZ;P2DIR |=BIT3+BIT4; /液晶的两条线init_lcd();ADC_init();wr_string(0,0,s1);wr_string(0,3,s2);for (;)ADC10CTL0 /ADC 不使能 其实这句话可以放在紧接着 CPU 唤醒之后的,因为 CPU 唤醒了,说明我们想要的/转换数据传送完成了,如果 ADC 继续转换,那么转换结果也不再传输,是无用的。所以紧接着放在 CPU 唤醒之后/计时
37、关闭 ADC,有利于降低功耗while (ADC10CTL1 / 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 次数据,所以每次传送完成了一个块,也就
38、是 4次,就会把中断标志位置位,产生中断/因为上面设置的地址为数组 adc_sample的首地址,所以每次转换的结果就会传送到该数组的前 4 位上,所以如果/一切正常的话,数组里应该是前 4 位为转换的结果,后 4 位为初始值 0 通过下面的显示,验证转换是正确的/一次触发首先对 A1、A0 采样,放入 a0和 a1中,再对 A1、A0 采样,放入a2和 a3中。如此循环下去。/验证得知,当多通道采样时,先采高的通道,再采低的通道。如上面每次采样时,先采 A1 再 A0/因为一共采样传送 4 次,所以数组的后 4 位为初始值 0ADC10CTL0 |= ENC + ADC10SC; / Sam
39、pling and conversion start ADC 使能,开始转换 ADC10SC 为采样触发源/不需要 cpu 的干预,DTC 就可以把采样结果存储到指定的存储区中_bis_SR_register(CPUOFF + GIE); / LPM0, ADC10_ISR will force exit 如果转换结果传送完成,/就会进入中断,CPU 唤醒 继续往下运行wr_int(2,0,adc_sample0); /显示转换结果 A1wr_int(6,0,adc_sample1); /A0wr_int(0,1,adc_sample2); /A1wr_int(3,1,adc_sample3)
40、; /A0wr_int(6,1,adc_sample4);wr_int(0,2,adc_sample5);wr_int(3,2,adc_sample6);wr_int(6,2,adc_sample7);/ 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 型的数组中。
41、也可以用指针直接指定要存放的地址,然后再用指针进行访问(理论上可以,但还没有试过)。也可以把存储结果直接存放在一个 16 位的寄存器中,如:ADC10SA = (unsigned int) / Data transfer location 把转换结果存储在 TACCR1 所在的/位置处,就相当于存储在 TACCR1 中 因为 ADC 转换结果和寄存器 TACCR1 都是 16 位的,所以要把地址强制转换为 16 位的/int 或 unsigned int 型5,ADC 采样注意事项:用片上的 ADC10 进行采样,如果外部分压电路的电阻过大(比如几 K 以上),AD 引脚会把电压拉高,使采样结
42、果发生很大的偏差。应换成小电阻(几十几百欧),如果要求更精确的话,要加运放进行电压跟随。6,AD 采样交流信号:一般是 50Hz,100Hz,1000Hz。方法是在交流信号的一个周期内采样多次(如 40 次,30 次等),然后利用公式可以求出交流信号的有效值,平均值等。7,片上温度传感器ADC 的 A10 通道接片上的温度传感器,MSP430 内嵌的温度传感器实际上就是一个输出电压随环境温度而变化的温度二极管。当使用片上温度传感器时,采样周期必须大于 30us 片上温度传感器的偏移很大,所以精确测量需要进行校准。选择片上温度传感器 INCH_10,ADC 其他的设置都和外部通道的设置相同,包括
43、参考电压源的选择和转换存储的选择选择了片上温度传感器,会自动地打开片上参考电压源发生器作为温度传感器的电压源,但是这并不会时能 VREF+输出,也不会影响 AD 转换参考源的选择,转换参考源的选择和其他通道的选择相同公式为:VTEMP=0.00355(TEMPC)+0.986片上温度传感器的校准,可以参见我的温度传感器校准程序,也可以参考其他的论文。下面只给出程序的一部分:void ADC_init()ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; / ADC10ON, interrupt enabled 参考电压选默认值 VCC 和 VSS/采样保持时
44、间为 16 x ADC10CLKs,ADC 开,中断使能ADC10CTL1 = INCH_10; / ADC 输入通道选择 A10,为内部的温度传感器/其他是默认,采样触发输入源选择为 ADC10SC,采样输入信号不翻转,转换时钟选择内部时钟源:ADC10OSC,3.76.3MHz/不分频,单通道单次转换/ADC10AE0 |= 0x02; / PA.1 ADC option select 使能模拟输入脚 A1/P1DIR |= 0x01; / Set P1.0 to output direction/所以是 P11 为 ADC 输入脚,P10 控制 led(五),通用串行通信接口(USCI)
45、1,USCI_A:支持 UART, IrDA, SPIUSCI_B:支持 I2C, SPI2,UART 这个模块没什么好说的,和其他的一写处理器如 S12,ARM 等差不多。只要设置好几个控制寄存器,波特率,写几个收发函数就可以了。下面就给出 msp430g2553 于PC 用 UART 通信的基本程序:#include “msp430g2553.h“unsigned char rev;char *string1=“Helloworld!“;char string2=“Get it!n“; /n 是换行符void putchar(unsigned char c) /发送字符函数while (!
46、(IFG2 / USCI_A0 TX buffer ready? 等待 TX buffer 为空UCA0TXBUF = c; / TX - RXed character 发送字符 cvoid putstr(char *s) /发送字符串函数IE2 /发送时先关闭接收中断,不接收while(*s)!=0) /如果没有发完,就继续循环发送putchar(*s);/ putchar(n); /发送换行符s+;IE2 |= UCA0RXIE; /发送完了打开接收中断void main(void)WDTCTL = WDTPW + WDTHOLD; / Stop WDTP1DIR=BIT0;BCSCTL1 = CALBC1_1MHZ; / Set DCO 为 1MHzDCOCTL = CALDCO_1MHZ;P1SEL = BIT1 + BIT2 ; / P1.1 = RXD, P1.2=TXDP1SEL2 = BIT1 + BIT2; /第二外围模式选择/ UCA0CTL1 |= UCSSEL_2; / SMCLK 其他默认:软件复位使能 USCI 逻辑保持在复位状态,用于设置串口/UCA0CTL0 全部为默认状态:无奇偶校验,LSB first,8bit_data,一位停止位,UART 模式,异步模式/ U