普通51的话需要模拟PWM,如果是加强版51有内置PWM模块,
PIC和AVR以及430还有STM也有集成PWM的型号!
如果是单纯输出方波的话就简单了。
程序如下:
//功能,按下P1_0的开关降低频率,按P1_1为升高频率
#includeAT89X52.H //引用AT89X52的库文件
#define uchar unsigned char //替换简称
#define uint unsigned int //替换简称
uchar sm; //定义临时变量
void delay_ms(uint ms) //延时子函数,一个循环12uS
{
while(--ms);
}
void T0_IRQ(void) interrupt TF0_VECTOR //定时器0中断函数
{
TH0=sm; //将变量赋予定时器0的高位
P2_0=!P2_0; //翻转IO
}
//寄存器初始化子函数
void mcu_init()
{
ET0=1; //开定时器0中断
EA=1; //开总中断
TMOD=0x01; //设置为16位定时器0
TH0=0xFF; //填充定时器高位
TR0=1; //开定时器0
sm=0xFF; //变量初始化
}
void main() //主函数
{
mcu_init(); //调用初始化函数
while(1) //主循环
{
if((!P1_0)||(!P1_1)) //检测是否有按键按下
{
delay_ms(8333); //延时去抖
if(!P1_0) //如果是P1_0按键按下
{
while(!P1_0); //等待按键放手
if(sm) //检测变量不为0
{
--sm; //自减1
P2_1=1; //取消边界LED
}
else P2_1=0; //到达边界点亮LED
}
else if(!P1_1) //否则如果P1_1按键按下
{
while(!P1_1); //等待按键放手
if(sm0xFF) //检测变量小于0xFF
{
++sm; //自加1
P2_1=1;
}
else P2_1=0;
}
}
}
}
对于C语言编写的程序你的要求太高了啊你可以使用keil进行软件仿真,你会发现连软件仿真这种形式也做不到500khz,实际场合就会误差更大主要是因为C这种语言已经忽略了指令周期这种概念,而且软件仿真可以看到,每次中断执行AA=!AA,结束之后程序会跳回主函数等待,这个时间已经是错过好一些中断了如果你还要执行其他任务的话就更难控制精度了。而1us的精度就连汇编也很难做到的,51单片机主要用在控制场合,而对于高精度或者强调复杂计算的场合还是少用,这个应该属于本身的局限。你可以把精度放低一些,或者试试其他的cpu
先根据你的单片机时钟,指令周期,计算出38KHZ对应的定时器初始值,使用2个计时器,1个控制总周期,1个控制占空比。例如T0控制总周期,T1控制占空比。
1、同时启动T0和T1,输出脚置位为1;
2、T1中断时,输出脚清位为0,并停T1;
3、在T0中断时,完成了1个周期,重新开始第一步。
也可以只使用1个计时器,不过麻烦一些。先装占空比的初始值,输出脚置位,带定时器中断时,输出脚清位为0,定时器再装入(总周期初始值-占空比的初始值)初始值,定时器再中断时,重复循环。
再给你个思路了,差不多就这模式,
#includereg52.h
#define uchar unsigned char
#define uint unsigned int
void isr_t0(void); //定时器T0中断,
sbit SINGAL1=P2^6; //两路PWM信号输出端口,
sbit SINGAL2=P2^7;
sbit clr=P1^1;
int a=100;
int b;
uchar c=5;
uint PWM1;
void isr_t0(void) interrupt 1 //定时器实现T0方波输出
{ int k,h,m,n;
TH0=0xFF; //定时初值0.1ms
TL0=0x9B;
PWM1++;
b=a/5*c;
if(clr==0);
{SINGAL1=0;
SIGNAL2=0;}
else {
if (PWM1=b) //a=10,初始频率为50Hz,
{ SINGAL1=0;
SINGAL2=1;}
else if ((PWM1b)(PWM12*a))
{SINGAL1=1;
SINGAL2=0;}
else (PWM1=2*a)
{PWM1=0;} }}
void main(void)
{
TMOD=0x01;
TH0=0xFF;
TL0=0x9B;
PWM1=0;
EA=1; //CPU中断总允许位,
ET0=1; //定时器计数器T0中断允许位,
ET1=1; //定时器计数器T1中断允许位
TR0=1; //启动定时器T0,
while(1) //无限循环,
{}
}
程序不完全正确,但思路就这个思路,只修改少许就实现了,你说的对P1.1清零,我理解为P1.1对输出波清0
#include reg52.h
#define uint usnigned int
#define uchar unsigned char
sbit p15=P1^5;
uint fru_num=20;
uint t=0;
void key()
{
}
void main()
{
TMOD=0x01;
TH0=(65526-50000)/256;//这是50ms的
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
while(1)
{
key();//改变fru_num并将t=0
}
}
void timer_t0 interrupt 1
{
TH0=(65526-50000)/256;//这是50ms的
TL0=(65536-50000)%256;
t++;
if(tfru_num)//设置为20,就是1s为高1s为低
{
t=0;
P15^=P15;
}
}
差不多这样吧
c52单片机反出方波指令的介绍就聊到这里吧,感谢您花时间阅读,谢谢。
本文标签:c52单片机反出方波指令