#include <at89x52.h>
#define uchar unsigned char
#define uint unsigned int
#define NOKEY 0xff
#define KEY_WOBBLE_TIME 3 //去抖动时间(待定)
#define KEY_OVER_TIME 100 //等待进入连击时间(待定),该常数要比正常 //按键时间要长,防止非目的性进入连击模式
#define KEY_QUICK_TIME 1000 //等待按键抬起的连击时间
#define KEY_P P3 //定义按键P口
sbit SDAA=P1^7;
sbit SCLA=P1^6;
sbit LDAC=P1^5;
sbit LOAD=P1^4; //tlc5620的位定义
uchar key_val=0xff; // 用于保存按键扫描返回的键值
uchar wave_flag=0; //波形选择标志,默认输出的是三角波
uchar time; //用于timer1计数
uchar time0; //timer1计数限制
/****************************产生三角波的参数定义***************************************/
bit bdata mode_bit1=0; //三角波幅度递增或递减标志变量,为0时上坡,为1下坡
uchar count1=0; //三角波的半周期计数器
float vouta=0; //三角波瞬态电压值存储变量
float ampl_tri_add; //三角波幅度增加值
/****************************产生方波的参数定义*****************************************/
uchar count0=50; //方波占空比
uchar count2=0; //方波的半周期计数器
uchar voutb=0; //方波瞬态电压值存储变量
uchar ampl; //方波输出幅度值
/****************************产生正弦波的参数定义***************************************/
uchar countsin; //正弦波形选择标志
uchar voutc=0; //正弦波瞬态电压值存储变量
uchar sine_index=0; //正弦波表的下标
uchar code sin_tab[]= { //正弦波表
64,67,70,73,76,79,82,85,88,91,94,96,99,102,104,106,
109,111,113,115,117,118,120,121,123,124,125,126,126,
127,127,127,127,127,127,127,126,126,125,124,123,121,
120,118,117,115,113,111,109,106,104,102,99,96,94,91,
88,85,82,79,76,73,70,67,64,60,57,54,51,48,45,42,39,
36,33,31,28,25,23,21,18,16,14,12,10,9,7,6,4,3,2,1,
1,0,0,0,0,0,0,0,1,1,2,3,4,6,7,9,10,12,14,16,18,21,23,
25,28,31,33,36,39,42,45,48,51,54,57,60};
uint config; //送往DA转换器的配置参数
/**********************tlc5620函数定义*********************************/
void ini_cpuio(void) //CPU的IO口初始化函数
{
SCLA=0;
SDAA=0;
LOAD=1;
LDAC=1;
}
void dac5620(uint config) //串行D/A转换
{
uchar m=0;
uint n;
for(;m<0x0b;m++)
{
SCLA=1;
n=config;
n=n&0x8000;
SDAA=(bit)n;
SCLA=0;
config<<=1;
}
LOAD=0;
LOAD=1;
LDAC=0;
LDAC=1;
}
void triangular(void) //周期三角波生成函数
{
config=(uint)vouta;
config<<=5;
config=config&0x1fff;
config=config|0x2000; //0010 0000 0000 0000 选择A通道,增益为1
dac5620(config);
}
void square(void) //周期方波生成函数
{ config=(uint)voutb;
config<<=5;
config=config&0x1fff;
config=config|0x2000;
dac5620(config);
}
void sine() //正弦波
{
if(sine_index<128)
{
if(countsin==0)
voutc=sin_tab[sine_index];
else if(countsin==1)
voutc=1.4*sin_tab[sine_index];
config=(uint)voutc;
config<<=5;
config=config&0x1fff;
config=config|0x2000;
dac5620(config);
}
else
sine_index=0;
}
/*************************按键扫描定义***************************************/
uchar Read_Key()
{
static uchar LastKey = NOKEY ; //LastKey用于保存上一次的键值
static uint KeyCount = 0 ; //KeyCount按键延时计数器
static uint KeyOverTime = KEY_OVER_TIME ; //KeyOverTime 按键抬起时间
uchar KeyTemp = NOKEY ; //KeyTemp 临时保存读到的键值
KeyTemp = KEY_P & 0xff ; //读键值
if( KeyTemp == 0xff )
{
KeyCount = 0 ;
KeyOverTime = KEY_OVER_TIME ;
return NOKEY ; //无键按下返回NOKEY
}
else
{
if( KeyTemp == LastKey ) //是否第一次按下
{
if( ++KeyCount == KEY_WOBBLE_TIME ) //不是第一次按下,则去抖动
{
return KeyTemp ; //去抖动结束,返回键值
}
else
{
if( KeyCount > KeyOverTime )
{
KeyCount = 0 ;
KeyOverTime = KEY_QUICK_TIME ;
}
return NOKEY ;
}
}
else //是第一次按下则保存键值,以便下次执行此函数时与读到的键值作比较
{
LastKey = KeyTemp ; //保存第一次读到的键值
KeyCount = 0 ; //延时计数器清零
KeyOverTime = KEY_OVER_TIME ;
return NOKEY ;
}
}
}
void system_init()
{
TMOD=0x11;
TH0=(65536-100)/256;
TL0=(65536-100)%256; // 用于输出波形
TH1=(65536-5000)/256;
TL1=(65536-5000)%256; //用于按键扫描
TR1=1;
ET1=1;
TR0=1;
ET0=1;
EA=1;
time0=15;
time=0;
wave_flag=0;
ampl=50;
ampl_tri_add=1.8;
countsin=0;
ini_cpuio();
sine_index=0;
}
void main(void)
{
system_init(); system_init();
while(1) //周期地进行转换,形成三角波和方波的周期信号
{
switch(wave_flag) // wave_flag
{
case 0: triangular(); break; //控制通道A输出三角波
case 1: square(); break; //控制通道A输出方波
case 2: sine(); break; //控制通道A输出正弦波
}
}
}
void timer0 () interrupt 1 //用于输出波形
{
TH0=(65536-100)/256;
TL0=(65536-100)%256;
switch(wave_flag) //flag=0时输出三角波,flag=1时输出方波,flag=2时输出正弦波
{
case 0:{
time++;
if(time>=time0) //防止time0减小时,time计数大于time0,time==time0造成的错误
{
time=0;
count1++;
if(count1<50)
{
if(!mode_bit1) //判断处于上坡还是下坡状态以决定是继续上升还是继续下降
{
vouta=vouta+ampl_tri_add;
if(vouta>=0xf0)
vouta=0x30;
}
else
{
vouta=vouta-ampl_tri_add;
if(vouta<=0x00)
vouta=0x30;
}
}
else
{
count1=0;
mode_bit1=~mode_bit1; //如果已经达到峰点(或谷点)则改变幅度递增或递减标志
}
}
}break;
case 1:{
time++;
if(time>=time0)
{
time=0;
count2++;
if(count2<count0) //根据方波幅度高低电平标志变量决定是输出高电平还是低电平
{
voutb=ampl;
}
else
voutb=0; //如果已经达到改变电平状态的时刻则改变方波幅度标志变量
if(count2>=100)
{
count2=0;
}
}
}break;
case 2:{
time++;
if(time>=time0)
{
time=0;
sine_index++;
}
}break;
}
}
void timer_1() interrupt 3 //用于按键扫描
{
TH1=(65536-5000)/256;
TL1=(65536-5000)%256;
key_val=Read_Key();
if(key_val==0xff) return; //减少无效按键判断,以提高效率
switch(key_val)
{
case 0xfe:{ //“1”号键,用于选择波形
wave_flag++;
if(wave_flag>=3)
wave_flag=0;
}break;
case 0xfd:{ //“2”号键,周期增大
time0=time0+5;
if(time0==200)
time0=100;
}break;
case 0xfb:{ //“3”号键,周期减小
time0=time0-5; //time0=time0-1;
if(time0<5)
time0=5;
}break;
case 0xf7:{ //“4”号键,幅度增加
if(wave_flag==1) //方波时
{
ampl++;
if(ampl>=120)
ampl=50;
}
if(wave_flag==0) //当为三角波时
{
ampl_tri_add=ampl_tri_add+0.1;