蓝桥杯单边机省赛一些总结

自己刷省赛的一些总结,有不足之处还望指正。

  1. 首先说一些读温度吧,元器件叫Ds18b20

官方提供的代码是onewire.h与onewire.c,但有一点要注意的是:

void Delay_OneWire(unsigned int t) //STC89C52RC

{

while(t--);

}

//我们需要给他加长12倍,因为我们蓝桥杯用的是stc15f系列。

void Delay_OneWire(unsigned int t) //STC89C52RC

{

while(t--)

{

unsigned char i = 0;

for (i = 0; i < 12; i++);

}

}

温度的读取代码,可以直接去网上找,我提供些细节:考题中有保留两位和一位或者无小数的读取。

我们开始需要知道:temp前5位为符号位,中间七位为整数,后面四位为小数。

我的建议是:定义一个 unsigned int temp;temp=((high&0x0f)<<8)|low;temp=temp*0.625;//一位小数,构成一个三位数(temp=temp*6.25;四位数,保留两位。temp=temp*0.0625;两位数,无小数)

代码:

unsigned int read_temp(){

unsigned int temp;

unsigned char high,low;



init_ds18b20();

Write_DS18B20(0xcc);

Write_DS18B20(0x44);



init_ds18b20();

Write_DS18B20(0xcc);

Write_DS18B20(0xbe);



low=Read_DS18B20();

high=Read_DS18B20();

temp=high&0x0f;

temp=((temp<<8)|low)*0.625;

return temp;

}

2.再说下时钟读取,Ds1302:

官方提供的是ds1302.h与ds1302.c。我感觉这没啥注意的,感觉要注意的就是16进制数存入,16进制读取。

代码:

void Read_time(unsigned char *time){

unsigned char i;

for(i=0;i<3;i++){

time[i]=Read_Ds1302_Byte(0x85-2*i);

}

}



void Write_time(unsigned char *time){

unsigned char i;

Write_Ds1302_Byte(0x8e,0);

for(i=0;i<3;i++){

Write_Ds1302_Byte(0x84-2*i,time[i]);

}

Write_Ds1302_Byte(0x8e,0x80);

}

3.电压的读取,pcf8591:

官方提供的是iic.h与iic.c。pcf8591有adc电压读取(分0x01光敏电阻读电压,0x03滑动变阻器RB2电压读取),dac电压存入,即dac输出。如果单单用到DAC输出的话,控制寄存器地址就是0x40。

在读取电压中,我的建议是:adc读取时unsigned int voltage;voltage=X*500/255;(V=X*1.961)要写括号这种,所得三位数,为电压扩大100倍。//x表示取出的值;

代码:

unsigned int Pcf_read(unsigned char dat){//dat==0x01或0x03

unsigned int valtage=0;

IIC_Start();

IIC_SendByte(0x90);

IIC_WaitAck();

IIC_SendByte(dat);

IIC_WaitAck();

IIC_Stop();



IIC_Start();

IIC_SendByte(0x91);

voltage=IIC_RecByte()*1.921;

IIC_SendAck(1);

IIC_Stop();

return voltage;

}

注意adc读取时, IIC_SendAck(1);//等待应答,如果写这句话的话,记得中间值是1,同时写在IIC_Stop()之前。

dac存入中,我的建议:X=Voltage*255/500;(X=Voltage*51/100;)

代码:

void Pcf8591_dac(unsigned char date){

IIC_Start();

IIC_Sendbyte(0x90);

IIC_Waitack();

IIC_Sendbyte(0x40);//如果单单用到DAC输出的话,控制寄存器地址就是0x40。如果是滑阻输入然后DAC输出的话,

//就是0x43。

IIC_Waitack();

IIC_Sendbyte(date);

iIIC_Waitack();

IIC_Stop();

}

4.数据的存储与读出,at24c02(Eeprom)

官方提供的也是iic.h与iic.c。AT24C02提供2048位的电可擦和可编程只读存储器(EEPROM)组织为256, 8位字。注意adc读取时, IIC_SendAck(0);//与上面电压不同

代码:

void E2prom_write(unsigned char date,unsigned char add){

IIC_Start();

IIC_SendByte(0xa0);

IIC_WaitAck();

IIC_SendByte(add);



IIC_WaitAck();

IIC_SendByte(date);

IIC_WaitAck();

IIC_Stop();

}



unsigned char E2prom_read(unsigned char add){

unsigned char num;

IIC_Start();

IIC_SendByte(0xa0);

IIC_WaitAck();

IIC_SendByte(add);

IIC_WaitAck();

IIC_Stop();



IIC_Start();

IIC_SendByte(0xa1);

IIC_WaitAck();

num=IIC_RecByte();

IIC_SendAck(0);

IIC_Stop();

return num;

}

5.频率的测量,P34与SIGNAL连接 ,TMOD=0x16,TH0=0xff,TL0=0xff,TH1与TL1自己设计,通过计数器0进行计数;这里官方没提供参考代码。TH1表示高8位,TL1表示低8位。其求1秒内的计数.

代码:

void Timer_init(){

TMOD=0x16;

TH0=0xff;

TL0=0xff;

TH1=(65536-1000)/256;//1毫秒的定时器

TL1=(65536-1000)%256;

EA=1;

ET0=1;

ET1=1;

TR0=1;

TR1=1;

}

void Timer_0() interrupt 1{

count++;

}

void Timer_1() interrupt 3{

TH1=(65536-1000)/256;//手动初始化

TL1=(65536-1000)%256;

if(++count_time>=1000){

count_time=0;

count_num=count;//count_num为测得的频率值

count=0;

}

}

6.按键

代码:

typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
uchar key_old,key_long_flag,key_long_time_flag;
uint key_long_time=0
unsigned char Key_read(){
	unsigned char num;
	unsigned int key_val=0;
	P34=P35=P42=P44=1;
	P34=0;
	key_val=P3;
	P34=1,P35=0;
	key_val=(key_val<<4)|(P3&0x0f);
	P35=1,P42=0;
	key_val=(key_val<<4)|(P3&0x0f);
	P42=1,P44=0;
	key_val=(key_val<<4)|(P3&0x0f);
	switch(~key_val){
		case 0x0008:num=4;break;
		case 0x0004:num=5;break;
		case 0x0002:num=6;break;
		case 0x0001:num=7;break;
		case 0x0080:num=8;break;
		case 0x0040:num=9;break;
		case 0x0020:num=10;break;
		case 0x0010:num=11;break;
		case 0x0800:num=12;break;
		case 0x0400:num=13;break;
		case 0x0200:num=14;break;
		case 0x0100:num=15;break;
		case 0x8000:num=16;break;
		case 0x4000:num=17;break;
		case 0x2000:num=18;break;
		case 0x1000:num=19;break;
		default :num=0;break;
	}
	return num;
}

void key_prc(){
	uchar key_up,key_down,key_val;
	key_val=Key_read();
	key_down=key_val&(key_val^key_old);//按下瞬间,key_down为1,key_up为0,按住的过程都为0
	key_up=(~key_val)&(key_val^key_old);//抬起数据为1
	if(key_down==12){//12按键按下
		
	}
    //对13按键进行2s长按键测试
	if(key_down==13){//key_down按下
        key_long_flag=1;
        key_long_time=0;
        key_long_time_flag=0;
	}
    if(key_up==13)//按键抬起
    {
        key_long_flag=0;
        key_long_time=0;
        key_long_time_flag=0;    
    }
	key_old=key_val;
	
}

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

void Timer0_Service() interrupt 1{
	key_time=(key_time+1)%10;
    if(key_long_flag==1){
        key_long_time=(key_long_time+1)%2000;   
    }
    if(key_long_time==0&&key_long_flag==1){
        key_long_time_flag=1;
        key_long_flag=0;
    }
}

void main(){
	Timer0Init();//一些初始化我就不配置了,比如关灯关闭蜂蜜器之类的
	while(1){
		if(!key_time){//10ms扫描一次按键
			key_prc();
            if(key_long_time_flag){//key13长按2sy以上
                key_long_time_flag=0;

            }
        }
	}
}

最后说点小总结,上面是模块化的总结

继电器L10为Y5中的P04;即P0=0x10;蜂鸣器Buzz为Y5中的P06;即P0=0x40;

LED或者数码管显示出现闪烁,说明他们间隔时间太长。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值