⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spwm_16k.c

📁 用PIC16F876A产生2路SPWM波
💻 C
字号:
#include<pic.h>
//PIC16F876A

//-系统配置,选择高速晶振,上电延时复位,掉电复位使能,代码保护,打开看门狗
__CONFIG( HS & PWRTEN & BOREN & PROTECT & WDTEN );


//----------------------------------------------------------
bank1 unsigned char tm_sum;//系统实际变量
bank1 float sin_am, sin_l, sin_d;//浮点数,幅值变量,临时变量,临时变量
bit sin_up;//sin函数正负半周标志
bit b_timer_ok;	//定时标志



const unsigned char PWM_TAB[]={

0,25,50,74,98,120,142,162,180,197,212,
225,235,244,250,254,255,254,250,244,235,
225,212,197,180,162,142,120,98,74,50,25
/*
	40,50,73,85,100,113,127,141,157,170,180,189,196,200,203,
	204,//正半周
	204,//负半周
	203,200,195,188,179,169,157,144,129,113,96,78,59,39,15
*/
};							
unsigned char index;//SIN函数表查表变量


//软件延时子程序*/
void DELAY(void)
{
 	unsigned int i;
   	for(i=2000;i>0;i--) CLRWDT();
}

/*****************************************************************************************************
* 函数:port_init()
* 功能:IO初始化
* 输入:无
* 输出:无
*****************************************************************************************************/
void port_init(void)//端口初始化
{
	//-端口b设置
/*
	TRISB0 = 0x00;	//RB端口方向设置,输出
	PORTB  = 0;		//输出0
	RBPU   = 0;		//使能内部弱上拉
	INTE   = 0;		//禁止RB0中断
	RBIF   = 0;
//	RBIE   = 1;		//允许RB端口电平变化中断
	*/
	//-端口c设置
	TRISC = 0x00;		//PORTC are outputs
	PORTC = 0;		//输出为0
/*	
	//-timer0 init
	T0CS = 0;		//选择内部指令时钟
	T0IF = 0;
	//T0IE=1;		//在第一次ccp1比较后打开中断使能
	//timer1
	TMR1CS=0;		//定时器模式
*/
}

/*****************************************************************************************************
* 函数:ISR_CCP()
* 功能:CCP初始化
* 输入:无
* 输出:无
*****************************************************************************************************/
void CCP_Init(void)
{
	CCPR2L = 0X00;	//设置CCP2,0%的脉宽输出
	CCPR1L = 0X00;	//设置CCP1,0%的脉宽输出
	TRISC1 = 0;
	TRISC2 = 0;		//RC1,RC2输入模式
	TRISC  = 0X00;	//PORTC are outputs
	PR2    = 0XFF;	//设置PWM的工作周期,16Mhz,PWM周期15.562khz
	CCP1M3 = 1;
	CCP1M2 = 1;		//CCP1模块PWM模式
	CCP2M3 = 1;
	CCP2M2 = 1;		//CCP2模块PWM模式
	sin_up = 1;		//正负半周SIN函数
	index  = 0;		//脉宽周期调整计数器
	sin_am = 1;		//sin函数的幅值
}

/*****************************************************************************************************
* 函数:ISR_CCP()
* 功能:CCP中断
* 输入:无
* 输出:无
*****************************************************************************************************/
void ISR_CCP(void)
{	
	if(index == 31)
	{
		index = 0;
		sin_up = !sin_up;
	}

	sin_l = sin_am * PWM_TAB[index];

	if(sin_l >= 255)
		sin_l = 255;	//限幅
		
	if( sin_up )
	{
		CCPR1L = 0;
		CCPR2L = (unsigned char)sin_l;
		
	}//换向
	else 
	{
		CCPR2L = 0;
		CCPR1L = (unsigned char)sin_l;
		
	}//换向
	
	index++;
}

/*****************************************************************************************************
* 函数:isr_servers()
* 功能:中断服务程序
* 输入:无
* 输出:无
*****************************************************************************************************/
void interrupt isr_servers(void)
{
	//--定时器2中断服务函数
	if(TMR2IF & TMR2IE)
	{
		TMR2IF = 0;
		ISR_CCP();
	}
	
	CLRWDT();//清除看门狗
	/*
	if(RBIF && RBIE)
	{
		RBIF=0;
		if(!RB6)
			k=1;
	}//端口b中断服务函数
*/
	//--定时器1中断服务函数
	if(TMR1IF & TMR1IE)
	{
		TMR1IF = 0;
		if( ++tm_sum >= 10 )
		{
			tm_sum = 0;
			//b_timer_ok = 1;
			RC3 = !RC3;
		}
	}
}

main(void)
{
	OPTION = 0x0F;

	CLRWDT(); 		//清除看门狗
	port_init();		//端口初始化

	PEIE    = 1;		//外围模块中断使能
	GIE     = 1;		//开全局中断

	TMR1CS  = 0;		//Fosc/4
	T1SYNC  = 0;		//与外部时钟输入同步
	TMR1H   = 0xFD;
	TMR1L   = 0x10;	//定时器1初值
	TMR1IE  = 1;		//定时器1中断使能	
 	TMR1ON  = 1;		//打开定时器1

	TOUTPS3 = 0;
	TOUTPS2 = 1;
	TOUTPS1 = 0;
	TOUTPS0 = 0;		//定时器2后分频器5分频
	TMR2IE  = 1;		//打开定时器2中断使能
	TMR2ON  = 1;		//打开定时器2

	CCP_Init();		//开始SPWM

	
	while(1)
	{
		CLRWDT(); 
		if( b_timer_ok )
		{
			b_timer_ok = 0;
		//	RC3 = !RC3;	
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -