物联网实训Day 05-倒车雷达

  • CC2530 + HC-SR04

  • 结合超声波模块及Timer1定时器实现超声波测距(倒车雷达)

一、(完整代码)

  • buzzer.h
#include <ioCC2530.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define buzzer P2_0



uchar time, count,t3count;//用于定时器计数

//单片机晶振采用32MHz   Tcy = 256 * (1/16000000)=16us;
// 频率周期数据表 
__code const uchar FREQL[] = {1, //0的时候没有音符
239, 213, 189, 179, 159, 142, 127, //低音1234567  3.817ms 3.401ms 3.030ms 2.858ms 2.552ms 2.273ms 2.024ms
119, 106, 95, 90, 80, 71, 63, 60,//1,2,3,4,5,6,7,i  1.908ms 1.700ms 1.514ms 1.432ms  1.276ms 1.136ms 1.012ms 0.955ms
53, 48, 45, 40, 36, 32, //高音 234567  0.852ms  0.759ms 0.717ms 0.638ms 0.568ms 0.506ms
30, 27, 24, 22, 20, 18, 16}; //超高音 1234567 0.478ms  0.426ms  0.379ms  0.358ms  0.319ms   0.284ms   0.253ms




/******蜂鸣器输出初始化******/
void Buzzer_Init(void)
{
  P2DIR |= 0x01;    //P2_0定义为输出
  buzzer = 1;
}

/**************每次发出的声音*****************/
__code const uchar voice[]={
5,3,1,0,0,0
};

/******中断初始化****/
void InitT3()
{     
      T3CTL |= 0x08 ;             //开溢出中断     
      T3IE = 1;                   //开总中断和T3中断
      T3CTL&=~0xE0;               //1分频,Tcy = 256 * (1/16000000)=16us; 其中256是timer3 装满一次是256步
      T3CTL &= ~0X03;            //自动重装 00->0xff  
      EA = 1; 
}
/********延时********/
void delay1(uint n)
{
	uint tt;
	for(tt = 0;tt<n;tt++);
	for(tt = 0;tt<n;tt++);
	for(tt = 0;tt<n;tt++);
	for(tt = 0;tt<n;tt++);
	for(tt = 0;tt<n;tt++);
}

/*********延时程序,控制发音的时间长度(1/4拍)*************/

void delay(uchar t) 
{


    uchar t1;
    ulong t2;
    for(t1 = 0; t1 < t; t1++)    //双重循环, 共延时t个半拍
      for(t2 = 0; t2 < 100; t2++); //延时期间
    T3CTL &=~0x10;               //关闭timer3, 停止发音
}
/****************演奏一个音符*****************/
void singachar() 
{
  T3CTL &=~0x10;               //关闭timer3
  count = t3count;             //控制音调
  T3CTL |=0X10;             //启动, 由timer3输出方波去发音
  delay(time);
  delay(2);
  //控制时间长度即 节拍
}

/**************发音***********************************/
void song(uchar const __code *str)
{
  uchar k,i;
  i = 0;
  time = 1;
  while(time)
  {
    k = str[i] + 7 * (str[i + 1]);//第i个是音符, 第i+1个是第几个八度
                        //从数据表中读出频率数值
    t3count = FREQL[k]; //实际上, 是定时的时间长度
    time = str[i + 2]; //读出时间长度数值 节拍时间
    i += 3;
    
    singachar();
  }
}
/********发音模式选择***********

模式一 快速的短鸣
模式二 有停顿的短鸣
模式三 长鸣
********************************/
void play(int i)
{
  //int msec = 1000;
  Buzzer_Init();    //初始化IO
  InitT3();
  if(i==1) //模式一
  {
    uint i;
    for (i=0; i<2; i++)
        
          {
              song(voice);//播放声音
           }
    
  }
  if(i==3) //模式三
  {
    uint m,n;
      for (m=0; m<2; m++)
        for (n=0; n<2; n++)
        {
         // if((IRCON &0x08) =0x08 )
         // {
         //   buzzer = ~buzzer;
         // }
                buzzer = 0;
                delay1(10);
                buzzer = 1;
                delay1(10);
         }
  }
  if(i==2) //模式二
  {
    uint k;//,l
      for (k=0; k<2;k++)
              {
                song(voice);
                delay(5);
              }
  }
}
/*
void main(void)
{
  
    while(1)
  {
    play(3);
  }

}
*/
/*******中断处理*********/
#pragma vector = T3_VECTOR 
 __interrupt void T3_ISR(void)  //timer3中断处理
 { 
        IRCON = 0x00;                  //清中断标志, 也可由硬件自动完成 
        if(--count == 0)                
        {         
         T3CTL &=~0X10;             //关闭timer3
         buzzer = ~buzzer;          //输出方波, 发音
         T3CTL |=0X10;             //启动
         count = t3count;          //下次的中断时间, 这个时间, 控制音调高低
        } 
        
 }
  • Radar_ranging.c
#include<iocc2530.h>
#include<string.h>
#include "buzzer.h"
#define ECHO P0_0               //ECHO引脚接在P0_0脚
#define TRIG P0_1               //TRIG引脚接在P2_0脚
//#define Buzzer P2_0              //蜂鸣器引脚

unsigned int count_Time;        //用于存放计数值
float  distance;                //存放距离值,float型提高测距精度
unsigned char count_TimeH;      //用于存放计数值高8位
unsigned char count_TimeL;      //用于存放计数值低8位
char buf[10];                   //存放串口发送数据
float D;

/*延时1us函数*/
void delay_1us(int m){
  while(m--){
  asm("NOP");
  asm("NOP");
  asm("NOP");
  }
}
/*延时1ms函数*/
void delayms(unsigned int ms)
{
  unsigned int i, j;
  for(i = ms; i > 0; i--)
    for(j = 578; j > 0; j--);
}
/*时钟初始化*/
void clk_Init(){
   CLKCONCMD &= ~0X40;          //设置第6位OSC系统时钟源为32MHZ晶振
   while(CLKCONSTA & 0x40);     //等待晶振稳定   
   CLKCONCMD &= ~0x3f;          //设置系统主时钟为32MHZ,定时器标记输出设置为32MHZ,时钟速度32MHZ         
}
/*串口初始化*/
void usart_Init(){
  PERCFG &= ~0x01;               //USART0备用位置1
  P0SEL |= 0x0c;                 //P0_2-P0_3为外设
  P2DIR &= ~0xc0;                //端口0外设优先级配置
  U0CSR |= 0X80;                 //设置为UART模式
  U0GCR |= 11;                   //设置波特率为115200
  U0BAUD |= 216;
  UTX0IF = 0;
}
/*I/O初始化*/
void io_Init(){
P0SEL &= ~0x02;                //P0_1作为通用I/O
P0DIR |= 0X02;                 //P0_1作为输出口
P0SEL &= ~0x01;                //P0_0作为通用I/O
P0DIR &= ~0X01;                //P0_0作为输入口
//P2SEL |= 0x01;               //
//P2DIR |= 0x01;                 //
//Buzzer = 1;                    //

//P0IF = 0;                       //清除端口0中断标志
//P0IE = 1;                       //允许P0口中断
P0IFG = 0x00;                    //*P0中断标志清零P35
//P0INP &= ~0X00;                 //*P0_0上拉或下拉
P0IEN |= 0x01;                 //开启P0_0外部中断
PICTL |= 0x01;                 //P0下降沿中断
IRCON = 0x00;                 //设置P0无端口未决
IEN1 |= 0x20;                  //*设置P0中断使能P38
EA = 1;                        //*开总中断
}
/*定时器1初始化*/
void timer1_Init(){
  T1CTL &= ~0x03;              //停止运行
  T1CTL |= 0X0c;               //设置为128分频
  T1CNTH = 0x00;
  T1CNTL = 0x00;
}
/*HC_RS04初始化*/
void hc_sr04_Init(){
  TRIG = 1;
  delay_1us(20);
  TRIG = 0;
  while(!ECHO);
  T1CTL |= 0x01;                      //开始自由运行模式
}
/*串口发送函数*/
void send(char *s){
  while(*s!='\0'){
  	U0DBUF= *s++;
 	while(UTX0IF == 0);               //等待标志位置1,为1时,表示当前字节发送完了
    UTX0IF = 0; 
  }
}
/*P0口中断*/
#pragma vector = P0INT_VECTOR
__interrupt void P0_isr(){
    if(P0IFG&0x01){                    //判断是否是P0_0中断
	  T1CTL &= ~0x03;                //停止T1运行
	  P0IF = 0;                      //清除端口0中断标志
	  P0IFG &= ~0x01;                //清除P0_0中断状态标志
	  count_TimeH = T1CNTH;          //取出定时器 1 计数器高位
	  count_TimeL = T1CNTL;          //取出定时器 1 计数器低位
  }
}

int main(){
  clk_Init();
  io_Init(); 
  usart_Init();
 // P1SEL |= 0x04;
 // P1DIR |= 0x04;     //P1_2定义为输出
 // Buzzer = 0;
  Buzzer_Init();
  int cnt=0;
  int sum=0;
  float temp=1000;
 // InitT3();         //
 // singachar();      //
  while(1){
          cnt++;
	  timer1_Init();                  //定时器初始化
	  hc_sr04_Init();                 //HC_SR04初始化
	//  delayms(10);
	  count_Time = count_TimeH*256+count_TimeL;//计算定时器1计数值
	  distance = count_Time*0.068;             //计算距离
          D = distance;
          if(cnt<=5)
          {
            sum+=D;
          }
          if(cnt>5)
          {
            sum/=5;
            temp=sum;
            sum=0;
            cnt=0;
             /*将浮点数转为字符串,便于发送(这里只保留了两位小数)*/
	  buf[0] = (unsigned int)temp/100+48;
	  buf[1] = (unsigned int)distance%100/10+48;
	  buf[2] = (unsigned int)distance%10+48;
	  buf[3] = '.';
	  buf[4] = (unsigned int)(distance*10)%10+48;
	  buf[5] = (unsigned int)(distance*100)%10+48;
	  buf[6] = '\n';
	  send(buf);
	  memset(buf,0,10);
          //清空数组
          }
          if(0<temp && temp<20)
          {
         //   Buzzer=0;
         //   delay_1us(10);
         //   Buzzer=1;
            buzzer = 0;
            delay_1us(50);
          }
           if(20<=temp && temp<60)
          {
          //  Buzzer=0;
          //  delay_1us(5);
          //  Buzzer=1;
          //  delay_1us(5);
            buzzer = 1 ;
            delay_1us(800);
            buzzer = 0;
            delay_1us(800);
          }
           else if(temp>60 && temp<100){
           
          //  Buzzer=0;
          //  delay_1us(10);
          //  Buzzer=1;
          //  delay_1us(10);
            buzzer = 1 ;
            delay_1us(1500);
            buzzer = 0;
            delay_1us(1500);
          }
           else if(temp>100){
             buzzer = 1;
             delay_1us(100);
           }
          
       
/*	
          //将浮点数转为字符串,便于发送(这里只保留了两位小数)
	  buf[0] = (unsigned int)temp/100+48;
	  buf[1] = (unsigned int)distance%100/10+48;
	  buf[2] = (unsigned int)distance%10+48;
	  buf[3] = '.';
	  buf[4] = (unsigned int)(distance*10)%10+48;
	  buf[5] = (unsigned int)(distance*100)%10+48;
	  buf[6] = '\n';
	  send(buf);
	  memset(buf,0,10);
          //清空数组
          */
            
  }
}
  • 可以根据距离 蜂鸣器变速响
  • 但 是用延时写的,最好用定时器

二、(关键部分)

  • 自由模式
#include <ioCC2530.h>
//#include "sound.h"
#define TRIG P0_0
#define ECHO P0_1
#define SPK P2_0
 
unsigned char ms_cnt = 0;
unsigned char err_flag = 0;
void rada_init(void);
int mark;
int getdistance();
void hc_sr04_init(void);
void Buzzer_Init(void);
void delay_10us(void);
void Buzzer_Init(void);
void led_init(void);

void main(void)
{
  led_init();
  rada_init();
  hc_sr04_init();
  Buzzer_Init();
  while(1)
  {
    mark = getdistance();
    if(mark <= 60){
      //buzzer = 1;
      LED1 = ON;
    }else{
      //buzzer = 0;
      LED1 = OFF;
    }
  }
}

void rada_init(void)
{
  P0SEL &= ~0x03;//普通IO置0,或者外设置1
  P0DIR |= 0x01;//方向:输出置1
  P0DIR &= 0x02;//输入置0
  P0INP &= 0x02;//置0,上拉/下拉
  P2INP |= 0x20;//置1,端口0所有引脚下拉
  
  P2SEL &= ~0x01;
  P2DIR |= 0x01;
  
  
  T1CTL = 0x04;//分频,2N
  T1CNTL = 0x00;
  T1CNTH = 0x00;
  T1CC0L = 0x00;
  T1CC0H = 0x07;
  
  IEN1 |= 0x02;   //端口0中断使能
  IRCON = 0x00;//中断标志寄存器 置0,无中断未决
  EA = 1;//开中断
  
}

//中断
#pragma vector=T1_VECTOR
__interrupt void time_ISR(void)
{
  if(T1STAT&0x20)//定时器1计数器溢出中断标志
  {
     err_flag = 1;
  }
   IRCON&=~0x02;
}
 

void hc_sr04_init()
{
  TRIG=1;
  delay_10us();//提供一个10us以上脉冲触发信号
  TRIG=0;
  while(!ECHO);
  T1CTL |= 0x01; //开始自由运行模式
}


int getdistance()
{
  unsigned char i;
  int distance = 0;
  unsigned char val;
  int reg_val = 0;
  for(i = 0; i < 5; i++)
  {
    TRIG = 1;
    delay_10us();
    TRIG = 0;
    while(!ECHO);
    T1CTL &= ~0x03;//先清零
    T1CTL |= 0x01;//自由u模式启动
    while(ECHO){
      if(!err_flag)
      {
        T1CTL &= ~0x03;
        T1CNTL = 0x00;
        T1CNTH |= 0x00;
        err_flag = 0;
        return 0;//非正常结束
      }
    }
    //测量正确
    T1CTL &= ~0x03;
    val = T1CNTL;
    reg_val = T1CNTH;
    reg_val = ((reg_val<<8) | val)>>1;
    distance += reg_val/59;//
    T1CNTL = 0x00;
    T1CNTH = 0x00; 
  } 
  return distance;
}



void delay_10us(void)
{
  int i;
  for(i = 0; i < 10; i++);
}


/******蜂鸣器输出初始化******/
void Buzzer_Init(void)
{
  P2SEL &= ~0x01;
  P2DIR |= 0x01;     //P2_0定义为输出
  buzzer = 0;
}

void led_init(void){
 P1SEL &= ~0x10; 
 P1DIR |= 0x10; 
 LED1   = OFF; 
}

三、参考代码

#include<iocc2530.h>
#include<string.h>
#define ECHO P0_0               //ECHO引脚接在P0_0脚
#define TRIG  P0_1               //TRIG引脚接在P2_0脚
#define ALARM P2_0              //蜂鸣器P0_1引脚
#define PERIOD 20
#define CYCLE 100

int pulse_high = PERIOD;
unsigned int count_Time;        //用于存放计数值
float  distance;                //存放距离值,float型提高测距精度
unsigned char count_TimeH;      //用于存放计数值高8位
unsigned char count_TimeL;      //用于存放计数值低8位
char buf[10];                   //存放串口发送数据
char info[2];                   //存放串口发送数据

/*延时1us函数*/
void delay_1us(int m){
  while(m--){
  asm("NOP");
  asm("NOP");
  asm("NOP");
  }
}
/*延时1ms函数*/
void delayms(unsigned int ms)
{
  unsigned int i, j;
  for(i = ms; i > 0; i--)
    for(j = 578; j > 0; j--);
}
/*时钟初始化*/
void clk_Init(){
   CLKCONCMD &= ~0X40;          //设置第6位OSC系统时钟源为32MHZ晶振
   while(CLKCONSTA & 0x40);     //等待晶振稳定   
   CLKCONCMD &= ~0x3f;          //设置系统主时钟为32MHZ,定时器标记输出设置为32MHZ,时钟速度32MHZ         
}
/*串口初始化*/
void usart_Init(){
  PERCFG &= ~0x01;               //USART0备用位置1
  P0SEL |= 0x0c;                 //P0_2-P0_3为外设
  P2DIR &= ~0xc0;                //端口0外设优先级配置
  U0CSR |= 0X80;                 //设置为UART模式
  U0GCR |= 11;                   //设置波特率为115200
  U0BAUD |= 216;
  UTX0IF = 0;
}
/*I/O初始化*/
void io_Init(){
P2SEL &= ~0x01;                //P2_0作为通用I/O
P2DIR |= 0X01;                 //P2_0作为输出口
P0SEL &= ~0x03;                //P0_0作为通用I/O
P0DIR &= ~0X01;                //P0_0作为输入口
P0DIR |= 0x02;

//P0IF = 0;                       //清除端口0中断标志
//P0IE = 1;                       //允许P0口中断
P0IFG = 0x00;                    //*P0中断标志清零P35
//P0INP &= ~0X00;                 //*P0_0上拉或下拉
P0IEN |= 0x01;                 //开启P0_0外部中断
PICTL |= 0x01;                 //P0下降沿中断
IRCON = 0x00;                 //设置P0无端口未决
IEN1 |= 0x20;                  //*设置P0中断使能P38
EA = 1;                        //*开总中断
}
/*定时器1初始化*/
void timer1_Init(){
  T1CTL &= ~0x03;              //停止运行
  T1CTL |= 0X0c;               //设置为128分频
  T1CNTH = 0x00;
  T1CNTL = 0x00;
}
/*HC_RS04初始化*/
void hc_sr04_Init(){                  //20us的声波模块触发信号
  TRIG = 1;
  delay_1us(20);
  TRIG = 0;
  while(!ECHO);
  T1CTL |= 0x01;                      //开始自由运行模式
  delayms(30);
}
/*串口发送函数*/
void send(char *s){
  while(*s!='\0'){
  	U0DBUF= *s++;
 	while(UTX0IF == 0);               //等待标志位置1,为1时,表示当前字节发送完了
        UTX0IF = 0; 
  }
}
/*P0口中断*/
#pragma vector = P0INT_VECTOR
__interrupt void P0_isr(){
    if(P0IFG&0x01){                    //判断是否是P0_0中断
	  T1CTL &= ~0x03;                //停止T1运行
	  P0IF = 0;                      //清除端口0中断标志
	  P0IFG &= ~0x01;                //清除P0_0中断状态标志
	  count_TimeH = T1CNTH;          //取出定时器 1 计数器高位
	  count_TimeL = T1CNTL;          //取出定时器 1 计数器低位
  }
} 



int main(){
  clk_Init();
  io_Init(); 
  usart_Init();
  ALARM = 1;
  
  while(1){
	  timer1_Init();                  //定时器初始化
	  hc_sr04_Init();                 //HC_SR04初始化
	 
	  count_Time = count_TimeH*256+count_TimeL;//计算定时器1计数值
	  distance = count_Time*0.068;             //计算距离
	  /*将浮点数转为字符串,便于发送(这里只保留了两位小数)*/
          if(distance < 100&&distance > 70)
          { 
            while(1)
            {
              if(P0IFG) 
              { 
                ALARM = 1;
                break;
              }
           
              ALARM=0;
              delayms(500);
              ALARM=1;
              delayms(500);
              
               /*int temp = 1000000;
              while(temp--)
              {
                if (temp % 999999 == 0)
                  ALARM = 1;  // 响1次
                else
                  ALARM = 0;
              }*/
            }
          }
          else if(distance <= 70&& distance >40)
          { 
            while(1){ 
              if(P0IFG) 
              { 
                ALARM = 1;
                break;
              }
              
              ALARM = 0;
              delayms(100);
              ALARM=1;                                                             
              delayms(100);
              
              /*int temp = 1000000;
              while (temp--)
              {
                if (temp % 499999 == 0)
                  ALARM = 1;  // 响次
                else
                  ALARM = 0;
              }
              */
            }
          }
         else if(distance <=40&& distance >=0)
          {
            while(1){ 
              
              if(P0IFG) 
              { 
                ALARM = 1;
                break;
              }
              /*
              int temp = 10000;
              while (temp--)
              {
                ALARM = 1;
              }*/
              ALARM = 0;

            }
          }
          else
          { 
            ALARM = 1;
          }

          
	  buf[0] = (unsigned int)distance/100+48;
	  buf[1] = (unsigned int)distance%100/10+48;
	  buf[2] = (unsigned int)distance%10+48;
	  buf[3] = '.';
	  buf[4] = (unsigned int)(distance*10)%10+48;
	  buf[5] = (unsigned int)(distance*100)%10+48;
	  buf[6] = '\n';
	  send(buf);
	  memset(buf,0,10);	//清空数组
  }

}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路灯谣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值