"测速直流电机的c程序"这是什么意思?直流电机测速还需要c程序?直流电机通电就转c程序可以通过PWM对其调速,但这与测速好像木有太大关系,下面是51单片机I/O模拟PWM程序:
/
声明: 在网上找的
Title: 模拟PWM输出
Description: 51单片机模拟PWM输出控制灯的100个档级
/
#include <reg51h>
#define uInt unsigned int
#define uchar unsigned char
uchar PWM_T = 0; //占空比控制变量
//////////////////主程序入口//////////////////////
void main(void)
{
bit flag = 1; //控制灯渐亮渐熄方式
uInt n;
TMOD=0x02; //定时器0,工作模式2,8位定时模式
TH0=210; //写入预置初值(取值1-255,数越大PWM频率越高)
TL0=210; //写入预置值 (取值1-255,数越大PWM频率越高)
TR0=1; //启动定时器
ET0=1; //允许定时器0中断
EA=1; //允许总中断
P1=0xff; //初始化P1
while(1)
{
for(n=0;n<600;n++); //延时,将响应定时器中断,灯会自动加/减一个档次的亮度
//取值0-65535,数字越大变化越慢
if(flag==1) //灯渐亮
PWM_T++;
else //灯渐熄
PWM_T--;
if(PWM_T>=100) //设置灯亮度级别为10
flag=0;
if(PWM_T==0) //限定最低亮度级别为0
flag = 1;
}
}
///////////////////定时器0中断模拟PWM////////////////////
timer0() interrupt 1 using 2
{
static uchar t ; //PWM计数
t++; //每次定时器溢出加1
if(t==100) //PWM周期
{
t=0; //使t=0,开始新的PWM周期
P1=0x00; //使LED灯亮
}
if(PWM_T==t) //按照当前占空比切换输出为高电平
P1=0xff; //使LED灯灭
}
#include<reg51h>
#define Tpwm 0xfc18//PWM周期对应的计数值1ms,基于12MHz晶振
unsigned int duty[]={0,/0/
0xff9c/100us/,0xff38/200us/,0xfed4/300us/,\
0xfe70/400us/,0xfe0c/500us/,0xfda8/600us/,\
0xfd44/700us/,0xfce0/800us/,0xfc7c/900us/,\
0xfc18/1000us/};//PWM高电平时间
unsigned char i=0;
sbit P32 = P3^2;
sbit P33 = P3^3;
sbit PWMOUT = P2^0;
sbit PWMIN1 = P2^1;
sbit PWMIN2 = P2^2;
bit flag = 1;//PWM输出电平状态,1为输出高电平时间,0为输出低电平时间
void delay10ms(int n);
void main(void)
{
PWMOUT = 0;//初始化L293D ,停止电机
PWMIN1 = 0;
PWMIN2 = 1;
EA = 1; //开总中断
IT0 = 1; //中断方式为跳变
IT1 = 1;
EX0 = 1; //打开外部中断0
EX1 = 1; //打开外部中断1
ET0 = 1; //开定时器0中断允许
TMOD = 0x01; //设置定时方式
while(1) //等待中断
{
/在此可以实现其它任务/
}
}
//10ms延时函数
void delay10ms(int n)
{
int i=0,j;
while(n--)
{
for(i=0;i<10;i++)
{
for(j = 0; j < 125; j++);
}
}
}
void keySpeeddownISR() interrupt 0 //按键中断服务程序
{
EA = 0; //关中断
delay10ms(2); //延时消抖
if (!P32) //确认按键按下,滤除键盘抖动干扰
{//减少PWM高电平时间
if(i>0)
i--;
if((TR0=1) && (i == 0))
{
TR0 = 0;
PWMOUT = 0;
}
}
EA = 1;
}
void keySpeedupISR() interrupt 2 //按键中断服务程序
{
EA = 0; //关中断
delay10ms(2); //延时消抖
if (!P33) //确认按键按下,滤除键盘抖动干扰
{//增加PWM高电平时间
if(i<=10)
i++;
if((TR0 == 0) && (i > 0))
{//启动PWM,电机顺时针旋转
PWMIN1 = 0;
PWMIN2 = 1;
PWMOUT = 1;
TH0 = duty[i]>>8;
TL0 = duty[i]&0xff;
TR0 = 1;
flag = 1;
}
}
EA = 1;
}
void T0ISR() interrupt 1 //定时器0中断服务程序
{
EA = 0; //关中断
if(flag)
{//高电平时间结束,输出低电平补齐PWM周期
PWMOUT = 0;
TH0 = (65535-(duty[i]-Tpwm))>>8;
TL0 = (65535-(duty[i]-Tpwm))&0xff;
flag = 0;
}else
{//周期结束
PWMOUT = 1;
TH0 = duty[i]>>8;
TL0 = duty[i]&0xff;
flag = 1;
}
EA = 1;
}
仅供参考。学单片机还需自己多多思考和练习
这个我经常用,电机调速控制,严格说这不是PWM,是可控硅移相触发。
电路很简单,一个可控硅触发电路,一个过零检测电路,配合一段中断服务程序就能完成。
不知道你应用的一些详情,简单说一下思路。
可控硅触发一般使用MOC3021,相关手册上有典型电路,CPU端接一个GPIO就可以。
闭环控制时过零检测不需要很精确,一般用一个双向光耦就足够,光耦输入接交流电输入,输出接CPU中断,用史密特整形一下输出信号最好。
中断程序的结构分成两部分,过零中断与延时中断。
过零中断做两件事,输出复位,开始延时。如果定时器有外部管脚复位启动功能,可以不要这段。
延时中断做一件事,触发输出。如果定时器有触发输出功能,可以没有这段中断程序。
具体的延时时间,由主程序控制,一般是根据PID的计算结果进行设置。注意,延时时间越长,输出电压越小。
P4SEL=0X0E; P4DIR=0xFF; P4OUT=0xFF;
TBCCTL1 = OUTMOD_7; // CCR1 reset/set
TBCCTL2 = OUTMOD_7; // CCR2 reset/set
TBCCTL3 = OUTMOD_7; // CCR3 reset/set
TBCCR0=5000;
TBCCR1=pwm1d1;
TBCCR2=pwm2d1;
TBCCR3=pwm3d1;
TBCTL = TBSSEL_2 + TBCLR + MC_1;//MCLK,UP
改变TBCCR1,TBCCR2,TBCCR3便改变占空比。TA的你自已改吧。单片机要选TA可以输出7路PWM的。
/
模块名称:PWMc
功 能:可调PWM波
说 明:按键AN1增加占空比,按键AN2减小占空比,P0^2口输出PWM波
/
#include < reg52h >
#define uchar unsigned char
#define uint unsigned int
uint T_1 = 10000; //定时器1初值变量
uchar flag; //按键返回变量
sbit PWM = P0^2; //PWM输出口
sbit AN1 = P0^0; //增加占空比
sbit AN2 = P0^1; //减小占空比
//调节占空比函数
/
函 数 名:timer_init()
功 能:定时器初始化函数
说 明:无
入口参数:无
返 回 值:无
/
void timer_init()
{
TMOD = 0x11; //定时器0、定时器1工作于模式1
EA = 1; //开总中断
ET0 = 1; //定时中断0允许
ET1 = 1; //定时中断1允许
TH0 = (65536-20000)/256; //定时器0装初值:20ms
TL0 = (65536-20000)%256;
TH1 = (65536-T_1)/256; //定时器1装初值:10ms
TL1 = (65536-T_1)%256;
TR0 = 1; //开启定时中断0
}
/
函 数 名:timer0()
功 能:定时中断0中断服务函数
说 明:产生高电平,中断固定时间20ms,频率50HZ
入口参数:无
返 回 值:无
/
void timer0() interrupt 1
{
TR0 = 0; //关闭定时中断0
PWM = 1; //脉冲高电平
TH0 = (65536-20000)/256; //定时器0装初值:20ms
TL0 = (65536-20000)%256;
TR1 = 1; //开启定时中断1
TR0 = 1; //开启定时中断0
}
/
函 数 名:timer1()
功 能:定时中断1中断服务函数
说 明:产生低电平,中断时间可变
入口参数:无
返 回 值:无
/
void timer1() interrupt 3
{
TR1 = 0; //关闭定时中断1
PWM = 0; //脉冲低电平
TH1 = (65536-T_1)/256; //定时器1装初值:10ms
TL1 = (65536-T_1)%256;
}
/
函 数 名:keyscan()
功 能:键盘扫描函数
说 明:无
入口参数:无
返 回 值:无
/
uchar keyscan(void)
{
if(AN1==0) //AN1按下
{
while(AN1==0); //AN1松开
return 1; //返回 1
}
if(AN2==0) //AN2按下
{
while(AN2==0); //AN2松开
return 2; //返回 2
}
else return 0; //返回 0
}
/
函 数 名:change()
功 能:调节占空比函数
说 明:无
入口参数:无
返 回 值:无
/
void change(void)
{
flag = keyscan(); //按键返回值保存
if(flag==1) //按键返回值为1,即AN1按下
{
if(T_1>=65435) //定时器初值变量大于等于65525
{
T_1 = 65530; //定时器初值变量等于65535
}
if(T_1<65525) //定时器初值变量小于65525
{
T_1 = T_1+100; //定时器初值变量加10
}
}
if(flag==2) //按键返回值为2,即AN2按下
{
if(T_1<=100) //定时器初值变量小于等于10
{
T_1 = 5; //定时器初值变量等于0
}
if(T_1>100) //定时器初值变量大于10
{
T_1 = T_1-100; //定时器初值变量减10
}
}
}
/
函 数 名:main()
功 能:主函数
说 明:无
入口参数:无
返 回 值:无
/
void main()
{
timer_init(); //定时器初始化
while(1)
{
change(); //改变占空比
}
}
你用Protues软件的示波器按照程序引脚图连一下,就是一个PWM波了,且占空比可调
首先弄清楚PID是一种控制算法!!!
1,“如果用单片机恒温可以使温度到达预定值就停止加热,低了就加热,用一个温度传感器反馈,这样算是一个自动控制吗”你这是控制系统,但是效果会非常差,尤其是对于温度控制这种大惯性系统,达到预定值就停止加热,但是由于惯性,温度肯定会继续上升,电炉烧水的时候,水开了,断电之后水还要沸腾一定时间的(沸腾是很消耗能量的,由此可见如果是加热的话温度上升更严重,你也可以自己用温度计试试看);“低了就加热”是同样的道理。如果系统对控制精度有要求,你这样做肯定达不到要求。PID是一种控制算法,相对于其他控制算法来说算是最简单的了。PID能够做到在温度快要达到设定值的时候降低加热功率,让温度上升速度变慢,最终稳定在设定值。如果用你的直接控制,温度会在设定值上下振荡,永远不会停在设定值。
2,一般的控制系统都需要加反馈,以构成闭环控制系统,相对的还有开环控制系统。开环控制系统,举个例子,就是你加热的时候事先计算好大约需要多少热量,然后考虑一下环境影响,计算出加热时间,然后控制加热系统按照你这个时间加热。你觉得这样的系统能够稳定工作吗?环境稍稍有变动就挂了!开环控制系统的特点就是很容易受到环境的影响;闭环控制系统就稳定很多,你用1L水可用,2L水也行,500W电能用,1000W电炉也能用,这就是闭环的优点。
因此,大多数的控制系统都是闭环的,开环很少单独使用,即使用到了也是有闭环的。开环其实也是有优点的,开环在控制系统里面叫做前馈(跟反馈对应的),比如你的系统里面电源电压上升了,加热速度肯定会变快,如果你对电源电压采样,将采样的结果输入到闭环里面,对闭环做一个轻微的修正,控制的精度会更好,这就是开环的优势,它是超前的,能够预知结果(根据地源电压提高就能知道需要降低输出功率了)。
说完这些,你应该明白了,反馈是必需的(前馈也可以要,但是不是必需的),PID不能被取代(除非你用其它更复杂的控制算法)。
以上就是关于求测速直流电机的c程序全部的内容,包括:求测速直流电机的c程序、基于Proteus的直流电机调速c程序、单片机控制PWM 要用到双向可控硅 求相关电路图和程序(最好是C语言的) 我把剩下的所有财富都给大家了急等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)