目录
一、省赛中开发平台涉及的模块:
1、AT24C02                       IIC驱动
 2、PCF8591                       IIC驱动
 3、DS1302                         DS1302驱动
 4、DS18B20                      ONEWIRE驱动
 5、定时器读取NE555频率
1、IIC驱动
在IIC中读取PCF的数据和读取AT24C02的数据是一样的步骤
只是这两个器件的地址不一样 [ 助记: 亵渎(先写后读)]
AT24C02的写地址0xa0,读地址是0xa1 [ 助记:Aa] 该地址前四位由厂家规定
PCF的写地址是0x90,读地址是0x91 [ 助记:C9] 该地址前四位由厂家规定
unsigned char read_adc(unsigned char channel)
{
	unsigned char dat;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(channel);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	dat=IIC_RecByte();
	IIC_Stop();	
	
	return dat;
}
unsigned char read_eeprom(unsigned char addr)
{
	unsigned char dat;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	dat=IIC_RecByte();
	IIC_Stop();	
	
	return dat;
} 
ERPROM的写函数
unsigned char write_eeprom(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();	
}
 
notes:EEPROM的写读之间一定要有延时
DAC的设置函数
void set_dac(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);    //使能模拟输出端
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
} 
    
2、DS1302驱动
写的第一个地址是0X80,读的第一个地址是0X81
unsigned char code WRITE_ADDR[]={0X80,0X82,0X84};
unsigned char code READ_ADDR[]={0X81,0X83,0X85};
unsigned char TIME[]={0X12,0X00,0X10};	//秒分时
void DS1302_Init()
{
	unsigned char i;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i=0;i<3;i++)
	{
		Write_Ds1302_Byte(WRITE_ADDR[i],TIME[i]);
	}
	Write_Ds1302_Byte(0x8e,0x80);
}
void DS1302_Read()
{
	unsigned char i;
	for(i=0;i<3;i++)
	{
		TIME[i]=Read_Ds1302_Byte(READ_ADDR[i]);
	}
} 
notes:只有写数据需要在控制寄存器0X8e设置允许(0x00)和禁止(0x80)写入,读操作不需要
3、onewire驱动
往年的驱动都需要改延时,函数变量扩大四倍。初始化的最后一个延时改为18
然后
unsigned int read_temp()
{
	unsigned int value_l,value_h,value;
	init_ds18b20();
	Write_DS18B20(0xcc);    //跳过ROM指令
	Write_DS18B20(0x44);    //启动温度转换
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);    //读取s pad的数值
	value_l=Read_DS18B20();
	value_h=Read_DS18B20();
	value=value_h<<8;
	value+=value_l;
	value=value*6.25+0.5;	//*6.25是扩大了100倍的数据
	return value;
} 
 
 
4、定时器读取NE555频率
设置定时器时一定要仔细(修改TOMD,TR0,允许中断),设置完后记得初始化
void Timer0Init(void)		//0毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD |= 0x05;		//0x04 0x05都可;与运算
	TL0 = 0x00;		//设置定时初始值
	TH0 = 0x00;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		
}
 
void Timer1Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x20;		//设置定时初始值
	TH1 = 0xD1;		//设置定时初始值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	
	ET1=1;
	EA=1;
}
void TIME1() interrupt 3
{
	value++;
	if(value==500)
	{
		TR0 = 0;
		value=0;
		fre=TH0<<8;
		fre+=TL0;
		TH0=0;
		TL0=0;
		TR0=1;
	}
} 
 
二、一些功能性操作
1、外部中断
EX0对应S5
P33=P32=P31=P30=1;
void EXO_INIT()        //记得放入main初始化
{
    IT0=1;    //下降沿触发
    ET0=1;
    EA=1;
}
void EX0_SERVICE() interrupt
{
    
} 
2、矩阵按键
P37映射为P44,P36映射为P42
当P34与SINGAL相接时,会影响矩阵键盘最右边的一列
可以利用while实现“按一次按键,操作只执行一次”
我的按键写法:先令横(H)为1 ,S为0 (简便易更改)
sbit H1=P3^0;
sbit H2=P3^1;
sbit H3=P3^2;
sbit H4=P3^3;
sbit S1=P4^4;
sbit S2=P4^2;
sbit S3=P3^5;
sbit S4=P3^4;
void matrix_scan()		
{
	S1=S2=S3=S4=0;H1=H2=H3=H4=1;
	if(H1==0)
	{
		delay(5);
		if(H1==0)
		{
			H1=0;
			S1=S2=S3=S4=1;
			if(S1==0)key_value=1;
			else if(S2==0)key_value=2;
			else if(S3==0)key_value=3;
			else if(S4==0)key_value=4;
		}
	}
	if(H2==0)
	{
		delay(5);
		if(H2==0)
		{
			H2=0;
			S1=S2=S3=S4=1;
			if(S1==0)key_value=5;
			else if(S2==0)key_value=6;
			else if(S3==0)key_value=7;
			else if(S4==0)key_value=8;
		}
	}
	if(H3==0)
	{
		delay(5);
		if(H4==0)
		{
			H4=0;
			S1=S2=S3=S4=1;
			if(S1==0)key_value=9;
			else if(S2==0)key_value=10;
			else if(S3==0)key_value=11;
			else if(S4==0)key_value=12;
		}
	}
	if(H4==0)
	{
		delay(5);
		if(H4==0)
		{
			H4=0;
			S1=S2=S3=S4=1;
			if(S1==0)key_value=13;
			else if(S2==0)key_value=14;
			else if(S3==0)key_value=15;
			else if(S4==0)key_value=16;
		}
	}
} 
 
3、PWM输出
uint tim_count=0;
void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初始值
	TH0 = 0xD1;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
    ET0=1;
    EA=1;
}
void Time0_serve() interrupt 1        //使LED在亮度减弱(频率100hz)
{
    ++tim_count;
    if(tim_count==10)tim_count=0;
    else if(tim_count<=3){P2&=0X1F;P2|=0X80;P0=0X00;}    
    else if(tim_count>3&&tim_count<=10){P2&=0X1F;P2|=0X80;P0=0Xff;}
}
 
 
4、毫秒延时函数
void delay(uint ms)
{
    uint i,j;
    for(i=ms;i<ms;i++)
    {
        for(j=0;j<845;j++);
    }
} 
 
三、需要注意的一些点
1、pwm的频率要大于60hz,效果才比较好
2、温度读取要用uint类型的数据
3、Read_DS18B20()函数先读取的是第Byte0(低八位),再次调用的时候读取的是Byte1。注意先后顺序
4、写矩阵键盘时注意P36 P37分别映射为P42 P44
5、定时器读频率时记得将SIGNAL与P34端接
6、判断变量的范围,不可直接if(0<adc_value<60),需要if(0<adc_value&&adc_value<60)
7、LED灯轮转时,若无延时,则会出现八个LED灯全部高频微闪的现象
8、更改Time[]的数值后,要将Time的数值重新写如芯片中
9、可以直接将十进制数与十六进制数进行比较










