一个PWM输出接口采用1字节(8位二进制)作为周期计数器,计算输出信号的控制精度是多少?

作者&投稿:汪冒 (若有异议请与网页底部的电邮联系)
8位单片机PID控制PWM的算法如何实现,C语言计算?~

PID控制在8位单片机中仍然有广泛的应用,比如温度控制,利用比例、积分、微分补偿来做恒温补偿控制,当然由于有这些数学处理,用C语言相对方便一些,以下是一个具体的实例。
#include
#include
#include
#include
struct PID {
unsigned int SetPoint; // 设定目标 Desired Value
unsigned int Proportion; // 比例常数 Proportional Const
unsigned int Integral; // 积分常数 Integral Const
unsigned int Derivative; // 微分常数 Derivative Const
unsigned int LastError; // Error[-1]
unsigned int PrevError; // Error[-2]
unsigned int SumError; // Sums of Errors
};
struct PID spid; // PID Control Structure
unsigned int rout; // PID Response (Output)
unsigned int rin; // PID Feedback (Input)
sbit data1=P1^0;
sbit clk=P1^1;
sbit plus=P2^0;
sbit subs=P2^1;
sbit stop=P2^2;
sbit output=P3^4;
sbit DQ=P3^3;
unsigned char flag,flag_1=0;
unsigned char high_time,low_time,count=0;//占空比调节参数
unsigned char set_temper=35;
unsigned char temper;
unsigned char i;
unsigned char j=0;
unsigned int s;
/***********************************************************
延时子程序,延时时间以12M晶振为准,延时时间为30us×time
***********************************************************/
void delay(unsigned char time)
{
unsigned char m,n;
for(n=0;n<time;n++)
for(m=0;m<2;m++){}
}
/***********************************************************
写一位数据子程序
***********************************************************/
void write_bit(unsigned char bitval)
{
EA=0;
DQ=0; /*拉低DQ以开始一个写时序*/
if(bitval==1)
{
_nop_();
DQ=1; /*如要写1,则将总线置高*/
}
delay(5); /*延时90us供DA18B20采样*/
DQ=1; /*释放DQ总线*/
_nop_();
_nop_();
EA=1;
}
/***********************************************************
写一字节数据子程序
***********************************************************/
void write_byte(unsigned char val)
{
unsigned char i;
unsigned char temp;
EA=0;
TR0=0;
for(i=0;i<8;i++) /*写一字节数据,一次写一位*/
{
temp=val>>i; /*移位操作,将本次要写的位移到最低位*/
temp=temp&1;
write_bit(temp); /*向总线写该位*/
}
delay(7); /*延时120us后*/
// TR0=1;
EA=1;
}
/***********************************************************
读一位数据子程序
***********************************************************/
unsigned char read_bit()
{
unsigned char i,value_bit;
EA=0;
DQ=0; /*拉低DQ,开始读时序*/
_nop_();
_nop_();
DQ=1; /*释放总线*/
for(i=0;i<2;i++){}
value_bit=DQ;
EA=1;
return(value_bit);
}
/***********************************************************
读一字节数据子程序
***********************************************************/
unsigned char read_byte()
{
unsigned char i,value=0;
EA=0;
for(i=0;i<8;i++)
{
if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/
value|=0x01<<i;
delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/
}
EA=1;
return(value);
}
/***********************************************************
复位子程序
***********************************************************/
unsigned char reset()
{
unsigned char presence;
EA=0;
DQ=0; /*拉低DQ总线开始复位*/
delay(30); /*保持低电平480us*/
DQ=1; /*释放总线*/
delay(3);
presence=DQ; /*获取应答信号*/
delay(28); /*延时以完成整个时序*/
EA=1;
return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/
}
/***********************************************************
获取温度子程序
***********************************************************/
void get_temper()
{
unsigned char i,j;
do
{
i=reset(); /*复位*/
} while(i!=0); /*1为无反馈信号*/
i=0xcc; /*发送设备定位命令*/
write_byte(i);
i=0x44; /*发送开始转换命令*/
write_byte(i);
delay(180); /*延时*/
do
{
i=reset(); /*复位*/
} while(i!=0);
i=0xcc; /*设备定位*/
write_byte(i);
i=0xbe; /*读出缓冲区内容*/
write_byte(i);
j=read_byte();
i=read_byte();
i=(i<<4)&0x7f;
s=(unsigned int)(j&0x0f); //得到小数部分
s=(s*100)/16;
j=j>>4;
temper=i|j; /*获取的温度放在temper中*/
}
/*====================================================================================================
Initialize PID Structure
=====================================================================================================*/
void PIDInit (struct PID *pp)
{
memset ( pp,0,sizeof(struct PID)); //全部初始化为0
}
/*====================================================================================================
PID计算部分
=====================================================================================================*/
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )
{
unsigned int dError,Error;
Error = pp->SetPoint - NextPoint; // 偏差
pp->SumError += Error; // 积分
dError = pp->LastError - pp->PrevError; // 当前微分
pp->PrevError = pp->LastError;
pp->LastError = Error;
return (pp->Proportion * Error // 比例项
+ pp->Integral * pp->SumError // 积分项
+ pp->Derivative * dError); // 微分项
}
/***********************************************************
温度比较处理子程序
***********************************************************/
void compare_temper()
{
unsigned char i;
if(set_temper>temper) //是否设置的温度大于实际温度
{
if(set_temper-temper>1) //设置的温度比实际的温度是否是大于1度
{
high_time=100; //如果是,则全速加热
low_time=0;
}
else //如果是在1度范围内,则运行PID计算
{
for(i=0;i<10;i++)
{
get_temper(); //获取温度
rin = s; // Read Input
rout = PIDCalc ( &spid,rin ); // Perform PID Interation
}
if (high_time<=100)
high_time=(unsigned char)(rout/800);
else
high_time=100;
low_time= (100-high_time);
}
}
else if(set_temper<=temper)
{
if(temper-set_temper>0)
{
high_time=0;
low_time=100;
}
else
{
for(i=0;i<10;i++)
{
get_temper();
rin = s; // Read Input
rout = PIDCalc ( &spid,rin ); // Perform PID Interation
}
if (high_time<100)
high_time=(unsigned char)(rout/10000);
else
high_time=0;
low_time= (100-high_time);
}
}
// else
// {}
}
/*****************************************************
T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期
******************************************************/
void serve_T0() interrupt 1 using 1
{
if(++count<=(high_time))
output=1;
else if(count<=100)
{
output=0;
}
else
count=0;
TH0=0x2f;
TL0=0xe0;
}
/*****************************************************
串行口中断服务程序,用于上位机通讯
******************************************************/
void serve_sio() interrupt 4 using 2
{
/* EA=0;
RI=0;
i=SBUF;
if(i==2)
{
while(RI==0){}
RI=0;
set_temper=SBUF;
SBUF=0x02;
while(TI==0){}
TI=0;
}
else if(i==3)
{
TI=0;
SBUF=temper;
while(TI==0){}
TI=0;
}
EA=1; */
}
void disp_1(unsigned char disp_num1[6])
{
unsigned char n,a,m;
for(n=0;n<6;n++)
{
// k=disp_num1[n];
for(a=0;a<8;a++)
{
clk=0;
m=(disp_num1[n]&1);
disp_num1[n]=disp_num1[n]>>1;
if(m==1)
data1=1;
else
data1=0;
_nop_();
clk=1;
_nop_();
}
}
}
/*****************************************************
显示子程序
功能:将占空比温度转化为单个字符,显示占空比和测得到的温度
******************************************************/
void display()
{
unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};
unsigned char disp_num[6];
unsigned int k,k1;
k=high_time;
k=k%1000;
k1=k/100;
if(k1==0)
disp_num[0]=0;
else
disp_num[0]=0x60;
k=k%100;
disp_num[1]=number[k/10];
disp_num[2]=number[k%10];
k=temper;
k=k%100;
disp_num[3]=number[k/10];
disp_num[4]=number[k%10]+1;
disp_num[5]=number[s/10];
disp_1(disp_num);
}
/***********************************************************
主程序
***********************************************************/
void main()
{
unsigned char z;
unsigned char a,b,flag_2=1,count1=0;
unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};
TMOD=0x21;
TH0=0x2f;
TL0=0x40;
SCON=0x50;
PCON=0x00;
TH1=0xfd;
TL1=0xfd;
PS=1;
EA=1;
EX1=0;
ET0=1;
ES=1;
TR0=1;
TR1=1;
high_time=50;
low_time=50;
PIDInit ( &spid ); // Initialize Structure
spid.Proportion = 10; // Set PID Coefficients 比例常数 Proportional Const
spid.Integral = 8; //积分常数 Integral Const
spid.Derivative =6; //微分常数 Derivative Const
spid.SetPoint = 100; // Set PID Setpoint 设定目标 Desired Value
while(1)
{
if(plus==0)
{
EA=0;
for(a=0;a<5;a++)
for(b=0;b<102;b++){}
if(plus==0)
{
set_temper++;
flag=0;
}
}
else if(subs==0)
{
for(a=0;a<5;a++)
for(b=0;a<102;b++){}
if(subs==0)
{
set_temper--;
flag=0;
}
}
else if(stop==0)
{
for(a=0;a<5;a++)
for(b=0;b<102;b++){}
if(stop==0)
{
flag=0;
break;
}
EA=1;
}
get_temper();
b=temper;
if(flag_2==1)
a=b;
if((abs(a-b))>5)
temper=a;
else
temper=b;
a=temper;
flag_2=0;
if(++count1>30)
{
display();
count1=0;
}
compare_temper();
}
TR0=0;
z=1;
while(1)
{
EA=0;
if(stop==0)
{
for(a=0;a<5;a++)
for(b=0;b<102;b++){}
if(stop==0)
disp_1(phil);
// break;
}
EA=1;
}
}

SG3524输出两路PWM,是双极性PWM那种,我不知道这是不是所谓的同步,但是我知道这种输出可以用单片机实现。
SG3524输出的PWM其实是对称的双极性,一个PWM输出口高电平的时候,另外一个PWM输出口
立即输出低电平,这个可以使用一个定时器做开关周期。
然后使用一个标志位作为一个死区时间。SG3524死区时间可调,可以根据输出电压信号来相应进行调节死区。
很多单片机内部寄存器设置有这种PWM功能,比如NXP 的LPC17XX系列就是
提供一种思路,程序没时间写。
1、PWM需要周期,因此定时器必须得设置匹配值,达到周期计数时间后复位TC值;
2、两个PWM波形需要产生可调的PWM,那么就需要让定时器知道什么时刻该让这个IO口输出高低电平。可以让两个输出提供参数,比如数值是多少后出现高电平,高电平持续多长数值?
3、最后就是关键点了,即将定时器TC值(周期值)细化,比如我脉宽周期设定TC值是3000时候复位,那么我可以将这个定时器定时300时候出现一次中断,600时候中断一次,900时候出现一次中断,一次类推,这样就可以得到很多的时间片段,即标志位COUNT。
4、我希望IO口在周期内出现可调节脉宽那么可以实现了,比如COUNT==IO1的时候让其出现高电平,持续多长时间后出现低电平(中断里面完成);
简单的示意程序:
void TIMER_HANDLE(void)
{
//判断是否达到TC值,如果达到则复位(COUNT清零),否则执行匹配中断
//在原有基础上设置匹配值中断,匹配值 +=300;
COUNT++;
if((COUNT == IO1_H_TIME)) //现在正好是需要高电平的时刻,因此值置高
{
//持续时间开启(自减),是否为0?
//不是0,那么继续输出高电平
//是0,关闭输出,同时清除高电平时刻
}
}
这个是使用一个定时器做两路PWM输出的思路,估计精度不怎么好。LPC1700的MCPWM有那种功能,而且价格便宜,芯片才40块钱一个,易上手,网上资料很多。

SG3524输出两路PWM,是双极性PWM那种,我不知道这是不是所谓的同步,但是我知道这种输出可以用单片机实现。
SG3524输出的PWM其实是对称的双极性,一个PWM输出口高电平的时候,另外一个PWM输出口
立即输出低电平,这个可以使用一个定时器做开关周期。
然后使用一个标志位作为一个死区时间。SG3524死区时间可调,可以根据输出电压信号来相应进行调节死区。
很多单片机内部寄存器设置有这种PWM功能,比如NXP 的LPC17XX系列就是
提供一种思路,程序没时间写。
1、PWM需要周期,因此定时器必须得设置匹配值,达到周期计数时间后复位TC值;
2、两个PWM波形需要产生可调的PWM,那么就需要让定时器知道什么时刻该让这个IO口输出高低电平。可以让两个输出提供参数,比如数值是多少后出现高电平,高电平持续多长数值?
3、最后就是关键点了,即将定时器TC值(周期值)细化,比如我脉宽周期设定TC值是3000时候复位,那么我可以将这个定时器定时300时候出现一次中断,600时候中断一次,900时候出现一次中断,一次类推,这样就可以得到很多的时间片段,即标志位COUNT。
4、我希望IO口在周期内出现可调节脉宽那么可以实现了,比如COUNT==IO1的时候让其出现高电平,持续多长时间后出现低电平(中断里面完成);
简单的示意程序:
void TIMER_HANDLE(void)
{
//判断是否达到TC值,如果达到则复位(COUNT清零),否则执行匹配中断
//在原有基础上设置匹配值中断,匹配值 +=300;
COUNT++;
if((COUNT == IO1_H_TIME)) //现在正好是需要高电平的时刻,因此值置高
{
//持续时间开启(自减),是否为0?
//不是0,那么继续输出高电平
//是0,关闭输出,同时清除高电平时刻
}
}
这个是使用一个定时器做两路PWM输出的思路,估计精度不怎么好。LPC1700的MCPWM有那种功能,而且价格便宜,芯片才40块钱一个,易上手,网上资料很多。


一个PWM输出接口采用1字节(8位二进制)作为周期计数器,计算输出信号的控 ...
1、PWM需要周期,因此定时器必须得设置匹配值,达到周期计数时间后复位TC值;2、两个PWM波形需要产生可调的PWM,那么就需要让定时器知道什么时刻该让这个IO口输出高低电平。可以让两个输出提供参数,比如数值是多少后出现高电平,高电平持续多长数值?3、最后就是关键点了,即将定时器TC值(周期值)细化,...

电脑pwm接口接哪里
右下角或者左上角。 大多数主板的pwm位置在右下角。3pin风扇的功能是,一个电源,一个接地,一个是信号线,用来向主板发送风扇转速的信息。4pin风扇是温控风扇的PWM信号线。黑线,接地。

普通玩具遥控器为什么不能传输pwm信号
需要一个接口、需要一个PWM采集器进行采集。1、普通玩具遥控器不能传输pwm信号是需要一个接口,连接接口即可传输pwm信号。2、需要一个PWM采集器进行采集才可以让普通玩具遥控器传输pwm信号。

主板pwm接口在哪
在右下角或左上角。主板的PWM接口位置会因主板型号和设计有所不同。大多数主板的PWM接口位置位于右下角,也有主板将位置放在左上角。主板的PWM接口是用于连接CPU风扇的接口,位于CPU风扇连接器的顶部。接口有4个针脚,2个针脚用于提供电源,另2个针脚用于传输控制信号。

主板pwm接口是指哪个
用于连接cpu风扇的接口。cpu风扇连接器是一种用于电脑主板的电源连接器,被称为cpu风扇头或cpu风扇接口,有4个针脚其中2个针脚用于提供电源,另外2个针脚用于传输控制信号,主板的pwm接口指的是用于连接cpu风扇的一种接口,位于cpu风扇连接器的顶部。

什么是PWM(脉宽调制) VGA接口是什么意思
举报 浏览8 次 可选中1个或多个下面的关键词,搜索相关资料。也可直接点“搜索资料”搜索整个问题。 脉宽调制 pwm vga 接口 意思 搜索资料 本地图片 图片链接 代码 提交回答 匿名 回答自动保存中 你的回答被采纳后将获得: 系统奖励15(财富值+成长值)+难题奖励20(财富值+成长值)为...

...控制一个舵机,还是两个接口的PWM信号共同控制一个舵机?
一个接口发出的PWM信号就可以控制一个舵机。

怎么把msp430149pwm封装成模块可以调用
1、首先,确定模块需要的输入和输出参数,如PWM的频率、占空比、输出端口等。2、其次,根据MSP430149的PWM寄存器设置和操作,编写函数来设置PWM的频率、占空比和输出端口等。3、然后,编写的函数封装成一个模块函数,并提供函数接口参数。4、最后,在主程序中调用PWM模块函数,并传入相应的参数,以实现PWM...

主板有几个4pinpwm接口
4个以上。主板上通常有多个散热风扇接口,遍布在主板各个位置,除了CPU散热风扇需要接上它,还有一些机箱的其他位置的散热风扇也都是通过它来驱动。散热风扇接口一般为4pin跳线针,跳针大多附着白色的防呆塑料片,接口附近会有“FAN”标示。而散热风扇有2、3、4pin之分,但是只要对准跳线针的防呆塑料片,...

pwmf接口是什么意思
脉冲调制宽度调制接口。PWM就是脉冲调制宽度调制接口,一般体现了类似正弦波的数字信号,多用于单片机电机控制。PWM(PulseWidthModulation)简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。

井研县17227232430: pwm几位是什么意思,例如8位pwm中8位的意思,是指一个pwm通道可以输出用8个二进制位表示pwm波吗 -
邢骂爱全: 是分辨率,8位的话,那就是说把一个周期可以分为256等分,进行调节高电平占的时间和低电平占的时间

井研县17227232430: S7 - 200CPU的高速输出脉冲在哪? -
邢骂爱全: s7-200有两台pto/pwm发生器,建立高速脉冲串或脉宽调节信号信号波形.一台发生器指定给数字输出点q0.0,另一台发生器指定给数字输出点q0.1.一个指定的特殊内存(sm)位置为每台发生器存储以下数据:一个控制字节(8位值)、一个...

井研县17227232430: 单片机输出的8位pwm波形是什么样子?8位是什么意思?
邢骂爱全: 首先要搞清楚PWM的含义,是脉冲宽度调制的意思,其作用是用来搞通信、开关电源等等. 脉宽调制的意思就是说在一个固定周期的方波(高电平时间与低电平时间和是固定的,高低电平的时间是可以变化的),其脉冲宽度是可调的, 8位PWM波形是指,输出波形的分辨率,即输出方波的周期固定的等分成256份,脉宽(高电平时间)是可以在0-255之内变化的,即占空比为0-100%之间变化. 如我们通常说的方波,其脉宽就是128/256=0.5,也就是占空比是50%. 如占空比是40%的脉冲,其脉宽时间应当是256*0.4=64

井研县17227232430: c8051单片机输出PWM波形的频率怎么设定 -
邢骂爱全: 具体可以使用三个方式,一个是通过DAC 进行对外输出PWM 或者通过PCA通过IO输出PWM的还可以直接用定时器来实现 程序我给你找找 我以前写过的 /********************************************************************** pca实现8位PWM* * 编写环境...

井研县17227232430: 为什么8位PWM的输出频率等于时钟频率除以256? 求大神解释? -
邢骂爱全: 你的问题可能是 写单片机内部寄存器 使单片机采用内部时钟频率/256作为PWM输出频率 比如: 产生一个 频率为125khz 的占空比为50%的载波,传输无线数据-------------------------------------------------------------8位PWM就是将输出方波周期固定分成...

井研县17227232430: 一个字节是由8位二进制组成,怎样算? -
邢骂爱全: 每8位(bit)为一个字节(byte),由于计算机是依靠数字电路(平)来实现的;在数字电路中,接通与断开电路为两个状态量,接通用1表示,断开用0表示.8条电路全部接通为11111111(2)换算为十进制为255,全部断开为00000000(2)十进制为0. 这也是为什么我们通常看到计算机中的总线通常是8根线组成的排线. 即每个字节可以表示0——255 种数字. 每个字节由八个二进制数组成是计算机设计时约定的.

井研县17227232430: 求写个51单片机的PWM程序,输出在一个管脚上,不需要按键控制调速,需要一个形参ZKB即控制ZKB=50 代表50% -
邢骂爱全: pwm(uchar zkb) { uchar x =100; led=0;delay(x*zkb/100); led=1; delay(x*zkb/100); }

井研县17227232430: 1字节等于8字位是什么意思 -
邢骂爱全: 电脑里面一个字节,好像是1B来着,表示8个二进制位,比如00110011这样

井研县17227232430: modbus rtu通讯协议中每字节有1个起始位,8个数据位, 1个奇偶校验位,1个停止位,这样一字节就有11位, -
邢骂爱全: 展开全部11位是通讯协议的时序,8位是数据,11位信号传输的数据只有8位,其余3位是协议开销.看通讯协议的细节可以看RS232的资料,这部分与MODBUS无关.

井研县17227232430: 8位等于1B(字节)? 8位是什么意思呀? 还有1兆的电压是多少V呀? -
邢骂爱全: 8位(Bit)等于1字节(Byte). 1位,就是1个(寄存)单位,有电为1、无电为0;有些电脑有电为0、无电为1. 早期的,是8位作为一个运算、或存储、或输送的单原,称为1字节.现在,已经到64位、或更高的作为一个运算、或存储、或输送单原.只是,习惯还用8位作1字节来称呼.

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网