在线情况
楼主
  • 头像
  • 级别
  • 门派
  • 职务总版主
  • 声望+9
  • 财富5
  • 积分3065
  • 经验390701
  • 文章6744
  • 注册2006-03-07
斜度计[参考设计]
“斜度计”设计,以下是他的源程序,提供微控会员参考。
可以参考<<MSP430系列16位超低功耗单片机原理与应用>>书中“斜度计”设计。

[COLOR=blue]/*****************************************************************************
*
* 程序说明:
*          斜度测试程序
*          程序对应的硬件设置为:MSP430-Test44x实验板,斜度计使用的
*          是ADXL202E,数字y连接TA1/P1.2,数据x连接P1.0/TA0,P4.6对应斜度计电源
*          每个方向的斜度显示时都占用三个字符,
*          斜度范围为0~90,高于90的,斜度为(180-斜度)
******************************************************************************/[/COLOR]
#include "msp430x44x.h"
#include "lcd.c"
#include "math.h"

#define RLEN 6
unsigned int rbuf[RLEN];
unsigned int sdata[RLEN];

unsigned char status1,status2,rd1,flag,cnt,tmpv;
float odata;
void main()
{  
    WDTCTL = 0x5a80;                // stop watch dog
    BTCTL  = 0x07;                  //  Basic Timer 1 中断频率设置
    IE2   |= 0x80;                  // 使能 basic timer 中断
    P4DIR &= 0x00;                  //
    P4DIR |= 0x40;                  //
    P4OUT |= 0x40;                  // 打开Tilt电源
    P1DIR  = 0x00;                  //
    P1SEL  = 0xff;                  //
    FLL_CTL1|=SELS+XT2OFF+SELM_XT2;        //开启第二个振荡器
    do
    {
      IFG1 &= ~OFIFG;                      // 清除OSCFault标志
      for(tmpv = 0xff;tmpv > 0;tmpv--);    //
    }while ((FLL_CTL0&XT2OF) == XT2OF );   // 第二个振荡器是否正常工作
   
    TACTL   = 0x0104; // 工作在辅助时钟,不分频
    TAR = 0;
    TACCTL0 = 0x4110;// IE=1,CAP=1,SCS=1,CCI0A选择,起始时只是上升沿捕获
    init_LCD();
    rd1     = 0;
    tmpv    = 0;
    status1 = 0;  // 状态为起始
    status2 = 0;
    for(tmpv=0;tmpv<6;tmpv++)
    {
        rbuf[tmpv] = 0x00;
    }
    TACTL |= 0x20;   // 连续计数模式
     _EINT();
    while(1);
   
}

#pragma vector = TIMERA1_VECTOR
__interrupt void B_ISR(void)
{
    if(status2==0)
    {
             rbuf[5] = CCR1;
             status2 = 1;
             TACCTL1 = 0x8110;  // 下降沿允许
    }else if(status2==1)
    {
             status2 = 2;
             rbuf[3] = rbuf[3] + CCR1 - rbuf[5];
      
             TACCTL1 = 0x0110;
             TACCTL1 = 0x8110;  // 上升沿允许
    }else if(status2==2)
    {
              rbuf[4]= CCR1 - rbuf[5] + rbuf[4];
              rd1 +=1;
              
              TACCTL1 = 0x0110;     // B停止捕获模式
              if(rd1== 100)
             {
                TACCTL1 = 0x0100;
                status1 = 3;
                TACTL &= 0xFFCF;
               
              }else
              {
                status1 = 0;
                TACCTL0 = 0x4110;    // A上升沿允许
              }
    }
}
#pragma vector = TIMERA0_VECTOR
__interrupt void A_ISR(void)
{
   
    if(status1==0)
    {
             rbuf[2] = CCR0;
             status1 = 1;
             TACCTL0 = 0x8110;      // 下降沿允许
    }else if(status1==1)
    {
             status1 = 2;
             rbuf[0] = rbuf[0] + CCR0 - rbuf[2];
      
             TACCTL0 = 0x0110;
             TACCTL0 = 0x4110;      // 上升沿允许
    }else if(status1==2)
    {
              rbuf[1]= CCR0 - rbuf[2] + rbuf[1];
              rd1 +=1;
              
              TACCTL0 = 0x0110;     // A停止捕获模式
              status2 = 0;
              TACCTL1 = 0x4110;     // B的上升沿允许
     }
}
 #pragma vector = BASICTIMER_VECTOR
 __interrupt void  BT_Interrupt(void)
 {    
      int tmpi;
     
      if(rd1==100)
      {  
           odata = rbuf[0]*1.0;             // 转成float型
           odata = odata/rbuf[1];
           odata = (odata  - 0.5)/0.116;    
            if(odata<0)
            {
               odata = -odata;
            }
            if(odata >=1) odata = 1;
            odata  = asin(odata);
            odata = odata/3.14159*180;
            tmpi = 0;
            while(odata>=1)//获取斜度
            {
               if(odata>=100)
               {
                  odata=odata-100;
                  tmpi+=100;
               }else if(odata>=10)
               {
                  odata -= 10;
                  tmpi +=10;
                }else if(odata >=1){
                   odata -=1;
                   tmpi += 1;
                }
            }
            for(tmpv=0;tmpv<3;tmpv++)
            {
               
                lcd_Buf[tmpv]= (char)(tmpi%10);
                tmpi =(tmpi/10);
            }
           
           odata = rbuf[3]*1.0;
           odata = odata/rbuf[4];
           odata = (odata  - 0.327)/0.0505; //系数的计算应该根据实际的电路测量后确定
           if(odata<0)
           {
               odata = -odata;
            }
            if(odata >=1) odata = 1;
            odata  = asin(odata);
            odata = odata/3.14159*180;
            tmpi = 0;
            while(odata>=1)//获取斜度
            {
               if(odata>=100)
               {
                  odata=odata-100;
                  tmpi+=100;
               }else if(odata>=10)
               {
                  odata -= 10;
                  tmpi +=10;
                }else if(odata >=1)
                {
                   odata -=1;
                   tmpi += 1;
                }
            }
           
            for(tmpv=3;tmpv<6;tmpv++)
            {
                lcd_Buf[tmpv]= (char)(tmpi%10); //填充数据到LCD缓冲区
                tmpi =(tmpi/10);
            }
            status1 = 0;               // 参数、状态重置,以避免TAR溢出
            rd1     = 0;
            cnt     = 0;
            rbuf[0] = 0;
            rbuf[3] = 0;
            rbuf[4] = 0;
            rbuf[1] = 0;
            TAR     = 0x00;
            TACCTL0 = 0x4110;            // 上升沿允许
            TACTL  |= 0x20;
            status1 = 0;
            lcd_Display();               // 使用LcD键盘数据  
         }
     
}



[COLOR=blue]/*                      - MATH.H -

   The ANSI-defined (+ a few additional) mathematical functions.
           
   $Name: V3_34K V3_34J V3_34I V3_34H V3_34G $
           
   Copyright 1986 - 1999 IAR Systems. All rights reserved.
*/[/COLOR]

#ifndef _MATH_INCLUDED
#define _MATH_INCLUDED

#include "sysmac.h"

#ifndef HUGE_VAL
#if __FLOAT_SIZE__ == __DOUBLE_SIZE__
#define HUGE_VAL 3.402823466e+38
#else
#define HUGE_VAL 1.7976931348623158e+308
#endif
#endif

/* What is returned if a domain error occurred */
#define __EDOM_VALUE    HUGE_VAL

/* PI, PI/2, PI/4, 1/PI, 2/PI */
#define __PI            3.141592653589793238462643
#define __PIO2          1.570796326794896619231
#define __PIO4          .785398163397448309615
#define __INVPI         0.31830988618379067154
#define __TWOOPI        0.63661977236758134308

/* SQRT(2), SQRT(2) + 1, SQRT(2) - 1,SQRT(2) / 2 */
#define __SQRT2         1.4142135623730950488016887
#define __SQ2P1         2.414213562373095048802
#define __SQ2M1         .414213562373095048802
#define __SQRTO2        0.707106781186547524

/* LN(10), TWO-LOG(e), LN(2) e */
#define __LN10          2.302585092994045684
#define __LOG2E         1.4426950408889634073599247
#define __LOG2          0.693147180559945309417232
#define __E             2.718281828459045235360287


#if __IAR_SYSTEMS_ICC__ < 2
#if __TID__ & 0x8000
#pragma function=intrinsic(0)
#endif
#endif

#ifndef MEMORY_ATTRIBUTE
#define MEMORY_ATTRIBUTE
#endif

__INTRINSIC MEMORY_ATTRIBUTE double atan(double);

__INTRINSIC MEMORY_ATTRIBUTE double atan2(double, double);

__INTRINSIC MEMORY_ATTRIBUTE double cos(double);

__INTRINSIC MEMORY_ATTRIBUTE double cosh(double);

__INTRINSIC MEMORY_ATTRIBUTE double fabs(double);

__INTRINSIC MEMORY_ATTRIBUTE double fmod(double, double);

__INTRINSIC MEMORY_ATTRIBUTE double exp(double);

__INTRINSIC MEMORY_ATTRIBUTE double ldexp(double, int);

__INTRINSIC MEMORY_ATTRIBUTE double log(double);

__INTRINSIC MEMORY_ATTRIBUTE double log10(double);

__INTRINSIC MEMORY_ATTRIBUTE double modf(double, double *);

__INTRINSIC MEMORY_ATTRIBUTE double pow(double , double);

__INTRINSIC MEMORY_ATTRIBUTE double sin(double);

__INTRINSIC MEMORY_ATTRIBUTE double sinh(double);

__INTRINSIC MEMORY_ATTRIBUTE double sqrt(double);

__INTRINSIC MEMORY_ATTRIBUTE double tan(double);

__INTRINSIC MEMORY_ATTRIBUTE double tanh(double);

__INTRINSIC MEMORY_ATTRIBUTE double floor(double);

__INTRINSIC MEMORY_ATTRIBUTE double ceil(double);

__INTRINSIC MEMORY_ATTRIBUTE double frexp(double, int *);

__INTRINSIC MEMORY_ATTRIBUTE double acos(double);

__INTRINSIC MEMORY_ATTRIBUTE double asin(double);

#if __IAR_SYSTEMS_ICC__ < 2
#if __TID__ & 0x8000
#pragma function=default
#endif
#endif

#endif /* _MATH_INCLUDED */



[COLOR=blue]******************************************************
* 文件名称:uart.c
* 文件说明:
*          RS232通迅使用的UART0 模块
*****************************************************/[/COLOR]
#ifndef MSP430XF449_H
#include <msp430x44x.h>
#endif

#define UART_BUF_SIZE 6
/*****************************************************/
/*   数据定义                                        */
/*****************************************************/
char uart_RBuf[UART_BUF_SIZE];   //接收缓冲区
char uart_TBuf[UART_BUF_SIZE];   //发送缓冲区
unsigned char uart_RDataPos,     //用于指示下一个存放接收数据的缓冲区位置
              uart_RFlag,        // 接收缓冲区缓存的数据数目(单位字符)
              uart_TNum,         // 发送缓冲区缓存的数据数目(单位字符)
              uart_TPos;         // 标识 uart 下一个要发送的数据的位置
/*******************************************************
*     模块初始化
*******************************************************/
void init_UART(void)
{
    unsigned char tmpv;
    FLL_CTL0 &= 0xbf;
    UCTL0 |=SWRST;
    UCTL0 |=CHAR;                           // 8-bit 字符
    /*UTCTL0= 0x10;                         // UCLK=ACLK
    UBR00 = 0x0d;                           // 在32768下进行 2400波特率通信
    UBR10 = 0x00;                           // 在32768下进行 2400波特率通信
    UMCTL0= 0x57;                           // 调整寄存器
   */
      
    FLL_CTL1|=SELS+XT2OFF+SELM_XT2;        //开启第二个振荡器
    do
    {
      IFG1 &= ~OFIFG;                      // 清除OSCFault标志
      for(tmpv = 0xff;tmpv > 0;tmpv--);    //
    }while ((FLL_CTL0&XT2OF) == XT2OF );   // 第二个振荡器是否正常工作
    UCTL0|=SWRST;
    UCTL0|=CHAR;                           // 8-bit 字符
    UTCTL0=SSEL0+SSEL1;                    // UCLK=SMCLK
    UBR00=0xa0;                            // 在4MHz下进行 9600波特率通信
    UBR10=0x01;                            // 在4MHz下进行 9600波特率通信
    UMCTL0=0x5e;                           // 调整寄存器
    UCTL0&=~SWRST;
   
    ME1|= (UTXE0 + URXE0);                 // 使能 USART0 TXD/RXD
    IE1|= URXIE0 ;
    IFG1 = 0x00;
    P2SEL |= 0x30;                         // P2.4,P2.5 = USART0 TXD/RXD
    P2DIR |= 0x10;
    uart_RDataPos = 0;
    uart_TNum =0 ;
    for(tmpv=0;tmpv<UART_BUF_SIZE;tmpv++)
    {
       uart_RBuf[tmpv] = 0;
    }
}
/****************************************************
*     数据发送
****************************************************/
void uart_Start(void)
{
    IE1 |= UTXIE0 ;
    while((UTCTL0 & 0x01 )!=0x01);        //等待直到没有数据发送
    TXBUF0 = uart_TBuf[0];                //发送数据
    uart_TPos = 1;
}

/****************************************************
*     数据接收中断
****************************************************/
#pragma vector = UART0RX_VECTOR
__interrupt void data_Receive(void)       // UART接收中断
{    
    uart_RBuf[uart_RDataPos]=RXBUF0-48;  //从asc码转变到单片机键码索引
                                         //从asc码转变到单片机键码索引
    uart_RDataPos = (uart_RDataPos + 1); //移动接收缓冲区指针
    if (uart_RDataPos >= UART_BUF_SIZE)
    {
        uart_RDataPos = 0;
    }
    uart_RFlag += 1;                    //接收数据计数器加1
}
#pragma vector = UART0TX_VECTOR
__interrupt void __uart_Send(void)
{
    uart_TNum -= 1;
    if (uart_TNum >0)
    {
        TXBUF0 = uart_TBuf[uart_TPos];
        uart_TPos +=1;
    }else {
       IE1 &= 0x7f;                   //disable UTXIE0
    }
}



[COLOR=blue]/*****************************************************
*  
*     文件名称:lcd.c
*    文件说明:LCD 模块
*****************************************************/[/COLOR]
#ifndef MSP430F449_H
#include <msp430x44x.h>
#endif

#define LCD_IN_USE 8
#define RADIX_POINT 0x08
/******************************************************
   数据定义                                        
*****************************************************/
const unsigned char NUM_LCD[16]={
                0x7B, 0x12, 0x4f, 0x1f, 0x36,  //'0'~ '4'
           0x3d, 0x7d, 0x13, 0x7f, 0x3f,  //'5' ~ '9'
           0x73, 0x7c, 0x69, 0x5e, 0x6f,  // '6'~ 'E'
           0x65};                         // F"
unsigned char lcd_Buf[LCD_IN_USE];             // 自定义显示缓冲区,用于
                                               // 外部设定要显示的数据
/*******************************************************
*     模块初始化
*******************************************************/
void init_LCD(void)
{
    char tmpv;
    BTCTL |= 0x10;                         // set LCD 时钟
    P3DIR  = 0xff;                         // 输出模式
    P5SEL  = 0xfc;                         // 置为外围模块
    LCDCTL = LCDON+LCD4MUX+LCDP1;          // 4Mux 模式
   
     for (tmpv = 0;tmpv<7;tmpv++)
     {
        LCDMEM[tmpv] = 0x00;               //clear LCD
     }
     LCDMEM[7] = 0x02;                      // 设置LCDMEM[7]             
   
}
/****************************************************
*
*    更新LCD缓冲区的内容,把数据显示到LCD
*    
****************************************************/
void lcd_Display()
{                      
    char tmpv;
    for(tmpv=0;tmpv<LCD_IN_USE-1;tmpv++)
    {  
        LCDMEM[tmpv] = NUM_LCD[lcd_Buf[tmpv]]; //更新LCDMEM中的内容
    }
     
}
/***************************************************
*  设置小数点
***************************************************/
void lcd_SetRP()
{
    LCDMEM[1] |= 0x80;                         // 显示小数点
}



[COLOR=blue]/*****************************************************
*  文件名称:
*           led.c
*  文件说明:显示的时候首先设置要显示的内容
*           然后使能相应的LED
*
*****************************************************/[/COLOR]

#ifndef MSP430F449_H
#include <msp430x44x.h>
#endif

#define LED_IN_USE 6
/*****************************************************/
/*   数据定义                                        */
/*****************************************************/
const unsigned char NUM_LED[18]=
                       {0xd7,0x14,0xcd,0x5d,0x1E,  // 0 ~ 4
                       0x5b,0xdb,0x15,0xdf,0x5f,   // 5 ~ 9
                       0x9f,0xda,0xc3,0xcc,0xcf,   // a ~ e
                       0x8b,0x00,0x08};                 //f,0x00使LED不显示

                       
unsigned char led_Buf[LED_IN_USE];  // LED显示缓冲区 ,
                                    // 存放要显示数据                         
unsigned char led_Ctrl;
/*******************************************************
*     模块初始化
*******************************************************/
void init_LED(void){
    char tmpv;
    P3DIR  = 0xff;    // 设置 p3 输出  
    P3OUT  = 0x00;    // 设置 初始值为0
    P4DIR |= 0x03;    // 设置 p4.0,p4.1 输出
    P4OUT &= 0xfc;    // 设置初始值
    led_Ctrl = 0;     // led_Ctrl用于控制那个LED可显示
    for(tmpv=0;tmpv<LED_IN_USE;tmpv++)
    {                 // 初始化缓冲区
      led_Buf[tmpv] = 0;
    }
   
}
/****************************************************
*     LED 显示  ,该函数可以放到定时器中断中
****************************************************/
void led_Display(){                   
    unsigned tmp ;
     
      tmp    = 0x01;
      if(led_Ctrl==0x20)
      {
            P3OUT  = NUM_LED[led_Buf[led_Ctrl]] + 0x20;  // 设置显示值
      }else{
            P3OUT  = NUM_LED[led_Buf[led_Ctrl]];  // 设置显示值
      }
     
      P4OUT |= 0x02;                        // 打开数据锁存器
      P4OUT &= 0XFD;                        // 关闭数据锁存
      P3OUT  = ~(tmp<<led_Ctrl);            // 设置那只LED显示
      P4OUT  |= 0x01;                       // 打开控制锁存
      P4OUT  &= 0XFE;                       // 关闭控制锁存
      led_Ctrl= (led_Ctrl +1) % LED_IN_USE; // 设置下一个要显示的LED
     
}
[COLOR=#0000ff]欢迎发贴分享设计心得、开源DIY...[/COLOR]
Powered by LeadBBS 9.2 .
Page created in 0.3750 seconds with 5 queries.