主程序:
#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的初始化設置=========================================
函數名稱: void CAP_Init()
函數功能:定時器A捕獲設置,用于捕獲上升下降沿
函數參數:
=========================================================================================*/
void CloseWDTCTL()
{
WDTCTL=WDTPW+WDTHOLD; //關狗
}
void ClockInit()
{
BCSCTL1=CALBC1_1MHZ; //設置范圍,粗調
DCOCTL=CALDCO_1MHZ; //細調
}
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時鐘,continuous mode
TACCR1=0;
//TACTL&=~CCIFG;
}
void send_15us()//超聲波發送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; //也可進入睡眠,下面的發送高電平,就先在睡眠前發一次,以后就在中斷里面下降沿結束,以及數據處理完后再給它發,或者你干脆把TX接高電平好得很,一直發送,省事
while(1)
{
send_15us();
delay(100);
}
}
/*==================================TA的中斷服務程序=========================================
函數名稱: Timer_AISR
函數功能: 定時器A中斷服務子函數,捕獲待測信號上升沿,下降沿
函數參數:這里注釋下吧,CCR0單獨的占用了個中斷,好像是TIMER0_A0_VECTOR,其他的合著用,所以進入中斷后要判斷是CCR1,還是CCR2產生的中斷,也就是TAOIV或者TA1IV對應case :2 和4,另外如果你不訪問TAIV這個寄存器,那你產生的一些標志位就要你手動的軟件復位了,反之是硬件自己復位。由于捕獲是硬件捕獲的,測距比較準。
=========================================================================================*/
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TAIV_ISR(void)
{
switch(TA0IV)
{
case 2: //ccr1中斷向量
if (TACCTL1&CCI) //上升沿觸發
{
result1_start=CCR1;//記錄初始值
index=0;
break;
}
else
{
unsigned juli;
result1_end=CCR1; //記錄結束值
if(result1_end>result1_start)//結果比開始數值肖,表示溢出了一次或者幾次,但是一般從0開始計數的話是不溢出的,這超聲波實際測不了那么遠,最多有個4米,5米的樣子已經很好了
//TACTL|=TACLR;//這句貌似不需要
temp=result1_end-result1_start;
else
temp=result1_end+index*65535-result1_start;
distance=temp*0.0172;
juli=distance*10+0.5; //取一位小數,四舍五入
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; //溢出中斷向量,其實就2,4,10號向量有用那些手冊里也沒說,用不到
default :break;
}
// TACCTL1&=~COV;//有時候要這句,但是沒用好像也行
}
頭文件:
#ifndef LCD1602_H_
#define LCD1602_H_
#define CPU_F ((double)1000000) //萬能延時函數,修改這里的對應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 //數據線 (RW?)
#define ds_1 P2OUT|=BIT3
#define rs_0 P2OUT&=~BIT5
#define rs_1 P2OUT|=BIT5 //RS-->P2.5 RS為寄存器選擇,高電平時選擇數據寄存器、低電平時選擇指令寄存器。
#define en_0 P2OUT&=~BIT4
#define en_1 P2OUT|=BIT4 //EN-->P2.4 E端為使能端,當E端由高電平跳變成低電平時,液晶模塊執行命令。
#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(); //從右往左整屏移動
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給一個上升沿脈沖即可讀走一位
}
}
/*-----------lcd寫指令-------------------------------*/
void write_com(uchar com)
{
write_595(com);
rs_0;
delay(3);
//rw=0;
rclk_1;
delay(3);
rclk_0;
}
/*-----------lcd寫數據-------------------------------*/
void write_data(uchar date )
{
write_595(date); //寫入數據
rs_1;
delay(3);
rclk_1;
delay_us(10);
rclk_0; //令595輸出,并用en輸出一個高脈沖
}
void init_lcd()
{
Ctrl_data_Dir|=0x38; //定義的三個使能端為輸出端
en_0;
delay(1);
write_com(0x38);
delay(3);
write_com(0x38);
delay(3);
write_com(0x38);
delay(3);
write_com(0x0c);//開顯示
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秒移動一個
}
}
#endif /* LCD1602_H_ */
|