蓝桥杯单片机模块代码完善:NE555、EEPROM与DS1302模块深度解析

以前写的那些模块的底层代码是可以正常使用的,但是当题目涉及到一些问题可能会出现乱码或者时序错误,本篇文章对部分的模块的底层代码需要更改的地方进行总结。

一、NE555+按键

  • NE555使用的时候默认使用定时器0去计数,定时器1去计时(不可颠倒),在使用的时候记得把按键的P34注释掉!!!
  • #include <key.h>
    
    unsigned char KeyDisp()
    {
    	unsigned char temp = 0;//一定要赋值!
    	
    	P44 = 0;
    	P42 = 1;
    	P35 = 1;
    	//P34 = 1;
    	if(P33 == 0) temp = 4;
    	if(P32 == 0) temp = 5;
    	
    	P44 = 1;
    	P42 = 0;
    	P35 = 1;
    	//P34 = 1;
    	if(P33 == 0) temp = 8;
    	if(P32 == 0) temp = 9;
    	
    	return temp;
    }
    
    void Timer0_Init(void)		//100微秒@12.000MHz
    {
    	TMOD &= 0xF0;			//设置定时器模式
    	TMOD |= 0x05;
    	TL0 = 0;				//设置定时初始值
    	TH0 = 0;				//设置定时初始值
    	TF0 = 0;				//清除TF0标志
    	TR0 = 1;				//定时器0开始计时
    }
    
    void Timer1_Init(void)		//1毫秒@12.000MHz
    {
    	AUXR &= 0xBF;			//定时器时钟12T模式
    	TMOD &= 0x0F;			//设置定时器模式
    	TL1 = 0x18;				//设置定时初始值
    	TH1 = 0xFC;				//设置定时初始值
    	TF1 = 0;				//清除TF1标志
    	TR1 = 1;				//定时器1开始计时
    	ET1 = 1;				//使能定时器1中断
    	EA = 1;
    }
    
    void Timer1_Isr(void) interrupt 3
    {
    	/*NE555*/
    	if(++Time_1s == 1000)
    	{
    		Time_1s = 0;
    		Freq = (TH0 << 8) | TL0;
    		TH0 = TL0 = 0;
    	}
    }
    
    void main()
    {
    	Timer0_Init();
    	Timer1_Init();
    	while(1)
    	{
    		//...
    	}
    }
    
  • 频率读取Freq和时间Time_1s一定要定义成unsigned int类型!
  • 二、EEPROM上锁问题

    1.什么时候要上锁?

    如果题目明确指定将数据存放到EEPROM的某个位置,这个时候是不用做其他操作的,正常读写EEPROM即可,例如:
    当题目没有明确存放的地方时,恭喜你,触发了隐藏副本,需要在读写数据前增加上锁工作,例如:

    2.怎么上锁?

    假如题目要在按键S4按下时将数据Date写入EEPROM,并且在上电时从EEPROM读出。
    正常写法:

    idata unsigned char Date = 1;
    void KeyProc()
    {
    	if(KeyDown == 4)
    		EepromWrite(&Date,0,1);
    }
    
    void main()
    {
    	EepromRead(&Date,0,1);
    	while(1);
    }
    

    上锁写法:

    idata unsigned char Date = 1;
    idata unsigned char Lock = 5;//锁
    void KeyProc()
    {
    	if(KeyDown == 4)
    	{
    		EepromWrite(&Date,0,1);
    		//将锁存放在EEPROM的下一页
    		EepromWrite(&Lock,8,1);
    	}
    }
    
    void main()
    {
    	unsigned char read;
    	//上电时先定义一个中间变量读取EEPROM的位置8的值
    	//将读取的值与锁进行比较
    	//如果读取的是锁值,则Date正常读取位置0的数据
    	//如果不是,则丢弃
    	EepromRead(&read,8,1);
    	if(read == Lock)
    		EepromRead(&Date,0,1);
    	while(1);
    }
    

    三、DS1302底层改为十进制

    除了将DS1302底层代码改为十进制,还增加读取时间时通过关开定时器中断防止时序对DS1302的影响。

    code unsigned char Ds1302_Arr[4] = {0x84,0x82,0x80,0x8E};
    
    void SetRtc(unsigned char *Rtc)
    {
    	unsigned char i;
    	Write_Ds1302_Byte(Ds1302_Arr[3],0x00);//关闭写保护
    	for(i = 0; i < 3; i++)
    		Write_Ds1302_Byte(Ds1302_Arr[i],(Rtc[i] / 10 << 4) | Rtc[i] % 10);
    	//打开写保护
    	Write_Ds1302_Byte(Ds1302_Arr[3],0x80);
    }
    void GetRtc(unsigned char *Rtc)
    {
    	unsigned char i, temp;
    	EA = 0;//关闭中断
    	for(i = 0; i < 3; i++)
    	{
    		temp = Read_Ds1302_Byte(Ds1302_Arr[i]+1);
    		Rtc[i] = temp / 16 * 10 + temp % 16;
    	}
    	EA = 1;//打开中断
    }
    

    四、IIC底层代码

    如果数码管显示的AD值会闪烁,其他时序都没问题,不妨试试以下改法:将DELAY_TIME的10改成5。

    作者:星光始终闪耀

    物联沃分享整理
    物联沃-IOTWORD物联网 » 蓝桥杯单片机模块代码完善:NE555、EEPROM与DS1302模块深度解析

    发表回复