目录
前言
一、超声波介绍
二、部分代码
三、总结
前言
哎,又双叒叕,电赛延期了,看起来像是遥遥无期,但是肯定要考虑大局,大家就继续抓紧时间学习知识,巩固自己的知识,更进一步。好了,今天主要是继承上一篇博文(OLED显示)写的,主要是写超声波测距的(US-015)
一、超声波介绍
利用TI公司的MSP430F5529单片机+超声波模块+OLED 实现
这里主要是利用单片机定时器的捕获功能来捕获超声波高电平持续时间,再计算得到距离,最后再在OLED 屏幕上显示出来,上图:
这里是把数字用了32号的,比较清晰,大家也可以自己更改
具体怎么接OLED 屏幕上一讲里面代码也有详细介绍,这里的超声波模块的Trig我接的是1.3,Echo接的是1.2
P1.2 为echo 设置为捕获模式
介绍:P1.2 具有端口中断的通用数字I / O ,TA0 CCR1捕获:CCI1A输入,比较:Out1输出 BSL接收输入
P1.3 为Trig 设置为 数字i/o模式
介绍:P1.3 具有端口中断的通用数字I / O , TA0 CCR2捕获:CCI2A输入,比较:Out2输出
二、部分代码
超声波模块初始化
void US_015_Init(void)
{
P1OUT &= ~( BIT2 + BIT3 );
P1DIR |= BIT3;
P1SEL |= BIT2;
TA0CTL = TASSEL__SMCLK + ID__8 + MC_2 + TACLR + TAIE;
TA0CCTL1 = CM_1 + SCS +CAP + CCIE + CCIS_0;
}
void Hc_sr_Open(void) //生成一个持续10us的高电平
{
Trig1(1);//这里就是把P1.2置1,即P1OUT |= BIT2
__delay_cycles(250);//这里我把系统时钟升为25MHZ,因此250/25000000=10us
Trig1(0);置0
}
我们选用的是P1.2, 根据端口定义,使用的是TA0CCR1,捕获输入引脚通过TA0CCTL1寄存器控制,捕获值存储在TA0CCR1中。
TASSEL(时钟源选择):SMCLK; ID分频(下面介绍):(这里分频系数会影响后面计算)4MHz/8 = 500k;计数模式:0 ==> 0xFFFF; 定时器清零位 ;中断使能。
TA0CCTL1:上升沿捕获 ;同步捕捉;捕获模式;中断使能;CCI1A输入。
(这里查了一下SCS和CAP都有两种模式,但是这里直接就是把寄存器代码搞上去,没有分出0和1两种模式,这里搞不太懂,哪位大佬解惑解惑?)
这里ID分频有两种写法,但是总共有四种分频:
MC的四种模式:停止、增加模式、连续上升、增减模式
CM的四种模式:不捕获、上升沿捕获、下降沿捕获、上升下降都捕获
原理:这里其实就是复用P1.2口为捕获,通过P1.3发出一个10us的高电平给超声波TRIG口触发进行测距,模块内部就返回一个信号,P1.2就捕获一个返回的高电平持续时间,再计算得出距离
公式:s=高电平持续时间*声速340/2(因为上面分频采用了8分频,因此我下面计算就不用除以2)
定时中断函数:
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch(__even_in_range(TA0IV,14))//采用这个range函数就是为了使switch函数效率高
{
case 0:break; // No interrupt
case 2:
state = TA0CCTL1 >> 14;
TA0CCTL1 &= ~CCIFG;//标志位清零
if( TA0CCTL1 & CM_1){//开始捕获高电平时间
cap_new = TA0CCR1;
TA0CCTL1 &= ~CM_1;
TA0CCTL1 |= CM_2;
}else if ( TA0CCTL1 & CM_2){
cap_old = TA0CCR1;
cap_data = ( cap_old - cap_new ) * 0.34/10/6.25;//这里外面解释!
Gui_DrawFont_Num32(10,50,BLUE,GRAY0,cap_data/100);//显示数字
Gui_DrawFont_Num32(37,50,BLUE,GRAY0,cap_data/10%10);
Gui_DrawFont_Num32(64,50,BLUE,GRAY0,cap_data%10);
TA0CCTL1 &= ~CM_2;
TA0CCTL1 |= CM_1;
}else
break; // CCR1 not used
case 4: break; // CCR2 not used
case 6: break; // reserved
case 8: break; // reserved
case 10: break; // reserved
case 12: break; // reserved
case 14:
TA0CTL &= ~TAIFG;
if(cap_old < cap_new ){
cap_N += 1;
}
break; // overflow
default: break;
}
}
这里其实都挺好理解的,就是大家可能对那个cap_data计算不太理解,首先为什么不除以2,是因为上面分频系数为8,(如果改为4,那么就应该除以2了),具体我也是测试出来的,至于为啥我觉得可能是分频系数为4时分频后频率为1MHZ,这样分频速率是最为正确的,但是8分频后为500KHZ就影响了原有的,相当于除以2了,哪位大佬可以帮忙解答哈哈,MSP430F5529我研究不是很长哈哈。然后后面除以10是因为计算的结果是MM为单位,我这里是以CM为单位,因此除以10;除以6.25是因为我升的时钟频率为25MHZ,跟原先的定时器4MHZ不对应,因此要换算即25/4=6.25,因此除以6.25。
最后面主函数:
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
upVcc();//升压
timerup();//时钟频率升为25MHZ
Lcd_Init();
LCD_LED_SET;//通过IO控制背光亮
Lcd_Clear(WHITE); //清屏
Hc_sr_Init();
__bis_SR_register(GIE);//开启中断
Gui_DrawFont_GBK16(10,0,BLUE,GRAY0,"电子2班");
Gui_DrawFont_GBK16(10,20,BLUE,GRAY0,"Dis:");
Gui_DrawFont_GBK24(100,60,BLUE,GRAY0,"CM");
while(1){
Hc_sr_Open();
__delay_cycles(1000000);
}
}
对了,漏了一些声明
#define Trig1(a) if(a==1) P1OUT |= BIT3; else P1OUT &= ~BIT3
unsigned int cap_new = 0; // 首次捕捉的ta0r值
unsigned int cap_old = 0; // 第二次捕捉的ta0r值
char cap_N = 0; // 溢出次数
char state = 0x00; // 状态
u16 cap_data ; // 距离值,u16
三、总结
到这里你可能对超声波测距有一个概念了,但是不够,一定要亲自上手实验,多琢磨,不要贪图省事,这样对你没有好处。
其实这里无非就是对定时器的应用,然后一些测量结果可能会出现误差,这是无法避免的,但是大体上影响不大,如果你不追求高精度测距和长距离测距的话,那么超声波测距是很好的选择!
这里我也是才学习这款单片机不久,有哪里写的不好的请见谅,有错误可以随时指正,欢迎大家踊跃评论,一起探讨交流,一起进步,谢谢!
题外话
挺喜欢彭于晏说的一句话:“我就是没有才华,所以才用命去拼!”文章来源:https://www.toymoban.com/news/detail-620042.html
学习32之路固然辛苦,但要是坚持下来了,那不是很酷?哈哈哈文章来源地址https://www.toymoban.com/news/detail-620042.html
到了这里,关于电赛MSP430F5529之超声波测距+OLED 显示(含主要代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!