51单片机必须加while(1)——51单片机IO配合定时器timer0中断产生一定频率的PWM波


在利用51定时器定时中断方式使用IO口产生一个PWM波时,遇到了一些bug:

问题

这段代码main里没有while1,导致定时器中断产生的PMW并没有输出。见下图

void main()
{
	uchar x = 66; 
	Init_LCD1602(); //LCD1602初始化
	Timer0Init();
	L293D_IN2 = 0;
	L293D_EN = 1;
	
//	while(1)
//	{
		LCD1602_Dis_OneChar(0,0,pwm_t/100+'0');
		LCD1602_Dis_OneChar(1,0,pwm_t%100/10+'0');
		LCD1602_Dis_OneChar(2,0,pwm_t%10+'0');
//	}
}


//中断函数
void TIM0_INTR()	interrupt 1
{
	pwm_t++;
	if(pwm_t == 250)
	{
		pwm_t = 0;
		L293D_IN1 = 0;
	}	
	if(pwm_t == pwm_value)
		L293D_IN1 = 1;
//	if(pwm_t == 250)
//		pwm_t = 0;
//	
//	if(pwm_t <= pwm_value)
//		L293D_IN1 = 1;
//	else	if(pwm_t <= 250)
//		L293D_IN1 = 0;
	LED = !LED;	
}

在这里插入图片描述

修改

加入while(1)《内容不重要》

void main()
{
	uchar x = 66; 
	Init_LCD1602(); //LCD1602初始化
	Timer0Init();
	L293D_IN2 = 0;
	L293D_EN = 1;
	
	while(1)
	{
		LCD1602_Dis_OneChar(0,0,pwm_t/100+'0');
		LCD1602_Dis_OneChar(1,0,pwm_t%100/10+'0');
		LCD1602_Dis_OneChar(2,0,pwm_t%10+'0');
	}
}


//中断函数
void TIM0_INTR()	interrupt 1
{
	pwm_t++;
	if(pwm_t == 250)
	{
		pwm_t = 0;
		L293D_IN1 = 0;
	}	
	if(pwm_t == pwm_value)
		L293D_IN1 = 1;
//	if(pwm_t == 250)
//		pwm_t = 0;
//	
//	if(pwm_t <= pwm_value)
//		L293D_IN1 = 1;
//	else	if(pwm_t <= 250)
//		L293D_IN1 = 0;
	LED = !LED;	
}

在这里插入图片描述
可以看到正常输出。

原因分析

如果不加while循环,程序跑完之后会被软复位,重新进入到main函数,即重复启动->运行->结束-> 软复位
因为在嵌入式中,main函数是不能返回的,而虽然我们所编写的单片机程序是用的是C语言,可最终下载到单片机里运行的程序包含两个部分:一是我们编写的程序代码,另一部分是编译器自动生成的代码,例如在keil里,观察我们所写的C语言程序在转换成汇编语言后,单片机的代码区,没有写程序的部分,例如全1或全0区域,程序运行到该区域后就会造成意料不到的结果,在没有while(1)的去情况下运行到最后一行的时候,会自动跳转到main函数的第一行,就造成了main()函数的返回。不同的C语言实现的单片机初始化代码会有不同的表现,例如:在cal_main后jmp,或者是在call_main后jmp 0,这些将会导致不可预料的结果。

验证分析–不严谨

使用LED的闪烁(因为之前的程序调试正好用到了)
在这里插入图片描述

在我最开始的验证过程中,可以从之前的程序中看到我加了一个LED,最开始两种情况都有LED闪烁,都符合程序预设的结果,不过频率不一样,但是没太在意;
但实际上就是闪烁频率不一样,才显示出了问题所在:

如果加了while(1),那么main会卡在while(1)处,此时定时器中断正常,如果设置LED没1s闪一次,那确实就会如此。
但是如果没加while(1),第一次执行LED翻转一次,然后马上返回main 的第一句,重新开始执行,又一次从暗到亮,也会有一个proteus中肉眼看见的翻转,但是频率很快,几乎看不见灭,这是因为重复执行main,只能看到第一次的效果。
所以我们可以确定,main函数不加while就会重复执行,有一个软复位的过程。

未解决疑惑点:

在上面的代码中,定时器中断里还有另一段代码,在之前的过程中,如果我用这段产生PWM,并且不加while1,他的占空比是变化的,也就是说,他是自动PWM调制了,类似呼吸灯的效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

以上两张图片就是仿真时截图,可以看到占空比不断变化,但是实在是不懂为什么会这样。。。。。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值