【蓝桥杯冲刺之模块详细总结】

蓝桥杯冲刺之模块详细总结

时间过得很快,第十三届蓝桥杯单片机组大赛已接近赛点。最近疫情也变得严重了起来,这真是一个不好的消息不知道会不会如期的举行,但不管怎样该准备的还是的好好准备,下面分享的纯属个人平时练习使用的模块有误请各位大佬指出。
青春时光才几年,疫情占据大半。希望疫情快快好转。

1.简单延时

自己在使用延时函数中,都是基于这个简单的延时(数码管和按键消抖)个人感觉还是可以的

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

2.74HC138操作锁存器

蓝桥杯开发板和我们平时使用的开发板有些不同,在我们需要进行外设控制(led 数码管 蜂鸣器和继电器)控制的时候是不能直接使用的,而需要我们先进行74hc138选择相应锁存器的使能后才能进行外设的控制。原理在这就不说了,看一下原理图就明白了。

void Init_74HC138(unsigned char n)
{
    
    
	switch(n)
	{
    
    
		case 4:P2 = (P2 & 0x1f) | 0x80;break; //Y4
		case 5:P2 = (P2 & 0x1f) | 0xa0;break; //Y5
		case 6:P2 = (P2 & 0x1f) | 0xc0;break; //Y6
		case 7:P2 = (P2 & 0x1f) | 0xe0;break; //Y7	
	}
}

3.数码管按位进行选择 | 数码管显示

进行数码管位选的时候有以下两种方式,我个人的话一般使用的是第一种方式。一般我写完上面锁存器函数就会将数码管模块需的代码全部写在一起。

//3.1 先封装一个按位选择函数
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
    
    
	Init_74HC138(6);   //选通Y6 进行位选
	P0 = (0x01 << pos);  //pos代表数码管的位置
	Init_74HC138(7); //选通Y7 进行数码管数据控制
	P0 = dat;;
}

//3.2 单独写一个关闭所有数码管的函数 进行数码管动态显示的时候用来消影
void SMG_Close(void)
{
    
    
	Init_74HC138(6);
	P0 = 0xff;			//选通所有数码管
	INit_74HC138(7);
	P0 = 0xff;         //数据位0
}
方式一:实现封装为一个函数

//smg_data[x] 为段码这里没有写知道就行了
void SMG_Display_Data(void)
{
    
    
	SMG_DisplayBit(0,smg_data[0]);
	delay(200);
	SMG_DisplayBit(1,smg_data[1]);
	delay(200);
	SMG_DisplayBit(2,smg_data[2]);
	delay(200);
	SMG_DisplayBit(3,smg_data[3]);
	delay(200);
	SMG_DisplayBit(4,smg_data[4]);
	delay(200);
	SMG_DisplayBit(5,smg_data[5]);
	delay(200);
	SMG_DisplayBit(6,smg_data[6]);
	delay(200);
	SMG_DisplayBit(7,smg_data[7]);
	delya(200);
	SMG_Close();
	delay(200);
}


//方式二:封装为四个显示函数 通过传参
void SMG_Display1(unsigned char yi,unsigned char er)
{
    
    
	SMG_DisplayBit(yi,smg_data[0]);
	delay(200);
	SMG_DisplayBit(er,smg_data[1]);
	delay(200);
}

void SMG_Display2(unsigned char san,unsigned char si)
{
    
    
	SMG_DisplayBit(san,smg_data[2]);
	delay(200);
	SMG_DisplayBit(si,smg_data[3]);
	delay(200);
}

void SMG_Display3(unsigned char wu,unsigned char liu)
{
    
    
	SMG_DisplayBit(wu,smg_data[4]);
	delay(200);
	SMG_DisplayBit(liu,smg_data[5]);
	delay(200);
}

void SMG_Display4(unsigned char qi,unsigned char ba)
{
    
    
	SMG_DisplayBit(qi,smg_data[6]);
	delay(200);
	SMG_DisplayBit(ba,smg_data[7]);
	delay(200);
}

上面就是数码管模板功能函数,到时候根据题目要求进行相应显示修改进行了,一般进行不同界面切换显示的时候分别将每个显示界面单独写一个函数,在不同条件下进行不同的显示的就行了。

4.系统初始化

系统初始化就先将led和蜂鸣器继电器外设关闭

void Init_System(void)
{
    
    
	Init_74HC138(4); //选通Y4 进行LED控制
	P0 = 0xff;       //关闭所有led 
	Init_74HC138(5); //选通Y5进行继电器和蜂鸣器控制
	P0 = 0x00;      //关闭继电器和蜂鸣器
}
//至于为什么是0x00,还是需要我们去看相应的原理图控制继电器和蜂鸣器的
//ULN2003内部电路是一个取反器,所有我们置为0 的时候使其输出为1,而继电器和蜂鸣器为低电平使能

5.定时器初始化

如果使用定时器题目没有要求一般我会这样写,还是那句话我们先将简单模板记住,到时候根据题目要求进行相应修改进行了。这里的一个建议是要熟悉掌握各个定时器相应寄存器的配置。这样会大大提高编程速度要不然上考场了还的去翻相应的数据手册


//5.1定时器初始化
void Init_Timer(void)
{
    
    
	TMOD = 0x01;  
	TH0  = (65535-50000)/256;//50ms
	TL0  = (65535-50000)%256;
	EA   = 1;
	ET0  = 1;
	TR0  = 1;
}


//5.2定时器中断
void Server_Timer0() interrupt 1
{
    
    
	TH0 = (65535-50000)/256; //50ms
	TL0 = (65535-50000)%256;
	//这样需要我们再次写一下初始化,因为不会自动重装载初值
	//下面就进行具体的逻辑编写
	if()
	{
    
    
	}
	else if()
	{
    
    
	}
	else
	{
    
    
	}
}

//中断函数编写我们需要注意的是:
//牢记这个中断的中断号
//中断关键字interrupt
//函数不能有返回值 不传参

6.串口初始化

个人认为这次串口考的概率还是比较小,不过各个模块的使用我们还是都要掌握,以防万一是吧

//6.1 串口初始化
void Init_Uart(void)
{
    
    
	TMOD = 0x20;//定时器1 方式2 自动重装载8位  最大值256
	TH1  = 0xfd; //波特率9600
	TL1  = 0xfd;
	AUXR = 0x00; //辅助寄存器这句必须要写不然后面收发数据会有问题
	SCON = 50;//8位接收
	ES   = 1; //中断使能开关
	EA   = 1; //中断总开关
}


//6.2 发送
void SendByte(unsigned char ch)
{
    
    
	SBUF = ch;
	while(TI == 0);//等待发送完成
	TI = 0; //发送完成TI标志位为1 需我们手动置0
}

//6.3 串口中断接收
void Server_uart() interrupt 4
{
    
    
	if(RI == 1) //接收完成
	{
    
    
		RI = 0;
		dat = SBUF;
		SendByte(dat);
	}
}

7.ds18b20温度采集

温度底层的驱动代码会提供,我们需要掌握的就是如何根据提供的驱动代码进行相应的功能函数编写,另外在看小蜜蜂老师的是视频中有提到底层驱动的延时函数可能是有问题的,需要我们进行相应的修改。还有一点需要注意的是到时候拿到驱动代码后一定要仔细检查相应的定义引脚是否和我们开发板一致。


unsigned char Read_Temperature(void)
{
    
    
	unsigned char LSB = 0,MSB = 0; 分别存储低第0字节和第一字节
 	init_ds18b20();	 //DS18B20复位初始化
	Write_DS18B20(0xCC);  //跳过ROM指令
	Write_DS18B20(0x44);  //开始温度转换
	delay(800);	 //延时700-900ms
	
	init_ds18b20();	//DS18B20复位初始化
	Write_DS18B20(0xCC);  //跳过ROM指令
	Write_DS18B20(0xBE);	 //读取高速暂存器

	LSB = Read_DS18B20(); //暂存器第0字节
	MSB = Read_DS18B20();//暂存器第1字节
	temp = MSB;
	temp = (temp << 8) | LSB;			//整体16字节数据
	temp = temp >> 4;	 //移除小数部分
	//下面为显示小数处理
 /*
	if((temp & 0xf800) == 0x0000)
	{
	 	temp >>= 4; //将小数移除
		temp = temp *10;
		temp = temp + (LSB & 0x0f)*0.625;
	}
	*/
	return temp*100;
}

//注意如果题目要求保留一位小数显示 我们可以可以先将获取到的温度扩大100倍
//方便后面数码管的显示 注意带小数点的数码管显示
//例
// unsigned int T = Read_Temperature();
//SMG_DisplayBit(0,smg_data[T/100]);
//SMG_DisplayBit(1,smg_data_dot[T/10%10]); //带有小数点
//SMG_DisplayBit(2,smg_data[T%10]);

8.PCF8591 ad/da转换

对于PCF8591我们需要掌握的是牢记各个相应设备的地址
光敏传感器接到AIN1 通道1 控制寄存器写入0x01
电位器Rb2接到AIN3 t通道2 控制寄存器写入0x01
同样相应的底层驱动还是会提供

// 8.1 ad
unsigned char PCF8591_ADC(void)
{
    
    
	unsigned char temp = 0;
	IIC_Start();
	IIC_SendByte(0x90);  //写
	IIC_WaitAck();
	IIC_SendByte(0x03);	//AIN3 可调电阻 
	IIC_WaitAck();
	IIC_Stop();

 	IIC_Start();
	IIC_SendByte(0x91); //读设备地址
	IIC_WaitAck();
	temp = IIC_RecByte();
	IIC_SendAck(1);	 //非应答
	IIC_Stop();
	return temp;
}


// 8.2 da
void PCF8591_DAC(float dat)
{
    
    
  IIC_Start();        //总线启动
  IIC_SendByte(0X90); //地址字节 写数据
  IIC_WaitAck();      //等待应答
  IIC_SendByte(0X40); //控制字节 模拟输出使能
  IIC_WaitAck();      //等待应答
  IIC_SendByte(dat);  //数据字节 数模转换的数据
  IIC_WaitAck();      //等待应答	
  IIC_Stop();         //总线停止
}

9.AT24C02

AT24C02设备地址
读操作地址:0xa1 写操作地址:0xa0
AT24C02的操作和PCF8591一样 只是相应的设备地址不同,牢记二者区别就行了 并且进行相应写和读操作的时候步骤差不多都是如此 大家都应该熟练的将这些模板写出来。

void Write_24C02(unsigned char addr,unsigned char dat)
{
    
    
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}
unsigned char Read_24C02(unsigned char addr)
{
    
    
	unsigned char temp;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	temp = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return temp;
}

10. 矩阵操作(重点)

对于矩阵的操作考的概率是非常大的,所以一定要掌握矩阵键盘如何编写,并且注意一些小细节,跳帽的切换 P4直接是用不要了 下面模拟代码会展现

sfr P4 = 0xC0;  //一定要注意不能漏写这句

//定义行
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;
//定义列
sbit L1 = P3^4;	
sbit L2 = P3^5;
sbit L3 = P4^2;
sbit L4 = P4^4;

void ArrayKeyScan()
{
    
    
	H1 = 0;//第一行置为0 依次来检测列
	H2 = H3 = H4 = 1;
	L1 = L2 = L3 = L4 = 1;
	if(L1 == 0)
	{
    
    
		delay(20);
		if(L1 == 0)
		{
    
    
			while(L1 == 0);//等待按键松开
			//功能逻辑
		}
	}	
	else if(L2 == 0)
	{
    
    
		delay(20);
		if(L2 == 0)
		{
    
    
			while(L2 == 0); //等待按键松开
			//功能逻辑
		}
	}
	else if(L3 == 0)
	{
    
    
		delay(20);
		if(L3 == 0)
		{
    
    
			while(L3 == 0); //等待按键松开
			//功能逻辑
		}
	}
	else if(L4 == 0)
	{
    
    
		delay(20);
		if(L4 == 0)
		{
    
    
			while(L4 == 0);
			//功能逻辑
		}
	}
	 //第二行值0 依次检测列
	 H2 = 0;
	 H1 = H3 = H4 = 1;
	 L1 = L2 = L3 = L4 = 1;
	 if(L1 == 0)
	 {
    
    
	 	delay(20);
	 	if(L1 == 0)
	 	{
    
    
	 		while(L1 == 0);
	 		//功能逻辑
		}
	 }
	else if(L2 == 0)
	{
    
    
		delay(20);
		if(L2 == 0)
		{
    
    
			while(L2 == 0);
			//功能逻辑
		}
	}
	.
	. //方式和上面一样
	.
	
	 //第三行值0 依次检测列
	 H3 = 0;
	 H1 = H2 = H4 = 1;
	 L1 = L2 = L3 = L4 = 1;
	 if(L1 == 0)
	 {
    
    
	 	delay(20);
	 	if(L1 == 0)
	 	{
    
    
	 		while(L1 == 0);
	 		//功能逻辑
		}
	 }
	else if(L2 == 0)
	{
    
    
		delay(20);
		if(L2 == 0)
		{
    
    
			while(L2 == 0);
			//功能逻辑
		}
	}
	.
	. //方式和上面一样
	.
 //第四行值0 依次检测列
	 H4 = 0;
	 H1 = H2 = H3 = 1;
	 L1 = L2 = L3 = L4 = 1;
	 if(L1 == 0)
	 {
    
    
	 	delay(20);
	 	if(L1 == 0)
	 	{
    
    
	 		while(L1 == 0);
	 		//功能逻辑
		}
	 }
	else if(L2 == 0)
	{
    
    
		delay(20);
		if(L2 == 0)
		{
    
    
			while(L2 == 0);
			//功能逻辑
		}
	}
	.
	. //方式和上面一样
	.
}

上面这种矩阵键盘方式是我个人平时写用的,可能是会比较复杂了一点,但是可以清晰的把功能做出来就好了 ,当然在比赛过程中一般不会用到所有按键 所以也不需要将这个全部写出来,根据题目要求来编写就好了,上面就是矩阵键盘操作的基础模板,相应的功能操作在功能逻辑部分进行编写就好了。

11.主函数

void main(void)
{
    
    
	Init_System();
	Init_Timer();
	...  //各种初始化函数
	while(1)
	{
    
    
		//功能函数显示
	}
}

11.总结

上面的分享就是在比赛中经常使用的模板(个人看法),对于这些基础的操作一定要熟练的编写出来,比赛中将我们所学用到的模块写完就已经成功了一半,剩下就靠逻辑组合了,所以在平时练习过程的一定要有自己的思考多练习,自己不会的就去借鉴大佬写的然后慢慢消化,下次遇到相同题目的时候可以很好的写出来。嗯不出意外的话距离比赛也只有半个月左右时间,剩下的时候多练习多总结。祝所有的朋友都可以在比赛中取得一个好成绩。

加油鸭

猜你喜欢

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