求大佬帮忙看看我这个基于at89c51的可调频率和占空比的方波发生器代码哪里有问题

墨㵘桑 2021-04-20 03:11:47
这是我做的方波发生装置,要求能输出5k到25k的方波,频率和占空比可调,但一直实现不了,求大佬帮忙。

代码如下:
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
float f=12000000;
sbit KEY1=P1^0;
sbit KEY2=P1^1;
sbit KEY3=P1^2;
sbit KEY4=P1^3;
sbit OUTPUT=P2^0;
uchar zkb;
uint freq;
uchar TIMER0_L,TIMER0_H,TIMER1_L,TIMER1_H;

void delay(uchar n)
{
uchar i;
while(n--)
{for(i=255;i>0;i--)
{}
}}

void SysInit(void)
{
P1=0x0f;
freq=5000;
zkb=50;
TIMER0_L=0xe0;
TIMER0_H=0xb1;
TIMER1_L=0xf0;
TIMER1_H=0xd8;
TL0=0xe0;
TH0=0xb1;
TL1=0xf0;
TH1=0xd8;
TMOD=0x11;
IT0=1;
EX0=1;
ET0=1;
ET1=1;
EA=1;
TR0=1;
TR1=1;
}

void main(void)
{
SysInit();
while(1)
{}
}

void Timer0_freq() interrupt 1
{
TR1=1;
TL0=TIMER0_L;
TH0=TIMER0_H;
OUTPUT=1;
}

void Timer1_zkb() interrupt 3
{
TR1=0;
TL1=TIMER1_L;
TH1=TIMER1_H;
OUTPUT=0;
}

void Keyscan() interrupt 0 using 1
{
float TF0,TZ1;
EX0=0;
delay(1);
if(P1!=0x0f)
{
if(KEY1==0) freq+=1000;
if(KEY2==0) freq+=100;
if(KEY3==0) zkb+=10;
if(KEY4==0) zkb+=1;
if(freq>25000) freq=5000;
if(zkb>100) zkb=10;
TF0=(65536-f/(12*freq));
TZ1=(65536-(f*zkb)/(12*100*freq));
TIMER0_H=(uint)TF0/256;
TIMER0_L=(uint)TF0%256;
TIMER1_H=(uint)TZ1/256;
TIMER1_L=(uint)TZ1%256;
}
P1=0x0f;
EX0=1;
TR0=1;
TR1=1;
}
...全文
201 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
dceacho 2021-04-21
  • 打赏
  • 举报
回复
要描述准确这样大家才容易帮你看哪里有可能出问题 比如你这个 是完全没波形 还是波形频率,占空比不对 还是有波形,但按键没有起到调节作用 或者说是编译链接就报错
  • 打赏
  • 举报
回复
就电路图来说画蛇添足,除了P0口外其他口都不需要上拉电阻,可见对硬件不甚了解缘故.
Ayyee 2021-04-21
  • 打赏
  • 举报
回复
建议查一下芯片数据手册,有完整的PWM输出控制。看你想输出一路还是两路。一路的话用定时器一个就够了。另外通过按键调节PWM占空比,可以不用中断。你现在写的这个处理函数,有单步运行过吗?应该是进不去的,没看到你有相关配置。
墨㵘桑 2021-04-21
  • 打赏
  • 举报
回复
感谢大佬,我在上面一句也加了强制转换,解决了
seedundersnow 2021-04-21
  • 打赏
  • 举报
回复
把括弧中的某个量强制转换成更长的类型比如32BIT或浮点,可以避免数值溢出。 TZ1=(65536-(f*zkb)/((float)12*100*freq)); 或者 TZ1=(65536-(f*zkb)/((unsigned long)12*100*freq));
seedundersnow 2021-04-21
  • 打赏
  • 举报
回复
TZ1=(65536-(f*zkb)/(12*100*freq)); 这个表达式,其中的(12*100*freq)计算应该会出问题。你的freq定义为16BIT,这个括弧中的计算结果会超出16BIT,产生了溢出,表达式的计算最后得到错误的值。
seedundersnow 2021-04-21
  • 打赏
  • 举报
回复
注意系统占用的符号名。 TF0是TIMER0溢出信号,在全局域定义这个符号名会报错,定义成局部变量不会报错,但是会使TIMER0的溢出信号无法访问。。。。虽然在你的程序里可能没有问题。
dceacho 2021-04-21
  • 打赏
  • 举报
回复
总感觉定时器值算的有问题 只有一个时
引用
void Timer0_freq() interrupt 1 { TR1=1; TL0=TIMER0_L; TH0=TIMER0_H; OUTPUT=1;//这里要改成取反OUTPUT=~OUTPUT }
墨㵘桑 2021-04-21
  • 打赏
  • 举报
回复
确实,我在单片机这方面还只是萌新,请各位大佬多多包涵。 我遇到的主要问题是在按键时,频率和占空比会乱掉,根本无法实现调节的功能,如下图: 然后我也试过只用一个定时器,但最后根本没有波形,所以才用来两个定时器,代码如下: #include<reg51.h> #define uchar unsigned char #define uint unsigned int float f=12000000; sbit KEY1=P1^0; sbit KEY2=P1^1; sbit KEY3=P1^2; sbit KEY4=P1^3; sbit output=P2^0; uchar zkb=50; uint freq=5000; uchar tcount=0; void delay(uchar n) { uchar i; while(n--) {for(i=255;i>0;i--) {} }} void SysInit(void) { P1=0x0f; TMOD=0x01; IT0=1; EX0=1; ET0=1; EA=1; TR0=1; TF0=(65536-f/(freq*12)); TH0=(uint)TF0/256; TL0=(uint)TF0%256; } void main(void) { SysInit(); while(1) {} } void Keyscan() interrupt 1 using 1 { float TF0; EX0=0; if(P1!=0x0f) { if(KEY1==0) freq+=1000; if(KEY2==0) freq+=100; if(KEY3==0) zkb+=10; if(KEY4==0) zkb+=1; if(freq>25000) freq=5000; if(zkb>100) zkb=10; TF0=(65536-f/(freq*12)); TH0=(uint)TF0/256; TL0=(uint)TF0%256; tcount++; if(tcount==(100-zkb)) {output=0;} else if(tcount==zkb) {output=1; tcount=0;} } P1=0x0f; EX0=1; TR0=1; }
seedundersnow 2021-04-20
  • 打赏
  • 举报
回复
抱歉,好像我的理解是错的。编译器会进行转换。
seedundersnow 2021-04-20
  • 打赏
  • 举报
回复
TIMER0_H=(uint)TF0/256; 这种强制类型转换,我的映像中是,编译器不会做转换,而是直接把原来的变量当成你指定的类型去用。不知道我是不是理解错了。如果像我理解的那样,你不会得到正确的结果的。

27,374

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧