|
MSP430捕获模式+HCSR04超声模块=测距
[复制链接]
硬件准备:
1.MSP430G2553(Launchpad)
2.HCSR04超声模块
3.杜邦线若干
4.Nokia5110(如没有,可注释这些语句)
程序编写:
PUDN下载完整版工程(使用IAR5.3) 下载点这里
//IAR Assembler for MSP430
// 5.30.1 (5.30.1.50284)
//
// BY: Elitezhe
// Southeast University
// School of Instrument and Engineering
// Launchpad + HCSR04超声模块 测距离
// 连接图:
// ACLK = n/a, MCLK = SMCLK = 1MHZ
//
// MSP430F5438
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// |P1.4 P2.5|-->LCD_RST
// | P2.4|-->LCD_CE
// | P2.3|-->LCD_DC
// | P2.2|-->LCD_DIN
// | P2.1|-->LCD_CLK
// | |
// | P1.4|-->Trig
// | P1.2|-->Echo
// | |
// | |
#include "msp430g2553.h"
#include "5110/nokia_5110.h"
#include "stdio.h"
#define TRIG BIT4
#define ECHO BIT2 //P1.1 DIR.0=0 + SEL.1=1 + SEL2.1=0 --> TA0.CCI0A
#define USOUND_DIR P1DIR
#define USONUD_OUT P1OUT
#define USOUND_IE P1IE
#define USOUND_IES P1IES
#define USOUND_SEL P1SEL
unsigned int capV = 0;
float distance;
void BCSplus_init(void);
char str[100];
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
BCSplus_init();
LCD_init();
LCD_clear();
LCD_write_english_string(0,0,"USONIC DIS MEASURE");
//sprintf(str, "%x", 255);
LCD_write_english_string(0,1,"EliteZhe");
LCD_write_english_string(0,2,"-----------------");
LCD_write_english_string(0,3,"TIME:");
LCD_write_english_string(0,4,"DIST:");
USONUD_OUT |= TRIG;
USOUND_DIR |= TRIG;
//USOUND_IES |= ECHO;
USOUND_SEL |= ECHO ; //CCI0A
while(1)
{
TA0CTL |= MC_2 + TASSEL_2 + TACLR; //计数 SMCLK 清计数
TA0CCTL1 |= CM_1 + CAP + SCS + CCIE + CCIS_0;//上升沿捕获 捕获模式 同步模式 使能中断 CCI0A
USONUD_OUT |= TRIG;
// _NOP();_NOP();_NOP();_NOP();_NOP();
// _NOP();_NOP();_NOP();_NOP();_NOP();
// _NOP();_NOP();_NOP();_NOP();_NOP();
__delay_cycles(200);
USONUD_OUT &= ~TRIG;
//_BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt
while((TA0CCTL1 & CCIFG) ==0); //等待上升沿
TA0CTL &= ~MC_3; //清除MC_的两位,否则 CM_1 | CM_2 = CM_3
TA0CTL |= MC_2 + TACLR; //连续计数 清除TA的计数值
TA0CCTL1 &= ~CCIFG; //清中断标志
TA0CCTL1 |= CM_2; //下降沿捕捉
while((TA0CCTL1 & CCIFG) ==0); //等待下降沿
capV = TA0CCR1; //得到计数器的值
distance = 1.12826e-3 * capV ;//计算距离
sprintf(str,"%4x",capV);
LCD_write_english_string(30,3,str);
sprintf(str,"%.3f",distance);
LCD_write_english_string(30,4,str);
TA0CCTL1 &= ~CCIFG; //清中断标志
unsigned int x,y;
for(x=5000;x>0;x--)
for(y=500;y>0;y--);
}
return 0;
}
/****************************************
* ======== BCSplus_init ========
* Initialize MSP430 Basic Clock System
*/
//MCLK = SMCLK = 1MHZ
void BCSplus_init(void)
{
/*
* Basic Clock System Control 2
*
* SELM_0 -- DCOCLK
* DIVM_0 -- Divide by 1
* ~SELS -- DCOCLK
* DIVS_0 -- Divide by 1
* ~DCOR -- DCO uses internal resistor
*
* Note: ~ indicates that has value zero
*/
BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;
if (CALBC1_16MHZ != 0xFF) {
/* Adjust this accordingly to your VCC rise time */
__delay_cycles(100000);
/* Follow recommended flow. First, clear all DCOx and MODx bits. Then
* apply new RSELx values. Finally, apply new DCOx and MODx bit values.
*/
DCOCTL = 0x00;
BCSCTL1 = CALBC1_16MHZ; /* Set DCO to 16MHz */
DCOCTL = CALDCO_16MHZ;
}
/*
* Basic Clock System Control 1
*
* XT2OFF -- Disable XT2CLK
* ~XTS -- Low Frequency
* DIVA_0 -- Divide by 1
*
* Note: ~XTS indicates that XTS has value zero
*/
BCSCTL1 |= XT2OFF + DIVA_0;
/*
* Basic Clock System Control 3
*
* XT2S_0 -- 0.4 - 1 MHz
* LFXT1S_0 -- If XTS = 0, XT1 = 32768kHz Crystal ; If XTS = 1, XT1 = 0.4 - 1-MHz crystal or resonator
* XCAP_1 -- ~6 pF
*/
BCSCTL3 = XT2S_0 + LFXT1S_0 + XCAP_1;
}
遗留问题:
1.测距最大测到50CM左右, 距离更远就只能显示50左右了,怀疑是超声模块的问题,但手头没有其他超声模块可尝试.先搁置吧...
心得体会:
第一次使用MSP430的TIMERA的捕获模式,完全是依照Userguide和datasheet来操作,不得不说看这两个英文文档 ,收获很大,但是问题也很多,很多关键问题,它没有着重强调.很多表格也看不太明白,实在令我很抓狂....本来这个程序很简单,但是由于文档有些地方理解错误.导致浪费了好几个小时.唉,和TI这些大牛的思维模式果然不是一个层次..
1.寄存器在与操作的时候,千万记得先清除后相加.
诸如: TACTL0 |= MC_1 ;
如果此时,我想让TA以MC_2计数模式,也许会想当然地写上
TACTL0 |= MC_2 ;
殊不知,此时TACTL0的真实情况是 TACTL0 |= MC_2 ;
为什么呢?
其实很简单, MC_1 = 01 MC_2=10
TACTL0 |= MC_1 ;
TACTL0 |= MC_2 ;
两句合起来其实就是:
TACTL0 |= (MC_1 | MC_2) ; // 很显然 01|10 = 11
这些细节不注意真的会很惨!!!
2.在捕获模式的时候,TA计数最好选择连续模式(Continus).
为什么呢?
因为CCR0默认为0,通常用作捕获模式,不会去设置它.
那么增计数(UP)或者增减计数(UP-DOWN),都是计数到CCR0时,重新开始,
那么,TA0R的值永远只能是0了
3.关于捕获输入的IO的问题
其实在datasheet上写的很详细,只是它说的不清楚,让我误解了很久,也走了很多弯路...
P1.1/TA0.0可作为Timer0_A的CCI0A输入
P1.2/TA0.1可作为Timer0_A的CCI1A输入
本次我使用的P1.2的CCI1A功能
只需使
P1DIR.2=0
P1SEL.2 = 1
P1SEL2.2=0
便使能了P1.2捕获输入的功能了
对应的,便应该使用TA0CCTL1 ,并且其TA0CCTL1 |= CCIS_0;
即使用CCI0A,而不使用CCI0B或VCC或GND
总之,TA0CCTL1的IFG是由P1.2的捕获输入触发的
其他的引脚我并未测试,按照我的猜测,
应该是:
P1.1 -->T0A0.CCI0A-->TA0CCTL0.CCIS_0
P1.2-->T0A1.CCI1A-->TA0CCTL1.CCIS_0
P2.0-->T1A0.CCI0A-->TA1CCTL0.CCIS_0
P2.1-->T1A1.CCI1A-->TA1CCTL1.CCIS_0
P2.2-->T1A1.CCI1B-->TA1CCTL1.CCIS_1
P2.3-->T1A0.CCI0B-->TA1CCTL0.CCIS_1
P2.4-->T1A1.CCI2A-->TA1CCTL2.CCIS_0
P2.5-->T1A2.CCI2B-->TA1CCTL2.CCIS_1
未经测试,仅个人猜测,欢迎大家反馈.
|
赞赏
-
1
查看全部赞赏
-
|