TI中文支持网
TI专业的中文技术问题搜集分享网站

【MSP430 LaunchPad设计心得】基于MSP430G2231分辨率为0.1℃普通IO口驱动LCD的温度计

       基于MSP430G2231分辨率为0.1℃普通IO口驱动LCD的温度计

 

                                     wenyangzeng     2012/04/30

为了降低成本,采用MSP430G2231单片机普通IO口驱动段码型LCD,本设计使用了2个中断源,在CCR0中断中顺序产生1/2Bias的COM0-COM3位码扫描信号,并通过USI-SPI功能控制1片74HC595产生8位段码信号,驱动了4位8段LCD显示屏。在CCR1中断中清零LCD显示数据,并产生ADC允许转换信号。温度传感器则利用MSP430G2231内部温度传感器,主程序检测到ADC允许转换信号后进行一次ADC转换,通过采用过采样技术,在采样10次温度值后,进行运算,得到精度达0.1℃的温度测量结果。

设计直接利用LanuchPad 实验板扩展槽,连接1片PCB板,板上焊接74HC595和LCD和COM分压电阻等。编译环境使用IAR-MSP430 for 5.40限制版,该版本将仿真窗口中变量、寄存器观察窗的显示值都屏蔽掉了,有点太吝舍了,给调试过程带来不少麻烦。

 运行结果见图1。

 

               

 

                        图1 运行结果

                     

                                               图2  原理图

附:代码

#include <msp430g2231.h>

#define setbit(var,bit)  ((var)|=(1<<(bit)))

#define clrbit(var,bit)  ((var)&=~(1<<(bit)))

unsigned char  frame[4];    /* LCD frame buffer  */

unsigned char  digit[4];    /* Digit frame buffer */ 

// LCD segment definitions (SoftBaugh SBLCDA4)

#define SEG_D   0x01                            //  AAAA

#define SEG_C   0x04                            // F    B

#define SEG_B   0x40                            // F    B

#define SEG_A   0x80                            //  GGGG

#define SEG_H   0x02                            // E    C

#define SEG_E   0x08                            // E    C

#define SEG_G   0x10                            //  DDDD

#define SEG_F   0x20

#define DIG_c   (SEG_E + SEG_G+ SEG_D)                                      // Displays 'c'

unsigned char const number[17] = {

  (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F),             // "0"

  (SEG_B | SEG_C),                                           // "1"

  (SEG_A + SEG_B + SEG_D + SEG_E + SEG_G),                  // "2"

  (SEG_A + SEG_B + SEG_C + SEG_D + SEG_G),                  // "3"

  (SEG_B + SEG_C + SEG_F + SEG_G),                          // "4"

  (SEG_A + SEG_C + SEG_D + SEG_F + SEG_G),                  // "5"

  (SEG_A + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G),          // "6"

  (SEG_A + SEG_B + SEG_C),                                  // "7"

  (SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G),  // "8"

  (SEG_A + SEG_B + SEG_C + SEG_D + SEG_F + SEG_G),          // "9"

  (SEG_A + SEG_B + SEG_C + SEG_E + SEG_F + SEG_G),          // "A"

  (SEG_C + SEG_D + SEG_E + SEG_F + SEG_G),                          // "B"

  (SEG_A + SEG_D + SEG_E + SEG_F),                          // "C"

  (SEG_B + SEG_C + SEG_D + SEG_E + SEG_G),                           // "D"

  (SEG_A + SEG_D + SEG_E + SEG_F +SEG_G),                   // "E"

  (SEG_A + SEG_E + SEG_F + SEG_G),                            // "F"

  0x00                                                       // Blank

};

long temp;

long DegC;

long IntDegC;

unsigned char Seg_Old,dispbuf[4];

unsigned char var=0,lcdcr=0,ADC_EN=0,t=0;

void display(unsigned int Number,unsigned char D_OR_H);

void main(void)

{unsigned char j=0;

  WDTCTL = WDTPW + WDTHOLD; 

  P1OUT   = 0X00;

  P1DIR   = 0xFF;

  USICTL0 |= USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE;

  USICTL1 |= USICKPH;             

  USICKCTL = USIDIV_1 + USISSEL_2;

  USICTL0 &= ~USISWRST; 

  USICNT = 8;

    CCTL0   = OUTMOD_3 + CCIE;

  CCTL1   = OUTMOD_3 + CCIE;

  TACCR0  = 200;

  TACTL   = TASSEL_2 +  MC_2 ;

  ADC10CTL1 = INCH_10 ;//+ ADC10DIV_3;        

  ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON ;

  _EINT();

  temp=0;

  for(;;)

  {

   if(ADC_EN==1)

    {  ADC_EN=0;

       ADC10CTL0 |= ENC + ADC10SC;

          while (!(ADC10IFG & ADC10CTL0));

     temp += ADC10MEM;

     j++;

     if(j==10)

     {

     IntDegC = ((temp – 673) * 423) / 1024;

     display(IntDegC,1);

     j=0;temp=0;

     }

    }

   }

}

//——————————————–

// Timer A0 interrupt service routine

//——————————————-

#pragma vector=TIMERA0_VECTOR

__interrupt void Timer_A0 (void)

{ unsigned char i;

   if(var==0)

    {

      var++;

        if(lcdcr==0)

            Seg_Old=frame[0];

        else

        if(lcdcr==1) 

            Seg_Old=frame[1];

        else

        if(lcdcr==2) 

            Seg_Old=frame[2];

        else

        if(lcdcr==3) 

            Seg_Old=frame[3];

     while (!(USIIFG & USICTL1));

      USISRL = Seg_Old;

      USICNT = 8;

          for(i=4;i>0;i–);

      P1OUT |= BIT4;

      P1OUT &=~BIT4;

      P1DIR &=~0X0F;

      clrbit(P1OUT,lcdcr);  

      setbit(P1DIR,lcdcr);

    }

  else

  {

    var=0;

     while (!(USIIFG & USICTL1));

     Seg_Old=~Seg_Old;;

      USISRL = Seg_Old;    

      USICNT = 8;

      for(i=4;i>0;i–);

      P1OUT |= BIT4;

      P1OUT &=~BIT4;

      P1DIR &=~0X0F;

      setbit(P1OUT,lcdcr); 

      setbit(P1DIR,lcdcr);

      lcdcr++;

         if (lcdcr>3) lcdcr =0;

  }

  CCR0 += 2300;                             

}

//—————————————————

// Timer_A2 Interrupt Vector (TAIV) handler

//————————————————–

#pragma vector=TIMERA1_VECTOR

__interrupt void Timer_A1(void)

{

  switch( TAIV )

  {unsigned char i;

  case  2:

    {  t++;

      if(t==50)

      {ADC_EN=1; 

      t=0;

      }

            while (!(USIIFG & USICTL1));

            USISRL = 0x00;

            USICNT = 8;

                for(i=4;i>0;i–);

            P1OUT |= BIT4;

            P1OUT &=~BIT4;

            P1OUT &=~0x0f;   //com全为0

            P1DIR  |=0X0F;

            CCR1 += 2300;

          

            break;

          }

  case 10: break;

  }

}

//——————————————————

//显示4位数字函数

//入口参数1:16位数值

//入口参数2:0-16进制/1-十进制

//—————————————————–

void display(unsigned int Number,unsigned char D_OR_H)

{ unsigned char a,b,c,d;

  if(D_OR_H==1)

  {

  a=Number%10000/1000;

  b=Number%1000/100;

  c=Number%100/10;

  d=Number%10;

  }

  else

  {  a=(Number>>12)&0x0f;

    b=(Number>>8)&0x0f;

    c=(Number>>4)&0x0f;

    d=Number&0x0f;

  }

  dispbuf[0]= DIG_c ;//number[d];

  dispbuf[1]= number[c]|SEG_H;

  dispbuf[2]= number[b];

  dispbuf[3]= number[a];

 

  frame[0]=dispbuf[0]&0x03;           

  frame[0] |=(dispbuf[1]<<2)&0x0c;

  frame[0] |=(dispbuf[2]<<4)&0x30;

  frame[0] |=(dispbuf[3]<<6)&0xc0;

 

  frame[1]=(dispbuf[0]>>2)&0x03;

  frame[1] |=(dispbuf[1]&0x0c);

  frame[1] |=(dispbuf[2]<<2)&0x30;

  frame[1] |=(dispbuf[3]<<4)&0xc0;

 

  frame[2]  =(dispbuf[0]>>4)&0x03;

  frame[2] |=(dispbuf[1]>>2)&0x0c;

  frame[2] |=dispbuf[2]&0x30;

  frame[2] |=(dispbuf[3]<<2)&0xc0;

 

  frame[3]  =(dispbuf[0]>>6)&0x03;

  frame[3] |=(dispbuf[1]>>4)&0x0c;

  frame[3] |=(dispbuf[2]>>2)&0x30;

  frame[3] |=(dispbuf[3]&0xc0);

 

}

 

 

wenyang zeng:

wenyang zeng:

为何图片上传后看不见??

wenyang zeng:

wenyang zeng基于MSP430G2231分辨率为0.1℃普通IO口驱动LCD的温度计
 
                                     wenyangzeng     2012/04/30

为了降低成本,采用MSP430G2231单片机普通IO口驱动段码型LCD,本设计使用了2个中断源,在CCR0中断中顺序产生1/2Bias的COM0-COM3位码扫描信号,并通过USI-SPI功能控制1片74HC595产生8位段码信号,驱动了4位8段LCD显示屏。在CCR1中断中清零LCD显示数据,并产生ADC允许转换信号。温度传感器则利用MSP430G2231内部温度传感器,主程序检测到ADC允许转换信号后进行一次ADC转换,通过采用过采样技术,在采样10次温度值后,进行运算,得到精度达0.1℃的温度测量结果。
设计直接利用LanuchPad 实验板扩展槽,连接1片PCB板,板上焊接74HC595和LCD和COM分压电阻等。编译环境使用IAR-MSP430 for 5.40限制版,该版本将仿真窗口中变量、寄存器观察窗的显示值都屏蔽掉了,有点太吝舍了,给调试过程带来不少麻烦。

               
 
                        图1 运行结果

                     
                                               图2  原理图

Fuchong Wang:

回复 wenyang zeng:

应该说是显示分辨率吧,好像内部温度传感器只能0.5左右的理论分辨率吧

功耗多少?

Charles Wu:

回复 Fuchong Wang:

没仔细看代码,看楼主说明里的意思,4个COM的电压都是一样的?全是1/2Vcc?

Charles Wu:

回复 Charles Wu:

另外,楼主用的IAR应该是4K的代码限制版吧。貌似watch,variable这些观察窗口都是可以用的啊,只是默认没有选择打开罢了。

wenyang zeng:

回复 Fuchong Wang:

谢谢楼上的细心指教。是你所说的显示分辨率。

wenyang zeng:

回复 Charles Wu:

4个COM当然都是1/2VCC,定时器中断里对它们进行分时扫描,分别得到VCC-1/2/VCC-0V的电压。

wenyang zeng:

回复 Charles Wu:

watch,variable这些观察窗口都是可以用,但是它们的仿真值显示不出来。

 

Fuchong Wang:

回复 wenyang zeng:

     setbit(P1OUT,lcdcr);

     setbit(P1DIR,lcdcr);

看着累吆

这种类型的LCD用MSP430操作,谁试验过到底可以做到最低功耗多少?例如做个最基本的电子时钟。如果考虑到功耗,难道只有用内部集成驱动的?

赞(0)
未经允许不得转载:TI中文支持网 » 【MSP430 LaunchPad设计心得】基于MSP430G2231分辨率为0.1℃普通IO口驱动LCD的温度计
分享到: 更多 (0)