要求:

设计要求

通过PCF8591获取光敏电阻的电压数值。

通过单片机的P34引脚测量NE555输出的脉冲信号。

通过数码管完成试题要求的界面显示功能。

通过指示灯实现界面指示功能。

显示要求

键值显示

数码管的第2、第3位固定显示当前按下的按键键值。

频率界面

频率界面由标识符(F)和频率值组成,频率单位为Hz,保留整数。显示如下图所示:

固定使用5位数码管显示频率数值,不足5位,高位(左侧)熄灭。

光照度界面

光照度界面由标识符(E)和光敏电阻电压值组成。电压单位为V,保留小数点后1位。显示如下图所示:

固定使用2位数码管显示光敏电阻电压值。

按键功能

有效按键:S8、S9、S12、S13,其余按键无任何功能。

S12:“界面”按键,按下按键S12,实现“频率界面”和“光照度界面”界面切换功能,切换模式如下图所示:

指示灯功能

L1:频率界面指示灯,在“频率界面下”,指示灯L1点亮,否则熄灭;

L2:光照度界面指示灯,在“光照度界面下”,指示灯L2点亮,否则熄灭;

初始状态

处于频率界面。

无按键按下,即数码管第2、3位处于熄灭状态。

备注

单片机IRC振荡器频率设置为12MHz;

扩展模式:IO模式;

键盘模式:矩阵键盘。

代码:

sys.h

#ifndef __SYS_H__ 
#define __SYS_H__ 

#include <STC12C5A60S2.H>
#include "intrins.h"
extern bit UI;//界面标志
extern unsigned char Seg_Buff[8];//数码管缓冲区
extern unsigned int ne555_count;//NE555计数值即频率
extern float pcf8591_count;//PCF8591计数值即光敏电阻电压值
extern unsigned char keynum;//按键值
void init74hc138(unsigned char n);//选通
void init();//系统初始化
float V_rd1();//电压转换
void Seg_Loop();//数码管刷新
void seg_ui();//数码管界面显示
void seg_key();//数码管按键显示
void Key_Loop();//按键动态扫描
void led_ui();//led界面标记

#endif

main.c

#include "sys.h"
bit flag_ne=0;
bit flag_v=0;
bit flag_seg=0;
bit flag_key=0;
//定时器0作为计数器
void Timer0_Init(void)		//100微秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x05;//设置为计数器模式
	TL0 = 0x00;		
	TH0 = 0x00;			
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	EA=1;
}
void Timer1_Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x40;			//定时器时钟1T模式
	TMOD &= 0x0F;			//设置定时器模式
	TL1 = 0x20;				//设置定时初始值
	TH1 = 0xD1;				//设置定时初始值
	TF1 = 0;				//清除TF1标志
	TR1 = 1;				//定时器1开始计时
	ET1 = 1;				//使能定时器1中断
	EA=1;
}
unsigned int get_count(){
	unsigned int temp;
	temp=TH0<<8|TL0;
	TH0=0x00;
	TL0=0x00;
	if(TF0){//说明溢出
		TF0=0;
		return 0xffff;
	}else{
		return temp;
	}
}
void main(){
	init();
	Timer0_Init();
	Timer1_Init();
	while(1){
		if(flag_key){
			flag_key=0;
			Key_Loop();
			seg_key();
			led_ui();
		}
		if(flag_seg){
			flag_seg=0;
			Seg_Loop();
		}
		if(flag_ne){
			flag_ne=0;
			ne555_count=get_count();
			seg_ui();
		}
		if(flag_v){
			flag_v=0;
			pcf8591_count=V_rd1();
			seg_ui();
		}
	}
}

void Timer1_Isr(void) interrupt 3
{
	static unsigned int count1=0,count2=0;
	static unsigned char count3=0,count4=0;
	count1++;count2++;count3++;count4++;
	if(count1==1000){//计时1s
		count1=0;
		flag_ne=1;
	}
	if(count2==500){
		count2=0;
		flag_v=1;
	}
	if(count3==2){
		count3=0;
		flag_seg=1;
	}
	if(count4==50){
		count4=0;
		flag_key=1;
	}
}

sys.c

#include "sys.h"
unsigned int ne555_count;
float pcf8591_count;
void init74hc138(unsigned char n){
	P2=(P2&0x1f)|(n<<5);
	P2=0x1f;
}
void init(){
	P0=0x00;
	init74hc138(5);
	P0=0xff;
	init74hc138(4);
}
void led(unsigned char n){
	P0=0x01<<n-1;
	P0=~P0;
	init74hc138(4);
	P0=0xff;
}
void led_ui(){
	if(UI){
		led(2);
	}else{
		led(1);
	}
}

seg_ui.c

#include "sys.h"
code unsigned char Seg_Table[] = 
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x86, //E 10 
0x8e, //F 11
0xff  //熄灭 12
};
unsigned char Seg_Buff[]={12,12,12,12,12,12,12,12};
bit UI=0;//界面标志

void seg(unsigned char addr,unsigned char num){
	P0=0xff;
	init74hc138(7);
	P0=0x01<<addr;
	init74hc138(6);
	P0=Seg_Table[num];
	if(UI&&addr==6){
		P0&=0x7f;
	}
	init74hc138(7);
}
void seg_key(){
	if(keynum==0)return;
	if(keynum>=10)
		Seg_Buff[1]=keynum/10;
	else
		Seg_Buff[1]=12;
	Seg_Buff[2]=keynum%10;
}
//void no_seg_key(){
//	Seg_Buff[1]=12;
//	Seg_Buff[2]=12;
//}
void seg_u1(){//UI=0时,处于频率界面
	Seg_Buff[7]=ne555_count%10;
	if(ne555_count>=10)
		Seg_Buff[6]=ne555_count/10%10;
	else 
		Seg_Buff[6]=12;
	if(ne555_count>=100)
		Seg_Buff[5]=ne555_count/100%10;
	else 
		Seg_Buff[5]=12;
	if(ne555_count>=1000)
		Seg_Buff[4]=ne555_count/1000%10;
	else 
		Seg_Buff[4]=12;
	if(ne555_count>=10000)
		Seg_Buff[3]=ne555_count/10000%10;
	else 
		Seg_Buff[3]=12;
	Seg_Buff[0]=11;//F
}
void seg_u2(){//UI=1时,处于光照界面
	Seg_Buff[7]=(unsigned char)(pcf8591_count*10)%10;
	Seg_Buff[6]=(unsigned char)(pcf8591_count*10)/10;
	Seg_Buff[5]=12;
	Seg_Buff[4]=12;
	Seg_Buff[3]=12;
	Seg_Buff[0]=10;//E
}
void seg_ui(){
	if(UI){
		seg_u2();
	}else{
		seg_u1();
	}
}
void Seg_Loop(){
	static unsigned char i=0;
	seg(i,Seg_Buff[i]);
	i++;
	if(i==8)i=0;
}

key.c

#include "sys.h"
unsigned char keyval,keyold,keyup,keydown,keynum=0;
unsigned char Key_Scan(){
	P42=0;P35=1;
	if(P33==0)return 8;
	if(P32==0)return 9;
	P35=0;P42=1;
	if(P33==0)return 12;
	if(P32==0)return 13;
	return 0;
}
void Key_Loop(){
	keyval=Key_Scan();
	keydown=keyval&(keyold^keyval);
	keyup=~keyval&(keyold^keyval);
	if(keyval==8&&keyold!=keyval){keynum=8;keyold=keyval;return;}
	if(keyval==9&&keyold!=keyval){keynum=9;keyold=keyval;return;}
	if(keyval==13&&keyold!=keyval){keynum=13;keyold=keyval;return;}
	if(keyval==12&&keyold!=keyval){UI=~UI;keynum=12;keyold=keyval;return;}
	keynum=0;
	keyold=keyval;
}

iic.c

#include "sys.h"
#define DELAY_TIME	5
sbit scl=P2^0;
sbit sda=P2^1;
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}
//从ADC读取数值
unsigned char adc(unsigned char addr){
	unsigned char temp;
	EA=0;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	temp=I2CReceiveByte();
	I2CWaitAck();
	I2CSendAck(1);
	I2CStop();
	EA=1;
	return temp;
}
//将读到的数值转化为电压值
float V_rd1(){
	float vrd1;
	vrd1=(float)adc(1)*5.0/255+0.05;
	return vrd1;
}

测试结果

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐