本帖最后由 jmkl128 于 2018-3-20 19:01 编辑
很简单的东西,输出方波的频率还比较准。程序中按键部分采用了新的方法。
//晶振:12M (6T使能)
/*T0-计时25 微秒溢出中断一次;P1.3 P1.4为增加、减少键P3.3 输出方波
变量的定义: pwm 设定的频率数
connter_1 根据设定频率计算后的,定时器溢的出次数值
connter : 定时器0计数溢出数
led_seg_code: 数码管7 段码
*/
/*用单片机产生频率可调的方波信号。输出方波的频率范围为1Hz-200Hz,频率误差比小于0.5%。
要求用"增加"、"减小"2 个按钮改变方波给定频率,按钮每按下一次,给定频率改变的步进步长为1Hz,
当按钮持续按下的时间超过2 秒后,给定频率以10 次/秒的速度连续增加(减少),输出方波的频率要求在数码管上显示。
P1.3,P1.4分别为增加和减小按键*/
#include<reg52.h>
#include<intrins.h>
#include <math.h>
sbit led_1=P2^4;
sbit led_2=P2^3;
sbit led_3=P2^2;
sbit led_4=P2^1;
sbit out=P2^0;
sbit pwm_out=P3^3;
unsigned char pwm;
unsigned int counter,counter_1;
unsigned char Trg; //点按
unsigned char Cont; //长按
unsigned char cnt_plus; //长按延时
unsigned char cnt_plus_time; //长按速度
unsigned char code seg_table[10]= {0xfa,0x22,0xb9,0xab,0x63,0x0cb,0x0db,0xa2,0xfb,0xeb}; //1~~~~9段选码
/**************************************
****************定时器初始化函数****************
**************************************/
void InitTimer(void)
{
TMOD &= 0xFF; //设置定时器模式 T0,8位自动加载,25us定时中断。T1,16位,20ms,用于按键检测
TMOD |= 0x12; //设置定时器模式
TL0 = 0xCE; //设置定时初值
TH0 = 0xCE; //设置定时重载值 25us
TF0=0; //清除中断标记
ET0 = 1; //TO使能
TR0 = 1; //T0开始计时
TL1 = 0xC0; //设置定时初值
TH1 = 0x63; //设置定时初值 20ms
TF1=0; //清除中断标记
ET1=1; //T1使能
TR1=1; //T1开始计时
EA = 1; //开总中断
}
/**************************************
****************延时1ms****************
**************************************/
void delay1ms(void) //@12.000MHz
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j)
{
;
}
}
while (--i);
}
/**************************************
****************按键检测****************
**************************************/
void Key(void)
{
unsigned char ReadData=P1^0xff;
Trg=ReadData&(ReadData^Cont);
Cont=ReadData;
if (Cont==0)
{
cnt_plus=0; //长按标志清0
}
if (Trg&0x10) //按下P1.3
{
pwm++;
if(pwm==201)
{
pwm=1;
}
}
if (Trg&0x08) //按下P1.4
{
pwm--;
if(pwm==0)
{
pwm=200;
}
}
if (cnt_plus<50)
{
cnt_plus++; //开始长按延时
}
if (cnt_plus>=50) //长按1秒后开始动作
{
cnt_plus_time++; //长按时速度变化
if (cnt_plus_time>10)
{
cnt_plus_time=0;
if (Cont&0X10) //长按P1.3
{
if(pwm<=190)
{
pwm=pwm+10;
}
else
{
pwm++;
}
if(pwm==201)
{
pwm=1;
}
}
if (Cont&0X08) //长按P1.4
{
if(pwm>=10)
{
pwm=pwm-10;
}
else
{
pwm--;
}
if(pwm==0)
{
pwm=200;
}
}
}
}
}
/**************************************
****************显示函数****************
**************************************/
void display()
{
P0=seg_table[pwm/100];
led_1=0;
led_2=1;
led_3=1;
led_4=1;
delay1ms();
led_1=1;
P0=seg_table[(pwm%100-(pwm%10))/10];
led_1=1;
led_2=0;
led_3=1;
led_4=1;
delay1ms();
led_2=1;
P0=seg_table[pwm%10];
led_1=1;
led_2=1;
led_3=0;
led_4=1;
delay1ms();
led_3=1;
P0=0x73;
led_1=1;
led_2=1;
led_3=1;
led_4=0;
delay1ms();
led_4=1;
}
/**************************************
****************T0中断溢出数计算****************
**************************************/
unsigned int get_T0_over_num(unsigned char p) //p 为频率数
{
unsigned int h;
double f,*k;
f=(double)p; //转化为浮点数
f=0.5/f; //半个周期的时间
f=f/0.0000272; //中断溢出数=f/0.000025;
h=f; //取整
if (modf(f,k)>=0.5)//四舍五入
{
h=h+1;
}
return h;
}
/* C51 有专门的库文件MATH.H,里面有个函数
它是这样定义的extern float modf(float x, float *ip);
调用它之后,整数部分被放入*ip, 小数部分作为返回值。
*/
/**************************************
****************主函数***************
**************************************/
void main ()
{
InitTimer();
pwm = 15;
while(1)
{
counter_1=get_T0_over_num(pwm);
display();
}
}
/**************************************
****************T0中断,用于改变方波频率****************
**************************************/
void Timer0Interrupt(void) interrupt 1
{
counter++;
if(counter==counter_1)
{
counter = 0 ;
pwm_out = ~pwm_out;
out= pwm_out;
}
}
/**************************************
****************T1中断,用于检测按键****************
**************************************/
void tm1_isr() interrupt 3 using 1
{
TR1=0; //关闭定时器T1
Key(); //执行键盘扫描
TL1 = 0xC0; //设置定时初值
TH1 = 0x63; //设置定时初值
TR1=1; //启动定时器T1
}
方波.rar
(1.96 KB, 下载次数: 73)
|