本实验是基于MSP430利用HC-SR04超声波传感器进行测距,测距范围是3-65cm,讲得到的数据显示在LCD 1602液晶屏上。
#include "msp430x14x.h"
#include "Config.h"
#include "1602.c"
#include "UART.h"
#define uchar unsigned char
#define uint unsigned int
/***************端口定义*******************************/
#define trig_H P2OUT|=BIT0 //触发端口
#define trig_L P2OUT&=~BIT0
#define echo P2IN & BIT1 //接收端口
uint cnt;
unsigned long int tim_data,dista_data,dista_data_all,dista_data_sum,count=0;
/***************延时*******************************/
void delay(uint n)
{
uchar i;
for(;n>0;n--)
for(i=10;i>0;i--);
}
/********************滤波,取十次数据平均值***************/
void dista_f(unsigned long int distance_data)
{
dista_data_all=dista_data_all+distance_data;
cnt=cnt+1;
if(cnt==16)
{
cnt=0;
dista_data_sum=dista_data_all>>4;
dista_data_all=0;
LCD1602_write_double(13,1,dista_data_sum); //在1602上显示距离
LCD1602_write_char(14,1,'m');
LCD1602_write_char(15,1,'m');
}
}
/**************初始化io口********************/
void Init_IO()
{
P2DIR = 0XFD;
P2OUT |= 0XFF;
P2IE |= BIT1; //打开P2端口中断
P2IES &=~BIT1; //设置为上升沿中断
}
/**************初始化定时器******************/
void Init_Timer()
{
TACTL|=TACLR+TASSEL_2+ID_3; //定时器A初始化
}
void InitTimerB()
{
TBCTL=TBSSEL1+ID1+ID0+MC0+TBCLR;//选择1/8SMCLK 增计数 清除TAR
TBCCTL0=CCIE;//CCR0中断允许 比较模式
TBCCR0=10000;//时间间隔10ms
}
/************主函数**************************/
//端口的初始化
void main( void )
{
WDTCTL = WDTPW + WDTHOLD;
InitTimerB();//关闭开门狗
Clock_Init(); //时钟初始化
Init_IO(); //初始化IO
Start_1602(); //打开1602
tim_data=0;cnt=0;dista_data=0;
delay(1000);
UART_Init();//间隔延迟
uchar string[] = "distance:";
LCD1602_write_str(0, 0, string);
_EINT(); //打开总中断
while(1)
{
trig_H; //开启高电平
delay(2); //持续15us
trig_L; //关闭高电平
delay(50); //等待触发
while(echo); //等待触发
delay(1000); //间隔延迟
}
}
/*****************************P2口中断*******************/
#pragma vector=PORT2_VECTOR
__interrupt void port_init(void)
{
if(echo) //上升沿中断
{
TACTL|=TACLR+TASSEL_2+ID_3;
TACTL|=MC_2; //接收到信号,打开计数器开始计数
P2IES|=BIT1; //改为P2口下降沿中断
}
else //下降沿中断
{
TACTL=0; //计数结束,停止计数
TACTL|=TASSEL_2+ID_3;
P2IES&=~BIT1; //改为P2口上升沿中断
tim_data=TAR; //取计数值
dista_data=(tim_data*1000/58); //计算为距离(厘米=us/58)
// dista_data=(tim_data*17/100);
dista_f(dista_data); //取十次平均值
}
P2IFG&=~BIT1; // P2口中断标志清除
}
#pragma vector=TIMERB0_VECTOR
__interrupt void TimerBINT()
{
count++;
if(count==300)
{
count=0;
Print_float(dista_data_sum,2);
}
}
/*****************************Config.h*******************/
/******************************************************************** //DM430-L型最小系统板外部资源配置文件Config.h //包含板载各个资源的硬件配置,如果用户使用过程中,对应的硬件发生了更改,可利用该头文件更改使用 //SD/MMC卡初始化硬件配置未包含 //调试环境:EW430 V5.30 //作者:www.avrgcc.com //时间:2014.03.01 ********************************************************************/ //延时函数,IAR自带,经常使用到 #define CPU_F ((double)8000000) //外部高频晶振8MHZ //#define CPU_F ((double)32768) //外部低频晶振32.768KHZ #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) //自定义数据结构,方便使用 #define uchar unsigned char #define uint unsigned int #define ulong unsigned long //8个LED灯,连接在P6口,可通过断开电源停止使用,ADC使用时断开电源 #define LED8DIR P6DIR #define LED8 P6OUT //P6口接LED灯,8个 //4个独立按键连接在P10~P13 #define KeyPort P1IN //独立键盘接在P10~P13 //串口波特率计算,当BRCLK=CPU_F时用下面的公式可以计算,否则要根据设置加入分频系数 #define baud 9600 //设置波特率的大小 #define baud_setting (uint)((ulong)CPU_F/((ulong)baud)) //波特率计算公式 #define baud_h (uchar)(baud_setting>>8) //提取高位 #define baud_l (uchar)(baud_setting) //低位 //RS485控制管脚,CTR用于控制RS485处于收或者发状态 #define RS485_CTR1 P5OUT |= BIT2; //控制线置高,RS485发送状态 #define RS485_CTR0 P5OUT &= ~BIT2; //控制线置低,RS485接收状态 //2.8寸TFT彩屏显示控制相关硬件配置 #define RS_CLR P5OUT &= ~BIT5 //RS置低 #define RS_SET P5OUT |= BIT5 //RS置高 #define RW_CLR P5OUT &= ~BIT6 //RW置低 #define RW_SET P5OUT |= BIT6 //RW置高 #define RD_CLR P5OUT &= ~BIT7 //E置低 #define RD_SET P5OUT |= BIT7 //E置高 #define CS_CLR P5OUT &= ~BIT0 //CS置低 #define CS_SET P5OUT |= BIT0 //CS置高 #define RST_CLR P5OUT &= ~BIT3 //RST置低 #define RST_SET P5OUT |= BIT3 //RST置高 #define LE_CLR P5OUT &= ~BIT1 //LE置低 #define LE_SET P5OUT |= BIT1 //LE置高 //2.8寸TFT彩屏触摸屏控制相关硬件配置 #define PEN_CLR P2OUT &= ~BIT0 //PEN置低,触碰触摸屏时,Penirq引脚由未触摸时的高电平变为低电平 #define PEN_SET P2OUT |= BIT0 //PEN置高 #define PEN (P2IN & 0x01) //P2.0输入的值 #define TPDO_CLR P2OUT &= ~BIT1 //TPDO置低 #define TPDO_SET P2OUT |= BIT1 //TPDO置高 #define TPDOUT ((P2IN>>1)&0x01) //P2.1输入的值 #define BUSY_CLR P2OUT &= ~BIT3 //BUSY置低 #define BUSY_SET P2OUT |= BIT3 //BUSY置高 #define TPDI_CLR P2OUT &= ~BIT4 //TPDI置低 #define TPDI_SET P2OUT |= BIT4 //TPDI置高 #define TPCS_CLR P2OUT &= ~BIT5 //TPCS置低 #define TPCS_SET P2OUT |= BIT5 //TPCS置高 #define TPCLK_CLR P2OUT &= ~BIT6 //TPCLK置低 #define TPCLK_SET P2OUT |= BIT6 //TPCLK置高 //彩屏/12864液晶/1602液晶的数据口,三液晶共用 #define DataDIR P4DIR //数据口方向 #define DataPort P4OUT //P4口为数据口 //12864/1602液晶控制管脚 #define RS_CLR P5OUT &= ~BIT5 //RS置低 #define RS_SET P5OUT |= BIT5 //RS置高 #define RW_CLR P5OUT &= ~BIT6 //RW置低 #define RW_SET P5OUT |= BIT6 //RW置高 #define EN_CLR P5OUT &= ~BIT7 //E置低 #define EN_SET P5OUT |= BIT7 //E置高 #define PSB_CLR P5OUT &= ~BIT0 //PSB置低,串口方式 #define PSB_SET P5OUT |= BIT0 //PSB置高,并口方式 #define RST_CLR P5OUT &= ~BIT1 //RST置低 #define RST_SET P5OUT |= BIT1 //RST置高 //12864应用指令集 #define CLEAR_SCREEN 0x01 //清屏指令:清屏且AC值为00H #define AC_INIT 0x02 //将AC设置为00H。且游标移到原点位置 #define CURSE_ADD 0x06 //设定游标移到方向及图像整体移动方向(默认游标右移,图像整体不动) #define FUN_MODE 0x30 //工作模式:8位基本指令集 #define DISPLAY_ON 0x0c //显示开,显示游标,且游标位置反白 #define DISPLAY_OFF 0x08 //显示关 #define CURSE_DIR 0x14 //游标向右移动:AC=AC+1 #define SET_CG_AC 0x40 //设置AC,范围为:00H~3FH #define SET_DD_AC 0x80 //设置DDRAM AC #define FUN_MODEK 0x36 //工作模式:8位扩展指令集 //颜色代码,TFT显示用 #define White 0xFFFF //显示颜色代码 #define Black 0x0000 #define Blue 0x001F #define Blue2 0x051F #define Red 0xF800 #define Magenta 0xF81F #define Green 0x07E0 #define Cyan 0x7FFF #define Yellow 0xFFE0 //NRF2401模块控制线 #define RF24L01_CE_0 P1OUT &=~BIT5 //CE在P15 #define RF24L01_CE_1 P1OUT |= BIT5 #define RF24L01_CSN_0 P2OUT &=~BIT7 //CS在P27 #define RF24L01_CSN_1 P2OUT |= BIT7 #define RF24L01_SCK_0 P3OUT &=~BIT3 //SCK在P33 #define RF24L01_SCK_1 P3OUT |= BIT3 #define RF24L01_MISO_0 P3OUT &=~BIT2 //MISO在P32 #define RF24L01_MISO_1 P3OUT |= BIT2 #define RF24L01_MOSI_0 P3OUT &=~BIT1 //MOSI在P31 #define RF24L01_MOSI_1 P3OUT |= BIT1 #define RF24L01_IRQ_0 P1OUT &=~BIT4 //IRQ在P14 #define RF24L01_IRQ_1 P1OUT |= BIT4 //DS18B20控制脚,单脚控制 #define DQ_IN P1DIR &= ~BIT7 //设置输入,DS18B20接单片机P53口 #define DQ_OUT P1DIR |= BIT7 //设置输出 #define DQ_CLR P1OUT &= ~BIT7 //置低电平 #define DQ_SET P1OUT |= BIT7 //置高电平 #define DQ_R P1IN & BIT7 //读电平 //红外接收头H1838控制脚,单脚控制 #define RED_IN P1DIR &= ~BIT6 //设置输入,红外接收头接单片机PE3口 #define RED_OUT P1DIR |= BIT6 //设置输出 #define RED_L P1OUT &= ~BIT6 //置低电平 #define RED_H P1OUT |= BIT6 //置高电平 #define RED_R (P1IN & BIT6) //读电平 //*********************************************************************** // 系统时钟初始化,外部8M晶振 //*********************************************************************** void Clock_Init() { uchar i; BCSCTL1&=~XT2OFF; //打开XT2振荡器 BCSCTL2|=SELM1+SELS; //MCLK为8MHZ,SMCLK为8MHZ do{ IFG1&=~OFIFG; //清楚振荡器错误标志 for(i=0;i<100;i++) _NOP(); } while((IFG1&OFIFG)!=0); //如果标志位1,则继续循环等待 IFG1&=~OFIFG; } //*********************************************************************** // 系统时钟初始化,内部RC晶振 //*********************************************************************** void Clock_Init_Inc() { uchar i; // DCOCTL = DCO0 + DCO1 + DCO2; // Max DCO // BCSCTL1 = RSEL0 + RSEL1 + RSEL2; // XT2on, max RSEL DCOCTL = 0x60 + 0x00; //DCO约3MHZ,3030KHZ BCSCTL1 = DIVA_0 + 0x07; BCSCTL2 = SELM_2 + DIVM_0 + SELS + DIVS_0; } //*********************************************************************** // 系统时钟初始化,外部32.768K晶振 //*********************************************************************** void Clock_Init_Ex32768() { uchar i; BCSCTL2|=SELM1 + SELM0 + SELS; //MCLK为32.768KHZ,SMCLK为8MHZ do{ IFG1&=~OFIFG; //清楚振荡器错误标志 for(i=0;i<100;i++) _NOP(); } while((IFG1&OFIFG)!=0); //如果标志位1,则继续循环等待 IFG1&=~OFIFG; } //*********************************************************************** // MSP430内部看门狗初始化 //*********************************************************************** void WDT_Init() { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 }
/*****************************1602.c*******************/
#include <msp430x14x.h> //************************************************************************* // 初始化IO口子程序 //************************************************************************* void LCD1602Port_init() { P4SEL = 0x00; P4DIR = 0xFF; //数据口输出模式 P5SEL = 0x00; P5DIR|= BIT5 + BIT6 + BIT7; //控制口设置为输出模式 } //*********************************************************************** // 显示屏命令写入函数 //*********************************************************************** void LCD1602_write_com(unsigned char com) { RS_CLR; RW_CLR; EN_SET; DataPort = com; //命令写入端口 delay_ms(5); EN_CLR; } //*********************************************************************** // 显示屏数据写入函数 //*********************************************************************** void LCD1602_write_data(unsigned char data) { RS_SET; RW_CLR; EN_SET; DataPort = data; //数据写入端口 delay_ms(5); EN_CLR; } //*********************************************************************** // 显示屏清空显示 //*********************************************************************** void LCD1602_clear(void) { LCD1602_write_com(0x01); //清屏幕显示 delay_ms(5); } //*********************************************************************** // 显示屏字符串写入函数 //*********************************************************************** void LCD1602_write_str(unsigned char x,unsigned char y,unsigned char *s) { if (y == 0) { LCD1602_write_com(0x80 + x); //第一行显示 } else { LCD1602_write_com(0xC0 + x); //第二行显示 } while (*s) { LCD1602_write_data( *s); s ++; } } //*********************************************************************** // 显示屏单字符写入函数 //*********************************************************************** void LCD1602_write_char(unsigned char x,unsigned char y,unsigned char data) { if (y == 0) { LCD1602_write_com(0x80 + x); //第一行显示 } else { LCD1602_write_com(0xC0 + x); //第二行显示 } LCD1602_write_data( data); } //*********************************************************************** // 显示屏初始化函数 //*********************************************************************** void LCD1602_init(void) { LCD1602_write_com(0x38); //显示模式设置 delay_ms(5); LCD1602_write_com(0x08); //显示关闭 delay_ms(5); LCD1602_write_com(0x01); //显示清屏 delay_ms(5); LCD1602_write_com(0x06); //显示光标移动设置 delay_ms(5); LCD1602_write_com(0x0C); //显示开及光标设置 delay_ms(5); } void LCD1602_write_double(unsigned char x,unsigned char y,unsigned int data) { uchar i; for(i=0;i<6;i++) { if(i==2) LCD1602_write_char( x--, y, '.'); else { LCD1602_write_char( x--, y, 0x30+data%10); data=data/10; } } } void LCD1602_write_int(unsigned char x,unsigned char y,unsigned int data) { uchar i; for(i=0;i<2;i++) { LCD1602_write_char( x--, y, 0x30+data%10); data=data/10; } } void Start_1602() { LCD1602Port_init(); //系统初始化,设置IO口属性 delay_ms(100); //延时100ms LCD1602_init(); //液晶参数初始化设置 }
/*****************************UART.h*******************/
#ifndef _UART_H_ #define _UART_H_ #include "msp430x14x.h" void Print_Str(uchar *s); //************************************************************************* // MSP430????? //************************************************************************* void UART_Init() { U0CTL|=SWRST + CHAR; //??SWRST,8????? U0TCTL|=SSEL1; //SMCLK????? U0BR1=baud_h; //BRCLK=8MHZ,Baud=BRCLK/N U0BR0=baud_l; //N=UBR+(UxMCTL)/8 U0MCTL=0x00; //??????0,???9600bps ME1|=UTXE0; //UART0???? ME1|=URXE0; //UART0???? U0CTL&=~SWRST; IE1|=URXIE0; //??????? P3SEL|= BIT4 + BIT5; //??IO????????,??UART??p3.4 p3.5 P3DIR|= BIT4; //??TXD0?????? } //************************************************************************* // ??0?????? //************************************************************************* void Send_Byte(uchar data) { while(!(IFG1&UTXIFG0)); //????????????? U0TXBUF=data; } //***************************************// void Print_float(unsigned int t, unsigned char position)//????? position ??????? { unsigned int s_int[5] = {0}; int i = 0; while(t>0) { s_int[i++] = t%10; t=t/10; } for(i=4;i>=0;i--) { if(i==position) { Send_Byte(0x30 + s_int[i]); Send_Byte(0x2E); } else { Send_Byte(0x30 + s_int[i]); } } //delay_ms(100); Send_Byte('m'); Send_Byte('m'); Send_Byte(' '); delay_ms(100); } //************************************************************************* // ??0??int??? //************************************************************************* void Print_int(unsigned int t) { unsigned int s_int[5]; unsigned int i = 1; while(t>0) { s_int[i] = t%10; t=t/10; i++; } i--; while(i) { Send_Byte(0x30 + s_int[i]); i--; } } //************************************************************************* // ??0??????? //************************************************************************* void Print_Str(uchar *s) { while(*s != '\0') { Send_Byte(*s++); } } #endif