⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 9851.c

📁 51单片机控制DDS的程序
💻 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 + -