用单片机内部的不行吗?
// 晶振使用24M,频率输出为40K
#include <AT89X51h>// 单片机为AT89S51或52
/
功能:串口中断服务程序
/
void int_t0(void) interrupt 1
{
P1_2=!P1_2; // 频率输出IO,24M晶振时频率为1M/(256-TH0)
}
void main(void)
{
TMOD = 0x02;// T0设置为8位定时器
ET0 = 1; // 开T0中断
TH0 = 231;
TL0 = 0;// 填充初值
TR0 = 1;// 打开T0定时器
EA = 1;// 开总中断
while(1);
}
希望对你有帮助
//超声波模块显示程序
#include <reg52h> //包括一个52标准内核的头文件
#define uchar unsigned char //定义一下方便使用
#define uint unsigned int
#define ulong unsigned long
sbit Tx = P3^3; //产生脉冲引脚
sbit Rx = P3^2; //回波引脚
uchar code SEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//数码管0-9
uint distance[4]; //测距接收缓冲区
uchar ge,shi,bai,temp,flag,outcomeH,outcomeL,i; //自定义寄存器
bit succeed_flag; //测量成功标志
//函数声明
void conversion(uint temp_data);
void delay_20us();
void pai_xu();
void main(void) // 主程序
{ uint distance_data,a,b;
uchar CONT_1;
i=0;
flag=0;
Tx=0; //首先拉低脉冲输入引脚
TMOD=0x11; //定时器0,定时器1,16位工作方式
TR0=1; //启动定时器0
IT0=0; //由高电平变低电平,触发外部中断
ET0=1; //打开定时器0中断
EX0=0; //关闭外部中断
EA=1; //打开总中断0
while(1) //程序循环
{
EA=0;
Tx=1;
delay_20us();
Tx=0; //产生一个20us的脉冲,在Tx引脚
while(Rx==0); //等待Rx回波引脚变高电平
succeed_flag=0; //清测量成功标志
EX0=1; //打开外部中断
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //
TR1=1; //启动定时器1
EA=1;
while(TH1 < 30);//等待测量的结果,周期65535毫秒(可用中断实现)
TR1=0; //关闭定时器1
EX0=0; //关闭外部中断
if(succeed_flag==1)
{
distance_data=outcomeH; //测量结果的高8位
distance_data<<=8; //放入16位的高8位
distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据
distance_data=12; //因为定时器默认为12分频
distance_data/=58; //微秒的单位除以58等于厘米
} //为什么除以58等于厘米, Y米=(X秒344)/2
// X秒=( 2Y米)/344 ==》X秒=00058Y米 ==》厘米=微秒/58
if(succeed_flag==0)
{
distance_data=0; //没有回波则清零
}
distance[i]=distance_data; //将测量结果的数据放入缓冲区
i++;
if(i==3)
{
distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;
pai_xu();
distance_data=distance[1];
a=distance_data;
if(b==a) CONT_1=0;
if(b!=a) CONT_1++;
if(CONT_1>=3)
{ CONT_1=0;
b=a;
conversion(b);
}
i=0;
}
}
}
//
//外部中断0,用做判断回波电平
INTO_() interrupt 0 // 外部中断是0号
{
outcomeH =TH1; //取出定时器的值
outcomeL =TL1; //取出定时器的值
succeed_flag=1; //至成功测量的标志
EX0=0; //关闭外部中断
}
//
//定时器0中断,用做显示
timer0() interrupt 1 // 定时器0中断是1号
{
TH0=0xfd; //写入定时器0初始值
TL0=0x77;
switch(flag)
{case 0x00:P0=ge; P2=0x7f;flag++;break;
case 0x01:P0=shi;P2=0xbf;flag++;break;
case 0x02:P0=bai;P2=0xdf;flag=0;break;
}
}
//显示数据转换程序
void conversion(uint temp_data)
{
uchar ge_data,shi_data,bai_data ;
bai_data=temp_data/100 ;
temp_data=temp_data%100; //取余运算
shi_data=temp_data/10 ;
temp_data=temp_data%10; //取余运算
ge_data=temp_data;
bai_data=SEG7[bai_data];
shi_data=SEG7[shi_data]&0x7f;
ge_data =SEG7[ge_data];
EA=0;
bai = bai_data;
shi = shi_data;
ge = ge_data ;
EA=1;
}
//
void delay_20us()
{ uchar bt ;
for(bt=0;bt<60;bt++);
}
void pai_xu()
{ uint t;
if (distance[0]>distance[1])
{t=distance[0];distance[0]=distance[1];distance[1]=t;}
if(distance[0]>distance[2])
{t=distance[2];distance[2]=distance[0];distance[0]=t;}
if(distance[1]>distance[2])
{t=distance[1];distance[1]=distance[2];distance[2]=t;}
}
这里有个直流电机调速的程序,可以参考一下
功能 : 通过P10口来控制直流电机的旋转的快慢
//
#include <reg52h>
#define uchar unsigned char
#define uint unsigned int
sbit KEY1 = P3^2; //定义调速的按键
sbit PWM = P1^0; //定义直流电机的控制端口
uchar CYCLE; //定义周期
uchar PWM_ON ; //定义低电平时间
/
名称 : Delay_1ms()
功能 : 延时子程序,延时时间为 1ms x
输入 : x (延时一毫秒的个数)
输出 : 无
/
void Delay(uint i)
{
uchar x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
void Time0(void)
{
TMOD |=0x01; //定时器设置 1ms in 12M crystal
TH0=(65536-1000)/256;
TL0=(65536-1000)%256; //定时1mS
IE= 0x82; //打开中断
TR0=1; //定时器打开
}
main()
{
uchar PWM_Num; //定义档位
Time0();
CYCLE = 10; //时间可以调整 这个是10步调整 周期10ms 8位PWM就是256步
PWM = 0;
while(1)
{
if(!KEY1)
{
Delay(15);
if(!KEY1)
{
PWM_Num++; //按一下P32口,就给直流电机换一个档位
if(PWM_Num==4)
{
PWM_Num=0;
}
switch(PWM_Num)
{
case 0:P0=0x06; PWM_ON=0;break; //低电平时长 //给P0口赋值,是让P0口显示:1,2,3,4 这四个档位
case 1:P0=0x5B; PWM_ON=2;break;
case 2:P0=0x4F; PWM_ON=4;break;
case 3:P0=0x66; PWM_ON=6;break;
default:break;
}
}
}
}
}
//
/ 定时中断 /
//
void tim(void) interrupt 1 using 1
{
static unsigned char count;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;//定时1mS
if(count==PWM_ON)
{
PWM = 1; //直流电机转
}
count++;
if(count == CYCLE)
{
count=0;
if(PWM_ON!=0) //如果左右时间是0 保持原来状态
{
PWM = 0; //直流电机不转
}
}
}
假设晶振是12M,要产生40K方波,需要延时125us,定时器的延时还要考虑函数返回,中断延迟等方面的;
如果要求精度很高的话,楼主的程序实现40k的方波比较困难
延时时间不是很长的话,建议用nop指令来实现
#include<reg51h>
#define uint unsigned int
uint pwm=50;
bit flag=0;
sbit pluse=P1^0;
sbit key=P1^4;
void t0isr() interrupt 1
{
if(flag)pluse=1;
else pluse=0;
flag=~flag;
}
main()
{
TMOD=0x02;
TH0=256-(char)(pwm28/100);
TL0=256-(char)(pwm28/100);
TR0=1;
ET0=1;
EA=1;
while(1)
{
if(key==0)
{
while(key==0);
pwm+=10;
if(pwm>=100)pwm=10;
}
if(flag)
{
TH0=256-(char)(pwm28/100);
TL0=256-(char)(pwm28/100);
}
if(!flag)
{
TH0=256-28+(char)(pwm28/100);
TL0=256-28+(char)(pwm28/100);
}
}
}
用定时器模拟PWM即可。具体就不算了,看你代码大体原理差不多,你可以试着接一个蜂鸣器,将输出角接到蜂鸣器上,查下声音的频率表,打出一个频率出来看发出的音对不对,我以前用类似的道理做过一个类似于贺卡那个铃声的东西。
以上就是关于8253地址为80H~83H.,8253通道0输出方波,CLK0为1MHZ,要求输出方波的重复频率为40KHZ,编写初始化程序。全部的内容,包括:8253地址为80H~83H.,8253通道0输出方波,CLK0为1MHZ,要求输出方波的重复频率为40KHZ,编写初始化程序。、51单片机控制的超声波测距仪程序、用51单片机控制电机的启动与停止,电机的驱动频率是40KHz,启动响应时间在3毫秒左右,关闭停止时间在1等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)