#include <REGX52.H>
#include <INTRINS.H>
// -------------------------- ???? --------------------------
typedef unsigned char u8;
typedef unsigned int u16;
// -------------------------- ???? --------------------------
// ?????
sbit Trig = P2^0;
sbit Echo = P2^1;
// ?????(?????,?????)
sbit Buzzer = P2^5;
// ????
sbit KEY1 = P3^1;
sbit KEY2 = P3^0;
sbit KEY3 = P3^2;
sbit KEY4 = P3^3;
// LCD1602??
sbit LCD_RS = P2^6;
sbit LCD_RW = P2^5;
sbit LCD_E = P2^7;
#define LCD_DataPort P0
// LED?(???,????,P1?)
#define LED_PORT P1
// -------------------------- ???? --------------------------
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0
#define MAX_DISTANCE 400 // ??????(cm)
#define MIN_DISTANCE 2 // ??????(cm)
#define TIMER0_1MS 0xFC67 // 11.0592MHz??,??1ms??
// -------------------------- ???? --------------------------
float distance = 0.0; // ????(cm)
u8 key = 0; // ???
unsigned int upper_limit = 50; // ?????(??50cm)
unsigned int lower_limit = 10; // ?????(??10cm)
bit setting_mode = 0; // ?????? 0-?? 1-??
bit set_upper = 1; // 1-???? 0-????
float saved_data[3] = {0.0, 0.0, 0.0}; // ?????
u8 save_index = 0; // ????
u8 view_index = 0; // ????
bit view_mode = 0; // ??????
// ???????(???????/LED)
u16 timer0_cnt = 0; // ???0??(1ms??)
bit buzzer_timer_en = 0; // ????????
bit buzzer_state = 0; // ?????
bit led_timer_en = 0; // LED?????
u8 led_step = 0; // LED????
u16 time_count = 0; // ??????
// -------------------------- ???? --------------------------
// 10us??(???)
void delay_10us(u16 ten_us) {
while(ten_us--) {
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
// ms??(???,???????/??)
void Delay(u16 ms) {
u16 i, j;
for(i = ms; i > 0; i--)
for(j = 110; j > 0; j--);
}
// 20us??(???????)
void Delay20us() {
delay_10us(2);
}
// -------------------------- ?????? --------------------------
// mode=0:????;mode=1:??
u8 key_scan(u8 mode) {
static u8 key_flag = 1;
if(mode) key_flag = 1; // ????????
if(key_flag == 1 && (KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0)) {
Delay(10); // 10ms??
key_flag = 0;
if(KEY1 == 0) return KEY1_PRESS;
else if(KEY2 == 0) return KEY2_PRESS;
else if(KEY3 == 0) return KEY3_PRESS;
else if(KEY4 == 0) return KEY4_PRESS;
} else if(KEY1 == 1 && KEY2 == 1 && KEY3 == 1 && KEY4 == 1) {
key_flag = 1; // ??????,????
}
return KEY_UNPRESS;
}
// -------------------------- LCD1602?? --------------------------
// LCD??1ms??
void LCD_Delay() {
u8 i, j;
i = 2;
j = 199;
do { while (--j); } while (--i);
}
// ???
void LCD_WriteCommand(u8 Command) {
LCD_RS = 0;
LCD_RW = 0;
LCD_DataPort = Command;
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
// ???
void LCD_WriteData(u8 Data) {
LCD_RS = 1;
LCD_RW = 0;
LCD_DataPort = Data;
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
// ???
void LCD_Init(void) {
LCD_WriteCommand(0x38); // 8?????,2???,5*8??
LCD_WriteCommand(0x0C); // ???,???
LCD_WriteCommand(0x06); // ????,?????
LCD_WriteCommand(0x01); // ??
}
// ??????(Line=1/2,Column=1~16)
void LCD_SetCursor(u8 Line, u8 Column) {
if(Line == 1)
LCD_WriteCommand(0x80 | (Column - 1));
else
LCD_WriteCommand(0x80 | (Column - 1) + 0x40);
}
// ??????
void LCD_ShowChar(u8 Line, u8 Column, u8 Char) {
LCD_SetCursor(Line, Column);
LCD_WriteData(Char);
}
// ?????
void LCD_ShowString(u8 Line, u8 Column, u8 *String) {
u8 i;
LCD_SetCursor(Line, Column);
for(i = 0; String[i] != '\0'; i++)
LCD_WriteData(String[i]);
}
// ??10?n??(??????)
int LCD_Pow(int X, int Y) {
u8 i;
int Result = 1;
for(i = 0; i < Y; i++)
Result *= X;
return Result;
}
// ???????(Length:????)
void LCD_ShowNum(u8 Line, u8 Column, unsigned int Number, u8 Length) {
u8 i;
LCD_SetCursor(Line, Column);
for(i = Length; i > 0; i--) {
LCD_WriteData('0' + Number / LCD_Pow(10, i - 1) % 10);
}
}
// ??
void LCD_Clear() {
LCD_WriteCommand(0x01);
}
// -------------------------- ???0??(????1ms) --------------------------
void Timer0Init(void) {
TMOD &= 0xF0; // ??Timer0??
TMOD |= 0x01; // Timer0????1(16???)
TH0 = TIMER0_1MS >> 8; // ??1ms??(?8?)
TL0 = TIMER0_1MS & 0xFF; // ??1ms??(?8?)
TF0 = 0; // ??????
TR0 = 1; // ?????0
ET0 = 1; // ??Timer0??
EA = 1; // ?????
}
// ???0??????(1ms????)
void Timer0_ISR() interrupt 1 {
// ??1ms??
TH0 = TIMER0_1MS >> 8;
TL0 = TIMER0_1MS & 0xFF;
timer0_cnt++;
// ???0.5Hz??(1000ms??????)
if(buzzer_timer_en) {
if(timer0_cnt >= 1000) {
timer0_cnt = 0;
buzzer_state = !buzzer_state;
Buzzer = buzzer_state;
}
}
// LED??????(500ms????)
if(led_timer_en) {
if(timer0_cnt >= 500) {
timer0_cnt = 0;
led_step = (led_step + 1) % 4;
// ??LED??(????)
switch(led_step) {
case 0: LED_PORT = 0xFC; break; // D1?D2?(11111100)
case 1: LED_PORT = 0xF3; break; // D3?D4?(11110011)
case 2: LED_PORT = 0xCF; break; // D5?D6?(11001111)
case 3: LED_PORT = 0x3F; break; // D7?D8?(00111111)
}
}
}
}
// -------------------------- ?????(??????+???) --------------------------
// ?????
void Init_Chaoshengbo(void) {
Trig = 1;
Delay20us(); // ??????10us
Trig = 0;
}
// ?????(??????,?????/??400)
void Chaoshengbo(void) {
u16 timeout = 0;
time_count = 0;
// ??Echo??(???100ms,????????)
while(Echo == 0) {
timeout++;
if(timeout > 10000) return; // ??,????
}
// ????(??????)
TH0 = 0;
TL0 = 0;
TR0 = 1; // ?????(????????,?????)
timeout = 0;
// ??Echo??(????????˜11m,??400cm)
while(Echo == 1) {
timeout++;
if(timeout > 60000) { // ??,????
TR0 = 0;
return;
}
}
// ????,???
TR0 = 0;
time_count = (TH0 << 8) | TL0;
}
// ????(????+????)
void Measure_Distance() {
Init_Chaoshengbo();
Chaoshengbo();
// ????:????(11.0592MHz??,??340m/s)
if(time_count > 0) {
// ?? = ??? * 1.085us(????) * 340m/s / 2 / 1000(?cm)
distance = (time_count * 1.085 * 0.034) / 2;
} else {
distance = 0; // ????,??0(???400)
}
// ????????(2cm~400cm)
if(distance > MAX_DISTANCE) distance = MAX_DISTANCE;
if(distance < MIN_DISTANCE) distance = 0;
}
// -------------------------- ?????(????+????) --------------------------
// ????(??/????)
void beep_tip() {
u16 i;
for(i = 0; i < 100; i++) { // 200us??,?20ms
Buzzer = !Buzzer;
delay_10us(10);
}
Buzzer = 1; // ??
}
// ????(????)
void beep_continuous() {
Buzzer = 0; // ?????
}
// ????
void beep_stop() {
Buzzer = 1; // ?????
buzzer_timer_en = 0; // ???????
buzzer_state = 0;
}
// ???????(???0.5Hz/??????/????)
void Buzzer_Control() {
if(view_mode || setting_mode) {
beep_stop();
return;
}
// ???:0.5Hz????(?????)
if(distance > upper_limit && distance > 0) {
buzzer_timer_en = 1;
timer0_cnt = 0; // ????,??????
}
// ????:????
else if(distance < lower_limit && distance > 0) {
buzzer_timer_en = 0;
beep_continuous();
}
// ????/????:????
else {
beep_stop();
}
}
// -------------------------- LED??(????+????) --------------------------
// LED??(??????/??????)
void LED_Control() {
if(view_mode || setting_mode) {
led_timer_en = 0;
LED_PORT = 0xFF; // ????LED
return;
}
// ???????????:??????
if(distance > lower_limit && distance < upper_limit && distance > 0) {
led_timer_en = 1;
timer0_cnt = 0; // ????,????????
// ??LED??(???????????)
switch(led_step) {
case 0: LED_PORT = 0xFC; break;
case 1: LED_PORT = 0xF3; break;
case 2: LED_PORT = 0xCF; break;
case 3: LED_PORT = 0x3F; break;
}
}
// ????:??LED
else {
led_timer_en = 0;
LED_PORT = 0xFF;
}
}
// -------------------------- LCD????(????) --------------------------
// ??????(??+???)
void LCD_Show_RealTime() {
LCD_Clear();
// ???:????
LCD_ShowString(1, 1, "Dist:");
if(distance > 0) {
LCD_ShowNum(1, 6, (unsigned int)distance, 3);
LCD_ShowChar(1, 9, '.');
LCD_ShowNum(1, 10, (u8)((unsigned int)(distance * 10) % 10), 1);
} else {
LCD_ShowString(1, 6, "---"); // ???????---
LCD_ShowChar(1, 9, '.');
LCD_ShowNum(1, 10, 0, 1);
}
LCD_ShowString(1, 11, "cm");
// ???:???
LCD_ShowString(2, 1, "U:");
LCD_ShowNum(2, 3, upper_limit, 3);
LCD_ShowString(2, 6, "cm L:");
LCD_ShowNum(2, 11, lower_limit, 3);
LCD_ShowString(2, 14, "cm");
}
// ??????(?????+????)
void LCD_Show_Setting() {
LCD_Clear();
LCD_ShowString(1, 1, "Setting:");
if(set_upper) {
LCD_ShowString(2, 1, "Upper >");
LCD_ShowNum(2, 8, upper_limit, 3);
LCD_ShowString(2, 11, "cm");
} else {
LCD_ShowString(2, 1, "Lower >");
LCD_ShowNum(2, 8, lower_limit, 3);
LCD_ShowString(2, 11, "cm");
}
}
// ??????(3???)
void LCD_Show_History() {
LCD_Clear();
LCD_ShowString(1, 1, "History ");
LCD_ShowNum(1, 9, view_index + 1, 1);
LCD_ShowString(1, 10, "/3");
// ?????????????
if(saved_data[view_index] > 0) {
LCD_ShowString(2, 1, "Dist:");
LCD_ShowNum(2, 6, (unsigned int)saved_data[view_index], 3);
LCD_ShowChar(2, 9, '.');
LCD_ShowNum(2, 10, (u8)((unsigned int)(saved_data[view_index] * 10) % 10), 1);
LCD_ShowString(2, 11, "cm");
} else {
LCD_ShowString(2, 1, "No Data");
}
}
// -------------------------- ?????? --------------------------
void Save_Data() {
if(distance > 0) { // ???????
saved_data[save_index] = distance;
save_index = (save_index + 1) % 3; // ????3???
// ??????
LCD_Clear();
LCD_ShowString(1, 1, "Saved Success!");
LCD_ShowString(2, 1, "Dist:");
LCD_ShowNum(2, 6, (unsigned int)distance, 3);
LCD_ShowChar(2, 9, '.');
LCD_ShowNum(2, 10, (u8)((unsigned int)(distance * 10) % 10), 1);
LCD_ShowString(2, 11, "cm");
Delay(1000); // ????1?
} else {
// ??????
LCD_Clear();
LCD_ShowString(1, 1, "Invalid Data!");
Delay(500);
}
}
// -------------------------- ???(????) --------------------------
void main() {
// ?????(?????)
LCD_Init();
Timer0Init();
beep_stop(); // ???????
LED_PORT = 0xFF; // ????LED
LCD_Show_RealTime(); // ????????
// ???
while(1) {
key = key_scan(0); // ????(????)
// 1. ?????(KEY2):????/?????;???????
if(key == KEY2_PRESS) {
Delay(10); // ????
if(view_mode) {
view_mode = 0;
LCD_Show_RealTime();
} else {
setting_mode = !setting_mode;
setting_mode ? LCD_Show_Setting() : LCD_Show_RealTime();
}
beep_tip();
}
// 2. ???(KEY1):??/????/????
if(key == KEY1_PRESS) {
Delay(10);
if(setting_mode) {
set_upper = !set_upper; // ????:?????
LCD_Show_Setting();
} else if(view_mode) {
view_index = (view_index + 1) % 3; // ????:????
LCD_Show_History();
} else {
Save_Data(); // ????:????
LCD_Show_RealTime();
}
beep_tip();
}
// 3. ???(KEY3):?????????;???????????
if(key == KEY3_PRESS) {
Delay(10);
if(setting_mode) {
// ????:????(??=400,??<??)
if(set_upper) {
upper_limit = (upper_limit >= MAX_DISTANCE) ? MAX_DISTANCE : upper_limit + 1;
} else {
lower_limit = (lower_limit >= upper_limit - 1) ? (upper_limit - 1) : lower_limit + 1;
}
LCD_Show_Setting();
beep_tip();
} else if(!view_mode) {
// ????:??200ms???????
Delay(200);
if(KEY3 == 0) {
view_mode = 1;
view_index = 0;
LCD_Show_History();
beep_tip();
}
}
}
// 4. ???(KEY4):?????????
if(key == KEY4_PRESS && setting_mode) {
Delay(10);
if(set_upper) {
upper_limit = (upper_limit <= lower_limit + 1) ? (lower_limit + 1) : upper_limit - 1;
} else {
lower_limit = (lower_limit <= MIN_DISTANCE) ? MIN_DISTANCE : lower_limit - 1;
}
LCD_Show_Setting();
beep_tip();
}
// 5. ????:??+??+???+LED??
if(!setting_mode && !view_mode) {
Measure_Distance();
LCD_Show_RealTime();
Buzzer_Control();
LED_Control();
}
}
}修改上述代码使得蜂鸣器能正常运行且能实现以下功能1、用超声波模块测量某个障碍物的距离;
2、可通过按键修改上下限报警值;
3、 在OLED屏上实时显示所测障碍物距离、已设定的距离测量的上下限报警值;
4、当超声波模块测的距离大于设定的上限值时,蜂鸣器以0.5Hz的频率报警。当超声波模块测得的距离小于设定的下限值时,蜂鸣器持续报警;
5、当超声波模块测得的距离处于设定的上限值和下限值之间时,蜂鸣器停止鸣叫,LED灯模块按D1~D8的顺序,两个两个地循环亮起;
1、具有数据保存按键,按下按键可以保存当前测定的距离数值;
2、具有历史数据查看按键,按下按键可查看1中保存的距离数据(至少保存3组数据),按一次调出一组数据,再按一次调出下一组数据,查看完最后一组数据后从第一组数据重新展示,循环往复。