代码实现:

#include <reg52.h> //头文件 #include <intrins.h>

#define uchar unsigned char #define uint unsigned int

//定义引脚 sbit beep=P2^3; //蜂鸣器 sbit key1=P3^4; //按键1 sbit key2=P3^5; //按键2 sbit key3=P3^6; //按键3 sbit scl=P1^0; //激光测距模块1的SCL引脚 sbit sda=P1^1; //激光测距模块1的SDA引脚 sbit scl2=P1^2; //激光测距模块2的SCL引脚 sbit sda2=P1^3; //激光测距模块2的SDA引脚

//lcd1602引脚定义 sbit RS = P0^0; //RS sbit RW = P0^1; //RW sbit EN = P0^2; //EN sbit LCD_D4 = P0^4; //数据线 sbit LCD_D5 = P0^5; sbit LCD_D6 = P0^6; sbit LCD_D7 = P0^7;

//函数声明 void delay(uint i); void write_com(uchar com); void write_data(uchar dat); void init_lcd1602(); void display(uchar *s); void clear_lcd1602(); void send_string(uchar *s); void init_iic(); uchar start_iic(); void stop_iic(); void send_ack(); void send_nack(); uchar read_iic(); void write_iic(uchar dat); void write_reg(uchar addr, uchar dat); uchar read_reg(uchar addr); void measure_distance(); void feedback_distance(); void alarm();

//全局变量 uchar distance1[5]; //存储测量值1 uchar distance2[5]; //存储测量值2 uchar standard[5] = "20.00"; //规定尺寸

void main() { init_lcd1602(); //初始化lcd1602 init_iic(); //初始化iic beep = 0; //初始化蜂鸣器 delay(10); display("Welcome!"); //lcd1602上显示欢迎语

while(1)
{
    if(key1 == 0) //按键1控制电机正转90°
    {
        delay(10);
        if(key1 == 0)
        {
            write_com(0x01); //清屏
            display("Turning..."); //lcd1602上显示正在转动
            write_reg(0x00, 0x00); //复位激光测距模块1
            write_reg(0x01, 0x40); //打开激光测距模块1
            measure_distance(); //测量尺寸1
            feedback_distance(); //反馈尺寸1
        }
        while(!key1); //等待按键释放
    }
    
    if(key2 == 0) //按键2控制电机反转90°
    {
        delay(10);
        if(key2 == 0)
        {
            write_com(0x01); //清屏
            display("Turning..."); //lcd1602上显示正在转动
            write_reg(0x00, 0x00); //复位激光测距模块2
            write_reg(0x01, 0x40); //打开激光测距模块2
            measure_distance(); //测量尺寸2
            feedback_distance(); //反馈尺寸2
        }
        while(!key2); //等待按键释放
    }
    
    if(key3 == 0) //按键3清楚lcd1602上显示的测量数据
    {
        delay(10);
        if(key3 == 0)
        {
            write_com(0x01); //清屏
        }
        while(!key3); //等待按键释放
    }
}

}

//延时函数 void delay(uint i) { while(i--); }

//写命令函数 void write_com(uchar com) { RS = 0; //RS=0,选择指令寄存器 RW = 0; //RW=0,选择写数据 LCD_D7 = com>>7; //高位写入 LCD_D6 = (com>>6)&0x01; LCD_D5 = (com>>5)&0x01; LCD_D4 = (com>>4)&0x01; EN = 1; //EN高电平 EN = 0; //EN低电平,结束 LCD_D7 = (com>>3)&0x01; //低位写入 LCD_D6 = (com>>2)&0x01; LCD_D5 = (com>>1)&0x01; LCD_D4 = com&0x01; EN = 1; //EN高电平 EN = 0; //EN低电平,结束 delay(5); //延时5ms }

//写数据函数 void write_data(uchar dat) { RS = 1; //RS=1,选择数据寄存器 RW = 0; //RW=0,选择写数据 LCD_D7 = dat>>7; //高位写入 LCD_D6 = (dat>>6)&0x01; LCD_D5 = (dat>>5)&0x01; LCD_D4 = (dat>>4)&0x01; EN = 1; //EN高电平 EN = 0; //EN低电平,结束 LCD_D7 = (dat>>3)&0x01; //低位写入 LCD_D6 = (dat>>2)&0x01; LCD_D5 = (dat>>1)&0x01; LCD_D4 = dat&0x01; EN = 1; //EN高电平 EN = 0; //EN低电平,结束 delay(5); //延时5ms }

//lcd1602初始化函数 void init_lcd1602() { write_com(0x38); //8位数据接口,2行显示,5x7点阵 write_com(0x0c); //显示开,光标关,闪烁关 write_com(0x06); //写入字符时,光标右移,屏幕不动 write_com(0x01); //清屏 delay(5); //延时5ms }

//在lcd1602上显示一串字符 void display(uchar *s) { while(*s) //循环取字符 { write_data(*s); //写入字符 s++; //指向下一个字符 } }

//清除lcd1602上的显示 void clear_lcd1602() { write_com(0x01); //清屏 }

//发送字符串 void send_string(uchar *s) { while(*s) //循环发送字符 { write_iic(*s); //写入字符 s++; //指向下一个字符 } }

//初始化iic总线 void init_iic() { scl = 1; //SCL初始状态为高电平 sda = 1; //SDA初始状态为高电平 }

//启动iic总线 uchar start_iic() { sda = 1; //SDA初始状态为高电平 scl = 1; //SCL初始状态为高电平 delay(5); //延时5ms sda = 0; //SDA拉低 delay(5); //延时5ms scl = 0; //SCL拉低 delay(5); //延时5ms if(sda) //SDA被拉高 { return 0; //启动失败 } else { return 1; //启动成功 } }

//停止iic总线 void stop_iic() { sda = 0; //SDA拉低 scl = 1; //SCL拉高 delay(5); //延时5ms sda = 1; //SDA拉高 delay(5); //延时5ms }

//发送应答信号 void send_ack() { sda = 0; //SDA拉低 scl = 1; //SCL拉高 delay(5); //延时5ms scl = 0; //SCL拉低 delay(5); //延时5ms sda = 1; //SDA拉高 delay(5); //延时5ms }

//发送非应答信号 void send_nack() { sda = 1; //SDA拉高 scl = 1; //SCL拉高 delay(5); //延时5ms scl = 0; //SCL拉低 delay(5); //延时5ms }

//读取iic总线上的数据 uchar read_iic() { uchar i, dat; dat = 0; sda = 1; //SDA拉高 for(i=0; i<8; i++) //循环读取8位数据 { scl = 1; //SCL拉高 delay(5); //延时5ms dat = dat<<1; //左移一位 dat |= sda; //读取数据 scl = 0; //SCL拉低 delay(5); //延时5ms } return dat; //返回读取到的数据 }

//写入iic总线上的数据 void write_iic(uchar dat) { uchar i; for(i=0; i<8; i++) //循环写入8位数据 { scl = 0; //SCL拉低 delay(5); //延时5ms sda = dat&0x80; //写入最高位 dat <<= 1; //左移一位 scl = 1; //SCL拉高 delay(5); //延时5ms } scl = 0; //SCL拉低 delay(5); //延时5ms sda = 1; //SDA拉高 delay(5); //延时5ms }

//向激光测距模块写入寄存器 void write_reg(uchar addr, uchar dat) { start_iic(); //启动iic总线 write_iic(0x52); //写入设备地址 if(read_iic() != 0x00) //等待应答 { stop_iic(); //停止总线 return; //写入失败 } write_iic(addr); //写入寄存器地址 if(read_iic() != 0x00) //等待应答 { stop_iic(); //停止总线 return; //写入失败 } write_iic(dat); //写入数据 if(read_iic() != 0x00) //等待应答 { stop_iic(); //停止总线 return; //写入失败 } stop_iic(); //停止总线 }

//从激光测距模块读取寄存器 uchar read_reg(uchar addr) { uchar dat; start_iic(); //启动iic总线 write_iic(0x52); //写入设备地址 if(read_iic() != 0x00) //等待应答 { stop_iic(); //停止总线 return 0; //读取失败 } write_iic(addr); //写入寄存器地址 if(read_iic() != 0x00) //等待应答 { stop_iic(); //停止总线 return 0; //读取失败 } start_iic(); //重新启动总线 write_iic(0x53); //写入设备地址,读模式 if(read_iic() != 0x00) //等待应答 { stop_iic(); //停止总线 return 0; //读取失败 } dat = read_iic(); //读取数据 send_nack(); //发送非应答信号 stop_iic(); //停止总线 return dat; //返回读取到的数据 }

//测量尺寸 void measure_distance() { uint distance; delay(10); //延时10ms distance = read_reg(0x0f); //读取距离值 distance <<= 8; //左移8位 distance |= read_reg(0x10); //读取距离值 distance /= 10; //转换为毫米 if(distance > 999) //如果距离超过999毫米 { distance = 999; //距离设为999毫米 } if(distance == 0) //如果距离为0 { distance = 1; //距离设为1毫米 } sprintf(distance1, "%04d", distance); //转换为字符串 }

//反馈尺寸 void feedback_distance() { uchar i; uchar flag = 0; //用于标记是否与规定尺寸相同 for(i=0; i<4; i++) //循环比较 { if(distance1[i] != standard[i]) //如果不相同 { flag = 1; //标记为不相同 break; //退出循环 } } if(flag) //如果不相同 { display("Warning!!!"); //lcd1602上显示警告信息 alarm(); //警报 } else //如果相同 { display(distance1); //lcd1602上显示测量值 } }

//警报 void alarm() { uint i; for(i=0; i<500; i++) //循环500次 { beep = 1; //蜂鸣器响 delay(1); //延时1ms beep = 0; //蜂鸣器不响 delay(1); //延时1ms } }

元器件: 1、1个单片机:STC89C52RC 2、1个转盘驱动模块:28BYJ-48步进电机驱动模块5V33VULN2003 3、2个激光测距模块:GY-530 VL53L0X激光测距传感器 4、1个输出反馈模块:lcd1602 5、1个报警模块:蜂鸣器 6、3个按键; 原理图: 1、单片机使用STC89C52RC; 2、ULN2003的IN1-IN4对应P27-P24另一边接入28BYJ-4

原文地址: https://www.cveoy.top/t/topic/bF3t 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录