【第十三届蓝桥杯单片机省赛冲刺-巩固练习重点】

第十三届蓝桥杯单片机省赛冲刺-巩固练习

下面内容来自小蜜蜂老师公众号更新内容,讲了AT24C02 、PCF8591、以及led和数码管冲突问题,在更新的内容中小蜜蜂老师换了之前对锁存器初始化的写法,主要是加了一句所有锁存器都不选择的代码,更好的可以避免不同操作之间的影响,其次在进行锁存器操作端口赋值的时候也换了写法,之前是先选择要操作的锁存器后再进行赋值,现在是先将要赋的值送到端口然后在打开锁存器。

小蜜蜂老师操作总结 yyds

在编程中应该把握的原则是,P0端口的数据只送到目标外设。我的一个经验是:在上电初始化完成时,把所有外设连接的锁存器关闭;在需要对目标外设传输数据时,先把数据送到P0端口,然后再打开外设对应的锁存器,用完马关闭锁存器。保证在不需要的时候P0端口的变化不影响任何外设,在需要控制时,外设只接收正确的信息

一、灯闪烁与数码管计数

在这里插入图片描述

#include "reg52.h"


sbit LED1 = P0^0;
sbit LED2 = P0^1;
sbit LED8 = P0^7;
unsigned char led_stat = 0xff;
unsigned char value1 = 0,value2 = 0;
unsigned char code smg_data[] = {
    
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};


void SMG_Display_Data(void);//1.简单延时

void delay(unsigned int t)
{
    
    
 	while(t--);
}


void Delay_s(unsigned int t)
{
    
    
  while(t--)
  {
    
    
    SMG_Display_Data();                //在延时期间保持数码管刷新
  }
}
//2.锁存器初始化
void Init_74HC138(unsigned char channel)
{
    
    
 	switch(channel)
	{
    
    
	 	case 4:P2 = (P2 & 0x1f) | 0x80;break;//Y4输出0,LED控制
		case 5:P2 = (P2 & 0x1f) | 0xa0;break;//Y5输出0,蜂鸣器和继电器控制
		case 6:P2 = (P2 & 0x1f) | 0xc0;break; //Y6输出0,数码管位选
		case 7:P2 = (P2 & 0x1f) | 0xe0;break;//Y7输出0,数码管段码
		case 0:P2 = (P2 & 0x1f) | 0x00;break;//所有锁存器不选择
	}
		P2 = (P2 & 0x1f) | 0x00;//所有锁存器不选择
}

//3.数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
    
    
 	P0 = (0x01 << pos); //数码管的段位
	Init_74HC138(6);
	P0 = dat;           //数码管显示内容
	Init_74HC138(7);
}

//4.操作所有数码管
void SMG_All(unsigned char dat)
{
    
    
 	P0 = 0xff;        //数码管的段位
	Init_74HC138(6);
	P0 = dat;         //数码管显示内容
	Init_74HC138(7);
}

//5.系统初始化
void Init_System(void)
{
    
    
 	P0 = 0xff;      //关闭所有led
	Init_74HC138(4);
	P0 = 0x00;     //关闭蜂鸣器和继电器
	Init_74HC138(5);
	SMG_All(0xff); //关闭所有数码管
}

//6.数码管数据显示
void SMG_Display_Data(void)
{
    
    
	SMG_DisplayBit(0,smg_data[value1]);
	delay(200);
	SMG_DisplayBit(1,0xff);
	delay(200);
	SMG_DisplayBit(2,0xff);
	delay(200);
	SMG_DisplayBit(3,0xff);
	delay(200);
	SMG_DisplayBit(4,0xff);
	delay(200);
	SMG_DisplayBit(5,0xff);
	delay(200);
	SMG_DisplayBit(6,smg_data[value2/10]);
	delay(200);
	SMG_DisplayBit(7,smg_data[value2%10]);
	delay(200);
	SMG_All(0xff);
	delay(200);	
}


//7.led操作
void Led_Tackle(void)
{
    
    
 	led_stat &= ~0x80;  //led8电亮
	P0 = led_stat;
	Init_74HC138(4);
	Delay_s(200);

	led_stat |= 0x80;   //熄灭
	P0 = led_stat;
	Init_74HC138(4);
	Delay_s(200);

	value2++;
	if(value2 == 100)
	{
    
    
	 	value2 = 0;
	}

	//led1 和led2 灯同时翻转
	if((led_stat & 0x03) == 0x03)
	{
    
    
	 	led_stat &= ~0x03;
	}
	else
	{
    
    
	 	led_stat |= 0x03;
	}
	P0 = led_stat;
	Init_74HC138(4);
	value1++;
	if(value1 > 9)
	{
    
    
	 	value1 = 0;
	} 
}

void main(void)
{
    
    
	Init_System();
	while(1)
	{
    
    
		Led_Tackle();
		SMG_Display_Data(); 	
	}
}

注意

在这个代码中需要我们注意的是,在进行led操作函数中我们进行延时的时候也要进行数码管的刷新显示,第一次写就只是简单延时没有进行数码管的刷新显示,结果就是数码管一直在跳led没有闪烁变化,在延时函数中加上数码管动态显示后就可以了。

二、24C02基本读写操作

在这里插入图片描述

#include "reg52.h"
#include "iic.h"

unsigned char dat1,dat2,dat3;
unsigned char code smg_data[] = {
    
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};

//1.简单延时
void delay(unsigned int t)
{
    
    
 	while(t--);
}

//2.锁存器操作
void Init_74HC138(unsigned char n)
{
    
    
 	switch(n)
	{
    
    
	 	case 4:P2 = (P2 & 0x1f) | 0x80;break;
		case 5:P2 = (P2 & 0x1f) | 0xa0;break;
		case 6:P2 = (P2 & 0x1f) | 0xc0;break;
		case 7:P2 = (P2 & 0x1f) | 0xe0;break;
		case 0:P2 = (P2 & 0x1f) | 0x00;break;
	}
	P2 = (P2 & 0x1f) | 0x00;
}

//3.数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
    
    
	P0 = (0x01 << pos);
	Init_74HC138(6);
	P0 = dat;
	Init_74HC138(7);
}

//关闭所有数码管
void SMG_Close(void)
{
    
    
 	P0 = 0xff;
	Init_74HC138(6);
	P0 = 0xff;
	Init_74HC138(7);
}

//4.系统初始化
void Init_System(void)
{
    
    
	Init_74HC138(0);
 	P0 = 0x00;
	Init_74HC138(5);
	P0 = 0xff;
	Init_74HC138(4);
}

//5.数码管数据显示
void SMG_Display_Data(void)
{
    
    
 	SMG_DisplayBit(0,smg_data[dat1/10]);
	delay(200);
	SMG_DisplayBit(1,smg_data[dat1%10]);
	delay(200);
	SMG_DisplayBit(2,0xbf);
	delay(200);
	SMG_DisplayBit(3,smg_data[dat2/10]);
	delay(200);
	SMG_DisplayBit(4,smg_data[dat2%10]);
	delay(200);
	SMG_DisplayBit(5,0xbf);
	delay(200);
	SMG_DisplayBit(6,smg_data[dat3/10]);
	delay(200);
	SMG_DisplayBit(7,smg_data[dat3%10]);
	delay(200);
	SMG_Close();
	delay(200);
}


//6.at24c02数据写
void AT24C02_Write(unsigned char addr,unsigned char dat)
{
    
    	
	IIC_Start();         //起始信号
	IIC_SendByte(0xa0);  //EEPROM的写设备地址
	IIC_WaitAck();       //等待从机应答
	IIC_SendByte(addr);  //内存单元地址
	IIC_WaitAck();      //等待从机应答
	IIC_SendByte(dat);   //内存写入数据
	IIC_WaitAck();      //等待从机应答
	IIC_Stop();       //停止信号
}

//7.at24c02数据读
unsigned char AT24C02_Read(unsigned char addr)
{
    
    
 	 unsigned char tmp = 0;
	  //首先,进行一个伪写操作
	  IIC_Start();          //起始信号
	  IIC_SendByte(0xa0);    //EEPROM的写设备地址
	  IIC_WaitAck();        //等待从机应答
	  IIC_SendByte(addr);    //内存单元地址
	  IIC_WaitAck();        //等待从机应答
	  //然后,开始字节读操作
	  IIC_Start();          //起始信号
	  IIC_SendByte(0xa1);    //EEPROM的读设备地址
	  IIC_WaitAck();        //等待从机应答
	  tmp = IIC_RecByte();  //读取内存中的数据
	  IIC_SendAck(1);        //产生非应答信号
	  IIC_Stop();            //停止信号
	  return tmp;
}

//8.数据处理
void Read_Write_Data(void)
{
    
    
 	//先读取数据
	dat1 = 	AT24C02_Read(0x01);
	dat2 =  AT24C02_Read(0x03);
	dat3 = 	AT24C02_Read(0x05);


	dat1  = dat1 +1;
	dat2  = dat2 +2;
	dat3  = dat3 + 3 ;
	if( dat1 > 10)
	{
    
    
	 	dat1 = 0;
	}
	if(dat2  > 20)
	{
    
    
	 	dat2 = 0;
	}
	if(dat3  > 30)
	{
    
    
	 	dat3 = 0;
	}

	//将数据写回去
	AT24C02_Write(0x01,dat1);
	delay(1000);
	AT24C02_Write(0x03,dat2);
	delay(1000);
	AT24C02_Write(0x05,dat3);
	delay(1000);

}
void main(void)
{
    
    
 	Init_System();
	Read_Write_Data();
	while(1)
	{
    
    		 	
		 SMG_Display_Data();
	}
}
三、24C02存储按键触发次数

在这里插入图片描述

#include "iic.h"
#include "reg52.h"

sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

unsigned char s4_value = 0,s5_value = 0,s6_value = 0;
unsigned char code smg_data[] = {
    
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};
//1.简单延时
void delay(unsigned int t)
{
    
    
 	while(t--);
}

//2.锁存器初始化
void Init_74HC138(unsigned char channel)
{
    
    
 	switch(channel)
	{
    
    
	 	case 4:P2 = (P2 & 0x1f) | 0x80;break;
		case 5:P2 = (P2 & 0x1f) | 0xa0;break;
		case 6:P2 = (P2 & 0x1f) | 0xc0;break;
		case 7:P2 = (P2 & 0x1f) | 0xe0;break;
		case 0:P2 = (P2 & 0x1f) | 0x00;break;
	}
	P2 = (P2 & 0x1f) | 0x00;
}

//3.数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
    
    
 	P0 = (0x01 << pos);
	Init_74HC138(6);
	P0 = dat;
	Init_74HC138(7);
}

//4.操作所有数码管
void SMG_All(unsigned char dat)
{
    
    
 	P0 = 0xff;
	Init_74HC138(6);
	P0 = dat;
	Init_74HC138(7);
}
//5.系统初始化
void Init_System(void)
{
    
    
 	P0 = 0xff;
	Init_74HC138(4);
	P0 = 0x00;
	Init_74HC138(5);
	SMG_All(0xff);
}

//6.数码管显示数据
void SMG_Display_Data(void)
{
    
    
 	SMG_DisplayBit(0,smg_data[s4_value/10]);
	delay(200);
	SMG_DisplayBit(1,smg_data[s4_value%10]);
	delay(200);
	SMG_DisplayBit(2,0xbf);
	delay(200);
	SMG_DisplayBit(3,smg_data[s5_value/10]);
	delay(200);
	SMG_DisplayBit(4,smg_data[s5_value%10]);
	delay(200);
	SMG_DisplayBit(5,0xbf);
	delay(200);
	SMG_DisplayBit(6,smg_data[s6_value/10]);
	delay(200);
	SMG_DisplayBit(7,smg_data[s6_value%10]);
	delay(200);
	SMG_All(0xff);
	delay(200);

}

//7.at24c02写数据
void AT24C02_Write(unsigned char addr,unsigned char dat)
{
    
    
 	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

//8.at24c04读数据
unsigned char AT24C02_Read(unsigned char addr)
{
    
    
	unsigned char temp = 0;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();

	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	temp = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return temp;
}

//9.系统上电后,先从24C04存储器的0x00、0x01和0x02这三个地址单元读取数据
void AT24C02_Data_Init(void)
{
    
    
 	s4_value = 	AT24C02_Read(0x00);
	delay(1000);
	s5_value =  AT24C02_Read(0x01);
	delay(1000);
	s6_value =  AT24C02_Read(0x02);
	delay(1000);

}

//10.按键控制
void Key_Scans(void)
{
    
    
 if(S4 == 0)
 {
    
    
		delay(20);
		if(S4 == 0)
		{
    
    
		 	while(S4 == 0);
			s4_value++;
			if(s4_value > 13)
			{
    
    
			 	s4_value = 0;
			}
			AT24C02_Write(0x00,s4_value);
		}
 }
 
 if(S5 == 0)
 {
    
    
		delay(20);
		if(S5 == 0)
		{
    
    
		 	while(S5 == 0);
			s5_value++;
			if(s5_value > 13)
			{
    
    
			 	s5_value = 0;
			}
			AT24C02_Write(0x01,s5_value);
		}
 	}
	
	if(S6 == 0)
 {
    
    
		delay(20);
		if(S6 == 0)
		{
    
    
		 	while(S6 == 0);
			s6_value++;
			if(s6_value > 13)
			{
    
    
			 	s6_value = 0;
			}
			AT24C02_Write(0x02,s6_value);
		}
 }				
}
void main(void)
{
    
    
	Init_System();
	AT24C02_Data_Init();
	while(1)
	{
    
    
	    SMG_Display_Data() ;
		Key_Scans();
	}
 	
}
四、采样可变电阻电压与光敏电阻电压

在这里插入图片描述

#include "iic.h"
#include "reg52.h"

sbit S4 = P3^3;
unsigned char channel = 1;
unsigned int adc_value = 0,adc_volt = 0;
unsigned char code smg_data[] = {
    
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90};
unsigned char code smg_dot[] ={
    
    0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

//1.简单延时
void delay(unsigned int t)
{
    
    
 	while(t--);
}

//2.锁存器初始化
void Init_74HC138(unsigned char channel)
{
    
    
 	switch(channel)
	{
    
    
	 	case 4:P2 = (P2 & 0x1f) | 0x80;break;
		case 5:P2 = (P2 & 0x1f) | 0xa0;break;
		case 6:P2 = (P2 & 0x1f) | 0xc0;break;
		case 7:P2 = (P2 & 0x1f) | 0xe0;break;
		case 0:P2 = (P2 & 0x1f) | 0x00;break;
	}
		P2 = (P2 & 0x1f) | 0x00;
}

//数码管安位操作
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
    
    
 	P0 = (0x01 << pos);
	Init_74HC138(6);
	P0 = dat;
	Init_74HC138(7);
}

//操作所有数码管
void SMG_All(unsigned char dat)
{
    
    
  P0 = 0xff;
	Init_74HC138(6);
	P0 = dat;
	Init_74HC138(7);
}

//系统初始化
void Init_System(void)
{
    
    
 	P0 = 0xff;
	Init_74HC138(4);
	P0 = 0x00;
	Init_74HC138(5);
	SMG_All(0xff);
}

//数码管数据显示
void SMG_Display_Data(void)
{
    
    
 	SMG_DisplayBit(0,0xbf);
	delay(200);
	SMG_DisplayBit(1,smg_data[channel]);
	delay(200);
	SMG_DisplayBit(2,0xbf);
	delay(200);
	SMG_DisplayBit(3,0xff);
	delay(200);
	SMG_DisplayBit(4,0xff);
	delay(200);
	SMG_DisplayBit(5,smg_dot[adc_volt/100]);
	delay(200);
	SMG_DisplayBit(6,smg_data[adc_volt/10%10]);
	delay(200);
	SMG_DisplayBit(7,smg_data[adc_volt%10]);
	delay(200);
	SMG_All(0xff);
	delay(200);
}

//PCF8591数据读取
void PCF8591_Read_Data(unsigned char channel)
{
    
    
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	if(channel == 1)
	{
    
    
	 	IIC_SendByte(0x01);	
	}
	else if(channel == 3)
	{
    
    
	 	IIC_SendByte(0x03);	
	}
	IIC_WaitAck();
	IIC_Stop();

	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	adc_value = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	adc_volt = adc_value * (5.0/255)*100;		//扩大100倍方便显示	 	
}

//按键操作
void Key_Tackle(void)
{
    
    
 	if(S4 == 0)
	{
    
    
	 	delay(20);
		if(S4 == 0)
		{
    
    
		 	while(S4 == 0)
			{
    
    
			 	if(channel == 1)
				{
    
    
				 	channel = 3;
				}
				else if(channel == 3)
				{
    
    
				 	channel = 1;
				}
				PCF8591_Read_Data(channel);
			  SMG_Display_Data();
			}

		}
	}
}

//主函数
void main(void)
{
    
    
 	Init_System();
 	while(1)
	{
    
    
		
		Key_Tackle();
		PCF8591_Read_Data(channel);
		SMG_Display_Data();
	}
}

加油

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/boybs/article/details/123758054