蓝桥杯单片机开发及应用-基础模块10-PWM脉宽调制

        关于中断以及按键、LED灯模块等都在之前的文章中介绍过了,此处不再介绍了。

一、先前知识

1.占空比

        占空比就是高电平的时间占整个周期的百分比。实质上就是定时器,是定时器的另一个用法。

        例如:100Hz,那么周期就是10ms(10000us),如果分成100小份,那么就是100us×100,如果占空比时60%,那么高电平就是60份,低电平时40份,在软件中用一个变量来进行计数,记到给定的值就翻转电平。

                                                              图一、占空比

二、所要实现的功能

        要求PWM脉宽信号的频率为100Hz,系统上电后L1处于熄灭状态,L1指示灯有四种亮度。分别是完全熄灭、10%的亮度、50%的亮度、90%的亮度。通过S7按键循环切换L1指示灯的四种亮度。程序循环实现上述功能。

三、代码实现

①参数及引脚定义

// 按键定义
sbit S7 = P3^0;

// LED灯定义
sbit L1 = P0^0;

// 参数定义
unsigned char count = 0;		// 定时器计数
unsigned char pwm_duty = 0;		// PWM数值
unsigned char state = 0;		// 按键状态

②138译码器通道选择函数

// 通道选择函数
void HC138_Init( unsigned char channel )
{
	switch( channel )
	{
		case 0:
			P2 = ( P2 & 0x1f ) | 0x00;	// 0
		break;
		case 4:
			P2 = ( P2 & 0x1f ) | 0x80;	// Y4C
		break;
		case 5:
			P2 = ( P2 & 0x1f ) | 0xa0;	// Y5C
		break;
		case 6:
			P2 = ( P2 & 0x1f ) | 0xc0;	// Y6C
		break;
		case 7:
			P2 = ( P2 & 0x1f ) | 0xe0;	// Y7C
		break;
	}
}

③初始化系统——关闭当前不需要的LED灯、蜂鸣器和继电器

// 系统初始化
void System_Init(void)
{
	// 关闭LED灯
	HC138_Init( 4 );
	P0 = 0xff;
	
	// 关闭蜂鸣器和继电器
	HC138_Init( 5 );
	P0 = 0xaf;			// 1010 1111
	
	HC138_Init( 0 );	// 关闭通道选择
}

④定时器0初始化函数

// 定时器0初始化
void Timer0_Init(void)
{
	TMOD = 0x01;    // 使用定时器0工作模式1
	ET0 = 1;
	EA = 1;
	
	// 定时初值
	TH0 = ( 65535 - 100 ) / 256;    // 10000us = 100us×100
	TL0 = ( 65535 - 100 ) % 256;
}

⑤定时器0服务函数

// 定时器0服务函数
void Timer0() interrupt 1
{
    // 由于是不能自动重装载的,所以要再次赋初值
	TH0 = ( 65535 - 100 ) / 256;
	TL0 = ( 65535 - 100 ) % 256;
	
	count++;	// 100us周期计数

    // LED灯是低电平点亮,所以实质上的占空比在这里不一样,而是低电平的周期
	if( count == pwm_duty )
	{
		L1 = 1;
	}
	else if( count == 100 )
	{
		L1 = 0;
		count = 0;
	}
}

⑥按键扫描函数

// 按键扫描
void Key_Scan(void)
{
	if( S7 == 0 )
	{
		Delay_tms( 20 );		// 消抖
		if( S7 == 0 )
		{
			while( S7 == 0 );	// 按键抬起后操作
			switch( state )
			{
				case 0:
					L1 = 0;
					TR0 = 1;	// 产生脉宽调制的时候再打开定时器,不能直接放在初始化函数中
					pwm_duty = 10;
					state = 1;
				break;
				
				case 1:
					pwm_duty = 50;
					state = 2;
				break;
				
				case 2:
					pwm_duty = 90;
					state = 3;
				break;
				
				case 3:
					L1 = 1;
					TR0 = 0;
					state = 0;
				break;
			}
		}
	}
}

⑦整个函数展示


#include <STC15F2K60S2.H>
#include "Delay_ms.h"


// 按键定义
sbit S7 = P3^0;

// LED灯定义
sbit L1 = P0^0;

// 参数定义
unsigned char count = 0;		// 定时器计数
unsigned char pwm_duty = 0;		// PWM数值
unsigned char state = 0;		// 按键状态


// 通道选择函数
void HC138_Init( unsigned char channel )
{
	switch( channel )
	{
		case 0:
			P2 = ( P2 & 0x1f ) | 0x00;	// 0
		break;
		case 4:
			P2 = ( P2 & 0x1f ) | 0x80;	// Y4C
		break;
		case 5:
			P2 = ( P2 & 0x1f ) | 0xa0;	// Y5C
		break;
		case 6:
			P2 = ( P2 & 0x1f ) | 0xc0;	// Y6C
		break;
		case 7:
			P2 = ( P2 & 0x1f ) | 0xe0;	// Y7C
		break;
	}
}


// 系统初始化
void System_Init(void)
{
	// 关闭LED灯
	HC138_Init( 4 );
	P0 = 0xff;
	
	// 关闭蜂鸣器和继电器
	HC138_Init( 5 );
	P0 = 0xaf;			// 1010 1111
	
	HC138_Init( 0 );	// 关闭通道选择
}


// 定时器0初始化
void Timer0_Init(void)
{
	TMOD = 0x01;    // 使用定时器0工作模式1
	ET0 = 1;
	EA = 1;
	
	// 定时初值
	TH0 = ( 65535 - 100 ) / 256;    // 10000us = 100us×100
	TL0 = ( 65535 - 100 ) % 256;
}


// 定时器0服务函数
void Timer0() interrupt 1
{
    // 由于是不能自动重装载的,所以要再次赋初值
	TH0 = ( 65535 - 100 ) / 256;
	TL0 = ( 65535 - 100 ) % 256;
	
	count++;	// 100us周期计数

    // LED灯是低电平点亮,所以实质上的占空比在这里不一样,而是低电平的周期
	if( count == pwm_duty )
	{
		L1 = 1;
	}
	else if( count == 100 )
	{
		L1 = 0;
		count = 0;
	}
}


// 按键扫描
void Key_Scan(void)
{
	if( S7 == 0 )
	{
		Delay_tms( 20 );		// 消抖
		if( S7 == 0 )
		{
			while( S7 == 0 );	// 按键抬起后操作
			switch( state )
			{
				case 0:
					L1 = 0;
					TR0 = 1;	// 产生脉宽调制的时候再打开定时器,不能直接放在初始化函数中
					pwm_duty = 10;
					state = 1;
				break;
				
				case 1:
					pwm_duty = 50;
					state = 2;
				break;
				
				case 2:
					pwm_duty = 90;
					state = 3;
				break;
				
				case 3:
					L1 = 1;
					TR0 = 0;
					state = 0;
				break;
			}
		}
	}
}




int main(void)
{
	System_Init();		// 系统初始化
	Timer0_Init();		// 定时器0初始化
	HC138_Init( 4 );    // 进行通道选择,要准备控制LED灯
	P0 = 0xff;
	while(1)
	{
		Key_Scan();		// 按键扫描
	}
}

四、运行图片

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽小迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值