- 結合超聲波模塊及Timer1定時器實現(xiàn)超聲波測距(倒車雷達)
一、(完整代碼)
- 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;//用于定時器計數(shù)
//單片機晶振采用32MHz Tcy = 256 * (1/16000000)=16us;
// 頻率周期數(shù)據(jù)表
__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;
}
/**************每次發(fā)出的聲音*****************/
__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++);
}
/*********延時程序,控制發(fā)音的時間長度(1/4拍)*************/
void delay(uchar t)
{
uchar t1;
ulong t2;
for(t1 = 0; t1 < t; t1++) //雙重循環(huán), 共延時t個半拍
for(t2 = 0; t2 < 100; t2++); //延時期間
T3CTL &=~0x10; //關閉timer3, 停止發(fā)音
}
/****************演奏一個音符*****************/
void singachar()
{
T3CTL &=~0x10; //關閉timer3
count = t3count; //控制音調(diào)
T3CTL |=0X10; //啟動, 由timer3輸出方波去發(fā)音
delay(time);
delay(2);
//控制時間長度即 節(jié)拍
}
/**************發(fā)音***********************************/
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個是第幾個八度
//從數(shù)據(jù)表中讀出頻率數(shù)值
t3count = FREQL[k]; //實際上, 是定時的時間長度
time = str[i + 2]; //讀出時間長度數(shù)值 節(jié)拍時間
i += 3;
singachar();
}
}
/********發(fā)音模式選擇***********
模式一 快速的短鳴
模式二 有停頓的短鳴
模式三 長鳴
********************************/
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; //輸出方波, 發(fā)音
T3CTL |=0X10; //啟動
count = t3count; //下次的中斷時間, 這個時間, 控制音調(diào)高低
}
}
- 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; //用于存放計數(shù)值
float distance; //存放距離值,float型提高測距精度
unsigned char count_TimeH; //用于存放計數(shù)值高8位
unsigned char count_TimeL; //用于存放計數(shù)值低8位
char buf[10]; //存放串口發(fā)送數(shù)據(jù)
float D;
/*延時1us函數(shù)*/
void delay_1us(int m){
while(m--){
asm("NOP");
asm("NOP");
asm("NOP");
}
}
/*延時1ms函數(shù)*/
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系統(tǒng)時鐘源為32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振穩(wěn)定
CLKCONCMD &= ~0x3f; //設置系統(tǒng)主時鐘為32MHZ,定時器標記輸出設置為32MHZ,時鐘速度32MHZ
}
/*串口初始化*/
void usart_Init(){
PERCFG &= ~0x01; //USART0備用位置1
P0SEL |= 0x0c; //P0_2-P0_3為外設
P2DIR &= ~0xc0; //端口0外設優(yōu)先級配置
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; //開始自由運行模式
}
/*串口發(fā)送函數(shù)*/
void send(char *s){
while(*s!='\0'){
U0DBUF= *s++;
while(UTX0IF == 0); //等待標志位置1,為1時,表示當前字節(jié)發(fā)送完了
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中斷狀態(tài)標志
count_TimeH = T1CNTH; //取出定時器 1 計數(shù)器高位
count_TimeL = T1CNTL; //取出定時器 1 計數(shù)器低位
}
}
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計數(shù)值
distance = count_Time*0.068; //計算距離
D = distance;
if(cnt<=5)
{
sum+=D;
}
if(cnt>5)
{
sum/=5;
temp=sum;
sum=0;
cnt=0;
/*將浮點數(shù)轉為字符串宫盔,便于發(fā)送(這里只保留了兩位小數(shù))*/
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);
//清空數(shù)組
}
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);
}
/*
//將浮點數(shù)轉為字符串,便于發(fā)送(這里只保留了兩位小數(shù))
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);
//清空數(shù)組
*/
}
}
- 可以根據(jù)距離 蜂鳴器變速響
- 但 是用延時寫的郭计,最好用定時器
二政供、(關鍵部分)
- 自由模式
#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計數(shù)器溢出中斷標志
{
err_flag = 1;
}
IRCON&=~0x02;
}
void hc_sr04_init()
{
TRIG=1;
delay_10us();//提供一個10us以上脈沖觸發(fā)信號
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; //用于存放計數(shù)值
float distance; //存放距離值,float型提高測距精度
unsigned char count_TimeH; //用于存放計數(shù)值高8位
unsigned char count_TimeL; //用于存放計數(shù)值低8位
char buf[10]; //存放串口發(fā)送數(shù)據(jù)
char info[2]; //存放串口發(fā)送數(shù)據(jù)
/*延時1us函數(shù)*/
void delay_1us(int m){
while(m--){
asm("NOP");
asm("NOP");
asm("NOP");
}
}
/*延時1ms函數(shù)*/
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系統(tǒng)時鐘源為32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振穩(wěn)定
CLKCONCMD &= ~0x3f; //設置系統(tǒng)主時鐘為32MHZ,定時器標記輸出設置為32MHZ,時鐘速度32MHZ
}
/*串口初始化*/
void usart_Init(){
PERCFG &= ~0x01; //USART0備用位置1
P0SEL |= 0x0c; //P0_2-P0_3為外設
P2DIR &= ~0xc0; //端口0外設優(yōu)先級配置
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的聲波模塊觸發(fā)信號
TRIG = 1;
delay_1us(20);
TRIG = 0;
while(!ECHO);
T1CTL |= 0x01; //開始自由運行模式
delayms(30);
}
/*串口發(fā)送函數(shù)*/
void send(char *s){
while(*s!='\0'){
U0DBUF= *s++;
while(UTX0IF == 0); //等待標志位置1招刨,為1時,表示當前字節(jié)發(fā)送完了
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中斷狀態(tài)標志
count_TimeH = T1CNTH; //取出定時器 1 計數(shù)器高位
count_TimeL = T1CNTL; //取出定時器 1 計數(shù)器低位
}
}
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計數(shù)值
distance = count_Time*0.068; //計算距離
/*將浮點數(shù)轉為字符串哀军,便于發(fā)送(這里只保留了兩位小數(shù))*/
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); //清空數(shù)組
}
}
————————————————
版權聲明:本文為CSDN博主「路燈謠」的原創(chuàng)文章沉眶,遵循CC 4.0 BY-SA版權協(xié)議,轉載請附上原文出處鏈接及本聲明杉适。
原文鏈接:https://blog.csdn.net/lululumiao/article/details/118613934