蓝桥杯单片机-各模块总结

本文总结了蓝桥杯单片机省赛中的重点技术,包括IIC驱动(AT24C02、PCF8591)、DS1302和DS18B20驱动、NE555频率读取、外部中断、矩阵按键、PWM输出等,并强调了在编程过程中的注意事项,如延时、中断、地址设置等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

 

一、省赛中开发平台涉及的模块:

1、IIC驱动

2、DS1302驱动

3、onewire驱动

4、定时器读取NE555频率

二、一些功能性操作

1、外部中断

2、矩阵按键

3、PWM输出

4、毫秒延时函数

三、需要注意的一些点


 

一、省赛中开发平台涉及的模块:

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、可以直接将十进制数与十六进制数进行比较

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值