蓝桥杯51单片机设计

#定时器中断原理#

(这个都是数模电模的知识,看不懂的宝子不用担心哒,但是原理还要知道一点哦^_^)

①定时器

由16位计数器组成,每加一次时间固定(1微秒)

②晶振原理

晶振具有压电效应,即在晶片俩极外加电压后晶体会产生变形,反过来,如果外力使晶片变形,则两极上就会产生电压

③晶振分类:

1.有源晶振:震荡器,有四个引脚,不需要CPU的内部振荡器,信号稳定,质量较好,连接方式简单,产生信号为方波信号(特例位正弦波信号)示波器测信号与GND之间,供电便能产生一个时钟信号,误差最小为0.1PPM

2.无源晶振:晶体,一般为2引脚的无极性器件,一般需要借助与负载电容形成的时钟电路才能产生震荡信号,产生正弦波信号,用示波器测一个引脚与地之间的波形,需要特殊的引脚搭配(XTAL1与XTAL2指的是8051系单片机上常见的用于接“晶振”的俩个引脚,从原理来说,这俩个引脚与MCU内部的反相器相连接,反相器与外部的晶振组成一个构成一个皮尔斯振荡器,误差最小为5PPM

下面为晶振原理图👇

晶振+俩个电容→形成12MHZ正弦波→(整形)方波12MHZ→(12分频)1MHZ(周期1微秒)

方波每一个脉冲为1微秒,提供时钟

④单片机中断逻辑

12MHZ晶振整形成12MHZ方波再分频成1MHZ的脉冲信号,周期为1微秒,一个脉冲信号使加法计数器加一,加到65535后,再加一就会溢出,产生中断标志位为1,触发定时器中断,进入中断服务函数,硬件将中断服务函数标志位归0,加法计数器开始加一(中断函数不能执行太久,不然又会进入中断,系统死机),中断服务函数执行完,返回主函数

(补充)51单片机为八位单片机(寄存器八位)

计数器为16位(高八位THO与低八位TLO整合)寄存器加一直到填满16位,十进制为65535,再加一,寄存器会清零,在16位外会产生1(进位信号→计数器中断的标志位,计数器计数完毕,进入中断函数,执行完毕后再执行主函数)

下面为示意图👇

16位计数器,从0开始计数到产生一个标志位,需要(65535(满)+1(溢出))微秒

⑤初始化

初始化 装初值①THO=(65536-你所需要的值)/256

       ②TLO=(65536-你所需要的值)%256

中断函数{

重装初值

①THO=(65536-你所需要的值)/256

②TLO=(65536-你所需要的值)%256

     }

⑥手动计算

⑦知识点:

1.15系列51单片机由单个定时/计数器,T0,T1,T2,为16位加法计数器,由低8位TL0(TL1,TL2)和高8位TH0(TH1,TH2)俩个寄存器组成,最大计数值位65535个计数脉冲

重中之重!!!

编写中断服务函数

11. 程序设计

12. 实现多个延时函数

.定时器初始化:(12MHZ 1ms  16位自动重装)

.中断服务函数:

count++;//count1++//count2++

If(count==200)//200ms计时

 count =0;

If(count1==500)  count 1=0;

If(count2==1000) count2=0;

15.函数编写示范

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char

//定义
sbit LSA=P2^5;
sbit LSB=P2^6;
sbit LSC=P2^7;

sbit S5=P3^2;
uchar state;

//hc573定义
void hc573(uint channel)
{
	switch(channel)
	{
		case 4:LSA=0;LSB=0;LSC=1;break;
		case 5:LSA=1;LSB=0;LSC=1;break;
		case 6:LSA=0;LSB=1;LSC=1;break;
		case 7:LSA=1;LSB=1;LSC=1;break;
	}
}
//延时函数
void delay_ms(uchar xms)	//@12.000MHz
{
	for( ;xms>0;xms--)
	{
		unsigned char data i, j;

		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);
	}
}

//初始化
void init()
{
	hc573(4);
	P0=0XFF;
	hc573(5);
	P0=0X00;
	EA=1;
	EX0=1;//外部中断0
	IT0=1;//外部中断0下降沿触发
	//外部中断函数的初始化
}

//led控制函数
void led()
{
	  hc573(4);
		if(state==1)
		{
			P0=0XFE;
		}
		else if(state==2)
		{
			P0=0XFF;
			delay_ms(500);
			P0=0XFE;
			delay_ms(500);
		}
		else
		{
			P0=0XFF;
		}
	//控制L1灯的开关于闭合,用state计数
	//state=0,灯灭
	//state=1,灯亮
    //state=3→state=0,灯灭
		//(循环)
}
//外部中断函数
void External() interrupt 0
{
	hc573(4);
	if(S5==0)
	{
		delay_ms(10);//延时消抖
		if(S5==0)//开关闭合
		{
			state = 1+state;//用于循环计数
			if(state==3)
			{
				state=0;
			}
			
			while(S5==0);//S5一直是闭合状态
			delay_ms(10);//延时消抖
			while(S5==0);//按键S5若是闭合,一直维持该状态
		}
	}//消抖			
}
	

//主函数
void main()
{
	init();
  while(1)
 {
    led();	 
 }
}
	

16.定时器解决之前led点亮问题

#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
//整体思路:
//跟随模式让L1亮起→LE为1→Y4C为1→Y4为0→P25 P26 P27 为001→倒着看为100(二进制)
//位定位
sbit LSA =P2^5;
sbit LSB =P2^6;
sbit LSC =P2^7;
sfr AUXR =0x8e;//

uchar count;//进入中断函数的次数
uchar state_led;//led1()的状态码
uchar position;//led2()led的移位
uchar direction;//led2()led的移动方向(向左移或者向右移)

//hc573初定义
void hc573(uint channel)
{
	switch(channel)
	{
		case 4:LSA=0;LSB=0;LSC=1;break;
		case 5:LSA=1;LSB=0;LSC=1;break;
		case 6:LSA=0;LSB=1;LSC=1;break;
		case 7:LSA=1;LSB=1;LSC=1;break;
	}
}
//蜂鸣器初始化
void init_system()
{
	hc573(5);
	P0=0X00;
	//LED初始化是熄灭状态
	hc573(4);//Y4为0状态→跟随模式
	P0=0Xff;//等势,灯全灭
}
////延时函数+时间单位
//void delay_ms(uint xms)//标参数,执行5次就是5ms
//{
//	//@12.000MHz
//	for ( ;xms>0;xms--)
//	{
//		unsigned char data i, j;

//		i = 12;
//		j = 169;
//		do
//		{
//			while (--j);
//		} while (--i);//执行1ms
//  }
//}

//定时器初始化50ms
void initial_timer0()
{
	AUXR &=0x7f;//定时器12t模式
	TMOD &=0xf0;//设置定时器模式
	TL0 =0xb0;
	TH0 =0x3c;//定时初值
	TF0=0;//清楚tf0标志
	EA=1;//总开关闭合
	ET0=1;//定时器0
	TR0=1;//定时器0开始计时标志
}
//定时器中断服务函数
void timer0() interrupt 1
{
	count ++;//记录次数
	if(count==10)//进行10次为500ms
	{
		count =0;//count归零
		state_led=1-state_led;//led1的状态变化
		//下面的函数跟之前做的for函数类似
		if(direction==0)//向右移(从左到右依次点亮)
		{
			position++;
			if(direction==8)//灯全部点亮状态,若是从俩边到中间点亮,需要改为4
			{
				direction=1;//方向改变,向左移(从右到左依次熄灭)
			}
		}
		else
		{
			position--;//从右到左依次熄灭
			if(position==0)//全部熄灭状态
			{
				direction=0;//改变方向
			}
		}
	}
}

//灯函数集
void led1()//led每隔500ms闪烁一次
{
	hc573(4);
	if(state_led==0)
	{
		P0=0XFF;
	}
	else 
	{
		P0=0X00;
	}
}

void led2()//led从左到右依次点亮,在从右到左依次熄灭
{
	hc573(4);
	P0=0XFF<<position;//实现条件,position每隔500ms加1(从左到右依次点亮)
	//再position每隔500ms依次减一(从右到左依次熄灭)
}

void led3()//led每次只亮一个,从左到右点亮,再从右到左点亮,时间间隔500ms
{
	hc573(4);
	P0=~(0X01>>position);
}
 void led4()//每次只亮俩个,从左到右依次点亮,再从右到左点亮
 {
	 hc573(4);
	 P0=~(0X03<<position);
 }
 
 void led5()//俩边到中间点亮,在从中间到俩边熄灭
 {
	 hc573(4);
	 P0=~((0XFF<<position)&(0XFF>>position));
 }
 void led6()//每次只亮俩个,从俩边到中间靠拢,在从中间道理啊Bain扩散,时间间隔500ms
 {
	 hc573(4);
	 P0=~((0X80>>position)&(0x01<<position));
 }
 //void led()
//{
//	 uint i=0;
//	for(i=0;i<9;i++)
//	{
//	     P0 = 0xff << i;
//		   delay_ms(500);
//	}
	//从俩边到中间点亮,再从中间到俩边熄灭
	/*for(i=0;i<4;i++)
	{
		P0=(0xff<<i) & (0xff>>i);
		delay_ms(500);
		
	}
	for(i=5;i<9;i++)
	{
		P0=(0xff>>i) | (0xff<<i);
		delay_ms(500);
	}
	*/
	//分别从左到右,从右到左依次点亮
	/*for(i=0;i<9;i++)
	{
		P0=0xff<<i;
		delay_ms(500);
	}
	for (i=8;i>0;i--)
	{
		P0=0xff<<i;
		delay_ms(500);
	}*/
		
	
	 /* P0=0X00;//L1=L2=L3=L4=L5=L6=L7=L8=0;
		delay_ms(500);
		P0=0XFF;//L1=L2=L3=L4=L5=L6=L7=L8=1;
	*/
//  	delay_ms(500);//亮灭持续
//}

//主函数
void main()//main函数只执行一遍 ,时间太短,看不出效果→加时长while循环
{
	init_system();
	initial_timer0();
	//LSA=0; LSB=0;LSC=1;//跟随模式
	//L1=0;//灯亮
	//俩边等势,灯灭
//	L2=L3=L4=L5=L6=L7=L8=1;
	while(1)
	{
		led1();
		led2();
		led3();
		led4();
		led5();
		led6();

		
	}
}

#添加一嘴,之前的LED模块的代码将所有情况代码重新编写了蓝桥杯51单片机设计-CSDN博客#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值