PWM调速的C语言程序编写非常简单
PWM调速的C语言程序编写
关于PWM的原理在上一篇文章中已经说的很详细了,现在就细说一下pwmC语言程序的编写。
C语言中PWM的编写有这么几种方法;一、用普通的I/O口输出的PWM,二、使用定时计数器编写,三、就是使用片内PWM了。
1先说使用普通的I\O口编写PWM程序了。
??????使用I/O口输出PWM波形你必须首先明白PWM他的实质是:调制占空比,占空比就是波形中高电平的长度与整个波长的比值。
我们写C语言的目的是写PWM波形的一个周期。
在这个周期内高低电平的比值是可以改变的。
这也就符合了PWM的原意脉宽调制。
即高电平的宽度的调制。
当然了PWM他也可用于改变频率,我们这里只先说他改变脉宽。
?????一旦我们的C语言程序写完那么他产生的PWM波形的频率就一定了。
(也可写频率变化的PWM,难度有点大)一般我们控制使用1K到10K的PWM波进行控制。
当然了你也可在要求不是很高的地方使用频率更低的PWM波。
比如在飞思卡尔智能车比赛中我们学校使用的PWM波频率只有600HZ.
?????我们要改变一个PWM波周期内的高电平的宽度显然需要将一个PWM波的周期分成单片机可以控制的N个小的周期,N的取值越大你的调速等级越高,但产生的PWM频率就越低。
我们下面以实现100级调速为例编写PWM程序。
????先写出程序再慢慢给大家分析
???voidpwm(ucharx,uinty)???//X为占空比Y为函数使用时间
{??uinti,j,a,b;
??for(i=y;i>0;i--)?????????????????????????//定时外函数{
???for(j=7;j>0;j--)??????????????????????//定时内函数??{
???for(a=y;a>0;a--)?????????????????//PWM波高电平宽度??{
???PORTA=0X01;
??}
for(b=100-y;b>0;b--)????????????//PWM低电平宽度
{
PORTA=0X00;
}
??}
??}
}
这个程序够简单吧轻松的实现AVR单片机的PA.0口输出7KHZ左右的PWM脉冲
你可以将PORTA=0X01;改为P1.0=0X01;就可以移植到51单片机上了
为什么使用参数Y定时是因为用普通I/O口控制它的开关没有使用定时器编写的灵活。
如果这不符合你的需要你可以不使用时间参数Y控制他的开关,只要去掉关于Y的部分利用控制I/O口的方向来控制它的使用
上面的程序参数如下
在mega16单片机上使用8M晶振??
一个PWM脉冲大约128μs????
循环7次是940ms??所以输出PWM脉冲频率是7KHZ左右
注意:我使用时精度要求不高所以没有考虑for语句运行时花费的时间故实际占空比略低,但误差是很小的。
需要高精度的朋友可以自己做修改。
2.下面说如何使用定时/计数器来编写PWMC语言程序;。
]单片机C语言编程模板(PWM脉宽调制)
[转]单片机C语言编程模板(PWM脉宽调制)修改浏览权限| 删除∙- MCS-51系列单片机C语言编程PWM脉宽调制器程序模板∙- 适用于STC系列内嵌PWM的单片机产品(以STC12C2052为例)- 以PWM控制LED亮度实验电路为例/********************************************************************************************* 函数名:PWM初始化函数调用:PWM_init();参数:无返回值:无结果:将PCA初始化为PWM模式,初始占空比为0备注:需要更多路PWM输出直接插入CCAPnH和CCAPnL即可/**********************************************************************************************/ void PWM_init (void){CMOD=0x02; //设置PCA定时器CL=0x00;CH=0x00;CCAPM0=0x42; //PWM0设置PCA工作方式为PWM方式(0100 0010)CCAP0L=0x00; //设置PWM0初始值与CCAP0H相同CCAP0H=0x00; // PWM0初始时为0//CCAPM1=0x42; //PWM1设置PCA工作方式为PWM方式(使用时删除//)//CCAP1L=0x00; //设置PWM1初始值与CCAP0H相同//CCAP1H=0x00; // PWM1初始时为0//CCAPM2=0x42; //PWM2设置PCA工作方式为PWM方式//CCAP2L=0x00; //设置PWM2初始值与CCAP0H相同//CCAP2H=0x00; // PWM2初始时为0//CCAPM3=0x42; //PWM3设置PCA工作方式为PWM方式//CCAP3L=0x00; //设置PWM3初始值与CCAP0H相同//CCAP3H=0x00; // PWM3初始时为0CR=1; //启动PCA定时器}/**********************************************************************************************//********************************************************************************************* 函数名:PWM0占空比设置函数调用:PWM0_set();参数:0x00~0xFF(亦可用0~255)返回值:无结果:设置PWM模式占空比,为0时全部高电平,为1时全部低电平备注:如果需要PWM1的设置函数,只要把CCAP0L和CCAP0H中的0改为1即可/**********************************************************************************************/ void PWM0_set (unsigned char a){CCAP0L= a; //设置值直接写入CCAP0LCCAP0H= a; //设置值直接写入CCAP0H}/**********************************************************************************************/ - 程序模块/********************************************************************************************* 程序名:PWM模块调试程序(仅实验用)编写人:杜洋编写时间:2009年7月22日硬件支持:STC12C2052 12MHz接口说明:LED灌电流接P3.7接口(PWM0)修改日志:NO.1-/********************************************************************************************* 说明:/*********************************************************************************************/ #include<STC12C2052AD.H> //头文件/********************************************************************************************* 函数名:PWM初始化函数调用:PWM_init();参数:无返回值:无结果:将PCA初始化为PWM模式,初始占空比为0备注:需要更多路PWM输出直接插入CCAPnH和CCAPnL即可/**********************************************************************************************/ void PWM_init (void){CMOD=0x02; //设置PCA定时器CL=0x00;CH=0x00;CCAPM0=0x42; //PWM0设置PCA工作方式为PWM方式(0100 0010)CCAP0L=0x00; //设置PWM0初始值与CCAP0H相同CCAP0H=0x00; // PWM0初始时为0//CCAPM1=0x42; //PWM1设置PCA工作方式为PWM方式(使用时删除//)//CCAP1L=0x00; //设置PWM1初始值与CCAP0H相同//CCAP1H=0x00; // PWM1初始时为0//CCAPM2=0x42; //PWM2设置PCA工作方式为PWM方式//CCAP2L=0x00; //设置PWM2初始值与CCAP0H相同//CCAP2H=0x00; // PWM2初始时为0//CCAPM3=0x42; //PWM3设置PCA工作方式为PWM方式//CCAP3L=0x00; //设置PWM3初始值与CCAP0H相同//CCAP3H=0x00; // PWM3初始时为0CR=1; //启动PCA定时器}/**********************************************************************************************//********************************************************************************************* 函数名:PWM0占空比设置函数调用:PWM0_set();参数:0x00~0xFF(亦可用0~255)返回值:无结果:设置PWM模式占空比,为0时全部高电平,为1时全部低电平备注:如果需要PWM1的设置函数,只要把CCAP0L和CCAP0H中的0改为1即可/**********************************************************************************************/ void PWM0_set (unsigned char a){CCAP0L= a; //设置值直接写入CCAP0LCCAP0H= a; //设置值直接写入CCAP0H}/**********************************************************************************************//********************************************************************************************* 函数名:主函数调用:无参数:无返回值:无结果:程序开始处,无限循环备注:/**********************************************************************************************/ void main (void){PWM_init(); //PWM初始化PWM0_set(0x10); //设置PWM占空比while(1){//无限循环程序}}/**********************************************************************************************/ /************************************************************** 杜洋工作室/*************************************************************/- 应用实例- 使用说明。
PWM调速的C语言程序编写(非常简单)
PWM调速的C语言程序编写关于PWM的原理在上一篇文章中已经说的很详细了,现在就细说一下pwm C语言程序的编写。
C语言中PWM的编写有这么几种方法;一、用普通的I/O 口输出的PWM ,二、使用定时计数器编写,三、就是使用片内PWM了。
1 先说使用普通的I\O口编写PWM程序了。
使用I/O口输出PWM波形你必须首先明白PWM他的实质是:调制占空比,占空比就是波形中高电平的长度与整个波长的比值。
我们写C语言的目的是写PWM波形的一个周期。
在这个周期内高低电平的比值是可以改变的。
这也就符合了PWM的原意脉宽调制。
即高电平的宽度的调制。
当然了PWM他也可用于改变频率,我们这里只先说他改变脉宽。
一旦我们的C语言程序写完那么他产生的PWM波形的频率就一定了。
(也可写频率变化的PWM,难度有点大)一般我们控制使用1K到10K的PWM波进行控制。
当然了你也可在要求不是很高的地方使用频率更低的PWM波。
比如在飞思卡尔智能车比赛中我们学校使用的PWM波频率只有600HZ.我们要改变一个PWM波周期内的高电平的宽度显然需要将一个PWM波的周期分成单片机可以控制的N个小的周期,N的取值越大你的调速等级越高,但产生的PWM频率就越低。
我们下面以实现100级调速为例编写PWM程序。
先写出程序再慢慢给大家分析void pwm (uchar x,uint y) //X 为占空比 Y为函数使用时间{ uint i,j,a,b;for(i=y;i>0;i--)//定时外函数{for(j=7;j>0;j--)//定时内函数{for(a=y;a>0;a--) / /PWM波高电平宽度{PORTA=0X01;}for(b=100-y;b>0;b--) //PWM低电平宽度{PORTA=0X00;}}}}这个程序够简单吧轻松的实现AVR单片机的PA.0口输出7KHZ左右的PWM脉冲你可以将PORTA=0X01;改为P1.0=0X01;就可以移植到51单片机上了为什么使用参数Y定时是因为用普通I/O口控制它的开关没有使用定时器编写的灵活。
PWM调速C程序编写
例如:实现周期为1000us,占空比为20%的PWM,用PA0实现
首先设置T0为83 (11.0592M晶振)
T1为65501
首先初始化PA0=1,两个定时器同时打开,在定时器T1中断时拉低PA0,
在定时器T0中断时在拉高PA0,同时将两定时器初始值初始化T0为83,T1为65501
一开始设置PA0为高电平,当count1加到200的时候拉低PA0,
等count1到1000了在拉高PA0,同时复位count1=0,
不过这样做的缺点是精度不高,要是PWM所需周期段,精度高的话还是用两个定时器来实现;
************************************************/
SREG=0x80;
while(1);
}
#pragma vector = TIMER0_OVF_vect
__interrupt void TIMER0_OVF(void)
{
PWM_PA0=1;
TCNT0=0x53;
}
#pragma vector = TIMER1_OVF_vect
__interrupt void TIMER1_OVF(void)
}
void timer0_init(void)
{
SREG=0x80;
TIMSK|=(1<<TOIE0);
TCCR0|=(0<<CS02)|(0<<CS01)|(1<<CS00);
TCNT0=0x91;
}
void main(void)
{
port_init();
PWM编程C语言例
Delay_ms(10); //延时10ms
}
}
/*PWMconf:PWM初始化设置--------------------------------*
*功能:PWM脉冲周期、占空比的设置*
*参数:rate=脉宽时钟数,cyc=脉冲周期时钟数*
*返回:无*
10.5.5 PWM编程C语言例
实例编号:C05_3路径:\C\C05_3PWM脉冲信号输出(PWM.prj)
/*-----------------------------------------------------*
*工程名:PWM.prj *
*硬件接线:PTD.4,即定时器1通道0(21脚)接指示灯或蜂鸣器*
if(Duty<Period)
Duty=Duty+1; //PWM占空比加1
else //占空比达到100%,设置占空比为0%
Duty=0;
T1SC|=(1<<5); //停止定时器1计数器计数
//[设置PWM脉宽]
T1CH0H = (Duty>>8); //设置高字节
T1CH0L = Duty; //设置低字节
unsigned int ; //PWM占空比
//[变量初始化]
Period =0x0180; //PWM周期默认为10ms
//[PWM初始化]
PWMInit(Period);
Duty = 0; //PWM占空比为0
//[主循环]
while(1)
{
//[判断脉宽是否达到周期的长度(占空比为100%)]
*-----------------------------------------------------*/
C语言程序-直流电机调速
#include<>#define uchar unsigned char#define uint unsigned int/* 端口定义*/sbit in1=P1^0;sbit in2=P1^1;sbit jian=P2^0;sbit jia=P2^1;sbit dir=P2^2;sbit run=P2^3;sbit inter_0=P3^2;sbit inter_1=P3^3;#define LCD_data P0 //数据口sbit LCD_RS = P2^7; //寄存器选择输入sbit LCD_RW = P2^6; //液晶读/写控制sbit LCD_EN = P2^5; //液晶使能控制sbit LCD_PSB = P2^4; //串/并方式控制uchar t10,t1,ce,cj,s1=0,pl=10;uchar zi[]={"电机转速:"};uchar num[3];uint nums=0,speed,k=1200;void delay_1ms(uchar x){uchar i,j;for(j=0;j<x;j++)for(i=0;i<110;i++);}/*******************************************************************/ /**//*写指令数据到LCD*//*RS=L,RW=L,E=高脉冲,D0-D7=指令码。
*//**//*******************************************************************/ void write_cmd(uchar cmd){LCD_RS = 0;LCD_RW = 0;LCD_EN = 0;P0 = cmd;delay_1ms(5);LCD_EN = 1;delay_1ms(5);LCD_EN = 0;}/*******************************************************************/ /**//*写显示数据到LCD*//*RS=H,RW=L,E=高脉冲,D0-D7=数据。
pwm电机调速程序
PWM电机调速程序*******************************************************************/ /* 程序名:PWM直流电机调速 *//* 晶振:11.00592 MHz CPU型号:AT89C51 *//* 直流电机的PWM波控制,可以直接的调速从0到20级的调速 *//*****************************************************************/ #include<reg51.h>#define TH0_TL0 (65536-1000)//设定中断的间隔时长unsigned char count0 = 50;//低电平的占空比unsigned char count1 = 0;//高电平的占空比bit Flag = 1;//电机正反转标志位,1正转,0反转sbit Key_add=P2 ^ 0; //电机减速sbit Key_dec=P2 ^ 1; //电机加速sbit Key_turn=P2 ^ 2; //电机换向sbit PWM1=P2^6;//PWM 通道 1,反转脉冲sbit PWM2=P2^7;//PWM 通道 2,正转脉冲unsigned char Time_delay;/************函数声明**************/void Delay(unsigned char x);void Motor_speed_high(void);void Motor_speed_low(void);void Motor_turn(void);void Timer0_init(void);/****************延时处理**********************/void Delay(unsigned char x){Time_delay = x;while(Time_delay != 0);//等待中断,可减少PWM输出时间间隔}/*******按键处理加pwm占空比,电机加速**********/void Motor_speed_high(void)//{if(Key_add==0)Delay(10);if(Key_add==0){count0 += 5;if(count0 >= 100){count0 = 100;}}while(!Key_add);//等待键松开}}/******按键处理减pwm占空比,电机减速*****/ void Motor_speed_low(void){if(Key_dec==0){Delay(10);if(Key_dec==0){count0 -= 5;if(count0 <= 0){count0 = 0;}}while(!Key_dec );}}/************电机正反向控制**************/ void Motor_turn(void){if(Key_turn == 0){Delay(10);if(Key_turn == 0){Flag = ~Flag;}while(!Key_turn);}/***********定时器0初始化***********/void Timer0_init(void){TMOD=0x01; //定时器0工作于方式1TH0=TH0_TL0/256;TL0=TH0_TL0%256;TR0=1;ET0=1;EA=1;}/*********主函数********************/void main(void){Timer0_init();while(1){Motor_turn();Motor_speed_high();Motor_speed_low();}}/**************定时0中断处理******************/ void Timer0_int(void) interrupt 1 using 1{TR0 = 0;//设置定时器初值期间,关闭定时器TL0 = TH0_TL0 % 256;TH0 = TH0_TL0 / 256 ;//定时器装初值TR0 = 1;if(Time_delay != 0)//延时函数用{Time_delay--;}if(Flag == 1)//电机正转{PWM1 = 0;if(++count1 < count0)PWM2 = 1;}elsePWM2 = 0;if(count1 >= 100){count1=0;}}else //电机反转{PWM2 = 0;if(++count1 < count0){PWM1 = 1;}elsePWM1 = 0;if(count1 >= 100){count1=0;}}}//-----------------------------------------------------------------------------#include <c8051f330.h> // SFR declarations#include <math.h>// Function Prototypes//-----------------------------------------------------------------------------#define CMD_RESET 0xA4 //HD7279复位#define DECODE1 0xc8 //方式0译码sbit cs=P1^3;sbit clk=P1^2;sbit dat=P1^1;sbit key=P1^0;sbit led_D1003=P0^7;sbit sw1=P1^7;sbit sw2=P1^6;sbit sw3=P1^5;sbit sw4=P1^4;void long_delay(void); //延时函数void short_delay(void);void delay10ms(unsigned char);void write7279(unsigned char,unsigned char); //HD7279写指令void send_byte(unsigned char);void delay(unsigned char);void disp1(unsigned int);void OSCILLATOR_Init (void);void PORT_Init (void);void PCA0_Init (void);void Timer0_Init(void);void Ext_Interrupt_Init (void);//-----------------------------------------------------------------------------// Global Variables//-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// main() Routine//-----------------------------------------------------------------------------unsigned int CEX0_Compare_Value; // Holds current PCA compare valueunsigned int tmr,Speed_evaluate;unsigned char num,num1,num2,num3,a;unsigned int Speed,pi,Speed2;unsigned int Speed1[10];typedef struct {double SetPoint; /* 设定目标Desired Value */double Proportion; /* 比例常数Proportional Const */double Integral; /* 积分常数Integral Const */double Derivative; /* 微分常数Derivative Const */double LastError; /* 前一项误差*/double PrevError; /* 前第二项误差*/double SumError; /* 误差和*/} PID;double PIDCalc( PID *pp, double NextPoint ){double dError,Error,Pout;Error = pp->SetPoint - NextPoint; /* */pp->SumError += Error; /* /dError = pp->LastError - pp->PrevError; /* */pp->PrevError = pp->LastError;pp->LastError = Error; /* */Pout= pp->Proportion * Error + pp->Integral * pp->SumError +pp->Derivative * dError ;if(Pout>1100)Pout=1000;if(Pout<100)Pout=100;return (Pout);}PID sPID; //定义PID结构体变量double rOut; //PID响应输出unsigned char rIn; //设置PID反馈值double x;double sumout;unsigned char dd;//设置PID输出void main (void){sPID.Proportion = 0.44; //设置PsPID.Integral = 0.70; //设置IsPID.Derivative = 0.0; //设置D//sPID.SetPoint = CEX0_Compare_Value;//sPID.SetPoint = CEX0_Compare_Value; //设置PID输出PCA0MD = 0x00; // Disable watchdog timerled_D1003=0;PORT_Init (); // Initialize crossbar and GPIOOSCILLATOR_Init (); // Initialize oscillatorPCA0_Init (); // Initialize PCA0IP=0x82; //定时器中断0高于外部中断0Timer0_Init();Ext_Interrupt_Init ();for (tmr=0;tmr<0x2000;tmr++);send_byte(CMD_RESET);//HD7279复位// Globally enable interruptsEA = 1;sPID.SetPoint=70;while (1){delay10ms(100);//键盘程序 -------------------------------------------------------------if(sw1==0) //按键1是否按下{if(sw1==0)//再次检查按键{num++; //若按键按下,num加1if(num==1) //到9归0{num=0;}while(sw1==0);//按键释放}// delay10ms(100);}write7279(DECODE1+4,num); //将num写入HD7279第1位 delay10ms(1);if(sw2==0){if(sw2==0){num1++;if(num1==2){num1=0;}while(!sw2);}// delay10ms(100);}write7279(DECODE1+5,num1);//将num1写入HD7279第2位delay10ms(1);if(sw3==0){if(sw3==0){num2++;if(num2==10){num2=0;}while(!sw3);}// delay10ms(100);}write7279(DECODE1+6,num2);//将num1写入HD7279第2位delay10ms(1);if(sw4==0){if(sw4==0){num3++;if(num3==10){num3=0;}while(!sw4);}// delay10ms(100);}write7279(DECODE1+7,num3);//将num1写入HD7279第2位delay10ms(1);Speed_evaluate=num*1000+num1*100+num2*10+num3;sPID.SetPoint=Speed_evaluate;//控制程序-----------------------------------------------------------------//---------------------------------------------------------------------------}}void OSCILLATOR_Init (void){OSCICN = 0x83; // Set internal oscillator torun// at its maximum frequencyCLKSEL = 0x00;}void PORT_Init (void){XBR0 = 0x00;XBR1 = 0x41;// Enable crossbar and weak pull-upsP0MDOUT |= 0x10; // Set CEX0 (P0.4) to push-pull P0SKIP |=0x0F; //P1SKIP = 0x00;P1MDOUT= 0x0f;}void PCA0_Init (void){PCA0CN = 0x00; // Stop counter; clear allflagsPCA0MD = 0x01; // Use Ettern ime basePCA0CPM0 = 0xCB; // Module 0 = 16-bit PWM modeand// enable Module 0 Match and Interrupt// Flags// Configure initial PWM duty cycle = 50%CEX0_Compare_Value = 65536 - (65536 * 0.15);PCA0CPL0 = (CEX0_Compare_Value & 0x00FF);PCA0CPH0 = (CEX0_Compare_Value & 0xFF00)>>8;EIE1 |= 0x10; // Enable PCA interrupts// Start PCA counterCR = 1;}void Ext_Interrupt_Init (void){TCON |= 0x05; // /INT 0 and /INT 1 are edge triggeredIT01CF = 0x10; // /INT0 active low; /INT0 on P0.0;// /INT1 active low; /INT1 on P0.1EX0 = 1; // Enable /INT0 interrupts}void Timer0_Init(void){TH0 = 0 ; // Init Timer0 High registerTL0 = 0 ; // Init Timer0 Low registerTMOD |= 0x01; // Timer0 in 16-bit mode方式1CKCON |= 0x02; // Timer0 uses a 1:48 prescalerET0 = 1; // Timer0 interrupt enabledTCON|=0x10;// Timer0 ON}// PCA0_ISR//-----------------------------------------------------------------------------void PCA0_ISR (void) interrupt 11{CCF0 = 0; // Clear module 0 interrupt flag.PCA0CPL0 = (CEX0_Compare_Value & 0x00FF);PCA0CPH0 = (CEX0_Compare_Value & 0xFF00)>>8;}void Timer0_ISR (void) interrupt 1{int j,sum;TF0=0;// Clear interrupt flag.a++;if (a==4){Speed1[pi]=Speed;if(pi>=3){ EX0 = 0;for(j=0;j<=3;j++){sum=sum+Speed1[j];Speed2=sum/4;disp1(Speed2);Speed=0;pi=0;EX0 = 1;}a=0;sum=0;if(pi>=3)pi=0;elsepi++;TH0 = 0; // Reinit Timer0 High register TL0 = 0; // Reinit Timer0 Low registerif(abs( sPID.SetPoint-Speed2)<=5) {CEX0_Compare_Value=CEX0_Compare_Value;}else{rIn =Speed2;for(dd=0;dd<50;dd++)x=rIn;//x = 5.0 * (double)rIn / 256.0;rOut = PIDCalc ( &sPID,x );// sumout=rOut*256/5;if(rOut==100)sumout=0;elsesumout= (0.85/1000.0)*rOut;//CEX0_Compare_Value=CEX0_Compare_Value-sumout;CEX0_Compare_Value = 65536 - (65536 * ( sumout+0.15));}}else{TH0 = 0; // Reinit Timer0 High registerTL0 = 0; // Reinit Timer0 Low register}}void INT0_ISR (void) interrupt 0{IE0=0; // // Clear interrupt flag.Speed++;}void write7279(unsigned char cmd, unsigned char dta) {send_byte(cmd);send_byte(dta);}void send_byte( unsigned char out_byte){unsigned char i;cs=0;long_delay();for (i=0;i<8;i++){if (out_byte&0x80){dat=1;}else{dat=0;}clk=1;short_delay();clk=0;short_delay();out_byte=out_byte*2; }dat=0;}void long_delay(void){unsigned char i;for (i=0;i<0x30;i++);}void short_delay(void){unsigned char i;for (i=0;i<8;i++);}void delay10ms(unsigned char time) {unsigned char i;unsigned int j;for (i=0;i<time;i++){for (j=0;j<0x390;j++);}}void disp1(unsigned int date){unsigned char d0, d1, d2 , d3; d0=date / 1000;d1=(date-d0*1000)/100;d2=(date-d0*1000-d1*100)/10 ;d3= date-d0*1000-d1*100-d2*10;write7279(DECODE1,d0);delay10ms(1);write7279(DECODE1+1,d1);delay10ms(1);write7279(DECODE1+2,d2);delay10ms(1);write7279(DECODE1+3,d3);delay10ms(1);}。
pwm调试程序
pwm调试程序#include"iostm8s105c6.h"unsigned int note;//音符标志(全局变量)void GPIO_INIT(void);//io口初始化void TIM3_INIT(void);//键盘矩阵计时的tim3的初始化void keynote_real(void);//键盘确定音符程序void delay (unsigned int time);//延时函数void TIM1_INIT(unsigned int music);//TIM1初始化void TIM1_OC(void);//TIM1输出比较初始化int main( void ){TIM1_OC();//TIM1输出比较初始化TIM1_CCER1|=0x01;//TIM1比较输出使能输出note=4;TIM1_INIT(note);TIM1_CR1|=0X01;//TIM1定时器使能}/*********************TIM1初始化****************/ void TIM1_INIT(unsigned int music){unsigned int pscr;//TIM1_PSCR的数值unsigned int arr;//TIM1_ARR的数值switch(music){case 1:pscr=43,arr=44;break;//对应的DO的设置case 2:pscr=40,arr=41;break;//对应的RE的设置case 3:pscr=38,arr=39;break;//对应的MI的设置case 4:pscr=37,arr=38;break;//对应的FA的设置case 5:pscr=35,arr=36;break;//对应的SO的设置case 6:pscr=33,arr=34;break;//对应的LA的设置case 7:pscr=31,arr=32;break;//对应的SI的设置case 8:pscr=30,arr=31;break;//对应的DO'的设置}TIM1_PSCRH=0;//数字小于256,高八位都为0TIM1_PSCRL=(unsigned char)pscr;TIM1_ARRH=0;//数字小于256,高八位都为0TIM1_ARRL=(unsigned char)arr;TIM1_CR1=0X04;//TIM1_CR1=0000 0100B,边沿对齐模式,向上计数,但是计数器还没使能TIM1_CNTRH=0;TIM1_CNTRL=0;//使一开始的方波完整}/**************TIM1输出比较初始化***************/void TIM1_OC(void){PC_DDR|=0X02;PC_CR1|=0X02;PC_CR2=0X00;//初始化TIM1_CH1的引脚PC1为输出方式,由后级电路决定选择推挽输出TIM1_CCR1H=0X00;TIM1_CCR1L=0X16;//初始化TIM1_CCR输出比较寄存器,由于选择011模式,所以CCR1的值可以是随意TIM1_CCMR1=0X38;//初始化TIM1_CCMR1的CC1S为00;以及OC1M[2:0]位为011,而且实用预装载功能TIM1_BKR=0X80;//初始化刹车寄存器TIM1_CCER1&=0xfd;//高电平有效,但是还没有使能pwm输出}。
c51单片机C语言编写的PWM程序
89c51单片机C语言编写的P W M程序(共3页)-本页仅作为预览文档封面,使用时请删除本页-89c51单片机C语言编写的PWM程序PWM, 单片机, C语言, 程序, 编写分享到:新浪微博 QQ空间开心网人人网说明:本程序使用STC89C52RC单片机,晶振,要使用本程序需要自己修改,我是用来控制直流电机的,外接了L298驱动电路,有问题或意见请回复,谢谢^_^#include ""#include ""转;speed<0.反转(-100~100)调用:extern int abs(int val); 取绝对值返回:/******************************************************************/ void motor(char speed1,char speed2){ //==============左边电机============= if (speed1>0) { IN1 =0;IN2 =1;//正转} else if (speed1<0) { IN1 =1;IN2 =0;//反转}//==============右边电机============= if (speed2>0) { IN3 =1;IN4 =0;//正转} else if (speed2<0) { IN3 =0;IN4 =1;//反转}}/******************************************************************名称:motor_PWM();功能:PWM占空比输出参数:无调用:无返回:无/******************************************************************/void motor_PWM (){ uchar PWM_abs1; uchar PWM_abs2;PWM_abs1=MOTO_speed1; PWM_abs2=MOTO_speed2;if (PWM_abs1>PWMAnd) ENA=1; //左边电机占空比输出else ENA=0; if (PWM_abs2>PWMAnd) ENB=1; //右边电机占空比输出else ENB=0; if (PWMAnd>=PWM_COUST) PWMAnd=0; //PWM计数清零else PWMAnd+=1;}/******************************************************************名称:void TIME_Init ();功能:定时器初始化指令:调用:无返回:无/******************************************************************/void TIME_Init (){//=========定时器T2初始化 PWM==================T2CON = 0x00;T2MOD = 0x00;RCAP2H = 0xff; //定时RCAP2L = 0x47; TH2 = 0xff; TL2 = 0x47; ET2 = 1; //定时器2中断开TR2 = 1; //PWM定时器关,PWM周期为10ms }/******************************************************************名称:void PWM_Time2 () interrupt 5功能:T2中断,PWM控制参数:调用:motor_PWM();//PWM占空比输出返回:/******************************************************************/ void PWM_Time2 () interrupt 5{ TR2 = 0; TF2 = 0; ET2 = 0; //定时器0中断禁止motor_PWM();//PWM占空比输出ET2 = 1; //定时中断0开启TR2 = 1;}main(){TIME_Init () ;motor(50,50);//左右电机的转速都是50}。
PWM调速的C语言程序编写(非常简单)
PWM调速的C语言程序编写关于PWM的原理在上一篇文章中已经说的很详细了,现在就细说一下pwm C语言程序的编写。
C语言中PWM的编写有这么几种方法;一、用普通的I/O 口输出的PWM ,二、使用定时计数器编写,三、就是使用片内PWM了。
1 先说使用普通的I\O口编写PWM程序了。
使用I/O口输出PWM波形你必须首先明白PWM他的实质是:调制占空比,占空比就是波形中高电平的长度与整个波长的比值。
我们写C语言的目的是写PWM波形的一个周期。
在这个周期内高低电平的比值是可以改变的。
这也就符合了PWM的原意脉宽调制。
即高电平的宽度的调制。
当然了PWM他也可用于改变频率,我们这里只先说他改变脉宽。
一旦我们的C语言程序写完那么他产生的PWM波形的频率就一定了。
(也可写频率变化的PWM,难度有点大)一般我们控制使用1K到10K的PWM波进行控制。
当然了你也可在要求不是很高的地方使用频率更低的PWM波。
比如在飞思卡尔智能车比赛中我们学校使用的PWM波频率只有600HZ.我们要改变一个PWM波周期内的高电平的宽度显然需要将一个PWM波的周期分成单片机可以控制的N个小的周期,N的取值越大你的调速等级越高,但产生的PWM频率就越低。
我们下面以实现100级调速为例编写PWM程序。
先写出程序再慢慢给大家分析void pwm (uchar x,uint y) //X 为占空比 Y为函数使用时间{ uint i,j,a,b;for(i=y;i>0;i--)//定时外函数{for(j=7;j>0;j--)//定时内函数{for(a=y;a>0;a--) / /PWM波高电平宽度{PORTA=0X01;}for(b=100-y;b>0;b--) //PWM低电平宽度{PORTA=0X00;}}}}这个程序够简单吧轻松的实现AVR单片机的PA.0口输出7KHZ左右的PWM脉冲你可以将PORTA=0X01;改为P1.0=0X01;就可以移植到51单片机上了为什么使用参数Y定时是因为用普通I/O口控制它的开关没有使用定时器编写的灵活。
无刷直流电机调速--C语言源程序
附录1. C语言源程序:#include"stdio.h"#include"myapp.h"#include"ICETEK-VC5502-EDU.h"#include"scancode.h"#include"lcd.h"#define CTRSTATUS (*(unsigned int * )0x608000) //port8000#define CTRLED (*(unsigned int * )0x608004) //port8004#define MCTRKEY (*(unsigned int * )0x608005) //port8005#define CTRCLKEY (*(unsigned int * )0x608006) //port8006#define CTRMOTORBSPEED (*(unsigned int * )0x608003)void InitMcBSP();void INTR_init( void );void InitForMotorB( void );void showparameters();void LCDPutString(unsigned int * pData,int x,int y,unsigned int nCharNumber,unsigned color);void PIDControl(int rk,int yk);void PrintParameters();//定时器分频参数#define T100 99 // 100个时钟周期中断一次#define T2Hz 20000 // 20000个时钟周期读取速度一次//工作变量usigned int uWork,uN,nCount,nCount1,nCount2,nCount3,nCount4;int nSSS,nJSSpeed,pwm1;int md,wc;unsigned int nScreenBuffer[30*128];float a=0.6f,b=0.2f,c=0.1f,duk;int ek,ek1,ek2,tz;int nInput;unsigned int *www=(unsigned int *)0x608003;Int m_nSpeed,m_bPCSet;// 主函数main(){unsigned char ccc;int speed[100],sp,lj;float ljh;int i,w1,w2,w3;unsigned int uWork1;unsigned int bWork1,*pWork;int breakflage;// 初始化工作变量for ( sp=0;sp<100;sp++ )speed[sp]=0;for ( sp=0;sp<1024;sp++ ) nScreenBuffer[sp]=0;sp=nSSS=nCount=nCount1=nCount2=nCount3=nCount4=nJSSpeed=0;nInput=tz=wc =0;ek=ek1=ek2=0;uN=40;md=70;pwm1=60;m_nSpeed=70;m_bPCSet=0;inputspeed=0;uWork1=0;breakflage=0;initemif();CLK_init();*(int*)0x400001=1;CREG=1; //使能外部总线接口InitCTR();CTRGR=0x80;CTRGR=0;CTRGR=0x80;LCDTurnoff();// 设置显示参数和内容LCDSetDelay(1); //设置延时等待参数LCDSetScreenBuffer(nScreenBuffer); // 显示缓冲区for (bWork=0,pWork=nScreenBuffer;bWork<30*128;bWork++,pWork++) (*pWork=0)LCDTurnOn();//打开显示LCDCLS();//清除显示内存LCDPutCString(str1,0,127,8,0);LCDPutCString(str2,0,111,2,1);LCDPutCString(str3,68,111,2,1);LCDPutCString(str4,68,79,2,1);LCDPutCString(str5,68,95,2,1);LCDPutCString(str6,0,95,2,1);LCDPutCString(str7,0,79,3,1);ShowParamctors();//参数显示InitMcBSP();INTR-init();InitForMotorB();While(!breakflage){if(nCount==0) //读取键盘标志{uWork=MCTRKEY;CTRCLKEY=0;Switch(uWork1){Casc 128;if(inputspecd!=0){Md=inputspecd;Inputspecd=0;LCDPutCString(numbers+104,104,79,1,1);LCDPutCString(numbers+104,112,79,1,1);LCDPutCString(numbers+104,120,79,1,1);LCDRefreshScreen();}break;case 64;breakflage=1;case 1;inputspeed=inputspeed+1break;case 2;inputspeed=inputspeed-1;break;case 4;inputspeed=inputspeed+10;break;case 8;inputspeed=inputspeed-10;break;}if(inputspeed>90){inputspeed=90;}if(inputspeed<0){inputspeed=0;}w1=inputspeed%1000/100;w2=inputspeed%100/10;w3=inputspeed%10; LCDPutString(numbers+w1*8,104,79,1,1);LCDPutString(numbers+w2*8,112,79,1,1);LCDPutString(numbers+w3*8,120,79,1,1);LCDRefreshScreen();}if(m-bPCSet){m-bPCSst=0;if (m-nSpeed>=0&&m-nSpeed<256){md=m-nSpeed;LCDPutCString(numbers+104,104,79,1,1); LCDPutCString(numbers+104,112,79,1,1); LCDPutCString(numbers+104,120,79,1,1); LCDRefreshScreen();printparameters();}}if(nJSSpeed==0) //读取速度标志{LED=1;nJSSpeed=0;ccc=CTRMOTORBSPEED; //读取端口速度计数ccc=ccc&0xff;nSSS=ccc;if(nSSS>=0 && nSSS<400) //合法性检测{speed(sp)=Nssssp++;sp%=33;}if(sp==0) //读取实际速度{lj=0;ljh=0;for(i=0;i<33;i++){if(speed(i)>=0&&speed(i)<400){ljh+=speed(i);lj++;}}nCount3++;nCount3%=3;if(nCount3==2){PIDControl(md,wc); //调用PID算法控制程序uN=100-pwml; //利用占空比调整控制Showparameters(); //显示各参数到LCD}CloseCTR();exit(0);}//PID算法控制子程序void PIDControl(int rk,int yk){ek=rk-yk;duk=a*ek+b*ek1+c*ek2; //计算控制输出ek2=ek1; ek1=ek;tz=(int)duk;pwm1+=tz; //计算当前占空比if(pwml<0) pwml=0;else if(pwml>99) pwml=99;}void interrupt Timer(){uWork=PCR1; //pwml输出if(nCont1>u N){uWork=4; //根据占空比设置FSR状态}else{uWork&=0x0fffb;}PCR1=uWork;//设置中断控制寄存器void INTR-init(void){asm(“BSET INTM”);IVPD=0x01;IVPH=0x01;IERO=0x10;DBIERO=0x10;IFRO=0xffff;asm(“BCLR INTM”);}void InitForMotorB(void){ioport unsigned int *GPTCTL1-0;ioport unsigned int *GPTPRD1-0;ioport unsigned int *GPTGCTL1-0;*GPTCTL1-0=0;*GPTPRD1-0=0x1d8;*GPTGCTL1-0=0x3;}//显示参数到LCDvoid ShowParameters(){int w1,w2,w3;w1=md%1000/100;w2=md%100/10,w3=md%10; LCDPutString(numbers+w1*8,36,111,1,1); LCDPutString(numbers+w2*8,44,111,1,1); LCDPutString(numbers+w3*8,52,111,1,1);if (ek>=0){LCDPutString(numbers+88,36,95,1,1);w3=((int)ek)%100;}else{LCDPutString(numbers+96,36,95,1,1);w3=((int)(-ek))%100;}for (j=0;j<16;j++,k<<=1){if (color==2) mcolor=2;else{mcolor=(pData(1*8+i)&k)(1):(0);if(color==0) mcolor=1-mcolor;}LCDPutPixel(x+1*8+I,y-j,mcolor);}int wwss;void PrintParameters(){wwcc=wc-md;printf(“测速(%3d) 设置(%3d) 误差(%+4d) PID调整量(%+3d) 占空比(%3d%%)\n”,wc,md,wwcc,tz,pwm1);}。
