8g-pwm
  ZeEFk3Vj14kb 2023年12月10日 25 0


```c
/*
标题:无源蜂鸣器播放音乐-两只老虎
主频:35MHz
用于:51单片机学习机-学电
资料:https://rationmcu.com
*/

#include "stc8g.h"
#include "intrins.h"

/* 寄存器定义 */
#define     PWM5C      (*(unsigned int volatile xdata *)0xFCA0)
#define     PWM53T1    (*(unsigned int volatile xdata *)0xFCC8)
#define     PWM53T2    (*(unsigned int volatile xdata *)0xFCCA)

/* 定义音调 低音 中音 高音
   音符频率对应的PWM5C值 
   低中高每种7个 一共是21个 */
unsigned int tone[21]={
0x20A0, 0x1D13, 0x19E7, 0x187E, 0x15CE, 0x136D, 0x1141, // 低音1234567
0x1058, 0x0E90, 0x0CF8, 0x0C3F, 0x0AE7, 0x09B7, 0x08A7, // 中音1234567
0x082A, 0x0746, 0x067B, 0x061E, 0x0574, 0x04DB, 0x0454  // 高音1234567
}; 

/* 两只老虎 乐谱音符 */
unsigned char music[32]={
7,8,9,7, 7,8,9,7, 9,10,11, 9,10,11,
11,12,11,10,9,7, 11,12,11,10,9,7, 7,4,7, 7,4,7
};

/* 两只老虎 每个音符的时长 
   本来是1/4 1/8 1/16 
   这里都乘以16 得出以下值 */
unsigned char time[32]={
4,4,4,4, 4,4,4,4, 4,4,8, 4,4,8,
3,1,3,1,4,4, 3,1,3,1,4,4, 4,4,8, 4,4,8
}; 


/* 固定延时1毫秒 */
void Delay1ms()		//@35MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	i = 15;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}

/* n毫秒延时函数 参数给几 就延时几毫秒 */
void delay_ms(unsigned int ms)
{
	while(ms--)
	{
		Delay1ms();
	}
}

/* 固定延时1微秒 */
void Delay1us()		//@35MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 9;
	while (--i);
}

/* n微秒延时函数 参数给几 就延时几微秒 */
void delay_us(unsigned int us)
{
	while(us--)
	{
		Delay1us();
	}
}


/* 蜂鸣器初始化 */
void beep_init()
{
	P_SW2 |= 0X80; // 允许访问XFR
	PWMSET |= (1<<5);// 使能PWM5模块
	PWM5CKS = 0X0F; // 设置为系统时钟的16分频
	PWM5C = tone[0];
	PWM53T1 = PWM5C/2; // 遇到T1输出低电平
	PWM53T2 = 0; // 遇到T2输出高电平
	PWM53CR = 0XC0;  // 把引脚设置为PWM输出口 初始电平是高电平 并关闭所有触发点中断
}
//P20-P21     P22-P23四个PWM
//10kHz
//
void PWM2_init()
{
	PWMSET |= (1<<2);// 使能PWM5模块
	P_SW2 |= 0X80; // 允许访问XFR
	PWM2CKS = 0X0B; // 设置为系统时钟的12分频
	PWM2C=(unsigned int)(921600/10000);//根据频率算得周期
	
	PWM20CR = 0XC0;  // 把引脚设置为PWM输出口 初始电平是1电平 并关闭所有触发点中断
	PWM21CR = 0XC0;  // 把引脚设置为PWM输出口 初始电平是1电平 并关闭所有触发点中断
	PWM22CR = 0XC0;  // 把引脚设置为PWM输出口 初始电平是1电平 并关闭所有触发点中断
	PWM23CR = 0XC0;  // 把引脚设置为PWM输出口 初始电平是1电平 并关闭所有触发点中断

//	PWM20T1 = PWM2C/2; // 遇到T1输出低电平
//	PWM20T2 = 0; // 遇到T2输出高电平
	
//	PWM21T1 = PWM2C/2; // 遇到T1输出低电平
//	PWM21T2 = 0; // 遇到T2输出高电平

//	PWM22T1 = PWM2C/2; // 遇到T1输出低电平
//	PWM22T2 = 0; // 遇到T2输出高电平
//	
//	PWM23T1 = PWM2C/2; // 遇到T1输出低电平
//	PWM23T2 = 0; // 遇到T2输出高电平
}
//******************************************
void HPWM2_Set(int PWMchannel, unsigned int f,float zkb)
{
    unsigned int  CycleTime;
	 P_SW2 |= 0X80; // 允许访问XFR
	//根据频率,计算周期=频率的倒数,设置计数周期
	//921600=11.0592Mhz/12=11059200/12,兆,等于10的6次方。
	//用到强制类型转换,将计算的小数强制转换为无符号整型,
	//因为计数器只能是整数,而且是0-32767之间。
//	CycleTime=(unsigned int)(921600/f);//根据频率算得周期
//	PWM2C=CycleTime; //设置PWM周期,放到对应的寄存器中。
//	CycleTime=(unsigned int)(921600/f);//根据频率算得周期
	CycleTime=100;
	PWM2C=100; //设置PWM周期,放到对应的寄存器中。
	//看设置的那个通道的占空比;
	switch(PWMchannel)
	{
		case 0:  //P20通道,PWM0的占空比,翻转点设置;
		   PWM20T1 =zkb*CycleTime; //N*zkb=Nt1
		   PWM20T2 = 0;//当计数到CYCLE的时候,会归0
		   break;
		case 1:	 //P21通道,PWM1的占空比,翻转点设置;
		   PWM21T1 =zkb*CycleTime;  //
       PWM21T2 = 0;//当计数到CYCLE的时候,会归0
		   break;
		case 2: //P22通道,PWM2的占空比,翻转点设置;
		   PWM22T1 =zkb*CycleTime;  //
       PWM22T2 =0; //当计数到CYCLE的时候,会归0
		   break;
		case 3:
		   PWM23T1 =zkb*CycleTime;   
       PWM23T2 = 0;//当计数到CYCLE的时候,会归0
		   break;	
		default:break;//
	}
	
	  P_SW2=0x00;//关闭设置开关
	
		PWMCFG23 |= 0X01;//开启PWM2,,
	// 开启PWM5,,	PWMCFG23 |= 0X10; ,,	PWMCFG45 &= ~0X10; // 关闭PWM5
}

/* 主函数 */
void main()
{
	/* 定义局部变量 */
	unsigned int i=0,j=0; // 定义两个16位变量
	
	/* 系统初始化 */
	P5M0 = 0X00;    //设置P5.0~P5.7为双向口模式
	P5M1 = 0X00;
		/* 系统初始化 */
	P2M0 = 0X00;    //设置P5.0~P5.7为双向口模式
	P2M1 = 0X00;
	
//		PWMSET |= (1<<2);// 使能PWM5模块
//	P_SW2 |= 0X80; // 允许访问XFR
//	PWM2CKS = 0X0B; // 设置为系统时钟的12分频
//	PWM2C=94;//根据频率算得周期
//	  PWM20T1 =47; //N*zkb=Nt1
//		   PWM20T2 = 0;//当计数到CYCLE的时候,会归0
//		PWM20CR = 0X80; 
//	P_SW2 = 0X00; // 允许访问XFR
//	PWMCFG23 = 0X01; // 开启PWM5
//	while(1);
//	
	//beep_init(); // 蜂鸣器初始化
PWM2_init();
	HPWM2_Set(0, 2000,0.5);

	while(1)
	{
		HPWM2_Set(0,2000,0.5);
		HPWM2_Set(1,1000,0.4);
		HPWM2_Set(2,1000,0.3);
		HPWM2_Set(3,1000,0.2);
	delay_ms(500);
		
				HPWM2_Set(0,2000,0);
		HPWM2_Set(1,1000,0);
		HPWM2_Set(2,1000,0);
		HPWM2_Set(3,1000,0);
	delay_ms(500);
			
				HPWM2_Set(0,2000,0.2);
		HPWM2_Set(1,1000,0.3);
		HPWM2_Set(2,1000,0.4);
		HPWM2_Set(3,1000,0.5);
	delay_ms(500);	
					
				HPWM2_Set(0,2000,0);
		HPWM2_Set(1,1000,0);
		HPWM2_Set(2,1000,0);
		HPWM2_Set(3,1000,0);
	delay_ms(500);	
//		for(i=0;i<32;i++)  // 两只老虎 共32个音符
//		{
//			/* 输出音符 */
//			PWM5C = tone[music[i]];//改变周期
//			PWM53T1 = tone[music[i]]/2;//占空比为50%
//			PWMCFG45 |= 0X10; // 开启PWM5
//			/* 输出音符对应的时长 */
//			delay_ms(time[i]*50);
//			/* 模仿钢琴 输出音符尾音 */
//			for(j=tone[music[i]]/2;j<tone[music[i]];j++) 
//			{
//				PWM53T1 = j;
//				delay_us(((unsigned long)time[i]*25000)/tone[music[i]]); 
//			}
//			/* 结束本次音符 */
//			PWMCFG45 &= ~0X10; // 关闭PWM5
//		}
//		delay_ms(1000);
	}
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月10日 0

暂无评论

ZeEFk3Vj14kb