[资料分享] 使用MSP430实现温控

fish001   2018-10-13 22:13 楼主
对于MSP430而言,实现温控模块以下几个模块互相配合。将分为下面几个部分进行讲解:

时钟源部分
ADC部分
中断部分
温控中代码逻辑的初步调试
UART的初步调试
一:时钟源部分:
现在项目中,需要使用msp430单片机作为控制端,所以,要先对msp430的时钟源进行了解和分析。
msp430拥有unified clock system (统一时钟系统),
-FLL(锁频环) for frequency stablization
-VLO(内部时钟源)
-内部参考源(REFO)
-32kHZ晶振
-高达32MHz的高频时钟
The clock system is supported by the Unified Clock System (UCS) module that includes support for a 32-kHz watch crystal oscillator (或者时钟XT1低频态 XT1 LF mode), an internal very-low-power low-frequency oscillator (内部低频低功耗振荡器VLO), an internal trimmed low-frequency oscillator (内部平衡低频晶振REFO), an integrated internal digitally controlled oscillator 内部数字控制振荡器(DCO), and a high frequency crystal oscillator (高频晶振XT1 HF mode or XT2). The UCS module is designed to meet the requirements of both low system cost and low power consumption.
The UCS module features digital frequency locked loop (FLL)hardware that, in conjunction with a digital modulator, stabilizes the DCO frequency to a programmable multiple of the selected FLL reference frequency. The internal DCO provides a fast turn-on clock source and stabilizes in less than 5 μs. The UCS module provides the following clock signals:
• Auxiliary clock (ACLK), sourced from a 32-kHz watch crystal, a high-frequency crystal, the internal lowfrequency
oscillator (VLO), the trimmed low-frequency oscillator (REFO), or the internal digitally controlled
oscillator DCO.
• Main clock (MCLK), the system clock used by the CPU. MCLK can be sourced by same sources made
available to ACLK.
• Sub-Main clock (SMCLK), the subsystem clock used by the peripheral modules. SMCLK can be sourced by
same sources made available to ACLK.
• ACLK/n, the buffered output of ACLK, ACLK/2, ACLK/4, ACLK/8, ACLK/16, ACLK/32.

因为不接外部晶振,所以本文主要是就DCO的设置进行研究。
msp430F5438A datasheet上给出的设置是:

可以见,DCORESL的频率调节范围大致如下:
DCORSEL = 0的调节范围约为0.20~0.70MHZ;
DCORSEL= 1的调节范围约为0.36~1.47MHZ;
DCORSEL = 2的调节范围约为0.75~3.17MHZ;
DCORSEL = 3的调节范围约为1.51~6.07MHZ;
DCORSEL = 4的调节范围约为3.2~12.3MHZ;
DCORSEL = 5的调节范围约为6.0~23.7MHZ;
DCORSEL = 6的调节范围约为10.7~39.7MHZ;
DCORSEL = 7的调节范围约为19.6~60MHZ。
可以看出有重叠的部分,理解了这些,就可以理解Ti官方代码了:
if (fsystem <= 630) // fsystem < 0.63MHz
UCSCTL1 = DCORSEL_0;
else if (fsystem < 1250) // 0.63MHz < fsystem < 1.25MHz
UCSCTL1 = DCORSEL_1;
else if (fsystem < 2500) // 1.25MHz < fsystem < 2.5MHz
UCSCTL1 = DCORSEL_2;
else if (fsystem < 5000) // 2.5MHz < fsystem < 5MHz
UCSCTL1 = DCORSEL_3;
else if (fsystem < 10000) // 5MHz < fsystem < 10MHz
UCSCTL1 = DCORSEL_4;
else if (fsystem < 20000) // 10MHz < fsystem < 20MHz
UCSCTL1 = DCORSEL_5;
else if (fsystem < 40000) // 20MHz < fsystem < 40MHz
UCSCTL1 = DCORSEL_6;
else
UCSCTL1 = DCORSEL_7;
DCO模块运行需要参考时钟REFCLK,REFCLK可以来自REFOCLK、XT1CLK和XT2CLK,通过UCSCTL3的SELREF选择,默认使用的XT1CLK,但如果XT1CLK不可用则使用REFOCLK。
DCO模块有两个输出时钟信号,级DCOCLK和DCOCLKDIV,其中,倍频计算公式如下:
DCOCLK = D*(N+1)*(REFCLK/n)
DCOCLKDIV = (N+1)*(REFCLK/n)
其中:
n即REFCLK输入时钟分频,可以通过UCSCTL3中的FLLCLKDIV设定,默认为0,也就是不分频;
D可以通过UCSCTL2中的FLLD来设定,默认为1,也就是2分频;
N可以通过UCSCTL2中的FLLN来设定,默认值为31。

为了验证上述的陈述,可以编写以下代码:
P1DIR |= BIT0;
P1SEL |= BIT0; //1口输出辅助时钟
UCSCTL3 |= SELREF_2; // FLLref = REFO 为32.768K
UCSCTL4 = SELM__DCOCLKDIV + SELS__DCOCLKDIV + SELA__DCOCLKDIV;// 时钟来源:主系统时钟来源DCOCLKDIV;子系统时钟来源DCOCLKDIV;辅助系统时钟来源DCOCLKDIV
UCSCTL5 |= DIVM__1 + DIVS__1 + DIVA__1; // 分频:主系统时钟1分频;子系统时钟1分频;辅助系统时钟1分频
所以由计算,DCOCLKDIV =32*32.768K = 1.048576M,也就是ACLK的时钟源(不分频)

根据测试结果我们可知T接近1ms,所以DCOCLKDIV差不多为1M,符合计算结果。
那么如果我要设置别的频率又该怎么办呢?
比如我现在需要大约5M的频率,那么由计算得知,当N=151时,大致满足要求。
那么代码写为:

P1DIR |= BIT0;
P1SEL |= BIT0;                                                           //1口输出辅助时钟
UCSCTL3 |= SELREF_2;                                               // FLLref = REFO 为32.768K
UCSCTL4 = SELM__DCOCLKDIV + SELS__DCOCLKDIV + SELA__DCOCLKDIV;// 时钟来源:主系统时钟来源DCOCLKDIV;子系统时钟来源DCOCLKDIV;辅助系统时钟来源DCOCLKDIV
UCSCTL1 = DCORSEL_4                                          //   5M < Fdco < 10M
UCSCTL2 |= FLLD__1 + 151;                                    //DCOCLKDIV=5M 为 Fdco/2   
UCSCTL5 |= DIVM__1 + DIVS__1 + DIVA__1; // 分频:主系统时钟1分频;子系统时钟1分频;辅助系统时钟1分频

运行,用示波器测P1.0的输出信号。

测出来的信号周期约为200ns,所以输出的ACLK信号就是约为5M,所以实验证实了想法。

二:ADC部分:

由于项目中需要使用到ADC模块,那么就有必要对ADC模块进行研究了。
这是msp430F5428A datasheet首页上面对于ADC的描述:
12-Bit Analog-to-Digital Converter (ADC)
– Internal Reference
– Sample-and-Hold
– Autoscan Feature
– 14 External Channels, 2 Internal Channels
ADC12_A (Link to User’s Guide)
The ADC12_A module supports fast 12-bit analog-to-digital conversions. The module implements a 12-bit SAR
core, sample select control, reference generator, and a 16-word conversion-and-control buffer. The conversionand-
control buffer allows up to 16 independent ADC samples to be converted and stored without any CPU
intervention.
也就是说ADC12_A可以同时转换16路的模拟信号。(没有cpu的介入)
把Msp430f5438A的ADC12_A的重要特点总结如下:
(1) 转换速率可以为200K/s
(2)12bit转换 无错码
(3) 由软件或计数器控制着的采样时间和保持时间
(4)内部有参考电压1.5V,2.0V及2.5V
(5)可以使用外接参考源,是否选择外部参考源由寄存器决定。
(6)有单沟道采样,重复单沟道采样,序列采样,重复序列采样4种模式可选(Single-channel, repeat-single-channel, sequence (autoscan), and repeat-sequence (repeated autoscan) conversion modes)
(7)16位转换结果存储寄存器ADC12MEMx,和ADC12转换结果存储寄存器ADC12MCTLx。
写下列程序:

void main(void)

{

WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer

ADC12CTL0 = ADC12ON+ADC12MSC+ADC12SHT0_15;// Turn on ADC12, set sampling time

ADC12CTL1 = ADC12SHP+ADC12CONSEQ_0; // Use sampling timer, single

ADC12MCTL0 =ADC12SREF_2 + ADC12INCH_3; // ref+=Veref=2.5V, channel = A3

// ADC12MCTL1 = ADC12INCH_2+ADC12EOS; // ref+=AVcc, channel = A9, end seq.

ADC12IE = 0x02; // Enable ADC12IFG.1, end channel

ADC12CTL0 |= ADC12ENC; // Enable conversions

ADC12CTL0 |= ADC12SC; // Start convn - software trigger

}

这个代码很好理解,先是程序进入Timer_A1的中断,然后初始化ADC12,再实现模数转换,进入ADC12的中断,将ADC采集到的数据传到result,然后再进入Timer_A1的中断。
调试过程没有问题,得到了定时采集ADC值的效果。
同时观察到红色LED灯闪烁,说明确实是隔了一段定时的时间进入中断。

到此为止,温控的程序逻辑算是调试结束了。

五:UART口调试

UART口调试部分没有完成,所以没有进行总结,仅将现在遇到的问题描述一下:

测试程序如下,意将一段语句“I’m MSP430 ”重复输出。

#include "msp430x54x.h"
unsigned char buffer[] = {"I'm MSP430!\n"};
void delay(unsigned int n)
{
  unsigned int i,j;
  for(i=0;i     for(j=0;j<1000;j++);
}

void main(void)
{
  unsigned int i;
  WDTCTL = WDTPW + WDTHOLD;          // 关狗

  P10SEL = 0x30;                            // P5_6和P5_7第二功能打开,设置方向
  P10DIR = 0x10;

  UCA3CTL1 |= UCSWRST;          // 首先使RST位置位,只有这样后面的设置才有效
  UCA3CTL1 |= UCSSEL_2;                  // SMCLK,为系统时钟1048576Hz
  UCA3BR0 = 9;                            // 1MHz 115200
  UCA3BR1 = 0;                            // 1MHz 115200
  UCA3MCTL |= UCBRS_1 + UCBRF_0;        // 设置调整参数UCBRSx=1, UCBRFx=0
  UCA3CTL1 &= ~UCSWRST;                // RST复位
  UCA3IE |= UCTXIE;              // 使能发送中断允许
  while(1)
  {
    while (!(UCA3IFG&UCTXIFG));  //等待BUF区准备好,当IFG=1时就表示准备好了
    for(i=0; i     {
      UCA3TXBUF = buffer
;      //向串口发送数据
      delay(20);                   //延时

    }
  }
}

但是最后这段代码仅会在重新上电复位的时候输出:

不能实现我需要的输出。

软件我已经调试很多天了,现在我怀疑可能是串口本身的问题,重新焊一块测试板是下一步的方案。

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复