通过以下代码用51单片机输出pwm时可以调节占空比 但无法设定频率 帮忙看下是代码的问题还是什么问题 用keil5 用普中烧录
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar time;
double count=55; //定义占空比,并初始占空比为55%
sbit PWM=P2^0; //P2^0口输出PWM
sbit key_add=P3^1; //电机加速的按键 的I/O口
sbit key_dec=P3^0; //电机减速的按键 的I/O口
/************函数声明**************/
void delayxms(uint z); //延时
void Motor_add(); //电机加速,即增加占空比
void Motor_dec(); //电机减速,即减少占空比
void timer0_init(); //定时器0初始化
/*********主函数********************/
void main()
{
timer0_init();
delayxms(5);
while(1)
{
Motor_add();
Motor_dec();
}
}
/****************延时处理**********************/
void delayxms(uint z) //延时xms程序
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void Motor_add() //电机加速
{
if(key_add==0)
{
delayxms(2); //此处时间不能太长,否者会的中断产生冲突
if(key_add==0)
{
count+=0.5; //每按一次加速按键占空比加0.5
if(count>=70) //限定占空比上限
{
count=70;
}
}
while(!key_add);
}
}
void Motor_dec()//电机减速
{
if(key_dec==0)
{
delayxms(2);//此处时间不能太长,否者会的中断产生冲突
if(key_dec==0)
{
count-=0.5; //每按一次减速按键占空比减0.5
if(count<=30) //限定占空比下限
{
count=30;
}
}
while(!key_dec);
}
}
/***********定时器0初始化***********/
void timer0_init()
{
TMOD=0x01; //定时器0工作于方式1
TH0=(65536-20)/256;
TL0=(65536-20)%256;
TR0=1;
ET0=1;
EA=1;
}
/**************定时0中断处理******************/
void timer0_int() interrupt 1
{
TR0=0; //设置定时器初值期间,关闭定时器
TH0=(65536-20)/256;
TL0=(65536-20)%256;
TR0=1;
time++;
if(time<count) //count为占空比
{
PWM=1; //输出高电平
}
else
PWM=0;
if(time>=100)
{
time=0;
}
}
频率是波总时间设定,占空比是波总时间范围内的调节,解释和自动调节荔枝。
对比下这个实例代码:
#include <reg52.h>
sbit PWM = P1^0; // 定义PWM输出引脚
void main() {
TMOD = 0x01; // 定时器0工作在模式1(16位计数器)
TH0 = 0xFF; // 定时器0的高8位初始值
TL0 = 0xFF; // 定时器0的低8位初始值
TR0 = 1; // 启动定时器0
while (1) {
// 输出PWM信号,调整占空比和频率
for (int i = 0; i < 255; i++) {
PWM = i; // 设置PWM占空比
_nop_(); // 延时一段时间,控制PWM频率
}
for (int i = 255; i >= 0; i--) {
PWM = i; // 设置PWM占空比
_nop_(); // 延时一段时间,控制PWM频率
}
}
}
在PWM低电平时间达到的时候把PWM置1并且把定时器赋初值
if(PWM==0)
{
TL1 =T1LL0[i];//高电平低八位数组
TH1 =T1HH0[i];//高电平高八位数组
PWM=1;
}
无法调节频率是因为你代码里写死了
if(time>=100)
{
time=0;
}
这里限定了PWM的周期是100次定时器中断,让这个100成为可调节的变量,即可调节PWM的频率。
但是从你代码里看,并没有看出调节频率的意图啊,只有调节占空比的,两个按钮就被用来调节速度了而已,如果你要调节频率,还要写两个类似的按键处理函数。我估计这个代码根本不是你自己写的吧?
另外,不建议用浮点数来计算占空比,会降低效率的,我看你每次增减0.5,直接用整数好了,数值上乘以2即可。对51来说,浮点运算效率太低了
看你的代码是通过T0的计数0到100来确定频率的,你只需要更改T0的初值就可以条件频率了,现在是 T0初始为(65536-20),20数字变大你的PWM频率就降低,减小你的频率就升高
可以看看
void Timer0_Init(void) //100微秒
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
// TMOD = 0X01;
TL0 = 0x9C; //设置定时初值
TH0 = 0xFF; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1;
ET0 = 1;
PT0 = 0;
}
unsigned int counter = 0;
void Timer0_Routine() interrupt 1
{
TL0 = 0x9C; //设置定时初值
TH0 = 0xFF; //设置定时初值
counter++;
if(counter == 100)
{
counter = 0;
}
}
频率调节借鉴参考 https://blog.csdn.net/weixin_56337907/article/details/124141071
检查一下时钟源、分频系数、定时器模式、计数器值等设置是否正确合理,同时通过调整占空比来改变PWM输出的平均电平。
根据您提供的代码,我看到您使用的是定时器0(Timer 0)来生成PWM信号。从代码中可以看出,您设置了一个定时器中断,在中断处理函数中控制PWM输出的高低电平来实现占空比的调节。
然而,关于您提到无法设定频率的问题,我注意到在定时器0的初始化部分,您设置了定时器工作于方式1(Timer Mode 1),这意味着它将作为一个16位定时器进行计数。
根据代码中的设定,您将TH0和TL0的初值设置为(65536-20),这将导致定时器0在每个溢出周期中计数20个机器周期。这将导致定时器中断的频率为时钟频率除以20。
要调整定时器0的频率,您可以尝试以下操作:
例如,如果您希望PWM的频率为100Hz,且MCU的时钟频率为12MHz(12,000,000Hz),您可以进行如下计算:
初值 = 65536 - (12,000,000 / (100 * 12)) = 45536
将初值设置为TH0和TL0,即 TH0 = 45536 / 256 = 177,TL0 = 45536 % 256 = 144。
请注意,这是一个简化的示例,您可能需要根据您的具体要求和MCU的特性进行调整。
通过调整定时器0的初值,您应该能够更好地控制PWM的频率。请尝试上述方法,并确保在计算初值时考虑到您使用的MCU的时钟频率和目标PWM频率。
回答部分参考、引用ChatGpt以便为您提供更准确的答案:
根据您提供的代码,您使用51单片机实现了通过PWM输出调节占空比的功能。然而,您遇到了无法设定频率的问题。以下是可能导致该问题的原因和解决方法:
timer0_int()
,但是在主函数中并没有将该函数与中断向量关联起来。请确保在主函数中正确设置中断向量,使得定时器0的中断能够被正确处理。综上所述,您需要检查定时器的设置、时钟源选择、中断处理函数和晶振频率等方面,以解决无法设定频率的问题。根据您使用的开发环境和单片机型号的不同,具体的解决方法可能会有所差异。建议您仔细查阅相关的单片机手册、开发工具文档或在线资源,以获取准确的设置步骤和示例代码。