|
主程序:
#include<msp430g2553.h>
#include"lcd1602.h"
unsigned char table[]="0123456789";
unsigned int result1_start,result1_end;
unsigned char index=0;
unsigned int temp;
double distance;
unsigned char name[]="the juli";
unsigned char juli_cm[]="000.0cm";
/*==================================TA的初始化設(shè)置=========================================
函數(shù)名稱: void CAP_Init()
函數(shù)功能:定時(shí)器A捕獲設(shè)置,用于捕獲上升下降沿
函數(shù)參數(shù):
=========================================================================================*/
void CloseWDTCTL()
{
WDTCTL=WDTPW+WDTHOLD; //關(guān)狗
}
void ClockInit()
{
BCSCTL1=CALBC1_1MHZ; //設(shè)置范圍,粗調(diào)
DCOCTL=CALDCO_1MHZ; //細(xì)調(diào)
}
void PortInit()
{
P1DIR &=~BIT2; //P1.2,為輸入引腳
P1SEL |= BIT2; // P1.2 = (InputDirection + TA0.1) = CCIxA.1 --> CCR1,P1.2作為輸入,CCI1A,指定輸入
P2DIR|=BIT0; //P2.0,trig
}
void Timer1Init()
{
TACCTL1 = CAP + CCIS_0 + CM_3 + CCIE+SCS; // Capture CCIxA, both edge, interrupt enable.CCI1A->p1.2
TACTL |=TASSEL_2 + ID_0 + MC_2+ TAIE+TACLR ;//選擇1M-SMCLK時(shí)鐘,continuous mode
TACCR1=0;
//TACTL&=~CCIFG;
}
void send_15us()//超聲波發(fā)送15us的高電平
{
P2OUT&=~BIT0;
delay_us(20);
P2OUT|=BIT0;
delay_us(15);
P2OUT&=~BIT0;
}
void main(void)
{
CloseWDTCTL();
ClockInit();
init_lcd();
PortInit();
Timer1Init();
write_com(0x01) ; // 清屏
lcd_1602(first,0,name);
_EINT();
// LPM0; //也可進(jìn)入睡眠,下面的發(fā)送高電平,就先在睡眠前發(fā)一次,以后就在中斷里面下降沿結(jié)束,以及數(shù)據(jù)處理完后再給它發(fā),或者你干脆把TX接高電平好得很,一直發(fā)送,省事
while(1)
{
send_15us();
delay(100);
}
}
/*==================================TA的中斷服務(wù)程序=========================================
函數(shù)名稱: Timer_AISR
函數(shù)功能: 定時(shí)器A中斷服務(wù)子函數(shù),捕獲待測(cè)信號(hào)上升沿,下降沿
函數(shù)參數(shù):這里注釋下吧,CCR0單獨(dú)的占用了個(gè)中斷,好像是TIMER0_A0_VECTOR,其他的合著用,所以進(jìn)入中斷后要判斷是CCR1,還是CCR2產(chǎn)生的中斷,也就是TAOIV或者TA1IV對(duì)應(yīng)case :2 和4,另外如果你不訪問(wèn)TAIV這個(gè)寄存器,那你產(chǎn)生的一些標(biāo)志位就要你手動(dòng)的軟件復(fù)位了,反之是硬件自己復(fù)位。由于捕獲是硬件捕獲的,測(cè)距比較準(zhǔn)。
=========================================================================================*/
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TAIV_ISR(void)
{
switch(TA0IV)
{
case 2: //ccr1中斷向量
if (TACCTL1&CCI) //上升沿觸發(fā)
{
result1_start=CCR1;//記錄初始值
index=0;
break;
}
else
{
unsigned juli;
result1_end=CCR1; //記錄結(jié)束值
if(result1_end>result1_start)//結(jié)果比開(kāi)始數(shù)值肖,表示溢出了一次或者幾次,但是一般從0開(kāi)始計(jì)數(shù)的話是不溢出的,這超聲波實(shí)際測(cè)不了那么遠(yuǎn),最多有個(gè)4米,5米的樣子已經(jīng)很好了
//TACTL|=TACLR;//這句貌似不需要
temp=result1_end-result1_start;
else
temp=result1_end+index*65535-result1_start;
distance=temp*0.0172;
juli=distance*10+0.5; //取一位小數(shù),四舍五入
juli_cm[0]=table[juli/1000];
juli_cm[1]=table[juli%1000/100];
juli_cm[2]=table[juli%100/10];
juli_cm[4]=table[juli%10];
lcd_1602(second,0,juli_cm); //顯示
index=0; //溢出清零
break;
}
case 4: break;
case 10: index++;break; //溢出中斷向量,其實(shí)就2,4,10號(hào)向量有用那些手冊(cè)里也沒(méi)說(shuō),用不到
default :break;
}
// TACCTL1&=~COV;//有時(shí)候要這句,但是沒(méi)用好像也行
}
頭文件:
#ifndef LCD1602_H_
#define LCD1602_H_
#define CPU_F ((double)1000000) //萬(wàn)能延時(shí)函數(shù),修改這里的對(duì)應(yīng)MCLK頻率即可,如用CPU是8M的MCLK,你是就該為8000000吧
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
#define uint unsigned int
#define uchar unsigned char
//#define datadir P1DIR
//#define P1 P1OUT
#define Ctrl_data_Dir P2DIR
#define first 0x00
#define second 0x40
#define ds_0 P2OUT&=~BIT3 //數(shù)據(jù)線 (RW?)
#define ds_1 P2OUT|=BIT3
#define rs_0 P2OUT&=~BIT5
#define rs_1 P2OUT|=BIT5 //RS-->P2.5 RS為寄存器選擇,高電平時(shí)選擇數(shù)據(jù)寄存器、低電平時(shí)選擇指令寄存器。
#define en_0 P2OUT&=~BIT4
#define en_1 P2OUT|=BIT4 //EN-->P2.4 E端為使能端,當(dāng)E端由高電平跳變成低電平時(shí),液晶模塊執(zhí)行命令。
#define rclk_0 P2OUT&=~BIT4
#define rclk_1 P2OUT|=BIT4
#define sclk_0 P2OUT&=~BIT5
#define sclk_1 P2OUT|=BIT5
void init_lcd();
void write_595(uchar date);
void write_com(uchar com) ;
void write_data(uchar date );
void lcd_1602(uchar x,uchar y ,uchar *p);
void zuoyi(); //從右往左整屏移動(dòng)
void write_595(uchar date)
{
uchar i;
for(i=0;i<8;i++)
{
sclk_0;
if(date&0x80)
ds_1;
else
ds_0;
delay(4);
sclk_1;
date<<=1; //sclk給一個(gè)上升沿脈沖即可讀走一位
}
}
/*-----------lcd寫(xiě)指令-------------------------------*/
void write_com(uchar com)
{
write_595(com);
rs_0;
delay(3);
//rw=0;
rclk_1;
delay(3);
rclk_0;
}
/*-----------lcd寫(xiě)數(shù)據(jù)-------------------------------*/
void write_data(uchar date )
{
write_595(date); //寫(xiě)入數(shù)據(jù)
rs_1;
delay(3);
rclk_1;
delay_us(10);
rclk_0; //令595輸出,并用en輸出一個(gè)高脈沖
}
void init_lcd()
{
Ctrl_data_Dir|=0x38; //定義的三個(gè)使能端為輸出端
en_0;
delay(1);
write_com(0x38);
delay(3);
write_com(0x38);
delay(3);
write_com(0x38);
delay(3);
write_com(0x0c);//開(kāi)顯示
delay(3);
write_com(0x06);
delay(3);
// write_com(0x01);//清屏
// delay(5);
}
void lcd_1602(uchar x,uchar y,uchar *p)//lcd第一行顯示
{
init_lcd();
delay(5);
//write_com(0x01);//清屏
write_com(0x80+x+y);
while(*p!='\0')
{
write_data(*p++);
delay(5);
}
}
void zuoyi()
{
uchar num;
for(num=0;num<16;num++)
{
write_com(0x18);//左移
delay(500); //0.5秒移動(dòng)一個(gè)
}
}
#endif /* LCD1602_H_ */
|
|