蓝桥杯省赛模板--->>规范自己的模板


一直是没有规矩的写,导致改BUG巨烦,这次一定要把自己的模板规范一下~.~ 图片可能查看不了,可以看我的笔记

main.c函数书写规范

在这一部分主要是主函数的逻辑代码,包含**数码管****按键****LED**,以及**定时器中断**

头文件引用宏定义

#include "ds1302.h"
#include "iic.h"
#include "onewire.h"

#define u8 unsigned char
#define u16 unsigned int

变量声明区

u8 code SegDuan[10] = {0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 , 0x92 , 0x82 , 0xf8 , 0x80 , 0x90};
//数码管段码
u8 code SegDat[8] = {0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff} , SegPos = 0;
//消隐数码管段码
u8 uLed = 0;
u8 KeyValue = 0 , KeyOldValue = 0 ,KeyDown = 0;
u16 KeyDly = 0 , SegDly = 0 , LedDly = 0;
u8 code RTC_write[3] = {0x80 , 0x82 , 0x84};//读写指令码
u8 code RTC_read[3] = {0x81 , 0x83 , 0x85};
u8 RTC_Tim[3] = {0x58 , 0x59 , 0x23};  //24H 实时时钟的时分秒采用BCD码开始写入和后续更新共用同一个数组
u16 T_dat = 0;
u16 Vp_dat = 0;
//频率计数
u16 Fre_dat = 0,u_1s = 0;
 
u8 AT24C02_addrInput = 0,AT24C02_darInput[N] = {20,10};
//标志位区   --------

系统初始化

/*
void SysInit()
{
	P0 = 0xff;
	P2 = (P2 & 0x1f) | (4 << 5);
	P2 &= 0x1f;
	
	P0 = 0x00;
	P2 = (P2 & 0x1f) | (5 << 5);
	P2 &= 0x1f;
}
 
void Disp_Bit(u8 *dat , u8 pos)
{
	P0 = 0x01 << pos;
	P2 = (P2 & 0x1f) | (6 << 5);
	P2 &= 0x1f;
	
	P0 = dat[pos];
	P2 = (P2 & 0x1f) | (7 << 5);
	P2 &= 0x1f;
}
*/这是原文使用的以下是自己经常用的系统初始化以及数码管位选
void Set_HC573(unsigned char channel, unsigned char dat)
{
  P0 = dat;                      //待设置数据
  switch(channel)                //选通锁存器
  {
    case 4:
      P2 = (P2 & 0x1f) | 0x80;  //Y4输出0,LED控制
    break;
    case 5:
      P2 = (P2 & 0x1f) | 0xa0;  //Y5输出0,蜂鸣器和继电器控制
    break;
    case 6:
      P2 = (P2 & 0x1f) | 0xc0;  //Y6输出0,数码管位选
    break;
    case 7:
      P2 = (P2 & 0x1f) | 0xe0;  //Y7输出0,数码管段码
    break;
    case 0:
      P2 = (P2 & 0x1f) | 0x00;  //所有锁存器不选择
    break;
  }
  P2 = (P2 & 0x1f) | 0x00;      //设置完成,关闭全部锁存器
}

void Disp_Bit(unsigned char pos, unsigned char value)
{
  Set_HC573(6, 0x01 << pos);    //数码管的段位
  Set_HC573(7, value);          //数码管显示内容
}
void SysInit()
{
  Set_HC573(0, 0x00);        	//关闭所有锁存器
  Set_HC573(5, 0x00);        	//关闭蜂鸣器和继电器
  Set_HC573(4, 0xff);     		//关闭全部指示灯
  DisplaySMG_All(0xff);      	//关闭全部数码管
}

DS1302实时时钟读取

void RTC_Config()
{
	u8 i;
	Write_Ds1302_Byte(0x8e , 0x00);
	for(i = 0;i < 3;i++)
	{
		Write_Ds1302_Byte(RTC_write[i] , RTC_Tim[i]);
	}
	Write_Ds1302_Byte(0x8e , 0x80);
}
 
void RTC_ReadProc()
{
	u8 i;
	for(i = 0;i < 3;i++)
	{
		RTC_Tim[i] = Read_Ds1302_Byte(RTC_read[i]);
	}
}

原理图
指令码
由此可以看出写0x8E是解除写保护的地址,最高位写1即0x80是开启写保护,0x00是解除写保护
u8 code RTC_write[3] = {0x80 , 0x82 , 0x84};//读写指令码,即上图的时分秒读取指令
u8 code RTC_read[3] = {0x81 , 0x83 , 0x85};

定时器0,1,2

void Timer1Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x20;		//设置定时初始值
	TH1 = 0xD1;		//设置定时初始值
	TF1 = 0;		//清除TF1标志
    
	ET1 = 1;
	EA = 1;
    TR1 = 1;		//定时器1开始计时
}
 
void Fre_Timer0()   //测量频率专用
{
	AUXR &= 0x7f;//12T
	TMOD |= 0x05;//16位不可重装载
	TH0 = 0;
	TL0 = 0;
	TF0 = 0;
	TR0 = 1;
}
/*
void Timer2Init(void)		//50毫秒@12.000MHz
{
	AUXR &= 0xFB;		//定时器时钟12T模式
	T2L = 0xB0;		//设置定时初值
	T2H = 0x3C;		//设置定时初值
	AUXR |= 0x10;//定时器2开始计时			
	IE2|=0x04;		//看手册找例程
	EA=1;

}
*/备选定时器

按键处理

//=================按键的功能实现函数==================
void S12_Funtion()
{

}

void S13_Funtion()
{

}

void S16_Funtion()
{

}

void S17_Funtion()
{

}

//==================矩阵键盘扫描处理===================
void Scan_Keys_2x2()
{	
    if(KeyDly)return;//定时器扫描
	KeyDly = 1;
    
	R1 = 0;
	R2 = 1;
	//扫描S12键
	if(C1 == 0)
	{
		DelaySMG(1000);
		if(C1 == 0)
		{
			S12_Funtion();
			while(C1 == 0)
			{
				 Display_Num();
			}
		}
	}
	//扫描S16键
	if(C2 == 0)
	{
		DelaySMG(1000);
		if(C2 == 0)
		{
			S16_Funtion();
			while(C2 == 0)
			{
				 Display_Num();
			}
		}
	}
 
	R1 = 1;
	R2 = 0;
	//扫描S13键
	if(C1 == 0)
	{
		DelaySMG(1000);
		if(C1 == 0)
		{
			S13_Funtion();
			while(C1 == 0)
			{
				 Display_Num();
			}
		}
	}
	//扫描S17键
	if(C2 == 0)
	{
		DelaySMG(1000);
		if(C2 == 0)
		{
			S17_Funtion();
			while(C2 == 0)
			{
				 Display_Num();
			}
		}
	}
  
}

数码管处理

void Disp_Tim()//时间显示
{
	//根据要求填写
	SegDat[0] = SegDuan[RTC_Tim[2] / 16];
	SegDat[1] = SegDuan[RTC_Tim[2] % 16];
	
	SegDat[3] = SegDuan[RTC_Tim[1] / 16];
	SegDat[4] = SegDuan[RTC_Tim[1] % 16];
	
	SegDat[6] = SegDuan[RTC_Tim[0] / 16];
	SegDat[7] = SegDuan[RTC_Tim[0] % 16];
}
 
void Disp_Tem()//温度显示
{
	//根据要求填写
	
	SegDat[0] = 0xc6;
	SegDat[1] = 0xff;
	SegDat[2] = 0xff;
	SegDat[3] = 0xff;
	SegDat[4] = 0xff;
	SegDat[5] = SegDuan[T_dat / 100];
	SegDat[6] = SegDuan[T_dat / 10 % 10] & 0x7f;
	SegDat[7] = SegDuan[T_dat % 10];
}
 
void Disp_Vp()//数模转换,精确电压
{
	//根据要求填写
	SegDat[0] = 0xc1;
	SegDat[1] = 0xff;
	SegDat[2] = 0xff;
	SegDat[3] = 0xff;
	SegDat[4] = 0xff;
	SegDat[5] = SegDuan[Vp_dat / 100] & 0x7f;//“&0x7F是加点的意思”!!
	SegDat[6] = SegDuan[Vp_dat / 10 % 10];
	SegDat[7] = SegDuan[Vp_dat % 10];
}
 
void Disp_Fre()//频率
{
	//根据要求填写
	SegDat[0] = 0x8e;
	SegDat[1] = 0xff;
	SegDat[2] = 0xff;
	SegDat[3] = SegDuan[Fre_dat / 10000];
	SegDat[4] = SegDuan[Fre_dat / 1000 % 10];
	SegDat[5] = SegDuan[Fre_dat / 100 % 10];
	SegDat[6] = SegDuan[Fre_dat / 10 % 10];
	SegDat[7] = SegDuan[Fre_dat % 10];
}
 
void Disp_AT24C02()
{
	SegDat[0] = SegDuan[AT24C02_darInput[0] / 100];
	SegDat[1] = SegDuan[AT24C02_darInput[0] / 10 % 10];
	SegDat[2] = SegDuan[AT24C02_darInput[0] % 10];
	SegDat[3] = 0xff;
	SegDat[4] = 0xff;
	SegDat[5] = SegDuan[AT24C02_darInput[1] / 100];
	SegDat[6] = SegDuan[AT24C02_darInput[1] / 10 % 10];
	SegDat[7] = SegDuan[AT24C02_darInput[1] % 10];
}
 
void SegProc()//数码管信息处理
{
	if(SegDly)return;
	SegDly = 1;
	
	RTC_ReadProc();
	T_dat = rd_temperature() * 0.0625 * 10 + 0.5;  //0.5用来四舍五入
	Vp_dat = PCF8591_ADC() * 500.0 / 255;
	AT24C02_Read(AT24C02_addrInput,N,AT24C02_darInput);
//	Disp_Tim();
//	Disp_Fre();
//	Disp_Tem();
//	Disp_Vp();
	Disp_AT24C02();
}


LED处理

void LedProc()
{
	if(LedDly)return;
	LedDly = 1;
	
	
}

中断服务函数

void Service1() interrupt 3
{
	//刷新时间
	if(++LedDly == 100)LedDly = 0;
	if(++SegDly == 500)SegDly = 0;
	if(++KeyDly == 10)KeyDly = 0;
	
	//频率计数
	if(++u_1s == 1000)
	{
		u_1s = 0;
		TR0 = 0;
		Fre_dat = (TH0 << 8) | TL0;
		TH0 = 0;
		TL0 = 0;
		TF0 = 0;
		TR0 = 1;
	}
	
	
	//数码管显示
	Disp_Bit(SegDat,SegPos);
	if(++SegPos == 8)SegPos = 0;
	
	//LED显示
	P0 = ~uLed;
	P2 = (P2 & 0x1f) | (4 << 5);
	P2 &= 0x1f;
}

部分原文参照链接:https://blog.csdn.net/qq_57511928/article/details/124726361

主函数main.c

void main()
{
	SysInit();
	Timer1Init();
	RTC_Config();
	Fre_Timer0();
	AT24C02_Write(AT24C02_addrInput,N,AT24C02_darInput);
	while(1)
	{
		KeyProc();//三个处理函数
		SegProc();
		LedProc();
	}

iic.c函数书写规范

PCF数模转换

sbit sda=P2^1;
sbit scl=P2^0;
unsigned char PCF8591_ADC()
{
	unsigned char Vp;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);  //Rb2		若需要DA转换尽量写成0x43,0x41
	//IIC_SendByte(0x01);  //光敏电阻
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	Vp = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	
	return Vp;
}
 
void PCF8591_DAC(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);  //打开out就行与通道无关
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

原理图
地址格式,因为原理图固定所以写地址固定为0x90
AD转换时直接通过iic发送回主机所以不需要模拟输出,但如果ad和da转换都有尽量全打开,避免误关
AIN1是光敏电阻0x41,AIN3是电位器0x43

AT24C02->EEPROM

void AT24C02_Read(unsigned char addr,unsigned char num,unsigned char *dat)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	while(num--)
	{
		*dat++ = IIC_RecByte();
		if(num)
			IIC_SendAck(0);
		else
			IIC_SendAck(1);
		IIC_Delay(200);		
	}
	IIC_Stop();
}
 
void AT24C02_Write(unsigned char addr,unsigned char num,unsigned char *dat)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	while(num--)
	{
		IIC_SendByte(*dat++);
		IIC_WaitAck();
	}
	IIC_Stop();
}


原理图
设备地址(device address)对于AT24C02(2K)写为0x90,读为0x91
指定地址写
随机地址读

onewire.c函数书写规范

DS18B20温度读取

unsigned int rd_temperature()
{
	unsigned int LSB,MSB,temp;
	init_ds18b20();
	Write_DS18B20(0xcc);//跳过rom
	Write_DS18B20(0x44);//转换
	//以上部分可以单独取出在函数开始前转化一次
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	
	temp = (MSB << 8) | LSB;//只取整数部分
	return temp;
}

指令集


机械电子狗 机械电子狗
9 个月前
16

扫描下方二维码手机阅读文章

0