Detailed explanation of the questions of the 10th Provincial Competition of Lanqiao Cup Microcontroller

I highly recommend you do it yourself before watching it! ! !

Demo video

Question explanation

Insert image description here
First debug the PCF8591 (analog input and output), buttons, digital tube, and NE555 of the program block diagram.
Insert image description here
The basic requirement is to connect the outputs of P34 and NE555 with an ultrasonic jumper cap.
Insert image description here
Just display the corresponding one on the digital tube. Note that only the frequency measurement needs to be displayed.

uchar tab[]={
    
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf,0x81,0xc1};//f u
uchar SMG[8]={
    
    20,20,20,20,20,20,20,20};//初始显示20,全息数码管
uint high=0,low=0,highdata=0,lowdata=0;//ne555高低时间
uint time;//ne555时间
uchar SMG_mode=0;//控制数码管模式
void main(void)
{
    
    
	init();
	Timer0Init();
	EA=1;ET0=1;
	while(1)
	{
    
    
		if(SMG_mode==0)
		{
    
    
			led &=0xfd;led |=0x01;//L2点亮,L1熄灭
			time=(1000000/((highdata+lowdata)*20));\
			SMG[0]=22;SMG[1]=20;
			if(time<10){
    
    SMG[2]=SMG[3]=SMG[4]=SMG[5]=SMG[6]=20;
				SMG[7]=time/10;}
			
			else if(time<100){
    
    SMG[2]=SMG[3]=SMG[4]=SMG[5]=20;
				SMG[6]=time%100/10;SMG[7]=time%10;}
			
			else if(time<1000){
    
    SMG[2]=SMG[3]=SMG[4]=20;
				SMG[5]=time%1000/100;
				SMG[6]=time%100/10;SMG[7]=time%10;}
			
			else if(time<10000){
    
    SMG[2]=SMG[3]=20;
			SMG[4]=time%10000/1000;SMG[5]=time%1000/100;
			SMG[6]=time%100/10;SMG[7]=time%10;}
			
			else if(time<100000){
    
    SMG[2]=20;SMG[3]=time/10000;
				SMG[4]=time%10000/1000;SMG[5]=time%1000/100;
				SMG[6]=time%100/10;SMG[7]=time%10;}
		}
		else if(SMG_mode==1)
		{
    
    
			led &=0xfe;led |=0x02;//L1点亮,L2熄灭
			SMG[0]=23;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20;
			move=1.9607*move;//move *(5 /255 *100) 将0-255转换到0-500,便于显示
			if(move<150)led |=0x04;//L3熄灭
			else if(move<250) led &=0xfb;//L3点亮
			else if(move<350)led |=0x04;//L3熄灭
			else led &=0xfb;//L3点亮
			SMG[5]=move/100+10;SMG[6]=move%100/10;SMG[7]=move%10;
			move=IIC_read(PCF8591_address,Move_address);//读取滑动变阻器
//			IIC_write(PCF8591_address,Output_address,move);//输出			
		}
}

Then look at the key controls.
Insert image description here
S4: Control voltage and frequency interface
S5: Control voltage output
S6: LED enable
S7: Digital tube display
First, establish corresponding variables for control, and then follow the corresponding buttons to add functions.

void Dkey_scan(void)
{
    
    
	static uchar keybyte=0;
	static uchar key;
	if(((P3&0X0F)!=0X0F)&&(keybyte==0))
	{
    
    
		Delay5ms();
		if((P3&0X0F)!=0X0F)
		{
    
    
			keybyte=1;key=P3&0x0f;
		}
	}
	if((keybyte==1)&&((P3&0X0F)==0X0F))
	{
    
    
		if((P3&0X0F)==0X0F)
		{
    
    
			switch(key)
			{
    
    
				case 0x0e: //S7
					if(SMG_out==0)SMG_out=1;
				else SMG_out=0;
					break;
				case 0x0d: //S6
					if(led_mode==0)led_mode=1;
				else led_mode=0;					
					break;
				case 0x0b: //S5
					if(Output_mode==0)Output_mode=1;
				else Output_mode=0;
					break;
				case 0x07: //S4
					if(SMG_mode==0)SMG_mode=1;
				else SMG_mode=0;
					break;
			}
			keybyte=0;
		}
	}
}
if(Output_mode==0){
    
    IIC_write(PCF8591_address,Output_address,102);
led |=0x10;}//输出2v  模式0
else {
    
    IIC_write(PCF8591_address,Output_address,move);
led &=0xef;}//输出move v  模式1

Insert image description here

Insert image description here
Then there is the LED mode.

if(SMG_mode==0)
{
    
    led &=0xfd;led |=0x01;//L2点亮,L1熄灭}
else if(SMG_mode==1)
{
    
    led &=0xfe;led |=0x02;//L1点亮,L2熄灭}

if(move<150)led |=0x04;//L3熄灭
else if(move<250) led &=0xfb;//L3点亮
else if(move<350)led |=0x04;//L3熄灭
else led &=0xfb;//L3点亮

if(Output_mode==0){
    
    IIC_write(PCF8591_address,Output_address,102);
led |=0x10;}//输出2v  模式0 L1熄灭
else {
    
    IIC_write(PCF8591_address,Output_address,move);
led &=0xef;}//输出move v  模式1 L1亮

if(time<1000)led |=0x08;  //L4熄灭
else if(time<5000)led &=0xf7; //L4点亮
else if(time<10000)led |=0x08; //L4熄灭
else led &=0xf7; //L4点亮

if(led_mode==1){
    
    P2=0X80;P0=led;}
else {
    
    P2=0X80;P0=0xff;}

Initialization requirements.
Insert image description here

complete program

main.c

#include<stc15f2k60s2.h>
#include"intrins.h"
#include "iic.h"
#define uchar unsigned char
#define uint unsigned int

#define PCF8591_address 0x90
#define Light_address 0x01
#define Move_address 0x03
#define Output_address 0x40

void SMG_output(void);
void init(void);
void Delay1ms(void);
void Timer0Init(void);
void Dkey_scan(void);
void Delay5ms(void);
uchar tab[]={
    
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf,0x8e,0xc1};//f u
uchar SMG[8]={
    
    20,20,20,20,20,20,20,20};//初始显示20,全息数码管
uint high=0,low=0,highdata=0,lowdata=0;//ne555高低时间
uint time;//ne555时间
uchar SMG_mode=0;//控制数码管模式
bit Output_mode=0;//控制输出电压
bit led_mode=0;//控制led
bit SMG_out=0;//数码管显示
uint move=0;//pcf8591的滑动变阻器读取值
uchar led=0xff;
void main(void)
{
    
    
	init();
	Timer0Init();
	EA=1;ET0=1;
	while(1)
	{
    
    
		if(SMG_out==1)
		{
    
    
			if(SMG_mode==0)
			{
    
    
				led &=0xfd;led |=0x01;//L2点亮,L1熄灭
				time=(1000000/((highdata+lowdata)*20));\
				SMG[0]=22;SMG[1]=20;
				if(time<10){
    
    SMG[2]=SMG[3]=SMG[4]=SMG[5]=SMG[6]=20;
					SMG[7]=time/10;}
				
				else if(time<100){
    
    SMG[2]=SMG[3]=SMG[4]=SMG[5]=20;
					SMG[6]=time%100/10;SMG[7]=time%10;}
				
				else if(time<1000){
    
    SMG[2]=SMG[3]=SMG[4]=20;
					SMG[5]=time%1000/100;
					SMG[6]=time%100/10;SMG[7]=time%10;}
				
				else if(time<10000){
    
    SMG[2]=SMG[3]=20;
				SMG[4]=time%10000/1000;SMG[5]=time%1000/100;
				SMG[6]=time%100/10;SMG[7]=time%10;}
				
				else if(time<100000){
    
    SMG[2]=20;SMG[3]=time/10000;
					SMG[4]=time%10000/1000;SMG[5]=time%1000/100;
					SMG[6]=time%100/10;SMG[7]=time%10;}
			}
			else if(SMG_mode==1)
			{
    
    
				led &=0xfe;led |=0x02;//L1点亮,L2熄灭
				SMG[0]=23;SMG[1]=SMG[2]=SMG[3]=SMG[4]=20;
				move=1.9607*move;//move *(5 /255 *100) 将0-255转换到0-500,便于显示
				if(move<150)led |=0x04;//L3熄灭
				else if(move<250) led &=0xfb;//L3点亮
				else if(move<350)led |=0x04;//L3熄灭
				else led &=0xfb;//L3点亮
				SMG[5]=move/100+10;SMG[6]=move%100/10;SMG[7]=move%10;
				move=IIC_read(PCF8591_address,Move_address);//读取滑动变阻器
	//			IIC_write(PCF8591_address,Output_address,move);//输出			
			}
		}
		else if(SMG_out==0)//关闭显示
		{
    
    
			SMG[0]=SMG[1]=SMG[6]=SMG[2]=SMG[3]=SMG[4]=SMG[5]=SMG[7]=20;//全息
		}
		
		if(Output_mode==0){
    
    IIC_write(PCF8591_address,Output_address,102);
		led |=0x10;}//输出2v  模式0 L1熄灭
		else {
    
    IIC_write(PCF8591_address,Output_address,move);
		led &=0xef;}//输出move v  模式1 L1亮
		
		if(time<1000)led |=0x08;  //L4熄灭
		else if(time<5000)led &=0xf7; //L4点亮
		else if(time<10000)led |=0x08; //L4熄灭
		else led &=0xf7; //L4点亮
		if(led_mode==1){
    
    P2=0X80;P0=led;}
		else {
    
    P2=0X80;P0=0xff;}
		SMG_output();
		Dkey_scan();
	}
}

void Dkey_scan(void)
{
    
    
	static uchar keybyte=0;
	static uchar key;
	if(((P3&0X0F)!=0X0F)&&(keybyte==0))
	{
    
    
		Delay5ms();
		if((P3&0X0F)!=0X0F)
		{
    
    
			keybyte=1;key=P3&0x0f;
		}
	}
	if((keybyte==1)&&((P3&0X0F)==0X0F))
	{
    
    
		if((P3&0X0F)==0X0F)
		{
    
    
			switch(key)
			{
    
    
				case 0x0e: //S7
					if(SMG_out==0)SMG_out=1;
				else SMG_out=0;
					break;
				case 0x0d: //S6
					if(led_mode==0)led_mode=1;
				else led_mode=0;					
					break;
				case 0x0b: //S5
					if(Output_mode==0)Output_mode=1;
				else Output_mode=0;
					break;
				case 0x07: //S4
					if(SMG_mode==0)SMG_mode=1;
				else SMG_mode=0;
					break;
			}
			keybyte=0;
		}
	}
}


void time0() interrupt 1
{
    
    
	if(P34==1)
	{
    
    
		high++;
		if(low !=0)
		{
    
    
			lowdata=low;
			low=0;
		}
	}
	else if(P34==0)
	{
    
    
		low++;
		if(high !=0)
		{
    
    
			highdata=high;
			high=0;
		}
	}	
}

void SMG_output(void)
{
    
    
	uchar i;
	for(i=0;i<8;i++)
	{
    
    
	P2=(P2&0X1F)|0Xc0;
	P0=(1<<i);
	P2=(P2&0X1F)|0Xe0;
	P0=tab[SMG[i]];
	Delay1ms();
	}
	P2=(P2&0X1F)|0Xc0;
	P0=0Xff;
	P2=(P2&0X1F)|0Xe0;
	P0=0Xff;	
}

void Timer0Init(void)		//20微秒@11.0592MHz
{
    
    
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x23;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}



void init(void)
{
    
    
	P2=(P2&0X1F)|0XA0;
	P0=0X00;
	P2=(P2&0X1F)|0X80;
	P0=0Xff;
	P2=(P2&0X1F)|0Xc0;
	P0=0Xff;
	P2=(P2&0X1F)|0Xe0;
	P0=0Xff;	
}

void Delay5ms()		//@11.0592MHz
{
    
    
	unsigned char i, j;

	i = 54;
	j = 199;
	do
	{
    
    
		while (--j);
	} while (--i);
}


void Delay1ms(void)		//@11.0592MHz
{
    
    
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
    
    
		while (--j);
	} while (--i);
}

iic.h

#ifndef _IIC_H
#define _IIC_H

#include "stc15f2k60s2.h"
#include "intrins.h"

#define uchar unsigned char
#define uint unsigned int

sbit SDA = P2^1;
sbit SCL = P2^0;

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
void IIC_write(uchar hw_address,uchar reg_address,uchar num);
uchar IIC_read(uchar hw_address,uchar reg_address);


#endif

iic.c

#include "iic.h"

#define DELAY_TIME 40

void IIC_write(uchar hw_address,uchar reg_address,uchar num)
{
    
    
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);
	IIC_WaitAck();
	IIC_SendByte(num);
	IIC_WaitAck();	
	IIC_Stop();	
}	

uchar IIC_read(uchar hw_address,uchar reg_address)
{
    
    
	uchar num;
	IIC_Start();
	IIC_SendByte(hw_address&0xfe);
	IIC_WaitAck();
	IIC_SendByte(reg_address);	
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(hw_address|0x01);
	IIC_WaitAck();
	num=IIC_RecByte();
	IIC_WaitAck();
	IIC_Stop();	
	
	return num;
}

//
void IIC_Delay(unsigned char i)
{
    
    
    do{
    
    _nop_();}
    while(i--);        
}

//
void IIC_Start(void)
{
    
    
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//
void IIC_Stop(void)
{
    
    
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//
void IIC_SendAck(bit ackbit)
{
    
    
    SCL = 0;
    SDA = ackbit;  					
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//
bit IIC_WaitAck(void)
{
    
    
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//
void IIC_SendByte(unsigned char byt)
{
    
    
    unsigned char i;

    for(i=0; i<8; i++)
    {
    
    
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//
unsigned char IIC_RecByte(void)
{
    
    
    unsigned char i, da;
    for(i=0; i<8; i++)
    {
    
       
    	SCL = 1;
		IIC_Delay(DELAY_TIME);
		da <<= 1;
		if(SDA) da |= 1;
		SCL = 0;
		IIC_Delay(DELAY_TIME);
    }
    return da;    
}

Project Files

Project Files

Guess you like

Origin blog.csdn.net/darlingqx/article/details/127622699