📄 9851.c
字号:
/*编译环境:CVAVR */
/*作者:屈朋伟 魏坤 李辉*/
/*联系:QPW2004@163.COM */
/*键盘返回值:
12 13 14 15
8 9 10 11
4 5 6 7
0 1 2 3*/
#include <mega16.h>
#include <delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "1602LCD.h"
#define ADC_VREF_TYPE 0x40
#define dat PORTB.0
#define clk PORTB.1
#define load PORTB.2
#define uchar unsigned char
#define uint unsigned int
unsigned char select=16,keys;
unsigned int k=512;
//unsigned int v; //设置电压值
/* 脉冲宽度设置函数 */
void Set_Process(void)
{
OCR1AH=k>>8;
OCR1AL=k&0xff;
}
/* 脉冲宽度加函数 */
void Add_OCR(void)
{
if(k!=593)//去AD603的1脚下限电压4.2V(10V时(1-42%)*1024=593)
k=k+1;
}
/* 脉冲宽度减函数 */
void Sub_OCR(void)
{
if(k!=204)//去AD603的1脚上限电压8V(10V时(1-80%)*1024=204)
k=k-1;
}
//外中断0服务程序(按键服务程序)
interrupt [EXT_INT0] void ext_int0_isr(void)
{
select=key();
do keys=key_port_pin&0xf0;//等待按键释放
while(keys!=0xf0);
key_port_ddr=0x0f;//中断前提
key_port=0xf0;
#asm("sei") //开中断!
}
//AD9851初始化
void ini9851(void)
{
clk=0;
load=0;
delay_us(5);
clk=1; //串行输入
delay_us(5);
clk=0;
delay_us(5);
load=1;
delay_us(5);
load=0;
delay_us(5);
}
//往AD9851写数据
void write_dds(unsigned long dds)
{
//unsigned char temp=0x80;
unsigned char i;
load=0;
clk=0;
for(i=0;i<40;i++)
{
clk=0;
delay_us(2);
if((dds&0x00000001)||(i==32))
{dat=1;
}
else dat=0;
clk=1;
delay_us(2);
dds=dds>>1;
}
load=1;
clk=0;
delay_us(2);
load=0;
}
//写入频率
void write_freq(unsigned long freq)
{
unsigned long dds;
dds=23.860929422*freq;
write_dds(dds);
}
// 读ADC转换结果
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
//写EEPROM数据函数
void Write_EEPROM(uchar Data,uint Address)
{if(EECR&0x20) //判断写使能是否为0
delay_ms(10); //延时
EEARH=Address>>8; //送高地址
EEARL=Address&0x00ff; //送低地址
EEDR=Data; //送数据
EECR=EECR|0x04; //主写使能置位
EECR=EECR|0x02; //写使能置位
delay_ms(10); //延时
}
//读EEPROM数据函数
uchar Read_EEPROM(uint Address)
{uchar i;
if(EECR&0x01) //判断读使能是否为0
delay_ms(10); //延时
EEARH=Address>>8; //送高地址
EEARL=Address&0x00ff; //送低地址
EECR=EECR|0x01; //读使能置位
delay_ms(10); //延时
i=EEDR; //读数据
return(i); //返回数据
}
//主程序
void main(void)
{ char t,ss[16]={"DDS"},yy[16]={"OUT Freq:"};
uchar eep;
unsigned long int str,sin[20]={10003090,10005878,10008090,10009511,10010000,10009511,10008090,10005878,10003090,10000000,
9996910,9994122,9991910,9990490,9990000,9990490,9991910,9994122,9996910,10000000};
unsigned int AD,min=0xc2,max=0xd7;
TCCR1A=0x83; //10位PWM,向上计数清除OC1A,向下计数置位OC1A
TCCR1B=0x01; //时钟1分频,PWM信号最小频率为8M/2046=4KHz
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x83;
// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// INT1: Off
// INT2: Off
GICR|=0x40;
MCUCR=0x00;
MCUCSR=0x00;
GIFR=0x40;
//LCD端口初始化
DDRA |= LCD_DATA;
DDRA |= LCD_RS | LCD_EN | LCD_RW;
DDRD.2=0;//键盘外中断1设置为输入
PORTD.2=1;
DDRD.5=1;//OC1A输出 PWM
key_port_ddr=0x0f;//中断前提
key_port=0xf0;
PORTB=0x07; //DDS数据准备为高电平
DDRB=0x07;
LCD_init();
LCD_write_char(0x01,0); //显示清屏
LCD_write_string(3,0,ss);
delay_ms(1000);//等dds稳定
eep=Read_EEPROM(0); //读EEPROM
str=eep;
str=str<<8;
eep=Read_EEPROM(1);
str=str|eep;
str=str<<8;
eep=Read_EEPROM(2);
str=str|eep;
str=str<<8;
eep=Read_EEPROM(3);
str=str|eep;
ini9851(); //DDS初始化
write_freq(str);//初始输出
for(t=0;t<3;t++)ss[t]=0;
t=0;
#asm("sei") //开中断!
while(1)
{
if(select==12){ss[t]='0';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==13){ss[t]='1';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==14){ss[t]='2';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==15){ss[t]='3';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==8){ss[t]='4';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==9){ss[t]='5';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==10){ss[t]='6';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==11){ss[t]='7';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==4){ss[t]='8';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==5){ss[t]='9';t++;select=16;LCD_write_char(0x01,0);LCD_write_string(0,0,ss);}
if(select==2)
{ while(1)
{
for(eep=0;eep<20;eep++) //20个采样点
{str=sin[eep];
write_freq(str);
delay_us(20);
}
}
}
if(select==3)
{
str=atol(ss);
write_freq(str);
eep=str>>24;//取频率高8位
Write_EEPROM(eep,0);
eep=(str>>16)&0xff;
Write_EEPROM(eep,1);
eep=(str>>8)&0xff;
Write_EEPROM(eep,2);
eep=str&0xff;//取频率低8位
Write_EEPROM(eep,3);
//分段矫正,0x00D7~0x00c2:1V左右
if(str<1000000){max=(int)(0x00D7*0.328);min=(int)(0x00c2*0.328);} //<1M
if((str>=1000000)&&(str<3000000)){max=(int)(0x00D7*0.328);min=(int)(0x00c2*0.328);} //1M~3M
if((str>=3000000)&&(str<5000000)){max=(int)(0x00D7*0.376);min=(int)(0x00c2*0.376);} //3M~5M
if((str>=5000000)&&(str<7000000)){max=(int)(0x00D7*0.435);min=(int)(0x00c2*0.435);} //5M~7M
if((str>=7000000)&&(str<9000000)){max=(int)(0x00D7*0.526);min=(int)(0x00c2*0.526);} //7M~9M
if((str>=9000000)&&(str<11000000)){max=(int)(0x00D7*0.625);min=(int)(0x00c2*0.625);} //9M~11M
if((str>=11000000)&&(str<13000000)){max=(int)(0x00D7*0.8);min=(int)(0x00c2*0.8);} //11M~13M
if((str>=13000000)&&(str<15000000)){max=(int)(0x00D7*1);min=(int)(0x00c2*1);} //13M~15M
if((str>=15000000)&&(str<17000000)){max=(int)(0x00D7*1.25);min=(int)(0x00c2*1.25);} //15M~17M
if((str>=17000000)&&(str<19000000)){max=(int)(0x00D7*1.429);min=(int)(0x00c2*1.429);} //17M~19M
if((str>=19000000)&&(str<21000000)){max=(int)(0x00D7*1.667);min=(int)(0x00c2*1.667);} //19M~21M
if(str>=21000000){max=1000;min=900;} //>21M
LCD_write_char(0x01,0); //显示清屏
LCD_write_string(0,0,yy);
LCD_write_string(0,1,ss);
select=16;
while(select>15)
{
AD=read_adc(0);
if((AD>max)||(AD<min))
{
if(AD>max)Add_OCR();
if(AD<min)Sub_OCR();
Set_Process();
delay_ms(50);
}
}
for(t=0;t<16;t++)ss[t]=0;
t=0;
}
#asm("cli") //关中断
AD=read_adc(0);
if((AD>max)||(AD<min))
{
if(AD>max)Add_OCR();
if(AD<min)Sub_OCR();
Set_Process();
delay_ms(50);
}
#asm("sei")
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -