程序在此:
#include<pic.h>
//12F675
//*****************
__CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & BOREN & PROTECT & CPD);
//__CONFIG(INTIO & WDTEN & PWRTEN & MCLRDIS & BOREN & PROTECT & CPD);
//内部RC振荡器普通IO口;无效看门狗;上电延时;内部复位;掉电复位;代码保护;数据保护
#define PWM GPIO5
#define PWM_DIR TRIS5
#define AD_CH1 GPIO0
#define ON 1
#define OFF 0
/////////////////////////////////////
//变量定义
volatile unsigned char out_pwm;
unsigned char input_ad;
unsigned char index=0; //用于周波控制的计数器
unsigned char index_len1 =100; //波形前段输出波形的周期.
unsigned char index_len2 =100; //波形后段输出波形的周期.
unsigned char index_on1; //波形前段的开 周波数
unsigned char index_off1; //波形前段的关 周波数
unsigned char state1_cnt; //波形前段的重复次数
unsigned char index_on2; //波形后段的开周波数
unsigned char index_off2; //波形后段的关周波数
unsigned char stage=0; //波形所处的阶段
////////////////////////////////////
// 定义0%-100%的波形数据数组.
// 先是开的波数,再是关的波数,然后又是开的波数,再是关的波数.以255为数据结束标记.
const unsigned char wave[51][5] =
{
//表格指定规则,开波数目和总波数(100),能约分先约分
//产生约分后的新的纵波束和开波数目
//将(总的波数)/(开波数)=重复次数...最后一次关波数
//为了方便列举各种情况,最后一次的开关波数均允许调整,
//因此重复次数要减1。
// 相当于(总的波数)/(开波数)有余数存在时,可将重复次数减1,将最后一个开关波,
// 当作个例来处理,如果没有余数存在则重复一次就可以了.最后一个开关波数均为0
// 51%-100%控制,可以将参考0-50的做法.将被控波改为关波数,
// 同时,关波数的数码就是(100-开波数)
0,2 ,1,0,2, //0:0-开波数,-2关波数-0次数,-最后一次的开关波数均为0
1,99,1,1,99, //1:1-开波数,-99关波数-次数1,-最后一次的开关波数均为0无需处理
1,49,1,1,49, //2:1on, 49off,1次,
1,32,2,1,33,//3:1on, on1off32 ,2times=66,再on1off33,共100
1,24,1,1,24, //4:1on, 24off,1times,last count 24,
1,19,1,1,19, //5
1,15,2,1,17,//6/100: 3/50相当于on1off15,2次共32波,加上on1off17,共50
1,13,6,1,15,//7/100: on1off13 6times共84,加上on1off15,共100波
1,11,1,1,12,//8/100=2/25
1,10,8,1,11,//9/100,
1,9 ,1,1,9, //10/100= 1/10 on1off9, 1times
1,8,10,1,9, //11/100 相当于:开1-关8,共10次再开1关9一次
1,7,2,1 ,8, //12/100=3/25; 开1关7共3次,最后一次多关1,为8
1,7,12,1,3, //13/100 ,开1关7,共12次,共96波 在开1关3,共计100
1,6,6,1,7, //14/100=7/50, 开1,关6,共6次,共42波,再开1关7,共计50
1,5,2,1,7, //15/100=3/20; on1off5 2times,再开1guan7.共20
1,5,3,1,6, //16/100=4/25,on1off5 ,3times, 再开1关6共25
1,5,16,1,3, //17/100on1off5,16times,再开1关3,共100
1,5,8,1,1, //18/100=9/50, on1off5,8times,再on1off1共50次
2,8,9,1,9, //19/100,on2off8, 9times,再on1off9,共100个波,开波数为2x9+1=19
1,4,1,1,4, //20/100=1/5, on1off4 1times,
1,4,19, 2,3, //21/100 on2off8, 9times,再on3off7,共100个波,开波数为2x9+3=21
1,4,9, 2,3, //22/100=11/50; on1off4, 9times,then on2off3,total50,on times=1x9+2
1,4,19, 4,1, //23/100 ,on2off8, 9times,再on5off5,共100个波,开波数为2x9+5=23
1,3,5, 1,4, //24/100=6/25,
1,3,1, 1,3, //25/100=1/4;
1,3,12, 1,1, //26/100=13/50, on1off 3,12times,then on1off1,total 48+2=50
2,5,13, 1,8, //27/100 on2off5 ,13time,=91+1+8=100,on times 2x13+1=27
1,3,6, 1,0, //28/100=7/25,
2,5,14, 1,1, //29/100,
1,2,2, 1,3, //30/100=3/10, on1off2, 2times,then on1off3.total 10
1,2,30, 1,9, //31/100
1,2,7, 1,3, //32/100=8/25;
1,2,32, 1,3, //33/100 ,
1,2,16, 1,1, //34/100=17/50,
1,2,6, 1,1, //35/100=7/20;
1,2,8, 1,0, //36/100=9/25,
1,2,31, 6,1, //37/100
1,2,15, 4,1, //38/100=19/50,
1,2,30, 9,1, //39/100,
1,1,1, 1,2, //40/100=2/5,
2,3,19, 3,2, //41/100
1,1,20, 1,9, //42/100=21/50;
2,3,19, 5,0, //43/100 ,
1,1,10, 1,4, //44/100=11/25,
1,1,8, 1,3, //45/100=9/20;
1,1,22, 1,5, //46/100=23/50,
1,1,46, 1,7, //47/100
1,1,11, 1,2, //48/100=12/25,
1,2,30, 9,1, //49/100,
1,1,1, 1,1, //50/100=1/2,
};
/////////////////////////////////////
// 函数声明
unsigned char ad_rd_filtered( void );
unsigned char ad_rd( void );
void interrupt zd(void); //中断函数
unsigned char get_pwm( unsigned char in_ad );
void delay_us( unsigned char n );
void pwm( unsigned char cmd );//操作pwm输出
//主函数***************************************************
void main( void )
{
TRISIO=0b11111111; //初始化IO端口
PWM_DIR = 0; //PWM所在引脚设置为输出
PWM =0 ;
delay_us(200);
CMCON=7; //不使用比较仪,即IO口为普通数字端口
ADCON0=0B00000001;
//*******************
//bit7--0:左移AD转换结果,使用10位结果中的高8位
//bit6--0:参考电压选用VDD
//bit5--0:无效
//bit4--0:无效
//bit3--0:两位共同表示AD转换的通道
//bit2--0:/本例选择通道0
//bit1--0:设定此位开始转换,转换完成硬件清0
//bit0--1:允许AD转换的总开关
//*******************
ANSEL=0B00010001;
//*******************
//bit7--0:无效
//bit6--0:
//bit5--0: >AD转换时钟选择位,本例选择"系统时钟/8"
//bit4--1:/
//bit3--0:
//bit2--0: IO引脚功能选择端,为1时作为模拟输入端,
//bit1--0: /为0时作为数字引脚
//bit0--1:/ 选择AD0作为输入
//*******************
OPTION=0B00000111;
//*******************
//bit7--0:无效
//bit6--0:
//bit5--0: >AD转换时钟选择位,本例选择"系统时钟/8"
//bit4--1:/
//bit3--0: PSA=0;将分频比分配给tmr0
//bit2--0:
//bit1--0: 设置tmr0的分频比为1/256
//bit0--1:/
//*******************
//T0IF=0; //清除TMR0中断标志位
GIE=1; //使能全局中断
//T0IE=1; //全能TMR0中断
/////////////////T1初始化
T1CON =0x00;//设置时钟为Fosc/4 分频比为1
TMR1IF = 0;//清楚t1中断标志
TMR1IE =1;//t1中断允许
PEIE =1; //允许外设中断
TMR1L = (65535 - 20000)%256;//加载初值, 20ms
TMR1H = (65535 - 20000)/256;//加载初值, 20ms
TMR1ON=1;//启动time1
while(1)
{
asm("clrwdt");//喂狗
}
}
//中断函数*************************************************
void interrupt zd(void)
{
if( TMR1IF == 1 )
{
TMR1IF = 0;
TMR1ON=0;//关闭定时器1
//////////////////////////////////////////////
//=========1 波形的初始化处理,读取波形表
if( stage == 0)
{
input_ad = ad_rd_filtered(); //读取电压值
out_pwm = get_pwm(input_ad); //计算输出的占空比
index =0;
if(out_pwm<=50)
{
index_on1=wave[out_pwm][0]; //波形开
index_off1=wave[out_pwm][1]; //波形关
state1_cnt=wave[out_pwm][2];//读取重复次数
index_len1 = wave[out_pwm][1]+wave[out_pwm][0];
//读取周期表中的周期(总的周波数)
index_len2 = wave[out_pwm][3]+wave[out_pwm][4];
//读取周期表中的周期(总的周波数)
index_on2 =wave[out_pwm][3]; //尾部波形-开
index_off2=wave[out_pwm][4]; //尾部波形 关
}
else//50以上.将pwm电平取反.当作50以下的情况处理
{
index_on1=wave[100-out_pwm][0]; //波形开
index_off1=wave[100-out_pwm][1]; //波形关
state1_cnt=wave[100-out_pwm][2];//读取重复次数
index_len1 = wave[100-out_pwm][1]+wave[100-out_pwm][0];
//读取周期表中的周期(总的周波数)
index_len2 = wave[100-out_pwm][3]+wave[100-out_pwm][4];
//读取周期表中的周期(总的周波数)
index_on2 =wave[100-out_pwm][3]; //尾部波形-开
index_off2=wave[100-out_pwm][4]; //尾部波形 关
}
//////////////////////////////////////
//波形开始时
if( index == 0 )
{ //////////////////////////////////////////////////////
if(out_pwm == 0)
{
pwm(OFF);
}
else
{
pwm(ON);
}
}
stage =1; //状态递进
index =1;
}
//end =========1 波形的初始化处理,读取波形表
////////////////////////////////////////////////////////////////////////////
//=========2 波形的前面段处理
/////////////////////////////////////////////////////////////////////////////
else if( stage ==1 )
{
/////////////波形由开到关
if(index ==index_on1 )
{
pwm(OFF);
}
/////////////////////////////////////////////////周期重新开始处理
else if( index == index_len1 )
{
index = 0;//归零,准备下一个周期
state1_cnt --;
pwm(ON);
if( state1_cnt ==0 )//前段波形循环结束
{
stage =2;
}
}
index++;
}
////////////////////////////////////////////////////////////////////////////
//end =========2 波形的前面段处理
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//=========3 波形的后段处理
////////////////////////////////////////////////////////////////////////
else if( stage ==2 )
{
///////////////////
//如果补充波形不为0
if(index_on2!=0)
{
if( index ==0 )
{
pwm(ON);
}
else
if( index >= index_on2)
{
pwm(OFF);
}
/////////////////////////////////////
index ++;
///////////////////////////////////完整的一个波形输出结束
if( index== index_len2)
{
index =0;
stage =0;
}
}
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////重新加载计数器初值
TMR1L = (65535 - 20000)%256;//加载初值, 20ms
TMR1H = (65535 - 20000)/256;//加载初值, 20ms
TMR1ON=1;//启动time1
}
}
/* ad转换程序 */
unsigned char ad_rd( void )
{
unsigned char ret=0;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
GODONE =1 ;
while(GODONE ==1);
ret = ADRESH;
return ret;
}
/* ad 滤波程序 */
unsigned char ad_rd_filtered( void )
{
unsigned char cnt=0;
unsigned char ret=0;
unsigned int total=0;
for( cnt =0 ;cnt<4 ; cnt++ )
{
total =total+ ad_rd();
}
total = total>>2;
ret = (unsigned char)total;
return ret;
}
/* 计算输出pwm百分比 */
unsigned char get_pwm( unsigned char in_ad )
{
unsigned char ret;
if( in_ad <= 51)//1v电压对应ad
{
ret = 0; //pwm百分比为0
}
else
if( in_ad >51 && in_ad <255 )
{
ret = ((unsigned int)(in_ad-51) *(unsigned int)100)/(unsigned int)(255- 51);
}
else
{
ret =100;
}
return ret;
}
void delay_us( unsigned char n )
{
while( n-- )
{
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
void pwm( unsigned char cmd )
{
if( cmd == ON )
{
if( out_pwm<=50 )
{
PWM =1; //到了关周期,将输出置为0;
}
else
{
PWM=0;
}
}
else
{
if( out_pwm<=50 )
{
PWM =0; //到了关周期,将输出置为0;
}
else
{
PWM=1;
}
}
}
5v对应,一定周期内周波为100%,如以2s为周期 ,控制波形再去触发一个固态继电器,控制输出的220vac的周波数,
实现一个周波过零控制
(原文件名:11.JPG)
一周热门 更多>