主程序:
#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_ */
|