“斜度计”设计,以下是他的源程序,提供微控会员参考。
可以参考<<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
}