基于51单片机的灯盘检测(PCF8591+CD4051 )

        基于51单片机的灯盘检测系统使用,AT89C51作为系统主控,采用PCF8591+CD4051进行循环检测,本次的led灯一共有90个并在每个led上做了一个断路模拟开关,部分led上还设置了击穿模拟开关,led点亮使用PNP三极管进行导通,低电平的导通方式。

一、参考代码

1、扫描灯盘

        本次设计使用PCF8591和CD4051配合进行90个led的扫描,首先使用传入的变量进行通道选择DA、DB、DC分别使用的引脚是P22、P23、P24进行CD4051通道的选择,ADC读取采取统一通道,即AN0通道。接着再使用成对的CD4051进行扫描,以此类推最后进行了90个led的扫描。

void ScanLed(unsigned char n)
{
	//选择灯盘 1110 0011
	P2 &= 0xE3;
	//选择灯盘
	P2 |= (n << 2);	
	//清除低四位
	P1 &= 0xF0;
	
	j=0;
	while(j<16){
		if(led_state == n+1){
			P1 &= 0xf0;
			//选择通道
			P1 |= j;
			//获取ADC的值
			Invalue = read_AD_data(0x40);
			
			if(Invalue==0 || Invalue>=250){
				if(n==0){err1_led[num1] = n*16+j-1;num1++;}
				if(n==1){err2_led[num2] = n*16+j-1;num2++;}
				if(n==2){err3_led[num3] = n*16+j-1;num3++;}
				if(n==3){err4_led[num4] = n*16+j-1;num4++;}
				if(n==4){err5_led[num5] = n*16+j-1;num5++;}
			}					
		}
		j++;	
	}
}

2、主函数

        下面是本次设计的主函数,实现了灯盘控制,检测灯一些逻辑,利用串口中断进行灯盘异常数据的获取并控制led灯。

#include <REGX52.H>
#include "LCD1602.H"
#include "delay.h" 
#include "PCF8591.h"
#include "UART.h"
 
sbit led1 = P3^3;
sbit led2 = P3^4;
sbit led3 = P3^5;
sbit led4 = P3^6;
sbit led5 = P3^7;

//轮询芯片的IO口
sbit DA = P2^2;
sbit DB = P2^3;
sbit DC = P2^4;

sbit DA0 = P1^0;
sbit DB0 = P1^1;
sbit DC0 = P1^2;
sbit DD0 = P1^3;
 
typedef unsigned char u8;
 
u8 Invalue=100;
u8 i=0,j=0;

u8 num1=0;
u8 num2=0;
u8 num3=0;
u8 num4=0;
u8 num5=0;

u8 err1_led[10] = {0};
u8 err2_led[10] = {0};
u8 err3_led[10] = {0};
u8 err4_led[10] = {0};
u8 err5_led[10] = {0};


u8 pos=0;
u8 close=0;

u8 cmd=0;
u8 led_state=0;

void ScanLed(unsigned char n)
{
	//选择灯盘 1110 0011
	P2 &= 0xE3;
	//选择灯盘
	P2 |= (n << 2);	
	//清除低四位
	P1 &= 0xF0;
	
	j=0;
	while(j<16){
		if(led_state == n+1){
			P1 &= 0xf0;
			//选择通道
			P1 |= j;
			//获取ADC的值
			Invalue = read_AD_data(0x40);
			
			if(Invalue==0 || Invalue>=250){
				if(n==0){err1_led[num1] = n*16+j-1;num1++;}
				if(n==1){err2_led[num2] = n*16+j-1;num2++;}
				if(n==2){err3_led[num3] = n*16+j-1;num3++;}
				if(n==3){err4_led[num4] = n*16+j-1;num4++;}
				if(n==4){err5_led[num5] = n*16+j-1;num5++;}
			}					
		}
		j++;	
	}
}

void main()
{
    LCD_Init();
	UART_Init();
	//led灯开启
	led1=1;
	led2=1;
	led3=1;
	led4=1;
	led5=1;
	while(1)
    {  
		Invalue = read_AD_data(0x40);
		//清空坏灯的数组
		for(i=0; i<5; i++){
			err1_led[i] = 0;
			err2_led[i] = 0;
			err3_led[i] = 0;
			err4_led[i] = 0;
			err5_led[i] = 0;
		}
		
		num1 = 0;
		if(led_state == 1){	
			ScanLed(0);
		}
		num2 = 0;
		if(led_state == 2){
			ScanLed(1);		
		}
		num3 = 0;
		if(led_state == 3){
			ScanLed(2);		
		}
		num4 = 0;
		if(led_state == 4){
			ScanLed(3);		
		}
		num5 = 0;
		if(led_state == 5){
			ScanLed(4);	
		}
		
		//红灯故障超过了4个,红灯灭掉
		if(num1 >= 5){
			led_state=6;
			led1=1;
		}
		else{
			
		}
		
		//其它四个灯盘,灭了超过4个,点亮红灯
		if(num2 >= 5 || num3 >= 5 || num4 >= 5 || num5 >= 5 ){
			led_state=1;
			led1=0;
			led2=1;
			led3=1;
			led4=1;
			led5=1;	
		}
			
		
		LCD_ShowNum(2, 1, num1+num2+num3+num4+num5, 2);	
		if(num1 != 0 || num2 != 0 || num3 != 0 || num4 != 0 || num5 != 0)
		{	
			//发送数据包过去
			UART_SendByte(0x5A);
			//显示坏灯的数据
			if(num1 != 0){
				//显示灯坏的数量			
				for(i=0; i<num1; i++){
					UART_SendByte(err1_led[i]);
				}			
			}	
			
			if(num2 != 0){
				//显示灯坏的数量			
				for(i=0; i<num2; i++){
					UART_SendByte(err2_led[i]);
				}			
			}	
			
			if(num3 != 0){
				//显示灯坏的数量				
				for(i=0; i<num3; i++){
					UART_SendByte(err3_led[i]);
				}			
			}	
			
			if(num4 != 0){
				//显示灯坏的数量			
				for(i=0; i<num4; i++){
					UART_SendByte(err4_led[i]);
				}			
			}	
			
			if(num5 != 0){
				//显示灯坏的数量				
				for(i=0; i<num5; i++){
					UART_SendByte(err5_led[i]);
				}			
			}	
			UART_SendByte(0xA5);				
		}
	}
}     

void UATR_Routine() interrupt 4
{
	if(RI==1)
	{
		cmd = SBUF;
		if(cmd=='a'){led_state=1;}
		if(cmd=='b'){led_state=2;}
		if(cmd=='c'){led_state=3;}
		if(cmd=='d'){led_state=4;}
		if(cmd=='e'){led_state=5;}
		if(cmd=='f'){led_state=6;}
		
		if(led_state==1){
			led1=0;
			led2=1;
			led3=1;
			led4=1;
			led5=1;
		}	
		
		if(led_state==2){
			led1=1;
			led2=0;
			led3=1;
			led4=1;
			led5=1;	
		}
		
		if(led_state==3){
			led1=1;
			led2=1;
			led3=0;
			led4=1;
			led5=1;		
		}
		
		
		if(led_state==4){
			led1=1;
			led2=1;
			led3=1;
			led4=0;
			led5=1;			
		}
		
		
		if(led_state==5){
			led1=1;
			led2=1;
			led3=1;
			led4=1;
			led5=0;		
		}
		
		if(led_state==6){
			led1=1;
			led2=1;
			led3=1;
			led4=1;
			led5=1;			
		}
		
		RI=0;
	}		
}	

二、功能演示

 1、串口控制亮灯

        串口分别发送a、b、c、d、e、f,分别是点亮这5个led灯盘和关闭所有灯盘,如图,发送指令a可以点亮第一个灯盘。如下,当我发送a的时候灯盘1灯被点亮。

2、故障检测

        如下图,利用串口助手发送c指令,第三个灯盘被点亮,同时串口循环打印检测到的故障灯,数据格式是0x5A+数据+0xA5这样的格式,如下图数据大致是 22、20、2d(0为开始数),表示第三个灯盘的第3个灯、第三个灯盘的第10个灯、第三个灯盘的第13个灯,同时lcd显示故障灯数量,这里是3个。

三、项目总结

        本次项目使用51单片机加PCF8591加CD4051实现了串口无线灯盘控制及检测,同时串口可以定位到具体得到故障灯盘,LCD显示灯盘故障数量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值