系统整体设计
1)本设计的控制器采用51单片机
2)ADC0808采集光敏电阻的分压
光照强度越弱,被点亮的LED数目越多,当弱到一定阈值的时候
Speaker报警
3)LCD1602显示当前电压值
具体实现如下代码
#include<reg51.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define DATA_PORT P0
#define OPEN 0
#define CLOSE 1
volatile uchar Speaker_Alarm = 0;
uchar Flag_2s = 0;
//——————————————-
// 管脚定义
//——————————————
sbit RS=P2^1; //数据(L)/命令(H)选择
sbit LCDRW=P2^2; //写,低电平有效
sbit EN=P2^3; //使能,低电平有效
sbit START= P1^2;
sbit ALE = P1^7;
sbit EOC = P1^1;
sbit OE = P1^0;
sbit CLOCK= P1^3;
sbit LED = P2^0;
sbit LED_1 = P2^4;
sbit LED_2 = P2^5;
sbit LED_3 = P2^6;
sbit LED_4 = P2^7;
//===========================================
// 函数声明
//——————————————-
void conv_start(void);
void conv_check(void);
int read_data(void);
void delay_lcd(char);
void write_data(char);
void write_com(char);
void LCD_clear(void);
void LCD_home(void);
void lcd_init();
void print_string(char*);
void delay_ms(int t);
void Timer0Init(void);
static float BubbleSort(int arr[]);
void main(void){
float vol=0.0;
float Arry_Vol[10] = {0};
char pr[8];
int loop_num = 0;
lcd_init();
Timer0Init();
LOOP:
for( loop_num = 0; loop_num < 10; loop_num+=1 ){
Arry_Vol[loop_num] = read_data();
}
vol=5.0*(int)BubbleSort(Arry_Vol)/255;
if(vol >= 2.80){Speaker_Alarm = OPEN;Flag_2s = 1;}else {Speaker_Alarm = CLOSE;}
if(vol >= 2.55)LED_4 = OPEN;else LED_4 = CLOSE;
if(vol >= 2.43)LED_3 = OPEN;else LED_3 = CLOSE;
if(vol >= 2.39)LED_2 = OPEN;else LED_2 = CLOSE;
if(vol >= 2.35)LED_1 = OPEN;else LED_1 = CLOSE;
sprintf(pr,"%.2f",vol);
LCD_home();
print_string("Voltage: ");
print_string(pr);
print_string("V ");
goto LOOP;
}
//********************************************************
//冒泡排序算法
static float BubbleSort(float arr[]){
int i,j;
for( i=0; i<sizeof(arr)-1; i++){ //表示趟数,一共arr.length-1次。
for( j=sizeof(arr)-1; j>i; j–){
if(arr[j] < arr[j-1]){
arr[j] = arr[j] + arr[j-1];
arr[j-1] = arr[j] – arr[j-1];
arr[j-1] = arr[j] – arr[j-1];
}
}
}
return ((arr[(sizeof(arr)/2)-1] + arr[sizeof(arr)/2])/2);
}
void Timer0Init(void) //10微秒@11.0592MHz
{
EA = 1;//打开总中断;
TMOD |= 0x01; //选定定时/计数器0的工作的方式
TH0 = (65536 – 10000) / 256;
TL0 = (65536 – 10000) % 256;//初始化定时/计数器的值?
ET0 = 1; //打开中断服务程序???
TR0 = 1;//打开计数器
}
void timer0_isr() interrupt 1//? 中断的服务的程序
{
static uint Process_1ms = 0;
TH0 = (65536 – 10000) / 256;
TL0 = (65536 – 10000) % 256;//触发中断后再一次初始化值
Process_1ms += 1;
if(Process_1ms >= 2000){
Process_1ms = 0;
Flag_2s = 0;
}
if(Speaker_Alarm == OPEN && Flag_2s == 1){
LED = ~LED;
}else{
LED = CLOSE;
}
CLOCK = ~CLOCK;
}
//——————————————–
// start ADC convert
//——————————————–
void conv_start(){
ALE=1;
START=1;
delay_ms(1); //当晶振较高时加延时
ALE=0;
START=0;
// delay_ms(5); //当晶振较高时加延时
}
int read_data(){
int i=0;
//delay_ms(5);
//while(!EOC); //IF EOC==0,means busy
OE=1;
conv_start();
while(!EOC);
//delay_ms(5);
i=P3;
OE=0;
return i;
}
//*******************************************************]
void delay_ms(int t){
int j;
for( ;t!=0; t–)
for (j=0;j<255;j++);
}
//********************************************************
//——————————————–
// 写数据函数
//——————————————–
void write_data(char dat){
RS=1; //数据
LCDRW=0; //写
DATA_PORT=dat; //把数据送到P口
delay_ms(5); //当晶振较高时加延时
EN=1;
delay_ms(5); //当晶振较高时加延时
EN=0; //关使能
}
//——————————————–
// 写命令函数
//——————————————–
void write_com(char com){
RS=0; //命令
LCDRW=0; //写
DATA_PORT=com;
delay_ms(5); //当晶振较高时加延时
EN=1;
delay_ms(5); //当晶振较高时加延时
EN=0;
}
void LCD_clear(void){
write_com(0x01);
}
void LCD_home(void){
write_com(0x02);
}
//——————————————–
// 1602初始化函数
//——————————————–
void lcd_init(){
LCDRW=0;
RS=0;
write_com(0x36); //set text home address
//write_com(0x0f); //display switch,display on,cursor on,blink on.
write_com(0x0c); //display on,cursor off,blink off
write_com(0x38);
write_com(0x06); //input set.
write_com(0x01); //screen clear
write_com(0x80); //DDRAM AD set to 00h,
}
void print_string(char* str){
int i;
for(i=0;str[i]!=0;i++)
{
write_data(str[i]);
}
}
//********************************************************